2 * Copyright (c) 1999-2003 Red Hat, Inc. All rights reserved.
4 * This software may be freely redistributed under the terms of the GNU
7 * You should have received a copy of the GNU General Public License
8 * along with this program; if not, write to the Free Software
9 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 #include <sys/signal.h>
31 extern regex_t **regList;
33 int forkCommand(char **args, int *outfd, int *errfd, int *cmdfd, int quiet) {
34 /* Fork command 'cmd', returning pid, and optionally pointer
35 * to open file descriptor fd */
36 int fdout=-1, fderr=-1, fdcmd=-1, pid;
37 int outpipe[2], errpipe[2], fdpipe[2];
40 if ( (pipe(outpipe)==-1) || (pipe(errpipe)==-1) || (pipe(fdpipe)==-1) ) {
64 fdcmd = open("/dev/null",O_WRONLY);
66 if (fdout==-1 || fderr==-1 || fdcmd==-1)
69 if ((pid = fork())==-1) {
73 /* We exec the command normally as the child. However, if we're getting passed
74 * back arguments via an fd, we'll exec it as the parent. Therefore, if Bill
75 * fucks up and we segfault or something, we don't kill rc.sysinit. */
76 if ( (cmdfd&&!pid) || (pid &&!cmdfd)) {
90 if ( (dup2(fdout,1)==-1) ) {
95 if ((dup2(open("/dev/null",O_WRONLY),1))==-1) {
101 if ((dup2(fderr,2)==-1)) {
106 if ((dup2(open("/dev/null",O_WRONLY),2))==-1) {
112 if ((dup2(fdcmd,CMD_FD)==-1)) {
126 /* close up extra fds, and hope this doesn't break anything */
127 sc_open_max = sysconf(_SC_OPEN_MAX);
128 if(sc_open_max > 1) {
130 for(fd = 3; fd < sc_open_max; fd++) {
131 if (!(cmdfd && fd == CMD_FD))
136 execvp(args[0],args);
142 int monitor(char *cmdname, int pid, int numfds, int *fds, int reexec, int quiet, int debug) {
152 char *procpath = NULL;
155 procpath=malloc(20*sizeof(char));
156 snprintf(procpath,20,"/proc/%d",pid);
159 pfds = malloc(numfds*sizeof(struct pollfd));
160 for (x=0;x<numfds;x++) {
162 pfds[x].events = POLLIN | POLLPRI;
167 if (((x=poll(pfds,numfds,500))==-1)&&errno!=EINTR) {
175 if (waitpid(pid,&rc,WNOHANG))
179 /* if /proc/pid ain't there and /proc is, it's dead... */
180 if (stat(procpath,&sbuf)&&!stat("/proc/cpuinfo",&sbuf))
187 if ( x && ((pfds[y].revents & (POLLIN | POLLPRI)) )) {
191 char *b, *buf=calloc(8193,sizeof(char));
193 bytesread = read(pfds[y].fd,buf,8192);
203 if (!quiet && !reexec)
204 write(1,buf,bytesread);
206 outbuf=realloc(outbuf,(outbuf ? strlen(outbuf)+bytesread+1 : bytesread+1));
207 if (!output) outbuf[0]='\0';
211 while ((tmpstr=getLine(&buf))) {
217 while (regList[count]) {
218 if (!regexec(regList[count],tmpstr,0,NULL,0)) {
227 if (getenv("IN_INITLOG")) {
228 char *buffer=calloc(8192,sizeof(char));
229 DDEBUG("sending =%s= to initlog parent\n",tmpstr);
230 snprintf(buffer,8192,"-n %s -s \"%s\"\n",
232 /* don't blow up if parent isn't there */
233 signal(SIGPIPE,SIG_IGN);
234 write(CMD_FD,buffer,strlen(buffer));
235 signal(SIGPIPE,SIG_DFL);
238 logString(cmdname,tmpstr);
247 poptParseArgvString(tmpstr,&cmdargc,&tmpargs);
248 cmdargs=malloc( (cmdargc+2) * sizeof(char *) );
249 cmdargs[0]=strdup("initlog");
250 for (z=0;z<(cmdargc);z++) {
251 cmdargs[z+1]=tmpargs[z];
253 cmdargs[cmdargc+1]=NULL;
254 processArgs(cmdargc+1,cmdargs,1);
260 if (tmpstr) free(tmpstr);
264 } while ( bytesread==8192 );
269 if ((!WIFEXITED(rc)) || (rc=WEXITSTATUS(rc))) {
270 /* If there was an error and we're quiet, be loud */
272 if (quiet && output) {
273 write(1,outbuf,strlen(outbuf));
290 int runCommand(char *cmd, int reexec, int quiet, int debug) {
293 char **args, **tmpargs;
296 poptParseArgvString(cmd,&x,&tmpargs);
297 args = malloc((x+1)*sizeof(char *));
298 for ( pid = 0; pid < x ; pid++) {
299 args[pid] = strdup(tmpargs[pid]);
302 if (strcmp(args[0],"sh") && strcmp(args[0],"/bin/sh"))
303 cmdname = basename(args[0]);
305 cmdname = basename(args[1]);
306 if ((cmdname[0] =='K' || cmdname[0] == 'S') &&
307 ( cmdname[1] >= '0' && cmdname[1] <= '9' ) &&
308 ( cmdname[2] >= '0' && cmdname[2] <= '9' ) )
311 pid=forkCommand(args,&fds[0],&fds[1],NULL,quiet);
314 x=monitor(cmdname,pid,2,fds,reexec,quiet,debug);
316 setenv("IN_INITLOG","yes",1);
317 pid=forkCommand(args,NULL,NULL,&fds[0],quiet);
320 unsetenv("IN_INITLOG");
321 x=monitor(cmdname,pid,1,&fds[0],reexec,quiet,debug);