Radix cross Linux

The main Radix cross Linux repository contains the build scripts of packages, which have the most complete and common functionality for desktop machines

452 Commits   2 Branches   1 Tag
Index: process.c
===================================================================
--- process.c	(nonexistent)
+++ process.c	(revision 5)
@@ -0,0 +1,324 @@
+/*
+ * Copyright (c) 1999-2003 Red Hat, Inc. All rights reserved.
+ *
+ * This software may be freely redistributed under the terms of the GNU
+ * public license.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/signal.h>
+#include <sys/poll.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <popt.h>
+
+#include <regex.h>
+
+#include "initlog.h"
+#include "process.h"
+
+extern regex_t **regList;
+
+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 fdout=-1, fderr=-1, fdcmd=-1, pid;
+    int outpipe[2], errpipe[2], fdpipe[2];
+    int ourpid;
+    
+    if ( (pipe(outpipe)==-1) || (pipe(errpipe)==-1) || (pipe(fdpipe)==-1) ) {
+	perror("pipe");
+	return -1;
+    }
+    
+    if (outfd) {
+       fdout = outpipe[1];
+      *outfd = outpipe[0];
+    } else {
+       if (!quiet)
+	 fdout=dup(1);
+    }
+    if (errfd) {
+       fderr = errpipe[1];
+      *errfd = errpipe[0];
+    } else {
+       if (!quiet)
+	 fderr=dup(2);
+    }
+    
+    if (cmdfd) {
+	*cmdfd = fdpipe[0];
+	fdcmd = fdpipe[1];
+    } else {
+        fdcmd = open("/dev/null",O_WRONLY);
+    }
+    if (fdout==-1 || fderr==-1 || fdcmd==-1)
+	return -1;
+    ourpid = getpid();
+    if ((pid = fork())==-1) {
+	perror("fork");
+	return -1;
+    }
+    /* We exec the command normally as the child. However, if we're getting passed
+     * back arguments via an fd, we'll exec it as the parent. Therefore, if Bill
+     * fucks up and we segfault or something, we don't kill rc.sysinit. */
+    if ( (cmdfd&&!pid) || (pid &&!cmdfd)) {
+	/* parent */
+	close(fdout);
+	close(fderr);
+	close(fdcmd);
+	if (!pid)
+	  return ourpid;
+	else
+	  return pid;
+    } else {
+	/* kid */
+       int sc_open_max;
+
+       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);
+
+        /* close up extra fds, and hope this doesn't break anything */
+	sc_open_max = sysconf(_SC_OPEN_MAX);
+	if(sc_open_max > 1) {
+	    int fd;
+	    for(fd = 3; fd < sc_open_max; fd++) {
+		    if (!(cmdfd && fd == CMD_FD))
+		      close(fd);
+	    }
+	}
+
+	execvp(args[0],args);
+	perror("execvp");
+	exit(-1);
+    }
+}
+
+int monitor(char *cmdname, int pid, int numfds, int *fds, int reexec, int quiet, int debug) {
+    struct pollfd *pfds;
+    char *outbuf=NULL;
+    char *tmpstr=NULL;
+    int x,y,rc=-1;
+    int done=0;
+    int output=0;
+    char **cmdargs=NULL;
+    char **tmpargs=NULL;
+    int cmdargc;
+    char *procpath = NULL;
+    
+    if (reexec) {
+	procpath=malloc(20*sizeof(char));
+	snprintf(procpath,20,"/proc/%d",pid);
+    }
+    
+    pfds = malloc(numfds*sizeof(struct pollfd));
+    for (x=0;x<numfds;x++) {
+	pfds[x].fd = fds[x];
+	pfds[x].events = POLLIN | POLLPRI;
+    }
+	
+    while (!done) {
+       usleep(500);
+       if (((x=poll(pfds,numfds,500))==-1)&&errno!=EINTR) {
+	  perror("poll");
+          free(pfds);
+          if (procpath)
+             free(procpath);
+	  return -1;
+       }
+       if (!reexec) {
+	  if (waitpid(pid,&rc,WNOHANG))
+	    done=1;
+       } else {
+	   struct stat sbuf;
+	   /* if /proc/pid ain't there and /proc is, it's dead... */
+	   if (stat(procpath,&sbuf)&&!stat("/proc/cpuinfo",&sbuf))
+	     done=1;
+       }
+       if (x<0)
+          continue;
+       y=0;
+       while (y<numfds) {
+	  if ( x && ((pfds[y].revents & (POLLIN | POLLPRI)) )) {
+	     int bytesread = 0;
+	     
+	     do {
+		char *b, *buf=calloc(8193,sizeof(char));
+		b = buf;
+		bytesread = read(pfds[y].fd,buf,8192);
+		if (bytesread==-1) {
+		   perror("read");
+                   free(pfds);
+                   if (procpath)
+                      free(procpath);
+                   free(buf);
+		   return -1;
+		}
+		if (bytesread) {
+		  if (!quiet && !reexec)
+		    write(1,buf,bytesread);
+		  if (quiet) {
+			  outbuf=realloc(outbuf,(outbuf ? strlen(outbuf)+bytesread+1 : bytesread+1));
+			  if (!output) outbuf[0]='\0';
+			  strcat(outbuf,buf);
+			  output = 1;
+		  }
+		  while ((tmpstr=getLine(&buf))) {
+		      int ignore=0;
+		      
+		      if (regList) {
+			  int count=0;
+			 
+			  while (regList[count]) {
+			      if (!regexec(regList[count],tmpstr,0,NULL,0)) {
+				  ignore=1;
+				  break;
+			      }
+			      count++;
+			  }
+		      }
+		      if (!ignore) {
+			  if (!reexec) {
+			      if (getenv("IN_INITLOG")) {
+				  char *buffer=calloc(8192,sizeof(char));
+				  DDEBUG("sending =%s= to initlog parent\n",tmpstr);
+				  snprintf(buffer,8192,"-n %s -s \"%s\"\n",
+					   cmdname,tmpstr);
+				  /* don't blow up if parent isn't there */
+				  signal(SIGPIPE,SIG_IGN);
+				  write(CMD_FD,buffer,strlen(buffer));
+				  signal(SIGPIPE,SIG_DFL);
+				  free(buffer);
+			      } else {
+				  logString(cmdname,tmpstr);
+			      }
+			  } else {
+			      int z; 
+			
+			      cmdargs=NULL;
+			      tmpargs=NULL;
+			      cmdargc=0;
+			      
+			      poptParseArgvString(tmpstr,&cmdargc,(const char ***)&tmpargs);
+			      cmdargs=malloc( (cmdargc+2) * sizeof(char *) );
+			      cmdargs[0]=strdup("initlog");
+			      for (z=0;z<(cmdargc);z++) {
+				  cmdargs[z+1]=tmpargs[z];
+			      }
+			      cmdargs[cmdargc+1]=NULL;
+			      processArgs(cmdargc+1,cmdargs,1);
+			      free(cmdargs[0]);
+			      free(tmpargs);
+			      free(cmdargs);
+			  }
+		      }
+		      if (tmpstr) free(tmpstr);
+		  }
+		}
+                free(b);
+	     } while ( bytesread==8192 );
+	  }
+	  y++;
+       }
+    }
+    if ((!WIFEXITED(rc)) || (rc=WEXITSTATUS(rc))) {
+      /* If there was an error and we're quiet, be loud */
+      
+      if (quiet && output) {
+	    write(1,outbuf,strlen(outbuf));
+      }
+      free(pfds);
+      if (procpath)
+         free(procpath);
+      if(outbuf)
+         free(outbuf);
+      return (rc);
+   }
+   free(pfds);
+   if (procpath)
+      free(procpath);
+   if(outbuf)
+      free(outbuf);
+   return 0;
+}
+
+int runCommand(char *cmd, int reexec, int quiet, int debug) {
+    int fds[2];
+    int pid,x;
+    char **args, **tmpargs;
+    char *cmdname;
+    
+    poptParseArgvString(cmd,&x,(const char ***)&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') && 
+        ( cmdname[1] >= '0' && cmdname[1] <= '9' ) &&
+        ( cmdname[2] >= '0' && cmdname[2] <= '9' ) )
+      cmdname+=3;
+    if (!reexec) {
+       pid=forkCommand(args,&fds[0],&fds[1],NULL,quiet);
+       if (pid == -1)
+          return -1;
+       x=monitor(cmdname,pid,2,fds,reexec,quiet,debug);
+    } else {
+       setenv("IN_INITLOG","yes",1);
+       pid=forkCommand(args,NULL,NULL,&fds[0],quiet);
+       if (pid == -1)
+          return -1;
+       unsetenv("IN_INITLOG");
+       x=monitor(cmdname,pid,1,&fds[0],reexec,quiet,debug);
+    }
+    return x;
+}