aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBill Nottingham <notting@redhat.com>1999-02-03 17:06:47 +0000
committerBill Nottingham <notting@redhat.com>1999-02-03 17:06:47 +0000
commitc3695a8497dcbc4f5dc3348f9dd0f4ffb01badee (patch)
treec5e85c9a3ac67e6eeba55138eaa9742004235844 /src
parent7b45621175cebb8ad2a59901e26593811047e818 (diff)
downloadinitscripts-c3695a8497dcbc4f5dc3348f9dd0f4ffb01badee.tar
initscripts-c3695a8497dcbc4f5dc3348f9dd0f4ffb01badee.tar.gz
initscripts-c3695a8497dcbc4f5dc3348f9dd0f4ffb01badee.tar.bz2
initscripts-c3695a8497dcbc4f5dc3348f9dd0f4ffb01badee.tar.xz
initscripts-c3695a8497dcbc4f5dc3348f9dd0f4ffb01badee.zip
add initlog stuff. do "halt -p", "umount -f" in shutdown. use %defattr in
specfile... um, I think that's it.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile31
-rw-r--r--src/initlog.148
-rw-r--r--src/initlog.c317
-rw-r--r--src/initlog.h16
-rw-r--r--src/minilogd.c164
-rw-r--r--src/process.c216
-rw-r--r--src/process.h9
7 files changed, 792 insertions, 9 deletions
diff --git a/src/Makefile b/src/Makefile
index c0e3f573..c2751e9e 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,6 +1,6 @@
-CFLAGS+=-Wall
+CFLAGS+=-Wall -D_GNU_SOURCE
-PROGS=usernetctl doexec netreport testd usleep ipcalc
+PROGS=usernetctl doexec netreport testd usleep ipcalc initlog minilogd
all: $(PROGS)
@@ -9,11 +9,14 @@ clean:
install:
mkdir -p $(ROOT)/bin $(ROOT)/usr/sbin $(ROOT)/usr/man/man1
- install -o 0 -g 0 -s -m 755 doexec $(ROOT)/bin/doexec
- install -o 0 -g 0 -s -m 755 usleep $(ROOT)/bin/usleep
- install -o 0 -g 0 -s -m 4755 usernetctl $(ROOT)/usr/sbin/usernetctl
- install -o 0 -g 0 -s -m 2755 netreport $(ROOT)/sbin/netreport
- install -o 0 -g 0 -s -m 755 ipcalc $(ROOT)/bin/ipcalc
+ install -s -m 755 doexec $(ROOT)/bin/doexec
+ install -s -m 755 usleep $(ROOT)/bin/usleep
+ install -s -m 4755 usernetctl $(ROOT)/usr/sbin/usernetctl
+ install -s -m 2755 netreport $(ROOT)/sbin/netreport
+ install -s -m 755 ipcalc $(ROOT)/bin/ipcalc
+ install -s -m 755 initlog $(ROOT)/sbin/initlog
+ install -s -m 755 minilogd $(ROOT)/sbin/minilogd
+ install -m 644 initlog.1 $(ROOT)/usr/man/man1
install -m 644 doexec.1 $(ROOT)/usr/man/man1
install -m 644 netreport.1 $(ROOT)/usr/man/man1
install -m 644 usleep.1 $(ROOT)/usr/man/man1
@@ -23,8 +26,18 @@ install:
# this daemon and initscript are useful for testing the up/down/status stuff
# not installed by default, only comes from sources.
install-test:
- install -o 0 -g 0 -s -m 755 testd $(ROOT)/usr/sbin/testd
- install -o 0 -g 0 -m 755 testdinit $(ROOT)/etc/rc.d/init.d/testd
+ install -s -m 755 testd $(ROOT)/usr/sbin/testd
+ install -m 755 testdinit $(ROOT)/etc/rc.d/init.d/testd
ipcalc: ipcalc.o
$(CC) $(LDFLAGS) -o $@ $< -lpopt
+
+minilogd: minilogd.o
+ $(CC) $(LDFLAGS) -o $@ $<
+
+initlog: initlog.o process.o
+ $(CC) $(LDFLAGS) -o $@ $< -lpopt
+
+clean:
+ rm ipcalc initlog minilogd *.o core *~
+
diff --git a/src/initlog.1 b/src/initlog.1
new file mode 100644
index 00000000..103ef3fd
--- /dev/null
+++ b/src/initlog.1
@@ -0,0 +1,48 @@
+.TH initlog 8 "Sun Jan 24 1999"
+.SH NAME
+initlog \- log messages and events to the system logger
+.SH SYNOPSIS
+.B initlog
+[\-cefnprs] [\-\-cmd=ARG] [\-\-event=ARG] [\-\-facility=ARG]
+[\-\-name=ARG] [\-\-priority=ARG] [\-\-run=ARG] [\-\-string=ARG]
+.SH DESCRIPTION
+\fBinitlog\fR logs messages and events to the system logger.
+It is mainly designed for use in init scripts.
+
+.SS OPTIONS
+.TP
+.I "\-c, \-\-cmd=[program]"
+Execute the specified program, logging anything output to
+stdout or stderr.
+.TP
+.I "\-e, \-\-event=[number]"
+Logs that the specified event happened. Usually used in conjuction
+with \fB\-\-name\fR. Currently specified events are:
+.nf
+ \fB1\fR the action completed successfully
+ \fB2\fR the action failed
+ \fB3\fR the action was cancelled at user request
+ \fB4\fR the action failed due to the failure of a dependent action
+.TP
+.I "\-f, \-\-facility=[facility]"
+
+Log at the specified syslog facility. The default
+is \fBdaemon\fR (see syslog(3)).
+.TP
+.I "\-n, \-\-name=[string]"
+Log the event under the specified string, such as
+"inetd".
+.TP
+.I "\-p, \-\-priority=[priority]"
+Log at the specified syslog priority. The default
+is \fBnotice\fR (see syslog(3)).
+.TP
+.I "\-r, \-\-run=[program]"
+Execute the specified program, with an open file
+descriptor so that the program can pass back
+commands to initlog.
+.TP
+.I "\-s, \-\-string=[string]
+Log the specified string to the logger.
+.SH "SEE ALSO"
+syslog(3), logger(1)
diff --git a/src/initlog.c b/src/initlog.c
new file mode 100644
index 00000000..96b5af87
--- /dev/null
+++ b/src/initlog.c
@@ -0,0 +1,317 @@
+
+#include <errno.h>
+#include <fcntl.h>
+#include <libintl.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define SYSLOG_NAMES
+#include <syslog.h>
+
+#include <sys/wait.h>
+
+#define _(String) gettext((String))
+
+#include <popt.h>
+
+#include "initlog.h"
+#include "process.h"
+
+static int logfacility=LOG_DAEMON;
+static int logpriority=LOG_NOTICE;
+static int reexec=0;
+static int quiet=0;
+
+static int logEntries = 0;
+struct logInfo *logData = NULL;
+
+char *getLine(char **data) {
+ /* Get one line from data */
+ char *x, *y;
+
+ if (!*data) return NULL;
+
+ for (x = *data; *x && (*x != '\n'); x++);
+ if (*x) {
+ x++;
+ } else {
+ if (x-*data) {
+ y=malloc(x-*data+1);
+ y[x-*data] = 0;
+ y[x-*data-1] = '\n';
+ memcpy(y,*data,x-*data);
+ } else {
+ y=NULL;
+ }
+ *data = NULL;
+ return y;
+ }
+ y = malloc(x-*data);
+ y[x-*data-1] = 0;
+ memcpy(y,*data,x-*data-1);
+ *data = x;
+ return y;
+}
+
+char **toArray(char *line, int *num) {
+ /* Converts a long string into an array of lines. */
+ char **lines;
+ char *tmpline;
+
+ *num = 0;
+ lines = NULL;
+
+ while ((tmpline=getLine(&line))) {
+ if (!*num)
+ lines = (char **) malloc(sizeof(char *));
+ else
+ lines = (char **) realloc(lines, (*num+1)*sizeof(char *));
+ lines[*num] = tmpline;
+ (*num)++;
+ }
+ return lines;
+}
+
+int startDaemon() {
+ int pid;
+ int rc;
+
+ if ( (pid = fork()) == -1 ) {
+ perror("fork");
+ return -1;
+ }
+ if ( pid ) {
+ /* parent */
+ waitpid(pid,&rc,0);
+ if (rc)
+ return -1;
+ else
+ return 0;
+ } else {
+ int fd;
+
+ fd=open("/dev/null",O_RDWR);
+ dup2(fd,0);
+ dup2(fd,1);
+ dup2(fd,2);
+ /* kid */
+ execlp("minilogd","minilogd",NULL);
+ perror("exec");
+ exit(-1);
+ }
+}
+
+int logLine(struct logInfo *logEnt) {
+ /* Logs a line... somewhere. */
+ int x;
+
+ /* Don't log empty or null lines */
+ if (!logEnt->line || !strcmp(logEnt->line,"\n")) return 0;
+
+ if ((x=access(_PATH_LOG,W_OK))) {
+ /* syslog isn't running, so start something... */
+ if ( (x=startDaemon()) ==-1) {
+ logData=realloc(logData,(logEntries+1)*sizeof(struct logInfo));
+ logData[logEntries]= (*logEnt);
+ logEntries++;
+ } else {
+ if (logEntries>0) {
+ for (x=0;x<logEntries;x++) {
+ openlog(logData[x].cmd,0,logData[x].fac);
+ printf("flushing %s\n",logData[x].line);
+ syslog(logData[x].pri,"%s",logData[x].line);
+ closelog();
+ }
+ free(logData);
+ logEntries = 0;
+ }
+ openlog(logEnt->cmd,0,logEnt->fac);
+ syslog(logEnt->pri,"%s",logEnt->line);
+ closelog();
+ }
+ } else {
+ if (logEntries>0) {
+ for (x=0;x<logEntries;x++) {
+ openlog(logData[x].cmd,0,logData[x].fac);
+ printf("flushing %s\n",logData[x].line);
+ syslog(logData[x].pri,"%s",logData[x].line);
+ closelog();
+ }
+ free(logData);
+ logEntries = 0;
+ }
+ openlog(logEnt->cmd,0,logEnt->fac);
+ syslog(logEnt->pri,"%s",logEnt->line);
+ closelog();
+ }
+ return 0;
+}
+
+int logEvent(char *cmd, int eventtype,char *string) {
+ char *eventtable [] = {
+ _("%s babbles incoherently"),
+ _("%s succeeded"),
+ _("%s failed"),
+ _("%s cancelled at user request"),
+ _("%s failed due to a failed dependency"),
+ /* insert more here */
+ NULL
+ };
+ int x=0,len;
+ struct logInfo logentry;
+
+
+ if (cmd) {
+ logentry.cmd = strdup(basename(cmd));
+ if ((logentry.cmd[0] =='K' || logentry.cmd[0] == 'S') && ( 30 <= logentry.cmd[1] <= 39 )
+ && ( 30 <= logentry.cmd[2] <= 39 ) )
+ logentry.cmd+=3;
+ } else
+ logentry.cmd = strdup(_("(none)"));
+ if (!string)
+ string = strdup(cmd);
+
+ while (eventtable[x] && x<eventtype) x++;
+ if (!(eventtable[x])) x=0;
+
+ len=strlen(eventtable[x])+strlen(string);
+ logentry.line=malloc(len);
+ snprintf(logentry.line,len,eventtable[x],string);
+
+ logentry.pri = logpriority;
+ logentry.fac = logfacility;
+
+ return logLine(&logentry);
+}
+
+int logString(char *cmd, char *string) {
+ struct logInfo logentry;
+
+ if (cmd) {
+ logentry.cmd = strdup(basename(cmd));
+ if ((logentry.cmd[0] =='K' || logentry.cmd[0] == 'S') && ( 30 <= logentry.cmd[1] <= 39 )
+ && ( 30 <= logentry.cmd[2] <= 39 ) )
+ logentry.cmd+=3;
+ } else
+ logentry.cmd = strdup(_(""));
+ logentry.line = strdup(string);
+ logentry.pri = logpriority;
+ logentry.fac = logfacility;
+
+ return logLine(&logentry);
+}
+
+void processArgs(int argc, char **argv) {
+ char *cmdname=NULL;
+ int cmdevent=0;
+ char *cmd=NULL;
+ char *logstring=NULL;
+ char *fac=NULL,*pri=NULL;
+ poptContext context;
+ int rc;
+ struct poptOption optTable[] = {
+ POPT_AUTOHELP
+ { "name", 'n', POPT_ARG_STRING, &cmdname, 0,
+ "name of service being logged", NULL
+ },
+ { "event", 'e', POPT_ARG_INT, &cmdevent, 0,
+ "event being logged (see man page)", NULL
+ },
+ { "cmd", 'c', POPT_ARG_STRING, &cmd, 0,
+ "command to run, logging output", NULL
+ },
+ { "run", 'r', POPT_ARG_STRING, &cmd, 3,
+ "command to run, accepting input on open fd", NULL
+ },
+ { "string", 's', POPT_ARG_STRING, &logstring, 0,
+ "string to log", NULL
+ },
+ { "facility", 'f', POPT_ARG_STRING, &fac, 1,
+ "facility to log at (default: 'daemon')", NULL
+ },
+ { "priority", 'p', POPT_ARG_STRING, &pri, 2,
+ "priority to log at (default: 'notice')", NULL
+ },
+ { "quiet", 'q', POPT_ARG_NONE, &quiet, 0,
+ "suppress stdout/stderr", NULL
+ },
+ { 0, 0, 0, 0, 0, 0 }
+ };
+
+ context = poptGetContext("initlog", argc, argv, optTable, 0);
+
+ while ((rc = poptGetNextOpt(context)) > 0) {
+ switch (rc) {
+ case 1:
+ logfacility=atoi(fac);
+ if ((logfacility == 0) && strcmp(fac,"0")) {
+ int x =0;
+
+ logfacility = LOG_DAEMON;
+ for (x=0;facilitynames[x].c_name;x++) {
+ if (!strcmp(fac,facilitynames[x].c_name)) {
+ logfacility = facilitynames[x].c_val;
+ break;
+ }
+ }
+ }
+ break;
+ case 2:
+ logpriority = atoi(pri);
+ if ((logpriority == 0) && strcmp(pri,"0")) {
+ int x=0;
+
+ logpriority = LOG_NOTICE;
+ for (x=0;prioritynames[x].c_name;x++) {
+ if (!strcmp(pri,prioritynames[x].c_name)) {
+ logpriority = prioritynames[x].c_val;
+ break;
+ }
+ }
+ }
+ break;
+ case 3:
+ reexec = 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if ((rc < -1)) {
+ fprintf(stderr, "%s: %s\n",
+ poptBadOption(context, POPT_BADOPTION_NOALIAS),
+ poptStrerror(rc));
+ exit(-1);
+ }
+ if ( (cmd && logstring) || (cmd && cmdname) ) {
+ fprintf(stderr, _("--cmd and --run are incompatible with --string or --name\n"));
+ exit(-1);
+ }
+ if ( cmdname && (!logstring && !cmdevent)) {
+ fprintf(stderr, _("--name requires one of --event or --string\n"));
+ exit(-1);
+ }
+ if (cmdevent) {
+ logEvent(cmdname,cmdevent,logstring);
+ } else if (logstring) {
+ logString(cmdname,logstring);
+ } else if ( cmd ) {
+ exit(runCommand(cmd,reexec,quiet));
+ } else {
+ fprintf(stderr,"nothing to do!\n");
+ exit(-1);
+ }
+}
+
+int main(int argc, char **argv) {
+
+ setlocale(LC_ALL,"");
+ bindtextdomain("initlog","/etc/locale");
+ textdomain("initlog");
+ processArgs(argc,argv);
+ exit (0);
+}
diff --git a/src/initlog.h b/src/initlog.h
new file mode 100644
index 00000000..244ff9a0
--- /dev/null
+++ b/src/initlog.h
@@ -0,0 +1,16 @@
+
+#ifndef INITLOG_H
+#define INITLOG_H
+
+struct logInfo {
+ char *cmd;
+ char *line;
+ int fac;
+ int pri;
+};
+
+char *getLine(char **data);
+int logString(char *cmd, char *string);
+void processArgs(int argc, char **argv);
+
+#endif
diff --git a/src/minilogd.c b/src/minilogd.c
new file mode 100644
index 00000000..d15b8d9a
--- /dev/null
+++ b/src/minilogd.c
@@ -0,0 +1,164 @@
+
+/* minilogd.c
+ *
+ * A pale imitation of syslogd. Most notably, doesn't write anything
+ * anywhere except possibly back to syslogd.
+ *
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+
+static int we_own_log=0;
+static char **buffer=NULL;
+static int buflines=0;
+
+void freeBuffer() {
+ struct sockaddr_un addr;
+ int sock;
+ int x=0,conn;
+
+ bzero(&addr,sizeof(addr));
+ addr.sun_family = AF_LOCAL;
+ strncpy(addr.sun_path,_PATH_LOG,sizeof(addr.sun_path)-1);
+ /* wait for klogd to hit syslog */
+ sleep(1);
+ sock = socket(AF_LOCAL, SOCK_STREAM,0);
+ conn=connect(sock,(struct sockaddr *) &addr,sizeof(addr));
+ while (x<buflines) {
+ if (!conn) write(sock,buffer[x],strlen(buffer[x])+1);
+ free(buffer[x]);
+ x++;
+ }
+}
+
+void cleanup(int exitcode) {
+ /* If we own the log, unlink it before trying to free our buffer.
+ * Otherwise, sending the buffer to /dev/log doesn't make much sense.... */
+ if (we_own_log) {
+ perror("wol");
+ unlink(_PATH_LOG);
+ }
+ /* Don't try to free buffer if we were called from a signal handler */
+ perror("foo");
+ if (exitcode<=0) {
+ if (buffer) freeBuffer();
+ exit(exitcode);
+ } else
+ exit(exitcode+128);
+}
+
+void runDaemon(int sock) {
+ struct sockaddr_un addr;
+ int x,len,addrlen,recvsock,done=0;
+ char *message;
+ struct stat s1,s2;
+ struct pollfd pfds;
+ FILE *foo;
+
+ foo=fopen("./foo","a");
+
+ daemon(0,-1);
+ /* try not to leave stale sockets lying around */
+ /* Hopefully, we won't actually get any of these */
+ signal(SIGHUP,cleanup);
+ signal(SIGINT,cleanup);
+ signal(SIGQUIT,cleanup);
+ signal(SIGILL,cleanup);
+ signal(SIGABRT,cleanup);
+ signal(SIGFPE,cleanup);
+ signal(SIGSEGV,cleanup);
+ signal(SIGPIPE,cleanup);
+ signal(SIGBUS,cleanup);
+ signal(SIGTERM,cleanup);
+ done = 0;
+ /* Get stat info on dev log so we can later check to make sure we
+ * still own it... */
+ stat(_PATH_LOG,&s1);
+ while (!done) {
+ pfds.fd = sock;
+ pfds.events = POLLIN|POLLPRI;
+ if ( ( (x=poll(&pfds,1,500))==-1) && errno !=EINTR) {
+ perror("poll");
+ cleanup(-1);
+ }
+ if ( (x>0) && pfds.revents & (POLLIN | POLLPRI)) {
+ printf("foo!\n");
+ message = calloc(8192,sizeof(char));
+ recvsock = accept(sock,(struct sockaddr *) &addr, &addrlen);
+ len = read(recvsock,message,8192);
+ if (buffer)
+ buffer = realloc(buffer,(buflines+1)*sizeof(char *));
+ else
+ buffer = malloc(sizeof(char *));
+ if (len>0) {
+ message[strlen(message)]='\n';
+ fprintf(foo,"%s",message);
+ buffer[buflines]=message;
+ buflines++;
+ close(recvsock);
+ }
+ else {
+ close(recvsock);
+ recvsock=-1;
+ }
+ }
+ if ( (x>0) && ( pfds.revents & (POLLHUP | POLLNVAL)) )
+ done = 1;
+ /* Check to see if syslogd's yanked our socket out from under us */
+ if ( (stat(_PATH_LOG,&s2)!=0) ||
+ (s1.st_ino != s2.st_ino ) || (s1.st_ctime != s2.st_ctime) ||
+ (s1.st_mtime != s2.st_mtime) || (s1.st_atime != s2.st_atime) ) {
+ done = 1;
+ we_own_log = 0;
+ }
+ }
+ fclose(foo);
+ cleanup(0);
+}
+
+int main() {
+ struct sockaddr_un addr;
+ int sock;
+ int pid;
+
+ /* just in case */
+ sock = open("/dev/null",O_RDWR);
+ dup2(sock,0);
+ dup2(sock,1);
+ dup2(sock,2);
+
+ bzero(&addr, sizeof(addr));
+ addr.sun_family = AF_LOCAL;
+ strncpy(addr.sun_path,_PATH_LOG,sizeof(addr.sun_path)-1);
+ sock = socket(AF_LOCAL, SOCK_STREAM,0);
+ unlink(_PATH_LOG);
+ /* Bind socket before forking, so we know if the server started */
+ if (!bind(sock,(struct sockaddr *) &addr, sizeof(addr))) {
+ we_own_log = 1;
+ listen(sock,5);
+ if ((pid=fork())==-1) {
+ perror("fork");
+ exit(-1);
+ }
+ if (pid) {
+ exit(0);
+ } else {
+ runDaemon(sock);
+ /* shouldn't get back here... */
+ exit(-1);
+ }
+ } else {
+ exit(-1);
+ }
+}
diff --git a/src/process.c b/src/process.c
new file mode 100644
index 00000000..48f3b314
--- /dev/null
+++ b/src/process.c
@@ -0,0 +1,216 @@
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/poll.h>
+#include <sys/wait.h>
+
+#include <popt.h>
+
+#include "initlog.h"
+#include "process.h"
+
+int forkCommand(char **args, int *outfd, int *errfd, int *cmdfd, int quiet) {
+ /* Fork command 'cmd', returning pid, and optionally pointer
+ * to open file descriptor fd */
+ int fdin, fdout, fderr, fdcmd, pid;
+ int outpipe[2], errpipe[2], fdpipe[2];
+
+ if ( (pipe(outpipe)==-1) || (pipe(errpipe)==-1) || (pipe(fdpipe)==-1) ) {
+ perror("pipe");
+ return -1;
+ }
+
+ dup2(0,fdin);
+ if (outfd) {
+ fdout = outpipe[1];
+ *outfd = outpipe[0];
+ } else {
+ if (!quiet)
+ dup2(1,fdout);
+ }
+ if (errfd) {
+ fderr = errpipe[1];
+ *errfd = errpipe[0];
+ } else {
+ if (!quiet)
+ dup2(2,fderr);
+ }
+ fdcmd = fdpipe[1];
+ if (cmdfd)
+ *cmdfd = fdpipe[0];
+ if ((pid = fork())==-1) {
+ perror("fork");
+ return -1;
+ }
+ if (pid) {
+ /* parent */
+ close(fdin);
+ close(fdout);
+ close(fderr);
+ close(fdcmd);
+ return pid;
+ } else {
+ /* kid */
+ if (outfd) {
+ if ( (dup2(fdout,1)==-1) ) {
+ perror("dup2");
+ exit(-1);
+ }
+ } else if (quiet)
+ if ((dup2(open("/dev/null",O_WRONLY),1))==-1) {
+ perror("dup2");
+ exit(-1);
+ }
+
+ if (errfd) {
+ if ((dup2(fderr,2)==-1)) {
+ perror("dup2");
+ exit(-1);
+ }
+ } else if (quiet)
+ if ((dup2(open("/dev/null",O_WRONLY),2))==-1) {
+ perror("dup2");
+ exit(-1);
+ }
+
+
+ if ((dup2(fdcmd,CMD_FD)==-1)) {
+ perror("dup2");
+ exit(-1);
+ }
+ close(fdout);
+ close(fderr);
+ close(fdcmd);
+ if (outfd)
+ close(*outfd);
+ if (errfd)
+ close(*errfd);
+ if (cmdfd)
+ close(*cmdfd);
+ execvp(args[0],args);
+ perror("execvp");
+ exit(-1);
+ }
+}
+
+int monitor(char *cmdname, int pid, int numfds, int *fds, int reexec, int quiet) {
+ struct pollfd *pfds;
+ char *buf=malloc(2048*sizeof(char));
+ int outpipe[2];
+ char *tmpstr=NULL;
+ int x,y,rc=-1;
+ int done=0;
+ int output=0;
+
+ pipe(outpipe);
+
+ pfds = malloc(numfds*sizeof(struct pollfd));
+ for (x=0;x<numfds;x++) {
+ pfds[x].fd = fds[x];
+ pfds[x].events = POLLIN | POLLPRI;
+ }
+
+ while (!done) {
+ if ((x=poll(pfds,numfds,500))==-1) {
+ perror("poll");
+ return -1;
+ }
+ if (waitpid(pid,&rc,WNOHANG))
+ done=1;
+ y=0;
+ while (y<numfds) {
+ if ( x && ((pfds[y].revents & (POLLIN | POLLPRI)) )) {
+ int bytesread = 0;
+
+ do {
+ buf=calloc(2048,sizeof(char));
+ bytesread = read(pfds[y].fd,buf,2048);
+ if (bytesread==-1) {
+ perror("read");
+ return -1;
+ }
+ if (bytesread) {
+ if (!quiet && !reexec)
+ write(1,buf,bytesread);
+ if (quiet) {
+ output = 1;
+ write(outpipe[1],buf,bytesread);
+ }
+ while ((tmpstr=getLine(&buf))) {
+ if (!reexec)
+ logString(cmdname,tmpstr);
+ else {
+ char **cmdargs=NULL;
+ char **tmpargs=NULL;
+ int cmdargc,x;
+
+ poptParseArgvString(tmpstr,&cmdargc,&tmpargs);
+ cmdargs=malloc( (cmdargc++) * sizeof(char *) );
+ cmdargs[0]=strdup("initlog");
+ for (x=0;x<(cmdargc-1);x++) {
+ cmdargs[x+1]=tmpargs[x];
+ }
+ processArgs(cmdargc,cmdargs);
+ }
+ }
+ }
+
+ } while ( bytesread==2048 );
+ }
+ y++;
+ }
+ }
+ rc = rc>>8;
+
+ if (!rc)
+ return 0;
+ else {
+ /* If there was an error and we're quiet, be loud */
+ int x;
+
+ if (quiet && output) {
+ buf=calloc(2048,sizeof(char));
+ do {
+ x=read(outpipe[0],buf,2048);
+ write(1,buf,x);
+ buf=calloc(2048,sizeof(char));
+ } while (x==2048);
+ }
+ return (rc);
+ }
+}
+
+int runCommand(char *cmd, int reexec, int quiet) {
+ int fds[2];
+ int pid,x;
+ char **args, **tmpargs;
+ char *cmdname;
+
+ poptParseArgvString(cmd,&x,&tmpargs);
+ args = malloc((x+1)*sizeof(char *));
+ for ( pid = 0; pid < x ; pid++) {
+ args[pid] = strdup(tmpargs[pid]);
+ }
+ args[pid] = NULL;
+ if (strcmp(args[0],"sh") && strcmp(args[0],"/bin/sh"))
+ cmdname = basename(args[0]);
+ else
+ cmdname = basename(args[1]);
+ if ((cmdname[0] =='K' || cmdname[0] == 'S') && ( 30 <= cmdname[1] <= 39 )
+ && ( 30 <= cmdname[2] <= 39 ) )
+ cmdname+=3;
+ if (!reexec) {
+ pid=forkCommand(args,&fds[0],&fds[1],NULL,quiet);
+ x=monitor(cmdname,pid,2,fds,reexec,quiet);
+ } else {
+ setenv("IN_INITLOG","yes",1);
+ pid=forkCommand(args,NULL,NULL,&fds[0],quiet);
+ unsetenv("IN_INITLOG");
+ x=monitor(cmdname,pid,1,&fds[0],reexec,quiet);
+ }
+ return x;
+}
diff --git a/src/process.h b/src/process.h
new file mode 100644
index 00000000..6c796cb2
--- /dev/null
+++ b/src/process.h
@@ -0,0 +1,9 @@
+#ifndef PROCESS_H
+#define PROCESS_H
+
+
+#define CMD_FD 21
+
+int runCommand(char *cmd, int reexec, int quiet);
+
+#endif