aboutsummaryrefslogtreecommitdiff
path: root/src/progman.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/progman.c')
-rw-r--r--src/progman.c258
1 files changed, 109 insertions, 149 deletions
diff --git a/src/progman.c b/src/progman.c
index d849368..81accfb 100644
--- a/src/progman.c
+++ b/src/progman.c
@@ -94,9 +94,6 @@ prog_tag (struct prog const *prog)
case TYPE_COMPONENT:
return prog->v.p.comp->tag;
- case TYPE_REDIRECTOR:
- return prog->v.r.tag;
-
case TYPE_COMMAND:
return prog->v.c.tag;
}
@@ -147,6 +144,21 @@ unlink_prog (struct prog *pp)
progtail = pp->prev;
}
+static inline void
+prog_stop_redirectors (struct prog *p)
+{
+ if (p->v.p.redir[RETR_OUT] != -1)
+ {
+ deregister_socket (p->v.p.redir[RETR_OUT]);
+ p->v.p.redir[RETR_OUT] = -1;
+ }
+ if (p->v.p.redir[RETR_ERR] != -1)
+ {
+ deregister_socket (p->v.p.redir[RETR_ERR]);
+ p->v.p.redir[RETR_ERR] = -1;
+ }
+}
+
void
destroy_prog (struct prog **pp)
{
@@ -163,27 +175,7 @@ destroy_prog (struct prog **pp)
if (p->v.p.status == status_listener && p->v.p.socket != -1)
deregister_socket (p->v.p.socket);
/* FIXME: Remove also all dependent progs (esp. tcpmux) */
- if (p->v.p.redir[RETR_OUT])
- p->v.p.redir[RETR_OUT]->v.r.master = NULL;
- if (p->v.p.redir[RETR_ERR])
- p->v.p.redir[RETR_ERR]->v.r.master = NULL;
- break;
-
- case TYPE_REDIRECTOR:
- {
- struct prog *master = p->v.r.master;
- component_ref_decr (p->v.r.comp);
- if (master)
- {
- if (p == master->v.p.redir[0])
- master->v.p.redir[0] = NULL;
- else if (p == master->v.p.redir[1])
- master->v.p.redir[1] = NULL;
- }
- /* else
- logmsg (LOG_NOTICE, _("orphan redirector: %s"), p->tag);*/
- free (p->v.r.tag);
- }
+ prog_stop_redirectors (p);
break;
case TYPE_COMMAND:
@@ -194,50 +186,6 @@ destroy_prog (struct prog **pp)
*pp = NULL;
}
-static char *
-redir_tag (struct prog *master, int type)
-{
- static char *redirstr[2] = { "stdout", "stderr" };
- char *str = NULL;
- size_t len = 0;
- char const *tag = prog_tag (master);
- if (type < ARRAY_SIZE(redirstr))
- grecs_asprintf (&str, &len, "%s/%s", tag, redirstr[type]);
- else
- grecs_asprintf (&str, &len, "%s/%d", tag, type);
- return str;
-}
-
-static struct prog *
-register_redir (int type, struct prog *master)
-{
- char *tag = redir_tag (master, type);
- struct prog *pp = grecs_zalloc (sizeof (*pp));
-
- pp->type = TYPE_REDIRECTOR;
- pp->v.r.tag = tag;
- pp->v.r.master = master;
- pp->v.r.comp = master->v.p.comp;
- component_ref_incr (pp->v.r.comp);
- link_prog (pp, NULL);
- return pp;
-}
-
-void
-update_redir (int type, struct prog *master, pid_t pid)
-{
- struct prog *pp;
- if (master->v.p.redir[type])
- {
- pp = master->v.p.redir[type];
- prog_stop (pp, SIGKILL); /* Just in case */
- }
-
- pp = register_redir (type, master);
- master->v.p.redir[type] = pp;
- pp->pid = pid;
-}
-
/* Given the component COMP find the element of the program list
after which to link in the new prog associated with that COMP.
The progs in the resulting list must be arranged exactly in the
@@ -403,7 +351,89 @@ redirect_to_file (struct prog *master, int stream)
}
return fd;
}
+
+struct read_buffer
+{
+ struct prog *master;
+ int stream;
+ char text[PIES_LOG_BUF_SIZE];
+ size_t len;
+ int overflow;
+};
+
+static int
+redirect_read (int fd, void *data)
+{
+ struct read_buffer *rb = data;
+ int n;
+ int prio = rb->master->v.p.comp->redir[rb->stream].v.prio;
+ char const *tag = prog_tag (rb->master);
+ pid_t pid = rb->master->pid;
+ char *p;
+
+ n = read (fd, rb->text + rb->len, sizeof (rb->text) - rb->len);
+ if (n == -1)
+ return -1;
+ if (n > 0)
+ {
+ rb->len += n;
+
+ while (rb->len)
+ {
+ p = memchr (rb->text, '\n', rb->len);
+ if (p)
+ {
+ *p++ = 0;
+ if (rb->overflow)
+ rb->overflow = 0;
+ else
+ pies_syslog_message (prio, rb->text, tag, pid);
+ n = rb->len - (p - rb->text);
+ if (n > 0)
+ memmove (rb->text, p, n);
+ rb->len = n;
+ }
+ else if (rb->len == sizeof (rb->text))
+ {
+ rb->text[sizeof (rb->text) - 1] = 0;
+ pies_syslog_message (prio, rb->text, tag, pid);
+ rb->len = 0;
+ rb->overflow = 1;
+ }
+ }
+ }
+ return 0;
+}
+
+static void
+read_buffer_free (void *p)
+{
+ free (p);
+}
+
+int
+redirect_to_syslog (struct prog *master, int stream, int *fd)
+{
+ struct read_buffer *rb;
+ int p[2];
+
+ if (pipe (p))
+ {
+ logmsg (LOG_CRIT, "pipe: %s", strerror (errno));
+ return -1;
+ }
+ rb = grecs_zalloc (sizeof (*rb));
+ rb->master = master;
+ rb->stream = stream;
+ rb->len = 0;
+ rb->overflow = 0;
+
+ register_socket (p[0], redirect_read, NULL, NULL, rb, read_buffer_free);
+ *fd = p[0];
+ return p[1];
+}
+
static void
close_fds (fd_set *fdset)
{
@@ -425,72 +455,20 @@ free_redirector (struct redirector *rp)
}
int
-open_redirector (struct prog *master, int stream)
+open_redirector (struct prog *master, int stream, int *fd)
{
- int p[2];
- FILE *fp;
- char *buf = NULL;
- size_t size = 0;
- pid_t pid;
- int prio;
- char *tag;
- fd_set fdset;
-
switch (master->v.p.comp->redir[stream].type)
{
case redir_null:
+ *fd = -1;
return -1;
case redir_file:
+ *fd = -1;
return redirect_to_file (master, stream);
case redir_syslog:
- break;
- }
-
- if (pipe (p))
- {
- logmsg (LOG_CRIT, "pipe: %s", strerror (errno));
- return -1;
- }
-
- switch (pid = fork ())
- {
- case 0:
- /* Redirector process */
- tag = redir_tag (master, stream);
- mf_proctitle_format ("%s redirector", tag);
- free (tag);
-
- FD_ZERO (&fdset);
- FD_SET (p[0], &fdset);
- close_fds (&fdset);
-
- diag_setup (0);
- signal_setup (redir_exit);
-
- close (p[1]);
- fp = fdopen (p[0], "r");
- if (fp == NULL)
- _exit (1);
- openlog (prog_tag (master), LOG_PID, master->v.p.comp->facility);
- prio = master->v.p.comp->redir[stream].v.prio;
- while (getline (&buf, &size, fp) > 0)
- syslog (prio, "%s", buf);
- _exit (0);
-
- case -1:
- logmsg (LOG_CRIT,
- _("cannot run redirector `%s': fork failed: %s"),
- prog_tag (master), strerror (errno));
- return -1;
-
- default:
- debug (1, (_("redirector for %s started, pid=%lu"),
- prog_tag (master), (unsigned long) pid));
- update_redir (stream, master, pid);
- close (p[0]);
- return p[1];
+ return redirect_to_syslog (master, stream, fd);
}
}
@@ -930,7 +908,7 @@ prog_execute (struct prog *prog)
execvp (prog->v.p.comp->program ?
prog->v.p.comp->program : prog->v.p.argv[0],
prog->v.p.argv);
- openlog (log_tag, LOG_PID, prog->v.p.comp->facility);
+ //FIXME: pies_syslog?
syslog (LOG_CRIT, _("cannot start `%s': %s"), prog_tag (prog),
strerror (errno));
_exit (EX_SOFTWARE);
@@ -1044,8 +1022,10 @@ prog_start (struct prog *prog)
if (prog_init (prog))
return; //FIXME
- redir[RETR_OUT] = open_redirector (prog, RETR_OUT);
- redir[RETR_ERR] = open_redirector (prog, RETR_ERR);
+ redir[RETR_OUT] = open_redirector (prog, RETR_OUT,
+ &prog->v.p.redir[RETR_OUT]);
+ redir[RETR_ERR] = open_redirector (prog, RETR_ERR,
+ &prog->v.p.redir[RETR_ERR]);
switch (pid = fork ())
{
@@ -1361,7 +1341,7 @@ prog_create_socket (struct prog *prog, void *data)
comp->privs.user, comp->umask);
if (fd == -1)
destroy_prog (&prog);
- else if (register_program_socket (comp->socket_type, fd, prog))
+ else if (register_program_socket (comp->socket_type, fd, prog, NULL))
{
close (fd);
destroy_prog (&prog);
@@ -1610,15 +1590,6 @@ prog_start_prerequisites (struct prog *prog)
}
void
-prog_stop_redirectors (struct prog *prog)
-{
- if (prog->v.p.redir[RETR_OUT])
- prog_stop (prog->v.p.redir[RETR_OUT], SIGTERM);
- if (prog->v.p.redir[RETR_ERR])
- prog_stop (prog->v.p.redir[RETR_ERR], SIGTERM);
-}
-
-void
prog_stop_dependents (struct prog *prog)
{
struct component *comp;
@@ -2254,17 +2225,6 @@ progman_cleanup (int expect_term)
break;
- case TYPE_REDIRECTOR:
- /* It was a redirector of an already finished process. */
- print_status (prog_tag (prog), pid, status,
- expect_term ||
- (prog->v.r.master &&
- prog->v.r.master->v.p.status == status_stopping));
- debug (1, (_("removing redirector %s, pid=%lu"),
- prog_tag (prog), (unsigned long)pid));
- destroy_prog (&prog);
- break;
-
case TYPE_COMMAND:
print_status (prog_tag (prog), pid, status, expect_term);
destroy_prog (&prog);
@@ -2351,7 +2311,7 @@ prog_activate_listener (struct prog *prog)
comp->privs.user, comp->umask);
if (fd == -1)
return -1;
- else if (register_program_socket (comp->socket_type, fd, prog))
+ else if (register_program_socket (comp->socket_type, fd, prog, NULL))
{
close (fd);
return -1;

Return to:

Send suggestions and report system problems to the System administrator.