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 }