--- vzctl-3.0.18.org/src/lib/env.c 2007-07-06 09:46:25.000000000 +0200 +++ vzctl-3.0.18/src/lib/env.c 2007-12-13 08:57:12.000000000 +0100 @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -290,6 +291,80 @@ return 0; } +static int terminate_init_observer = 0; + +void +_sigterm_handler (int signum) +{ + terminate_init_observer = 1; +} + +#define INIT_FIFO "/var/log/init.fifo" +#define INIT_LOG "/var/log/init.log" + +void +_observe_init_fifo (void) { + struct sigaction act; + int fd; + int fifo; + int len; + + char buf[4096]; + char *txt; + char txtbuf[4096]; + + sigemptyset(&act.sa_mask); + act.sa_handler = _sigterm_handler; + act.sa_flags = SA_RESETHAND; + sigaction(SIGTERM, &act, NULL); + + if ((fd = open(INIT_LOG, O_CREAT|O_WRONLY|O_TRUNC, 0644)) == -1) { + exit (-1); + } + + if ((fifo = open(INIT_FIFO, O_RDONLY)) == -1) { + sprintf (txtbuf, "Error: unable to open fifo: %s\n", strerror(errno)); + write (fd, txtbuf, strlen (txtbuf)); + exit (-1); + } + + while (1) { + + len = read (fifo, buf, 4096); + + if (terminate_init_observer) { // got signal + if (len > 0) { + write (fd, buf, len); + } + break; + } + if (len == -1) { + if (errno == EAGAIN || errno == EINTR) { + continue; + } + + sprintf (txtbuf, "ERROR: unable to read fifo: %s\n", strerror(errno)); + write (fd, txtbuf, strlen (txtbuf)); + break; + } + + if (len == 0) { // EOF - try later + sleep (1); + continue; + } + write (fd, buf, len); + } + + // terminated - just write a CR + txt = "\n"; write (fd, txt, strlen (txt)); + + close (fifo); + close (fd); + + exit (0); +} + + static int _env_create(vps_handler *h, envid_t veid, int wait_p, int err_p, void *data) { @@ -298,7 +373,7 @@ int fd, ret; vps_res *res; char *argv[] = {"init", "-z", " ", NULL}; - char *envp[] = {"HOME=/", "TERM=linux", NULL}; + char *envp[] = {"HOME=/", "TERM=linux", NULL, NULL}; res = (vps_res *) data; memset(&create_param, 0, sizeof(create_param)); @@ -386,6 +461,18 @@ if (read(wait_p, &ret, sizeof(ret)) != 0) return 0; logger(10, 0, "Starting init"); + + if ((mkfifo (INIT_FIFO, 0600) == 0) || (errno == EEXIST)) { + envp[2] = "CONSOLE=" INIT_FIFO; + if (!fork()) { // observer child + close (wait_p); close (err_p); + _observe_init_fifo (); + exit (-1); + } + } else { + logger(-1, errno, "unable to create init fifo"); + } + execve("/sbin/init", argv, envp); execve("/etc/init", argv, envp); execve("/bin/init", argv, envp);