aboutsummaryrefslogtreecommitdiff
path: root/src/progman.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/progman.c')
-rw-r--r--src/progman.c126
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
{

Return to:

Send suggestions and report system problems to the System administrator.