]> git.pld-linux.org Git - projects/rc-scripts.git/blob - src/process.c
- merge from TOTALNEW branch (see NEWS for more info)
[projects/rc-scripts.git] / src / process.c
1
2 #include <errno.h>
3 #include <fcntl.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <unistd.h>
7
8 #include <sys/signal.h>
9 #include <sys/poll.h>
10 #include <sys/stat.h>
11 #include <sys/wait.h>
12
13 #include <popt.h>
14
15 #include <regex.h>
16
17 #include "initlog.h"
18 #include "process.h"
19
20 extern regex_t **regList;
21
22 int forkCommand(char **args, int *outfd, int *errfd, int *cmdfd, int quiet) {
23    /* Fork command 'cmd', returning pid, and optionally pointer
24     * to open file descriptor fd */
25     int fdout, fderr, fdcmd, pid;
26     int outpipe[2], errpipe[2], fdpipe[2];
27     int ourpid;
28     
29     if ( (pipe(outpipe)==-1) || (pipe(errpipe)==-1) || (pipe(fdpipe)==-1) ) {
30         perror("pipe");
31         return -1;
32     }
33     
34     if (outfd) {
35        fdout = outpipe[1];
36       *outfd = outpipe[0];
37     } else {
38        if (!quiet)
39          fdout=dup(1);
40     }
41     if (errfd) {
42        fderr = errpipe[1];
43       *errfd = errpipe[0];
44     } else {
45        if (!quiet)
46          fderr=dup(2);
47     }
48     
49     if (cmdfd) {
50         *cmdfd = fdpipe[0];
51         fdcmd = fdpipe[1];
52     } else {
53         fdcmd = open("/dev/null",O_WRONLY);
54     }
55     ourpid = getpid();
56     if ((pid = fork())==-1) {
57         perror("fork");
58         return -1;
59     }
60     /* We exec the command normally as the child. However, if we're getting passed
61      * back arguments via an fd, we'll exec it as the parent. Therefore, if Bill
62      * fucks up and we segfault or something, we don't kill rc.sysinit. */
63     if ( (cmdfd&&!pid) || (pid &&!cmdfd)) {
64         /* parent */
65         close(fdout);
66         close(fderr);
67         close(fdcmd);
68         if (!pid)
69           return ourpid;
70         else
71           return pid;
72     } else {
73         /* kid */
74        int sc_open_max;
75
76        if (outfd) { 
77          if ( (dup2(fdout,1)==-1) ) {
78             perror("dup2");
79             exit(-1);
80          }
81        } else if (quiet)
82             if ((dup2(open("/dev/null",O_WRONLY),1))==-1) {
83              perror("dup2");
84              exit(-1);
85             }
86
87        if (errfd)  {
88          if ((dup2(fderr,2)==-1)) {
89             perror("dup2");
90             exit(-1);
91          }
92        } else if (quiet) 
93             if ((dup2(open("/dev/null",O_WRONLY),2))==-1)  {
94                perror("dup2");
95                exit(-1);
96             }
97
98  
99        if ((dup2(fdcmd,CMD_FD)==-1)) {
100             perror("dup2");
101             exit(-1);
102         }
103         close(fdout);
104         close(fderr);
105         close(fdcmd);
106         if (outfd)
107           close(*outfd);
108         if (errfd)
109           close(*errfd);
110         if (cmdfd)
111           close(*cmdfd);
112
113         /* close up extra fds, and hope this doesn't break anything */
114         sc_open_max = sysconf(_SC_OPEN_MAX);
115         if(sc_open_max > 1) {
116             int fd;
117             for(fd = 3; fd < sc_open_max; fd++) {
118                     if (!(cmdfd && fd == CMD_FD))
119                       close(fd);
120             }
121         }
122
123         execvp(args[0],args);
124         perror("execvp");
125         exit(-1);
126     }
127 }
128
129 int monitor(char *cmdname, int pid, int numfds, int *fds, int reexec, int quiet, int debug) {
130     struct pollfd *pfds;
131     char *buf=malloc(8192*sizeof(char));
132     char *outbuf=NULL;
133     char *tmpstr=NULL;
134     int x,y,rc=-1;
135     int done=0;
136     int output=0;
137     char **cmdargs=NULL;
138     char **tmpargs=NULL;
139     int cmdargc;
140     char *procpath;
141     
142     if (reexec) {
143         procpath=malloc(20*sizeof(char));
144         snprintf(procpath,20,"/proc/%d",pid);
145     }
146     
147     pfds = malloc(numfds*sizeof(struct pollfd));
148     for (x=0;x<numfds;x++) {
149         pfds[x].fd = fds[x];
150         pfds[x].events = POLLIN | POLLPRI;
151     }
152         
153     while (!done) {
154        usleep(500);
155        if (((x=poll(pfds,numfds,500))==-1)&&errno!=EINTR) {
156           perror("poll");
157           return -1;
158        }
159        if (!reexec) {
160           if (waitpid(pid,&rc,WNOHANG))
161             done=1;
162        } else {
163            struct stat sbuf;
164            /* if /proc/pid ain't there and /proc is, it's dead... */
165            if (stat(procpath,&sbuf)&&!stat("/proc/cpuinfo",&sbuf))
166              done=1;
167        }
168        y=0;
169        while (y<numfds) {
170           if ( x && ((pfds[y].revents & (POLLIN | POLLPRI)) )) {
171              int bytesread = 0;
172              
173              do {
174                 buf=calloc(8192,sizeof(char));
175                 bytesread = read(pfds[y].fd,buf,8192);
176                 if (bytesread==-1) {
177                    perror("read");
178                    return -1;
179                 }
180                 if (bytesread) {
181                   if (!quiet && !reexec)
182                     write(1,buf,bytesread);
183                   if (quiet) {
184                           outbuf=realloc(outbuf,(outbuf ? strlen(outbuf)+bytesread+1 : bytesread+1));
185                           if (!output) outbuf[0]='\0';
186                           strcat(outbuf,buf);
187                           output = 1;
188                   }
189                   while ((tmpstr=getLine(&buf))) {
190                       int ignore=0;
191                       
192                       if (regList) {
193                           int count=0;
194                          
195                           while (regList[count]) {
196                               if (!regexec(regList[count],tmpstr,0,NULL,0)) {
197                                   ignore=1;
198                                   break;
199                               }
200                               count++;
201                           }
202                       }
203                       if (!ignore) {
204                           if (!reexec) {
205                               if (getenv("IN_INITLOG")) {
206                                   char *buffer=calloc(8192,sizeof(char));
207                                   DDEBUG("sending =%s= to initlog parent\n",tmpstr);
208                                   snprintf(buffer,8192,"-n %s -s \"%s\"\n",
209                                            cmdname,tmpstr);
210                                   /* don't blow up if parent isn't there */
211                                   signal(SIGPIPE,SIG_IGN);
212                                   write(CMD_FD,buffer,strlen(buffer));
213                                   signal(SIGPIPE,SIG_DFL);
214                                   free(buffer);
215                               } else {
216                                   logString(cmdname,tmpstr);
217                               }
218                           } else {
219                               int z; 
220                         
221                               cmdargs=NULL;
222                               tmpargs=NULL;
223                               cmdargc=0;
224                               
225                               poptParseArgvString(tmpstr,&cmdargc,&tmpargs);
226                               cmdargs=malloc( (cmdargc+2) * sizeof(char *) );
227                               cmdargs[0]=strdup("initlog");
228                               for (z=0;z<(cmdargc);z++) {
229                                   cmdargs[z+1]=tmpargs[z];
230                               }
231                               cmdargs[cmdargc+1]=NULL;
232                               processArgs(cmdargc+1,cmdargs,1);
233                           }
234                       }
235                   }
236                 }
237              } while ( bytesread==8192 );
238           }
239           y++;
240        }
241     }
242     if ((!WIFEXITED(rc)) || (rc=WEXITSTATUS(rc))) {
243       /* If there was an error and we're quiet, be loud */
244       
245       if (quiet && output) {
246             write(1,outbuf,strlen(outbuf));
247       }
248       return (rc);
249    }
250    return 0;
251 }
252
253 int runCommand(char *cmd, int reexec, int quiet, int debug) {
254     int fds[2];
255     int pid,x;
256     char **args, **tmpargs;
257     char *cmdname;
258     
259     poptParseArgvString(cmd,&x,&tmpargs);
260     args = malloc((x+1)*sizeof(char *));
261     for ( pid = 0; pid < x ; pid++) {
262         args[pid] = strdup(tmpargs[pid]);
263     }
264     args[pid] = NULL;
265     if (strcmp(args[0],"sh") && strcmp(args[0],"/bin/sh")) 
266       cmdname = basename(args[0]);
267     else
268       cmdname = basename(args[1]);
269     if ((cmdname[0] =='K' || cmdname[0] == 'S') && ( '0' <= cmdname[1] <= '9' )
270        && ( '0' <= cmdname[2] <= '9' ) )
271       cmdname+=3;
272     if (!reexec) {
273        pid=forkCommand(args,&fds[0],&fds[1],NULL,quiet);
274        x=monitor(cmdname,pid,2,fds,reexec,quiet,debug);
275     } else {
276        setenv("IN_INITLOG","yes",1);
277        pid=forkCommand(args,NULL,NULL,&fds[0],quiet);
278        unsetenv("IN_INITLOG");
279        x=monitor(cmdname,pid,1,&fds[0],reexec,quiet,debug);
280     }
281     return x;
282 }
This page took 0.098993 seconds and 4 git commands to generate.