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