aboutsummaryrefslogtreecommitdiff
path: root/src/progman.c
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2012-12-30 15:36:56 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2013-01-04 12:29:27 +0200
commitcf14c349fad774e477a80d1c5e6572f21f17ced1 (patch)
treed8d73b072902cadc5aea5583119ec9e4e8ced2bc /src/progman.c
parent64c343ff8f11c8379ec21916ba915a2894495797 (diff)
downloadpies-cf14c349fad774e477a80d1c5e6572f21f17ced1.tar.gz
pies-cf14c349fad774e477a80d1c5e6572f21f17ced1.tar.bz2
Initial support for running as init process.
* grecs: Upgrade. * lib/Makefile.am: Use AM_CPPFLAGS instead of INCLUDES. * src/Makefile.am: Likewise. * src/acl.c: Update grecs_keyword definitions. * src/inetd.c (inetd_conf_file): Bugfix. The ws structure could be free'd prior to initialization. * src/pies.c: Update grecs_keyword definitions. (init_process,initdefault,dfl_level): New globals. (modetab) <once>: New keyword. (component_keywords)<runlevels,initdefault>: New keywords. (main): Initial support for init(8) mode. * src/pies.h (pies_comp_mode) <pies_comp_exec_once>: New constant. (component)<runlevels>: New member. (init_process,console_device,initdefault): New externs. * src/progman.c (prog_status)<status_finished>: New status. (prog)<runlevels>: New member. (progman_running_p): New function. (prog_start): Special handling for init process mode. (progman_start): Likewise. Take into account runlevels. (progman_dump_stats): New flag 'f' for status_finished.
Diffstat (limited to 'src/progman.c')
-rw-r--r--src/progman.c185
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;

Return to:

Send suggestions and report system problems to the System administrator.