diff options
Diffstat (limited to 'src/progman.c')
-rw-r--r-- | src/progman.c | 185 |
1 files changed, 157 insertions, 28 deletions
diff --git a/src/progman.c b/src/progman.c index c2b09c1..639c22f 100644 --- a/src/progman.c +++ b/src/progman.c @@ -15,6 +15,7 @@ along with GNU Pies. If not, see <http://www.gnu.org/licenses/>. */ #include "pies.h" +#include <termios.h> enum prog_type { @@ -32,6 +33,7 @@ enum prog_status status_sleeping, /* Component is sleeping. An attempt to start it will be made at prog->v.p.timestamp + SLEEPTIME */ status_stopping, /* Component is being stopped */ + status_finished, /* A "once" component has finished */ }; struct conn_class @@ -61,6 +63,7 @@ struct prog time_t timestamp; /* Time of last startup */ size_t failcount; /* Number of failed starts since timestamp */ enum prog_status status; /* Current component status */ + char *runlevels; /* If status == status_listener: */ size_t num_instances; /* Number of running instances */ /* If comp->type == pies_comp_inetd && status == status_enabled */ @@ -400,6 +403,17 @@ prog_rebuild_prerequisites (struct prog *prog) prog->prereq[depc] = NULL; } +int +progman_running_p () +{ + struct prog *prog; + + for (prog = proghead; prog; prog = prog->next) + if (prog->pid > 0) + return 1; + return 0; +} + size_t progman_running_count () { @@ -1096,6 +1110,68 @@ progman_run_comp (struct component *comp, int fd, prog_execute (prog); } +static int +console_open (int mode) +{ + int i, fd; + + for (i = 0; i < 5; i++) + { + fd = open (console_device, mode | O_NONBLOCK); + if (fd >= 0) + { + fcntl (fd, F_SETFL, mode); + return fd; + } + } + return -1; +} + +static void +console_stty () +{ + struct termios tty; + int fd; + + if ((fd = console_open (O_RDWR|O_NOCTTY)) < 0) + { + logmsg (LOG_CRIT, "can't open %s", console_device); + return; + } + + tcgetattr (fd, &tty); + + tty.c_cflag &= CBAUD|CBAUDEX|CSIZE|CSTOPB|PARENB|PARODD; + tty.c_cflag |= HUPCL|CLOCAL|CREAD; + + tty.c_cc[VINTR] = 3; /* ctrl('c') */ + tty.c_cc[VQUIT] = 28; /* ctrl('\\') */ + tty.c_cc[VERASE] = 127; + tty.c_cc[VKILL] = 24; /* ctrl('x') */ + tty.c_cc[VEOF] = 4; /* ctrl('d') */ + tty.c_cc[VTIME] = 0; + tty.c_cc[VMIN] = 1; + tty.c_cc[VSTART] = 17; /* ctrl('q') */ + tty.c_cc[VSTOP] = 19; /* ctrl('s') */ + tty.c_cc[VSUSP] = 26; /* ctrl('z') */ + + /* + * Set pre and post processing + */ + tty.c_iflag = IGNPAR|ICRNL|IXON|IXANY; + tty.c_oflag = OPOST|ONLCR; + tty.c_lflag = ISIG|ICANON|ECHO|ECHOCTL|ECHOPRT|ECHOKE; + + /* + * Now set the terminal line. + * We don't care about non-transmitted output data + * and non-read input data. + */ + tcsetattr (fd, TCSANOW, &tty); + tcflush(fd, TCIOFLUSH); + close (fd); +} + static void prog_start (struct prog *prog) { @@ -1164,9 +1240,12 @@ prog_start (struct prog *prog) prog->v.p.comp->builtin->fun (prog->v.p.socket, prog->v.p.comp); return; } - - redir[RETR_OUT] = open_redirector (prog, RETR_OUT); - redir[RETR_ERR] = open_redirector (prog, RETR_ERR); + + if (!init_process) + { + redir[RETR_OUT] = open_redirector (prog, RETR_OUT); + redir[RETR_ERR] = open_redirector (prog, RETR_ERR); + } switch (pid = fork ()) { @@ -1179,15 +1258,35 @@ prog_start (struct prog *prog) { case pies_comp_pass_fd: case pies_comp_exec: - if (redir[RETR_OUT] == -1) - { - close (1); - open ("/dev/null", O_WRONLY); - } - else if (redir[RETR_OUT] != 1) - { - dup2 (redir[RETR_OUT], 1); - } + case pies_comp_once: + if (init_process) + { + int fd = console_open (O_RDWR|O_NOCTTY); + if (fd < 0) + { + logmsg (LOG_CRIT, "open(%s): %s", + console_device, strerror (errno)); + fd = open("/dev/null", O_RDWR); + } + if (fd != 0) + dup2 (fd, 0); + if (fd != 1) + dup2 (fd, 1); + if (fd != 2) + dup2 (fd, 2); + } + else + { + if (redir[RETR_OUT] == -1) + { + close (1); + open ("/dev/null", O_WRONLY); + } + else if (redir[RETR_OUT] != 1) + { + dup2 (redir[RETR_OUT], 1); + } + } break; case pies_comp_accept: @@ -1200,19 +1299,22 @@ prog_start (struct prog *prog) prog->v.p.socket = -1; break; } - - if (redir[RETR_ERR] == -1) - { - if (!DIAG_OUTPUT (DIAG_TO_STDERR)) + + if (!init_process) + { + if (redir[RETR_ERR] == -1) { - close (2); - open ("/dev/null", O_WRONLY); + if (!DIAG_OUTPUT (DIAG_TO_STDERR)) + { + close (2); + open ("/dev/null", O_WRONLY); + } } - } - else if (redir[RETR_ERR] != 1) - { - dup2 (redir[RETR_ERR], 2); - } + else if (redir[RETR_ERR] != 1) + { + dup2 (redir[RETR_ERR], 2); + } + } /* Close unneeded descripitors */ FD_ZERO (&fdset); @@ -1244,7 +1346,8 @@ prog_start (struct prog *prog) { disable_socket (prog->v.p.socket); } - else if (prog->v.p.comp->mode != pies_comp_exec) + else if (prog->v.p.comp->mode != pies_comp_exec && + prog->v.p.comp->mode != pies_comp_once) close (prog->v.p.socket); prog->pid = pid; prog->v.p.status = status_enabled; @@ -1657,6 +1760,14 @@ progman_recompute_alarm () +static int +runlevel_match (struct prog *prog) +{ + if (!initdefault || !prog->v.p.comp->runlevels) + return 1; + return !!strchr (prog->v.p.comp->runlevels, initdefault); +} + void progman_start () { @@ -1669,7 +1780,8 @@ progman_start () { if (prog->v.p.comp->mode == pies_comp_inetd) { - if (prog->v.p.comp->flags & CF_DISABLED) + if ((prog->v.p.comp->flags & CF_DISABLED) + || !runlevel_match (prog)) disable_socket (prog->v.p.socket); else { @@ -1677,7 +1789,8 @@ progman_start () enable_socket (prog->v.p.socket); } } - else if ((prog->v.p.status == status_enabled && prog->pid == 0) + else if ((prog->v.p.status == status_enabled && prog->pid == 0 + && runlevel_match (prog)) || prog->v.p.status == status_sleeping) prog_start (prog); } @@ -1792,9 +1905,13 @@ prog_start_prerequisites (struct prog *prog) check_stopping (dp, time (NULL)); ret = 1; continue; + + case status_finished: + continue; } - prog_start (prog_lookup_by_tag (prog->prereq[i])); - if (!(dp->v.p.status == status_enabled && dp->pid)) + prog_start (dp); + if (dp->v.p.comp->mode == pies_comp_once || + !(dp->v.p.status == status_enabled && dp->pid)) ret = 1; } return ret; @@ -2338,6 +2455,10 @@ progman_cleanup (int expect_term) if (listener->v.p.comp->flags & CF_WAIT) enable_socket (listener->v.p.socket); } + else if (prog->v.p.comp->mode == pies_comp_once) + { + prog->v.p.status = status_finished; + } else { prog->v.p.status = status_enabled; @@ -2441,6 +2562,10 @@ progman_dump_stats (const char *filename) fbuf[fidx++] = 'C'; break; + case pies_comp_once: + fbuf[fidx++] = 'c'; + break; + case pies_comp_accept: fbuf[fidx++] = 'A'; break; @@ -2473,6 +2598,10 @@ progman_dump_stats (const char *filename) case status_stopping: fbuf[fidx++] = 'S'; + break; + + case status_finished: + fbuf[fidx++] = 'f'; } break; |