Mercurial > dovecot > original-hg > dovecot-1.2
comparison src/master/login-process.c @ 1275:af685269ead0 HEAD
login: Wait until we're connected to auth process before executing command
from client.
inetd usage: --group=name can now specify which login group to use. Default
is the binary name before '-' character (ie. imap or pop3).
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 05 Mar 2003 00:38:07 +0200 |
parents | 2cf2e08a6ee9 |
children | 04ed7a2536cc |
comparison
equal
deleted
inserted
replaced
1274:f7fc5d52ac7c | 1275:af685269ead0 |
---|---|
65 static struct hash_table *processes; | 65 static struct hash_table *processes; |
66 static struct login_group *login_groups; | 66 static struct login_group *login_groups; |
67 | 67 |
68 static void login_process_destroy(struct login_process *p); | 68 static void login_process_destroy(struct login_process *p); |
69 static void login_process_unref(struct login_process *p); | 69 static void login_process_unref(struct login_process *p); |
70 static int login_process_init_group(struct login_process *p); | |
70 | 71 |
71 static void login_group_create(struct login_settings *login_set) | 72 static void login_group_create(struct login_settings *login_set) |
72 { | 73 { |
73 struct login_group *group; | 74 struct login_group *group; |
74 | 75 |
140 "notification"); | 141 "notification"); |
141 return; | 142 return; |
142 } | 143 } |
143 | 144 |
144 p->listening = FALSE; | 145 p->listening = FALSE; |
145 p->group->listening_processes--; | 146 |
146 | 147 if (p->group != NULL) { |
147 p->prev_nonlisten = p->group->newest_nonlisten_process; | 148 p->group->listening_processes--; |
148 | 149 p->prev_nonlisten = p->group->newest_nonlisten_process; |
149 if (p->group->newest_nonlisten_process != NULL) | 150 |
150 p->group->newest_nonlisten_process->next_nonlisten = p; | 151 if (p->group->newest_nonlisten_process != NULL) |
151 p->group->newest_nonlisten_process = p; | 152 p->group->newest_nonlisten_process->next_nonlisten = p; |
152 | 153 p->group->newest_nonlisten_process = p; |
153 if (p->group->oldest_nonlisten_process == NULL) | 154 |
154 p->group->oldest_nonlisten_process = p; | 155 if (p->group->oldest_nonlisten_process == NULL) |
156 p->group->oldest_nonlisten_process = p; | |
157 } | |
158 } | |
159 | |
160 static struct login_group *login_group_process_find(const char *name) | |
161 { | |
162 struct login_group *group; | |
163 struct login_settings *login; | |
164 | |
165 if (login_groups == NULL) { | |
166 for (login = set->logins; login != NULL; login = login->next) | |
167 login_group_create(login); | |
168 } | |
169 | |
170 for (group = login_groups; group != NULL; group = group->next) { | |
171 if (strcmp(group->set->name, name) == 0) | |
172 return group; | |
173 } | |
174 | |
175 return NULL; | |
176 } | |
177 | |
178 static int login_process_read_group(struct login_process *p) | |
179 { | |
180 struct login_group *group; | |
181 const char *name; | |
182 char buf[256]; | |
183 unsigned int len; | |
184 ssize_t ret; | |
185 | |
186 /* read length */ | |
187 ret = read(p->fd, buf, 1); | |
188 if (ret != 1) | |
189 len = 0; | |
190 else { | |
191 len = buf[0]; | |
192 if (len >= sizeof(buf)) { | |
193 i_error("login: Process name length too large"); | |
194 return FALSE; | |
195 } | |
196 | |
197 ret = read(p->fd, buf, len); | |
198 } | |
199 | |
200 if (ret < 0) | |
201 i_error("login: read() failed: %m"); | |
202 else if (len == 0 || (size_t)ret != len) | |
203 i_error("login: Process name wasn't sent"); | |
204 else { | |
205 name = t_strndup(buf, len); | |
206 group = login_group_process_find(name); | |
207 if (group == NULL) { | |
208 i_error("login: Unknown process group '%s'", name); | |
209 return FALSE; | |
210 } | |
211 | |
212 p->group = group; | |
213 return login_process_init_group(p); | |
214 } | |
215 return FALSE; | |
155 } | 216 } |
156 | 217 |
157 static void login_process_input(void *context) | 218 static void login_process_input(void *context) |
158 { | 219 { |
159 struct login_process *p = context; | 220 struct login_process *p = context; |
160 struct auth_process *auth_process; | 221 struct auth_process *auth_process; |
161 struct login_auth_request *authreq; | 222 struct login_auth_request *authreq; |
162 struct master_login_request req; | 223 struct master_login_request req; |
163 int client_fd, ret; | 224 int client_fd; |
225 ssize_t ret; | |
226 | |
227 if (p->group == NULL) { | |
228 /* we want to read the group */ | |
229 if (!login_process_read_group(p)) | |
230 login_process_destroy(p); | |
231 return; | |
232 } | |
164 | 233 |
165 ret = fd_read(p->fd, &req, sizeof(req), &client_fd); | 234 ret = fd_read(p->fd, &req, sizeof(req), &client_fd); |
166 if (ret != sizeof(req)) { | 235 if (ret != sizeof(req)) { |
167 if (ret == 0) { | 236 if (ret == 0) { |
168 /* disconnected, ie. the login process died */ | 237 /* disconnected, ie. the login process died */ |
220 login_process_new(struct login_group *group, pid_t pid, int fd) | 289 login_process_new(struct login_group *group, pid_t pid, int fd) |
221 { | 290 { |
222 struct login_process *p; | 291 struct login_process *p; |
223 | 292 |
224 i_assert(pid != 0); | 293 i_assert(pid != 0); |
225 i_assert(group != NULL); | |
226 | 294 |
227 p = i_new(struct login_process, 1); | 295 p = i_new(struct login_process, 1); |
228 p->group = group; | 296 p->group = group; |
229 p->refcount = 1; | 297 p->refcount = 1; |
230 p->pid = pid; | 298 p->pid = pid; |
236 IO_PRIORITY_DEFAULT, FALSE); | 304 IO_PRIORITY_DEFAULT, FALSE); |
237 | 305 |
238 PID_ADD_PROCESS_TYPE(pid, PROCESS_TYPE_LOGIN); | 306 PID_ADD_PROCESS_TYPE(pid, PROCESS_TYPE_LOGIN); |
239 hash_insert(processes, POINTER_CAST(pid), p); | 307 hash_insert(processes, POINTER_CAST(pid), p); |
240 | 308 |
241 p->group->processes++; | 309 if (p->group != NULL) { |
242 p->group->listening_processes++; | 310 p->group->processes++; |
311 p->group->listening_processes++; | |
312 } | |
243 return p; | 313 return p; |
244 } | 314 } |
245 | 315 |
246 static void login_process_remove_from_lists(struct login_process *p) | 316 static void login_process_remove_from_lists(struct login_process *p) |
247 { | 317 { |
318 if (p->group == NULL) | |
319 return; | |
320 | |
248 if (p == p->group->oldest_nonlisten_process) | 321 if (p == p->group->oldest_nonlisten_process) |
249 p->group->oldest_nonlisten_process = p->next_nonlisten; | 322 p->group->oldest_nonlisten_process = p->next_nonlisten; |
250 else | 323 else |
251 p->prev_nonlisten->next_nonlisten = p->next_nonlisten; | 324 p->prev_nonlisten->next_nonlisten = p->next_nonlisten; |
252 | 325 |
266 | 339 |
267 if (!p->initialized && io_loop_is_running(ioloop)) { | 340 if (!p->initialized && io_loop_is_running(ioloop)) { |
268 i_error("Login process died too early - shutting down"); | 341 i_error("Login process died too early - shutting down"); |
269 io_loop_stop(ioloop); | 342 io_loop_stop(ioloop); |
270 } | 343 } |
271 if (p->listening) | 344 |
345 if (p->listening && p->group != NULL) | |
272 p->group->listening_processes--; | 346 p->group->listening_processes--; |
273 | 347 |
274 o_stream_close(p->output); | 348 o_stream_close(p->output); |
275 io_remove(p->io); | 349 io_remove(p->io); |
276 if (close(p->fd) < 0) | 350 if (close(p->fd) < 0) |
277 i_error("close(login) failed: %m"); | 351 i_error("close(login) failed: %m"); |
278 | 352 |
279 if (!p->listening) | 353 if (!p->listening) |
280 login_process_remove_from_lists(p); | 354 login_process_remove_from_lists(p); |
281 | 355 |
282 p->group->processes--; | 356 if (p->group != NULL) |
357 p->group->processes--; | |
358 | |
283 if (p->pid != 0) | 359 if (p->pid != 0) |
284 hash_remove(processes, POINTER_CAST(p->pid)); | 360 hash_remove(processes, POINTER_CAST(p->pid)); |
285 | 361 |
286 login_process_unref(p); | 362 login_process_unref(p); |
287 } | 363 } |
419 struct login_process *p; | 495 struct login_process *p; |
420 | 496 |
421 /* don't start raising the process count if they're dying all | 497 /* don't start raising the process count if they're dying all |
422 the time */ | 498 the time */ |
423 p = hash_lookup(processes, POINTER_CAST(pid)); | 499 p = hash_lookup(processes, POINTER_CAST(pid)); |
424 if (p != NULL) | 500 if (p != NULL && p->group != NULL) |
425 p->group->wanted_processes_count = 0; | 501 p->group->wanted_processes_count = 0; |
426 } | 502 } |
427 | 503 |
428 static void login_hash_destroy(void *key __attr_unused__, void *value, | 504 static void login_hash_destroy(void *key __attr_unused__, void *value, |
429 void *context __attr_unused__) | 505 void *context __attr_unused__) |
514 | 590 |
515 env_clean(); | 591 env_clean(); |
516 return ret; | 592 return ret; |
517 } | 593 } |
518 | 594 |
595 static int login_process_init_group(struct login_process *p) | |
596 { | |
597 p->group->processes++; | |
598 p->group->listening_processes++; | |
599 | |
600 if (login_process_send_env(p) < 0) { | |
601 i_error("login: Couldn't send environment"); | |
602 return FALSE; | |
603 } | |
604 | |
605 return TRUE; | |
606 } | |
607 | |
519 static void inetd_login_accept(void *context __attr_unused__) | 608 static void inetd_login_accept(void *context __attr_unused__) |
520 { | 609 { |
521 struct login_process *p; | 610 struct login_process *p; |
522 int fd; | 611 int fd; |
523 | 612 |
527 i_fatal("accept(inetd_login_fd) failed: %m"); | 616 i_fatal("accept(inetd_login_fd) failed: %m"); |
528 } else { | 617 } else { |
529 net_set_nonblock(fd, TRUE); | 618 net_set_nonblock(fd, TRUE); |
530 fd_close_on_exec(fd, TRUE); | 619 fd_close_on_exec(fd, TRUE); |
531 | 620 |
532 p = login_process_new(login_groups, ++login_pid_counter, fd); | 621 p = login_process_new(NULL, ++login_pid_counter, fd); |
533 p->initialized = TRUE;; | 622 p->initialized = TRUE; |
534 | |
535 if (login_process_send_env(p) < 0) { | |
536 i_warning("Couldn't send environment to login process"); | |
537 login_process_destroy(p); | |
538 } | |
539 } | 623 } |
540 } | 624 } |
541 | 625 |
542 void login_processes_init(void) | 626 void login_processes_init(void) |
543 { | 627 { |
548 processes = hash_create(default_pool, default_pool, 128, NULL, NULL); | 632 processes = hash_create(default_pool, default_pool, 128, NULL, NULL); |
549 if (!IS_INETD()) { | 633 if (!IS_INETD()) { |
550 to = timeout_add(1000, login_processes_start_missing, NULL); | 634 to = timeout_add(1000, login_processes_start_missing, NULL); |
551 io_listen = NULL; | 635 io_listen = NULL; |
552 } else { | 636 } else { |
553 /* use the first login group for everyone */ | |
554 login_group_create(set->logins); | |
555 | |
556 to = NULL; | 637 to = NULL; |
557 io_listen = io_add(inetd_login_fd, IO_READ, | 638 io_listen = io_add(inetd_login_fd, IO_READ, |
558 inetd_login_accept, NULL); | 639 inetd_login_accept, NULL); |
559 } | 640 } |
560 } | 641 } |