]> git.pld-linux.org Git - projects/rc-scripts.git/blame - src/process.c
- merge from TOTALNEW branch (see NEWS for more info)
[projects/rc-scripts.git] / src / process.c
CommitLineData
cee18a41
AM
1
2#include <errno.h>
3#include <fcntl.h>
4#include <stdlib.h>
5#include <string.h>
6#include <unistd.h>
7
458f14b7 8#include <sys/signal.h>
cee18a41 9#include <sys/poll.h>
458f14b7 10#include <sys/stat.h>
cee18a41
AM
11#include <sys/wait.h>
12
13#include <popt.h>
14
458f14b7
AM
15#include <regex.h>
16
cee18a41
AM
17#include "initlog.h"
18#include "process.h"
19
458f14b7
AM
20extern regex_t **regList;
21
cee18a41
AM
22int 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 */
de1fc6ce 25 int fdout, fderr, fdcmd, pid;
cee18a41 26 int outpipe[2], errpipe[2], fdpipe[2];
458f14b7 27 int ourpid;
cee18a41
AM
28
29 if ( (pipe(outpipe)==-1) || (pipe(errpipe)==-1) || (pipe(fdpipe)==-1) ) {
30 perror("pipe");
31 return -1;
32 }
33
cee18a41
AM
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 }
de1fc6ce
JR
48
49 if (cmdfd) {
50 *cmdfd = fdpipe[0];
51 fdcmd = fdpipe[1];
52 } else {
53 fdcmd = open("/dev/null",O_WRONLY);
54 }
458f14b7 55 ourpid = getpid();
cee18a41
AM
56 if ((pid = fork())==-1) {
57 perror("fork");
58 return -1;
59 }
458f14b7
AM
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)) {
cee18a41 64 /* parent */
cee18a41
AM
65 close(fdout);
66 close(fderr);
67 close(fdcmd);
458f14b7
AM
68 if (!pid)
69 return ourpid;
70 else
71 return pid;
cee18a41
AM
72 } else {
73 /* kid */
de1fc6ce
JR
74 int sc_open_max;
75
cee18a41
AM
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);
de1fc6ce
JR
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
cee18a41
AM
123 execvp(args[0],args);
124 perror("execvp");
125 exit(-1);
126 }
127}
128
129int monitor(char *cmdname, int pid, int numfds, int *fds, int reexec, int quiet, int debug) {
130 struct pollfd *pfds;
458f14b7
AM
131 char *buf=malloc(8192*sizeof(char));
132 char *outbuf=NULL;
cee18a41
AM
133 char *tmpstr=NULL;
134 int x,y,rc=-1;
135 int done=0;
136 int output=0;
458f14b7
AM
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 }
cee18a41 146
cee18a41
AM
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) {
458f14b7 154 usleep(500);
cee18a41
AM
155 if (((x=poll(pfds,numfds,500))==-1)&&errno!=EINTR) {
156 perror("poll");
157 return -1;
158 }
458f14b7
AM
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 }
cee18a41
AM
168 y=0;
169 while (y<numfds) {
170 if ( x && ((pfds[y].revents & (POLLIN | POLLPRI)) )) {
171 int bytesread = 0;
172
173 do {
458f14b7
AM
174 buf=calloc(8192,sizeof(char));
175 bytesread = read(pfds[y].fd,buf,8192);
cee18a41
AM
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) {
458f14b7
AM
184 outbuf=realloc(outbuf,(outbuf ? strlen(outbuf)+bytesread+1 : bytesread+1));
185 if (!output) outbuf[0]='\0';
186 strcat(outbuf,buf);
187 output = 1;
cee18a41
AM
188 }
189 while ((tmpstr=getLine(&buf))) {
458f14b7
AM
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;
cee18a41 220
458f14b7
AM
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 }
cee18a41
AM
235 }
236 }
458f14b7 237 } while ( bytesread==8192 );
cee18a41
AM
238 }
239 y++;
240 }
241 }
242 if ((!WIFEXITED(rc)) || (rc=WEXITSTATUS(rc))) {
243 /* If there was an error and we're quiet, be loud */
cee18a41
AM
244
245 if (quiet && output) {
458f14b7 246 write(1,outbuf,strlen(outbuf));
cee18a41
AM
247 }
248 return (rc);
249 }
250 return 0;
251}
252
253int 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"))
de1fc6ce 266 cmdname = basename(args[0]);
cee18a41 267 else
de1fc6ce 268 cmdname = basename(args[1]);
458f14b7
AM
269 if ((cmdname[0] =='K' || cmdname[0] == 'S') && ( '0' <= cmdname[1] <= '9' )
270 && ( '0' <= cmdname[2] <= '9' ) )
cee18a41
AM
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.126554 seconds and 4 git commands to generate.