diff options
Diffstat (limited to 'src/progman.c')
-rw-r--r-- | src/progman.c | 126 |
1 files changed, 92 insertions, 34 deletions
diff --git a/src/progman.c b/src/progman.c index 3263172..85a5068 100644 --- a/src/progman.c +++ b/src/progman.c @@ -388,6 +388,19 @@ redirect_to_file (struct prog *master, int stream) return fd; } +static void +close_fds (fd_set *fdset) +{ + int i; + + for (i = getmaxfd (); i >= 0; i--) + { + if (fdset && FD_ISSET (i, fdset)) + continue; + close (i); + } +} + int open_redirector (struct prog *master, int stream) { @@ -398,6 +411,7 @@ open_redirector (struct prog *master, int stream) pid_t pid; int i, prio; char *tag; + fd_set fdset; switch (master->v.p.comp->redir[stream].type) { @@ -420,11 +434,9 @@ open_redirector (struct prog *master, int stream) mf_proctitle_format ("%s redirector", tag); free (tag); - for (i = getmaxfd (); i >= 0; i--) - { - if (i != p[0]) - close (i); - } + FD_ZERO (&fdset); + FD_SET (p[0], &fdset); + close_fds (&fdset); diag_setup (0); signal_setup (redir_exit); @@ -605,7 +617,8 @@ prog_start (struct prog *prog) pid_t pid; time_t now; int redir[2]; - + fd_set fdset; + if (prog->pid > 0 || !IS_COMPONENT (prog)) return; @@ -658,6 +671,7 @@ prog_start (struct prog *prog) case pies_comp_accept: prog->v.p.socket = create_socket (prog->v.p.comp->socket_url, + prog->v.p.comp->socket_type, prog->v.p.comp->privs.user, prog->v.p.comp->umask); if (prog->v.p.socket == -1) @@ -771,14 +785,14 @@ prog_start (struct prog *prog) dup2 (redir[RETR_ERR], 2); } - /* Close unneded descripitors */ - for (i = getmaxfd (); i > 2; i--) - { - if (prog->v.p.comp->mode == pies_comp_pass_fd - && i == prog->v.p.socket) - continue; - close (i); - } + /* Close unneeded descripitors */ + FD_ZERO (&fdset); + FD_SET (0, &fdset); + FD_SET (1, &fdset); + FD_SET (2, &fdset); + if (prog->v.p.comp->mode == pies_comp_pass_fd) + FD_SET (prog->v.p.socket, &fdset); + close_fds (&fdset); execvp (prog->v.p.comp->program ? prog->v.p.comp->program : prog->v.p.comp->argv[0], @@ -802,7 +816,11 @@ prog_start (struct prog *prog) prog->v.p.comp->pass_fd_timeout : DEFAULT_PASS_FD_TIMEOUT); /* FIXME: Error code */; } - if (prog->v.p.comp->mode != pies_comp_exec) + if (prog->v.p.comp->flags & CF_WAIT) + { + disable_socket (prog->v.p.socket); + } + else if (prog->v.p.comp->mode != pies_comp_exec) close (prog->v.p.socket); prog->pid = pid; prog->v.p.status = status_enabled; @@ -836,38 +854,29 @@ check_acl (pies_acl_t acl, struct sockaddr *s, int salen) return 0; } -int -progman_accept (int socket) +static int +_prog_accept (struct prog *p) { int fd; - struct prog *p, *pinst; + struct prog *pinst; union { struct sockaddr s_in; struct sockaddr s_un; } addr; socklen_t addrlen = sizeof addr; - - fd = accept (socket, (struct sockaddr*) &addr, &addrlen); + + fd = accept (p->v.p.socket, (struct sockaddr*) &addr, &addrlen); if (fd == -1) { logmsg (LOG_ERR, _("accept failed: %s"), strerror (errno)); return 1; } - p = prog_lookup_by_socket (socket); - if (!p) - { - logmsg (LOG_EMERG, - _("INTERNAL ERROR: no matching prog for fd %d"), socket); - close (fd); - return 1; - } - if (debug_level >= 1) { char *s = sockaddr_to_astr ((struct sockaddr *)&addr, addrlen); - logmsg (LOG_DEBUG, "%s wants %s", s, p->tag); + logmsg (LOG_DEBUG, _("%s wants %s"), s, p->tag); free (s); } @@ -901,6 +910,51 @@ progman_accept (int socket) return 0; } +static int +_prog_wait (struct prog *p) +{ + struct prog *pinst; + + debug (1, (_("someone wants %s"), p->tag)); + + if (p->v.p.comp->max_instances + && p->v.p.num_instances >= p->v.p.comp->max_instances) + { + logmsg (LOG_ERR, + _("%s: too many instances running, dropping connection"), + p->tag); + return 1; + } + + pinst = register_prog0 (p->v.p.comp, -1); + pinst->v.p.socket = p->v.p.socket; + pinst->v.p.listener = p; + prog_start (pinst); + + pinst->v.p.socket = -1; + + p->v.p.num_instances++; + return 0; +} + +int +progman_accept (int socket) +{ + struct prog *p = prog_lookup_by_socket (socket); + if (!p) + { + logmsg (LOG_EMERG, + _("INTERNAL ERROR: no matching prog for fd %d"), socket); + return 1; + } + + if (p->v.p.comp->socket_type == SOCK_STREAM + && !(p->v.p.comp->flags & CF_WAIT)) + return _prog_accept (p); + + return _prog_wait (p); +} + void component_fixup_depend (struct component *comp) @@ -1077,10 +1131,11 @@ progman_create_sockets () if (comp->mode == pies_comp_inetd) { int fd = create_socket (comp->socket_url, + comp->socket_type, comp->privs.user, comp->umask); if (fd == -1) prog->v.p.status = status_disabled; - else if (register_listener (fd)) + else if (register_socket (comp->socket_type, fd)) { close (fd); prog->v.p.status = status_disabled; @@ -1664,8 +1719,7 @@ run_command (struct action *act, struct prog *prog, unsigned retcode, setenv ("PIES_STATUS", umaxtostr (STATUS_CODE (retcode), buf), 1); /* FIXME: see above */ - for (i = getmaxfd (); i >= 0; i--) - close (i); + close_fds (NULL); argv[0] = "/bin/sh"; argv[1] = "-c"; @@ -1707,9 +1761,13 @@ progman_cleanup (int expect_term) print_status (prog->tag, pid, status, expect_term); if (prog->v.p.comp->mode == pies_comp_inetd) { - prog->v.p.listener->v.p.num_instances--; + struct prog *listener = prog->v.p.listener; + + listener->v.p.num_instances--; prog_stop_redirectors (prog); destroy_prog (&prog); + if (listener->v.p.comp->flags & CF_WAIT) + enable_socket (listener->v.p.socket); } else { |