]> git.pld-linux.org Git - projects/rc-scripts.git/blame - src/process.c
- merge my private tree
[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 11#include <sys/wait.h>
7824432b
AM
12#include <sys/time.h>
13#include <sys/resource.h>
cee18a41
AM
14
15#include <popt.h>
16
458f14b7
AM
17#include <regex.h>
18
cee18a41
AM
19#include "initlog.h"
20#include "process.h"
21
458f14b7
AM
22extern regex_t **regList;
23
cee18a41
AM
24int 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 */
aa8f8aa6 27 int fdout, fderr, fdcmd, pid;
cee18a41 28 int outpipe[2], errpipe[2], fdpipe[2];
458f14b7 29 int ourpid;
cee18a41
AM
30
31 if ( (pipe(outpipe)==-1) || (pipe(errpipe)==-1) || (pipe(fdpipe)==-1) ) {
32 perror("pipe");
33 return -1;
34 }
35
cee18a41
AM
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 }
aa8f8aa6
AM
50
51 if (cmdfd) {
52 *cmdfd = fdpipe[0];
53 fdcmd = fdpipe[1];
54 } else {
55 fdcmd = open("/dev/null",O_WRONLY);
56 }
458f14b7 57 ourpid = getpid();
cee18a41
AM
58 if ((pid = fork())==-1) {
59 perror("fork");
60 return -1;
61 }
458f14b7
AM
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)) {
cee18a41 66 /* parent */
cee18a41
AM
67 close(fdout);
68 close(fderr);
69 close(fdcmd);
458f14b7
AM
70 if (!pid)
71 return ourpid;
72 else
73 return pid;
cee18a41
AM
74 } else {
75 /* kid */
aa8f8aa6
AM
76 int sc_open_max;
77
cee18a41
AM
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);
aa8f8aa6
AM
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
cee18a41
AM
125 execvp(args[0],args);
126 perror("execvp");
127 exit(-1);
128 }
129}
130
131int monitor(char *cmdname, int pid, int numfds, int *fds, int reexec, int quiet, int debug) {
132 struct pollfd *pfds;
458f14b7
AM
133 char *buf=malloc(8192*sizeof(char));
134 char *outbuf=NULL;
cee18a41
AM
135 char *tmpstr=NULL;
136 int x,y,rc=-1;
137 int done=0;
138 int output=0;
458f14b7
AM
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 }
cee18a41 148
cee18a41
AM
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) {
458f14b7 156 usleep(500);
cee18a41
AM
157 if (((x=poll(pfds,numfds,500))==-1)&&errno!=EINTR) {
158 perror("poll");
159 return -1;
160 }
458f14b7
AM
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 }
cee18a41
AM
170 y=0;
171 while (y<numfds) {
172 if ( x && ((pfds[y].revents & (POLLIN | POLLPRI)) )) {
173 int bytesread = 0;
174
175 do {
458f14b7
AM
176 buf=calloc(8192,sizeof(char));
177 bytesread = read(pfds[y].fd,buf,8192);
cee18a41
AM
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) {
458f14b7
AM
186 outbuf=realloc(outbuf,(outbuf ? strlen(outbuf)+bytesread+1 : bytesread+1));
187 if (!output) outbuf[0]='\0';
188 strcat(outbuf,buf);
189 output = 1;
cee18a41
AM
190 }
191 while ((tmpstr=getLine(&buf))) {
458f14b7
AM
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;
cee18a41 222
458f14b7
AM
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 }
cee18a41
AM
237 }
238 }
458f14b7 239 } while ( bytesread==8192 );
cee18a41
AM
240 }
241 y++;
242 }
243 }
244 if ((!WIFEXITED(rc)) || (rc=WEXITSTATUS(rc))) {
245 /* If there was an error and we're quiet, be loud */
cee18a41
AM
246
247 if (quiet && output) {
458f14b7 248 write(1,outbuf,strlen(outbuf));
cee18a41
AM
249 }
250 return (rc);
251 }
252 return 0;
253}
254
255int 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"))
aa8f8aa6 268 cmdname = basename(args[0]);
cee18a41 269 else
aa8f8aa6 270 cmdname = basename(args[1]);
458f14b7
AM
271 if ((cmdname[0] =='K' || cmdname[0] == 'S') && ( '0' <= cmdname[1] <= '9' )
272 && ( '0' <= cmdname[2] <= '9' ) )
cee18a41
AM
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}
7824432b
AM
285
286void 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.08387 seconds and 4 git commands to generate.