]> git.pld-linux.org Git - projects/rc-scripts.git/blame - src/process.c
- update from initscripts-8.54, except killing startDaemon() and adding deprecation...
[projects/rc-scripts.git] / src / process.c
CommitLineData
00196ec7
AM
1/*
2 * Copyright (c) 1999-2003 Red Hat, Inc. All rights reserved.
3 *
4 * This software may be freely redistributed under the terms of the GNU
5 * public license.
6 *
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.
10 *
11 */
cee18a41
AM
12
13#include <errno.h>
14#include <fcntl.h>
15#include <stdlib.h>
16#include <string.h>
17#include <unistd.h>
18
458f14b7 19#include <sys/signal.h>
cee18a41 20#include <sys/poll.h>
458f14b7 21#include <sys/stat.h>
cee18a41
AM
22#include <sys/wait.h>
23
24#include <popt.h>
25
458f14b7
AM
26#include <regex.h>
27
cee18a41
AM
28#include "initlog.h"
29#include "process.h"
30
458f14b7
AM
31extern regex_t **regList;
32
cee18a41
AM
33int 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 */
52471a31 36 int fdout=-1, fderr=-1, fdcmd=-1, pid;
cee18a41 37 int outpipe[2], errpipe[2], fdpipe[2];
458f14b7 38 int ourpid;
cee18a41
AM
39
40 if ( (pipe(outpipe)==-1) || (pipe(errpipe)==-1) || (pipe(fdpipe)==-1) ) {
41 perror("pipe");
42 return -1;
43 }
44
cee18a41
AM
45 if (outfd) {
46 fdout = outpipe[1];
47 *outfd = outpipe[0];
48 } else {
49 if (!quiet)
50 fdout=dup(1);
51 }
52 if (errfd) {
53 fderr = errpipe[1];
54 *errfd = errpipe[0];
55 } else {
56 if (!quiet)
57 fderr=dup(2);
58 }
de1fc6ce
JR
59
60 if (cmdfd) {
61 *cmdfd = fdpipe[0];
62 fdcmd = fdpipe[1];
63 } else {
64 fdcmd = open("/dev/null",O_WRONLY);
65 }
52471a31
AM
66 if (fdout==-1 || fderr==-1 || fdcmd==-1)
67 return -1;
458f14b7 68 ourpid = getpid();
cee18a41
AM
69 if ((pid = fork())==-1) {
70 perror("fork");
71 return -1;
72 }
458f14b7
AM
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)) {
cee18a41 77 /* parent */
cee18a41
AM
78 close(fdout);
79 close(fderr);
80 close(fdcmd);
458f14b7
AM
81 if (!pid)
82 return ourpid;
83 else
84 return pid;
cee18a41
AM
85 } else {
86 /* kid */
de1fc6ce
JR
87 int sc_open_max;
88
cee18a41
AM
89 if (outfd) {
90 if ( (dup2(fdout,1)==-1) ) {
91 perror("dup2");
92 exit(-1);
93 }
94 } else if (quiet)
95 if ((dup2(open("/dev/null",O_WRONLY),1))==-1) {
96 perror("dup2");
97 exit(-1);
98 }
99
100 if (errfd) {
101 if ((dup2(fderr,2)==-1)) {
102 perror("dup2");
103 exit(-1);
104 }
105 } else if (quiet)
106 if ((dup2(open("/dev/null",O_WRONLY),2))==-1) {
107 perror("dup2");
108 exit(-1);
109 }
110
111
112 if ((dup2(fdcmd,CMD_FD)==-1)) {
113 perror("dup2");
114 exit(-1);
115 }
116 close(fdout);
117 close(fderr);
118 close(fdcmd);
119 if (outfd)
120 close(*outfd);
121 if (errfd)
122 close(*errfd);
123 if (cmdfd)
124 close(*cmdfd);
de1fc6ce
JR
125
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) {
129 int fd;
130 for(fd = 3; fd < sc_open_max; fd++) {
131 if (!(cmdfd && fd == CMD_FD))
132 close(fd);
133 }
134 }
135
cee18a41
AM
136 execvp(args[0],args);
137 perror("execvp");
138 exit(-1);
139 }
140}
141
142int monitor(char *cmdname, int pid, int numfds, int *fds, int reexec, int quiet, int debug) {
143 struct pollfd *pfds;
458f14b7 144 char *outbuf=NULL;
cee18a41
AM
145 char *tmpstr=NULL;
146 int x,y,rc=-1;
147 int done=0;
148 int output=0;
458f14b7
AM
149 char **cmdargs=NULL;
150 char **tmpargs=NULL;
151 int cmdargc;
00196ec7 152 char *procpath = NULL;
458f14b7
AM
153
154 if (reexec) {
155 procpath=malloc(20*sizeof(char));
156 snprintf(procpath,20,"/proc/%d",pid);
157 }
cee18a41 158
cee18a41
AM
159 pfds = malloc(numfds*sizeof(struct pollfd));
160 for (x=0;x<numfds;x++) {
161 pfds[x].fd = fds[x];
162 pfds[x].events = POLLIN | POLLPRI;
163 }
164
165 while (!done) {
458f14b7 166 usleep(500);
cee18a41
AM
167 if (((x=poll(pfds,numfds,500))==-1)&&errno!=EINTR) {
168 perror("poll");
52471a31
AM
169 free(pfds);
170 if (procpath)
171 free(procpath);
cee18a41
AM
172 return -1;
173 }
458f14b7
AM
174 if (!reexec) {
175 if (waitpid(pid,&rc,WNOHANG))
176 done=1;
177 } else {
178 struct stat sbuf;
179 /* if /proc/pid ain't there and /proc is, it's dead... */
180 if (stat(procpath,&sbuf)&&!stat("/proc/cpuinfo",&sbuf))
181 done=1;
182 }
52471a31
AM
183 if (x<0)
184 continue;
cee18a41
AM
185 y=0;
186 while (y<numfds) {
187 if ( x && ((pfds[y].revents & (POLLIN | POLLPRI)) )) {
188 int bytesread = 0;
189
190 do {
61e209ec
AM
191 char *b, *buf=calloc(8193,sizeof(char));
192 b = buf;
458f14b7 193 bytesread = read(pfds[y].fd,buf,8192);
cee18a41
AM
194 if (bytesread==-1) {
195 perror("read");
52471a31
AM
196 free(pfds);
197 if (procpath)
198 free(procpath);
199 free(buf);
cee18a41
AM
200 return -1;
201 }
202 if (bytesread) {
203 if (!quiet && !reexec)
204 write(1,buf,bytesread);
205 if (quiet) {
458f14b7
AM
206 outbuf=realloc(outbuf,(outbuf ? strlen(outbuf)+bytesread+1 : bytesread+1));
207 if (!output) outbuf[0]='\0';
208 strcat(outbuf,buf);
209 output = 1;
cee18a41
AM
210 }
211 while ((tmpstr=getLine(&buf))) {
458f14b7
AM
212 int ignore=0;
213
214 if (regList) {
215 int count=0;
216
217 while (regList[count]) {
218 if (!regexec(regList[count],tmpstr,0,NULL,0)) {
219 ignore=1;
220 break;
221 }
222 count++;
223 }
224 }
225 if (!ignore) {
226 if (!reexec) {
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",
231 cmdname,tmpstr);
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);
236 free(buffer);
237 } else {
238 logString(cmdname,tmpstr);
239 }
240 } else {
241 int z;
cee18a41 242
458f14b7
AM
243 cmdargs=NULL;
244 tmpargs=NULL;
245 cmdargc=0;
246
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];
252 }
253 cmdargs[cmdargc+1]=NULL;
254 processArgs(cmdargc+1,cmdargs,1);
61e209ec
AM
255 free(cmdargs[0]);
256 free(tmpargs);
257 free(cmdargs);
458f14b7
AM
258 }
259 }
61e209ec 260 if (tmpstr) free(tmpstr);
cee18a41
AM
261 }
262 }
61e209ec 263 free(b);
458f14b7 264 } while ( bytesread==8192 );
cee18a41
AM
265 }
266 y++;
267 }
268 }
269 if ((!WIFEXITED(rc)) || (rc=WEXITSTATUS(rc))) {
270 /* If there was an error and we're quiet, be loud */
cee18a41
AM
271
272 if (quiet && output) {
458f14b7 273 write(1,outbuf,strlen(outbuf));
cee18a41 274 }
52471a31
AM
275 free(pfds);
276 if (procpath)
277 free(procpath);
278 if(outbuf)
279 free(outbuf);
cee18a41
AM
280 return (rc);
281 }
52471a31
AM
282 free(pfds);
283 if (procpath)
284 free(procpath);
285 if(outbuf)
286 free(outbuf);
cee18a41
AM
287 return 0;
288}
289
290int runCommand(char *cmd, int reexec, int quiet, int debug) {
291 int fds[2];
292 int pid,x;
293 char **args, **tmpargs;
294 char *cmdname;
295
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]);
300 }
301 args[pid] = NULL;
302 if (strcmp(args[0],"sh") && strcmp(args[0],"/bin/sh"))
de1fc6ce 303 cmdname = basename(args[0]);
cee18a41 304 else
de1fc6ce 305 cmdname = basename(args[1]);
00196ec7
AM
306 if ((cmdname[0] =='K' || cmdname[0] == 'S') &&
307 ( cmdname[1] >= '0' && cmdname[1] <= '9' ) &&
308 ( cmdname[2] >= '0' && cmdname[2] <= '9' ) )
cee18a41
AM
309 cmdname+=3;
310 if (!reexec) {
311 pid=forkCommand(args,&fds[0],&fds[1],NULL,quiet);
52471a31
AM
312 if (pid == -1)
313 return -1;
cee18a41
AM
314 x=monitor(cmdname,pid,2,fds,reexec,quiet,debug);
315 } else {
316 setenv("IN_INITLOG","yes",1);
317 pid=forkCommand(args,NULL,NULL,&fds[0],quiet);
52471a31
AM
318 if (pid == -1)
319 return -1;
cee18a41
AM
320 unsetenv("IN_INITLOG");
321 x=monitor(cmdname,pid,1,&fds[0],reexec,quiet,debug);
322 }
323 return x;
324}
This page took 0.140964 seconds and 4 git commands to generate.