Commit | Line | Data |
---|---|---|
528b0614 | 1 | /* |
b0af3d20 | 2 | * Copyright (c) 1980,1986 Regents of the University of California. |
528b0614 DF |
3 | * All rights reserved. The Berkeley software License Agreement |
4 | * specifies the terms and conditions for redistribution. | |
5 | */ | |
6 | ||
37c640e2 | 7 | #ifndef lint |
e618cb0b | 8 | static char sccsid[] = "@(#)init.c 5.7 (Berkeley) %G%"; |
528b0614 | 9 | #endif not lint |
37c640e2 | 10 | |
7c8ab0e6 BJ |
11 | #include <signal.h> |
12 | #include <sys/types.h> | |
13 | #include <utmp.h> | |
14 | #include <setjmp.h> | |
215943cc | 15 | #include <sys/reboot.h> |
f570e1ff | 16 | #include <errno.h> |
d0ca48ff | 17 | #include <sys/file.h> |
9479aa87 | 18 | #include <ttyent.h> |
b0af3d20 | 19 | #include <sys/syslog.h> |
25efc242 | 20 | #include <sys/stat.h> |
7c8ab0e6 BJ |
21 | |
22 | #define LINSIZ sizeof(wtmp.ut_line) | |
0dfaf495 | 23 | #define CMDSIZ 200 /* max string length for getty or window command*/ |
25efc242 | 24 | #define ALL p = itab; p ; p = p->next |
7c8ab0e6 BJ |
25 | #define EVER ;; |
26 | #define SCPYN(a, b) strncpy(a, b, sizeof(a)) | |
27 | #define SCMPN(a, b) strncmp(a, b, sizeof(a)) | |
28 | ||
29 | char shell[] = "/bin/sh"; | |
7c8ab0e6 BJ |
30 | char minus[] = "-"; |
31 | char runc[] = "/etc/rc"; | |
25efc242 | 32 | char utmpf[] = "/etc/utmp"; |
7c8ab0e6 BJ |
33 | char wtmpf[] = "/usr/adm/wtmp"; |
34 | char ctty[] = "/dev/console"; | |
7c8ab0e6 BJ |
35 | |
36 | struct utmp wtmp; | |
7c8ab0e6 BJ |
37 | struct tab |
38 | { | |
39 | char line[LINSIZ]; | |
068e4187 | 40 | char comn[CMDSIZ]; |
7c8ab0e6 BJ |
41 | char xflag; |
42 | int pid; | |
068e4187 RC |
43 | int wpid; /* window system pid for SIGHUP */ |
44 | char wcmd[CMDSIZ]; /* command to start window system process */ | |
43236707 BJ |
45 | time_t gettytime; |
46 | int gettycnt; | |
a936c74e MK |
47 | time_t windtime; |
48 | int windcnt; | |
25efc242 JB |
49 | struct tab *next; |
50 | } *itab; | |
7c8ab0e6 BJ |
51 | |
52 | int fi; | |
53 | int mergflag; | |
54 | char tty[20]; | |
abf0db3c | 55 | jmp_buf sjbuf, shutpass; |
f570e1ff | 56 | time_t time0; |
7c8ab0e6 BJ |
57 | |
58 | int reset(); | |
f570e1ff | 59 | int idle(); |
7c8ab0e6 BJ |
60 | char *strcpy(), *strcat(); |
61 | long lseek(); | |
62 | ||
068e4187 | 63 | struct sigvec rvec = { reset, sigmask(SIGHUP), 0 }; |
d0ca48ff | 64 | |
25efc242 | 65 | |
e618cb0b | 66 | #if defined(vax) || defined(tahoe) |
7c8ab0e6 BJ |
67 | main() |
68 | { | |
e618cb0b SL |
69 | #if defined(tahoe) |
70 | register int r12; /* make sure r11 gets bootflags */ | |
71 | #endif | |
215943cc | 72 | register int r11; /* passed thru from boot */ |
d0ca48ff | 73 | #else |
8d3a6b89 TL |
74 | main(argc, argv) |
75 | char **argv; | |
76 | { | |
d0ca48ff | 77 | #endif |
215943cc BJ |
78 | int howto, oldhowto; |
79 | ||
f570e1ff | 80 | time0 = time(0); |
e618cb0b | 81 | #if defined(vax) || defined(tahoe) |
215943cc | 82 | howto = r11; |
d0ca48ff | 83 | #else |
8d3a6b89 TL |
84 | if (argc > 1 && argv[1][0] == '-') { |
85 | char *cp; | |
86 | ||
87 | howto = 0; | |
88 | cp = &argv[1][1]; | |
89 | while (*cp) switch (*cp++) { | |
90 | case 'a': | |
91 | howto |= RB_ASKNAME; | |
92 | break; | |
93 | case 's': | |
94 | howto |= RB_SINGLE; | |
95 | break; | |
96 | } | |
97 | } else { | |
98 | howto = RB_SINGLE; | |
99 | } | |
d0ca48ff | 100 | #endif |
076ae92c | 101 | openlog("init", LOG_CONS|LOG_ODELAY, LOG_AUTH); |
d0ca48ff | 102 | sigvec(SIGTERM, &rvec, (struct sigvec *)0); |
f570e1ff | 103 | signal(SIGTSTP, idle); |
7c8ab0e6 | 104 | signal(SIGSTOP, SIG_IGN); |
7c8ab0e6 BJ |
105 | signal(SIGTTIN, SIG_IGN); |
106 | signal(SIGTTOU, SIG_IGN); | |
d0ca48ff SL |
107 | (void) setjmp(sjbuf); |
108 | for (EVER) { | |
215943cc BJ |
109 | oldhowto = howto; |
110 | howto = RB_SINGLE; | |
abf0db3c BJ |
111 | if (setjmp(shutpass) == 0) |
112 | shutdown(); | |
215943cc BJ |
113 | if (oldhowto & RB_SINGLE) |
114 | single(); | |
115 | if (runcom(oldhowto) == 0) | |
116 | continue; | |
7c8ab0e6 BJ |
117 | merge(); |
118 | multiple(); | |
119 | } | |
120 | } | |
121 | ||
abf0db3c BJ |
122 | int shutreset(); |
123 | ||
7c8ab0e6 BJ |
124 | shutdown() |
125 | { | |
126 | register i; | |
25efc242 | 127 | register struct tab *p, *p1; |
7c8ab0e6 | 128 | |
25efc242 | 129 | close(creat(utmpf, 0644)); |
7c8ab0e6 | 130 | signal(SIGHUP, SIG_IGN); |
25efc242 | 131 | for (p = itab; p ; ) { |
7c8ab0e6 | 132 | term(p); |
25efc242 JB |
133 | p1 = p->next; |
134 | free(p); | |
135 | p = p1; | |
7c8ab0e6 | 136 | } |
25efc242 | 137 | itab = (struct tab *)0; |
abf0db3c | 138 | signal(SIGALRM, shutreset); |
b0af3d20 MK |
139 | (void) kill(-1, SIGTERM); /* one chance to catch it */ |
140 | sleep(5); | |
abf0db3c | 141 | alarm(30); |
d0ca48ff | 142 | for (i = 0; i < 5; i++) |
7c8ab0e6 | 143 | kill(-1, SIGKILL); |
d0ca48ff | 144 | while (wait((int *)0) != -1) |
7c8ab0e6 BJ |
145 | ; |
146 | alarm(0); | |
abf0db3c BJ |
147 | shutend(); |
148 | } | |
149 | ||
150 | char shutfailm[] = "WARNING: Something is hung (wont die); ps axl advised\n"; | |
151 | ||
152 | shutreset() | |
153 | { | |
154 | int status; | |
155 | ||
156 | if (fork() == 0) { | |
157 | int ct = open(ctty, 1); | |
158 | write(ct, shutfailm, sizeof (shutfailm)); | |
159 | sleep(5); | |
160 | exit(1); | |
161 | } | |
162 | sleep(5); | |
163 | shutend(); | |
164 | longjmp(shutpass, 1); | |
165 | } | |
166 | ||
167 | shutend() | |
168 | { | |
f570e1ff | 169 | register i, f; |
abf0db3c | 170 | |
f570e1ff | 171 | acct(0); |
7c8ab0e6 | 172 | signal(SIGALRM, SIG_DFL); |
d0ca48ff | 173 | for (i = 0; i < 10; i++) |
7c8ab0e6 | 174 | close(i); |
d0ca48ff | 175 | f = open(wtmpf, O_WRONLY|O_APPEND); |
f570e1ff | 176 | if (f >= 0) { |
f570e1ff BJ |
177 | SCPYN(wtmp.ut_line, "~"); |
178 | SCPYN(wtmp.ut_name, "shutdown"); | |
37c640e2 | 179 | SCPYN(wtmp.ut_host, ""); |
f570e1ff BJ |
180 | time(&wtmp.ut_time); |
181 | write(f, (char *)&wtmp, sizeof(wtmp)); | |
182 | close(f); | |
183 | } | |
d0ca48ff | 184 | return (1); |
7c8ab0e6 BJ |
185 | } |
186 | ||
187 | single() | |
188 | { | |
189 | register pid; | |
f570e1ff BJ |
190 | register xpid; |
191 | extern errno; | |
7c8ab0e6 | 192 | |
d0ca48ff SL |
193 | do { |
194 | pid = fork(); | |
195 | if (pid == 0) { | |
196 | signal(SIGTERM, SIG_DFL); | |
197 | signal(SIGHUP, SIG_DFL); | |
198 | signal(SIGALRM, SIG_DFL); | |
9479aa87 | 199 | signal(SIGTSTP, SIG_IGN); |
d0ca48ff SL |
200 | (void) open(ctty, O_RDWR); |
201 | dup2(0, 1); | |
202 | dup2(0, 2); | |
203 | execl(shell, minus, (char *)0); | |
204 | exit(0); | |
205 | } | |
206 | while ((xpid = wait((int *)0)) != pid) | |
207 | if (xpid == -1 && errno == ECHILD) | |
208 | break; | |
209 | } while (xpid == -1); | |
7c8ab0e6 BJ |
210 | } |
211 | ||
215943cc BJ |
212 | runcom(oldhowto) |
213 | int oldhowto; | |
7c8ab0e6 BJ |
214 | { |
215 | register pid, f; | |
215943cc | 216 | int status; |
7c8ab0e6 BJ |
217 | |
218 | pid = fork(); | |
d0ca48ff SL |
219 | if (pid == 0) { |
220 | (void) open("/", O_RDONLY); | |
221 | dup2(0, 1); | |
222 | dup2(0, 2); | |
215943cc BJ |
223 | if (oldhowto & RB_SINGLE) |
224 | execl(shell, shell, runc, (char *)0); | |
225 | else | |
226 | execl(shell, shell, runc, "autoboot", (char *)0); | |
227 | exit(1); | |
7c8ab0e6 | 228 | } |
d0ca48ff | 229 | while (wait(&status) != pid) |
7c8ab0e6 | 230 | ; |
d0ca48ff SL |
231 | if (status) |
232 | return (0); | |
233 | f = open(wtmpf, O_WRONLY|O_APPEND); | |
7c8ab0e6 | 234 | if (f >= 0) { |
7c8ab0e6 BJ |
235 | SCPYN(wtmp.ut_line, "~"); |
236 | SCPYN(wtmp.ut_name, "reboot"); | |
37c640e2 | 237 | SCPYN(wtmp.ut_host, ""); |
f570e1ff BJ |
238 | if (time0) { |
239 | wtmp.ut_time = time0; | |
240 | time0 = 0; | |
241 | } else | |
242 | time(&wtmp.ut_time); | |
7c8ab0e6 BJ |
243 | write(f, (char *)&wtmp, sizeof(wtmp)); |
244 | close(f); | |
245 | } | |
d0ca48ff | 246 | return (1); |
7c8ab0e6 BJ |
247 | } |
248 | ||
068e4187 | 249 | struct sigvec mvec = { merge, sigmask(SIGTERM), 0 }; |
d0ca48ff SL |
250 | /* |
251 | * Multi-user. Listen for users leaving, SIGHUP's | |
252 | * which indicate ttys has changed, and SIGTERM's which | |
253 | * are used to shutdown the system. | |
254 | */ | |
7c8ab0e6 BJ |
255 | multiple() |
256 | { | |
257 | register struct tab *p; | |
258 | register pid; | |
25efc242 | 259 | int omask; |
7c8ab0e6 | 260 | |
d0ca48ff SL |
261 | sigvec(SIGHUP, &mvec, (struct sigvec *)0); |
262 | for (EVER) { | |
7c8ab0e6 | 263 | pid = wait((int *)0); |
d0ca48ff | 264 | if (pid == -1) |
7c8ab0e6 | 265 | return; |
25efc242 | 266 | omask = sigblock(SIGHUP); |
068e4187 RC |
267 | for (ALL) { |
268 | /* must restart window system BEFORE emulator */ | |
269 | if (p->wpid == pid || p->wpid == -1) | |
270 | wstart(p); | |
d0ca48ff | 271 | if (p->pid == pid || p->pid == -1) { |
068e4187 RC |
272 | /* disown the window system */ |
273 | if (p->wpid) | |
274 | kill(p->wpid, SIGHUP); | |
7c8ab0e6 BJ |
275 | rmut(p); |
276 | dfork(p); | |
277 | } | |
068e4187 | 278 | } |
25efc242 | 279 | sigsetmask(omask); |
7c8ab0e6 BJ |
280 | } |
281 | } | |
282 | ||
d0ca48ff SL |
283 | /* |
284 | * Merge current contents of ttys file | |
285 | * into in-core table of configured tty lines. | |
286 | * Entered as signal handler for SIGHUP. | |
287 | */ | |
288 | #define FOUND 1 | |
289 | #define CHANGE 2 | |
068e4187 | 290 | #define WCHANGE 4 |
d0ca48ff SL |
291 | |
292 | merge() | |
293 | { | |
294 | register struct tab *p; | |
9479aa87 | 295 | register struct ttyent *t; |
25efc242 | 296 | register struct tab *p1; |
d0ca48ff | 297 | |
d0ca48ff SL |
298 | for (ALL) |
299 | p->xflag = 0; | |
9479aa87 BJ |
300 | setttyent(); |
301 | while (t = getttyent()) { | |
302 | if ((t->ty_status & TTY_ON) == 0) | |
303 | continue; | |
d0ca48ff | 304 | for (ALL) { |
9479aa87 | 305 | if (SCMPN(p->line, t->ty_name)) |
d0ca48ff SL |
306 | continue; |
307 | p->xflag |= FOUND; | |
9479aa87 | 308 | if (SCMPN(p->comn, t->ty_getty)) { |
d0ca48ff | 309 | p->xflag |= CHANGE; |
9479aa87 | 310 | SCPYN(p->comn, t->ty_getty); |
d0ca48ff | 311 | } |
068e4187 RC |
312 | if (SCMPN(p->wcmd, t->ty_window)) { |
313 | p->xflag |= WCHANGE|CHANGE; | |
314 | SCPYN(p->wcmd, t->ty_window); | |
315 | } | |
d0ca48ff SL |
316 | goto contin1; |
317 | } | |
068e4187 | 318 | |
25efc242 JB |
319 | /* |
320 | * Make space for a new one | |
321 | */ | |
322 | p1 = (struct tab *)calloc(1, sizeof(*p1)); | |
323 | if (!p1) { | |
324 | syslog(LOG_ERR, "no space for '%s' !?!", t->ty_name); | |
d0ca48ff SL |
325 | goto contin1; |
326 | } | |
25efc242 JB |
327 | /* |
328 | * Put new terminal at the end of the linked list. | |
329 | */ | |
330 | if (itab) { | |
331 | for (p = itab; p->next ; p = p->next) | |
332 | ; | |
333 | p->next = p1; | |
334 | } else | |
335 | itab = p1; | |
336 | ||
337 | p = p1; | |
338 | SCPYN(p->line, t->ty_name); | |
339 | p->xflag |= FOUND|CHANGE; | |
340 | SCPYN(p->comn, t->ty_getty); | |
341 | if (strcmp(t->ty_window, "") != 0) { | |
342 | p->xflag |= WCHANGE; | |
343 | SCPYN(p->wcmd, t->ty_window); | |
344 | } | |
d0ca48ff SL |
345 | contin1: |
346 | ; | |
347 | } | |
9479aa87 | 348 | endttyent(); |
25efc242 | 349 | p1 = (struct tab *)0; |
d0ca48ff SL |
350 | for (ALL) { |
351 | if ((p->xflag&FOUND) == 0) { | |
352 | term(p); | |
068e4187 | 353 | wterm(p); |
25efc242 JB |
354 | if (p1) |
355 | p1->next = p->next; | |
356 | else | |
357 | itab = p->next; | |
358 | free(p); | |
359 | p = p1 ? p1 : itab; | |
360 | } else { | |
361 | /* window system should be started first */ | |
362 | if (p->xflag&WCHANGE) { | |
363 | wterm(p); | |
364 | wstart(p); | |
365 | } | |
366 | if (p->xflag&CHANGE) { | |
367 | term(p); | |
368 | dfork(p); | |
369 | } | |
d0ca48ff | 370 | } |
25efc242 | 371 | p1 = p; |
d0ca48ff SL |
372 | } |
373 | } | |
374 | ||
7c8ab0e6 | 375 | term(p) |
d0ca48ff | 376 | register struct tab *p; |
7c8ab0e6 BJ |
377 | { |
378 | ||
d0ca48ff | 379 | if (p->pid != 0) { |
7c8ab0e6 BJ |
380 | rmut(p); |
381 | kill(p->pid, SIGKILL); | |
382 | } | |
383 | p->pid = 0; | |
068e4187 RC |
384 | /* send SIGHUP to get rid of connections */ |
385 | if (p->wpid > 0) | |
386 | kill(p->wpid, SIGHUP); | |
7c8ab0e6 BJ |
387 | } |
388 | ||
30e1f894 SL |
389 | #include <sys/ioctl.h> |
390 | ||
7c8ab0e6 | 391 | dfork(p) |
d0ca48ff | 392 | struct tab *p; |
7c8ab0e6 BJ |
393 | { |
394 | register pid; | |
43236707 BJ |
395 | time_t t; |
396 | int dowait = 0; | |
397 | ||
398 | time(&t); | |
399 | p->gettycnt++; | |
400 | if ((t - p->gettytime) >= 60) { | |
401 | p->gettytime = t; | |
402 | p->gettycnt = 1; | |
068e4187 RC |
403 | } else if (p->gettycnt >= 5) { |
404 | dowait = 1; | |
405 | p->gettytime = t; | |
406 | p->gettycnt = 1; | |
43236707 | 407 | } |
7c8ab0e6 | 408 | pid = fork(); |
d0ca48ff | 409 | if (pid == 0) { |
30e1f894 SL |
410 | signal(SIGTERM, SIG_DFL); |
411 | signal(SIGHUP, SIG_IGN); | |
a936c74e | 412 | sigsetmask(0); /* since can be called from masked code */ |
43236707 | 413 | if (dowait) { |
068e4187 RC |
414 | syslog(LOG_ERR, "'%s %s' failing, sleeping", p->comn, p->line); |
415 | closelog(); | |
43236707 | 416 | sleep(30); |
ef9abb5f | 417 | } |
068e4187 | 418 | execit(p->comn, p->line); |
7c8ab0e6 BJ |
419 | exit(0); |
420 | } | |
421 | p->pid = pid; | |
422 | } | |
423 | ||
d0ca48ff SL |
424 | /* |
425 | * Remove utmp entry. | |
426 | */ | |
7c8ab0e6 | 427 | rmut(p) |
d0ca48ff | 428 | register struct tab *p; |
7c8ab0e6 BJ |
429 | { |
430 | register f; | |
ef9abb5f | 431 | int found = 0; |
25efc242 JB |
432 | static unsigned utmpsize; |
433 | static struct utmp *utmp; | |
434 | register struct utmp *u; | |
435 | int nutmp; | |
436 | struct stat statbf; | |
7c8ab0e6 | 437 | |
25efc242 | 438 | f = open(utmpf, O_RDWR); |
d0ca48ff | 439 | if (f >= 0) { |
25efc242 JB |
440 | fstat(f, &statbf); |
441 | if (utmpsize < statbf.st_size) { | |
442 | utmpsize = statbf.st_size + 10 * sizeof(struct utmp); | |
443 | if (utmp) | |
444 | utmp = (struct utmp *)realloc(utmp, utmpsize); | |
445 | else | |
446 | utmp = (struct utmp *)malloc(utmpsize); | |
447 | if (!utmp) | |
448 | syslog(LOG_ERR, "utmp malloc failed"); | |
449 | } | |
450 | if (statbf.st_size && utmp) { | |
451 | nutmp = read(f, utmp, statbf.st_size); | |
452 | nutmp /= sizeof(struct utmp); | |
453 | for (u = utmp ; u < &utmp[nutmp] ; u++) { | |
454 | if (SCMPN(u->ut_line, p->line) || | |
455 | u->ut_name[0]==0) | |
456 | continue; | |
457 | lseek(f, ((long)u)-((long)utmp), L_SET); | |
458 | SCPYN(u->ut_name, ""); | |
459 | SCPYN(u->ut_host, ""); | |
460 | time(&u->ut_time); | |
461 | write(f, (char *)u, sizeof(*u)); | |
462 | found++; | |
463 | } | |
7c8ab0e6 BJ |
464 | } |
465 | close(f); | |
466 | } | |
ef9abb5f | 467 | if (found) { |
d0ca48ff | 468 | f = open(wtmpf, O_WRONLY|O_APPEND); |
ef9abb5f BJ |
469 | if (f >= 0) { |
470 | SCPYN(wtmp.ut_line, p->line); | |
471 | SCPYN(wtmp.ut_name, ""); | |
37c640e2 | 472 | SCPYN(wtmp.ut_host, ""); |
ef9abb5f | 473 | time(&wtmp.ut_time); |
ef9abb5f BJ |
474 | write(f, (char *)&wtmp, sizeof(wtmp)); |
475 | close(f); | |
476 | } | |
13408cfa SL |
477 | /* |
478 | * After a proper login force reset | |
479 | * of error detection code in dfork. | |
480 | */ | |
481 | p->gettytime = 0; | |
a936c74e | 482 | p->windtime = 0; |
7c8ab0e6 BJ |
483 | } |
484 | } | |
485 | ||
486 | reset() | |
487 | { | |
d0ca48ff | 488 | |
7c8ab0e6 BJ |
489 | longjmp(sjbuf, 1); |
490 | } | |
f570e1ff | 491 | |
d0ca48ff SL |
492 | jmp_buf idlebuf; |
493 | ||
494 | idlehup() | |
495 | { | |
496 | ||
497 | longjmp(idlebuf, 1); | |
498 | } | |
499 | ||
f570e1ff BJ |
500 | idle() |
501 | { | |
502 | register struct tab *p; | |
503 | register pid; | |
504 | ||
d0ca48ff | 505 | signal(SIGHUP, idlehup); |
068e4187 | 506 | for (EVER) { |
d0ca48ff | 507 | if (setjmp(idlebuf)) |
f570e1ff | 508 | return; |
d0ca48ff SL |
509 | pid = wait((int *) 0); |
510 | if (pid == -1) { | |
511 | sigpause(0); | |
512 | continue; | |
f570e1ff | 513 | } |
068e4187 RC |
514 | for (ALL) { |
515 | /* if window system dies, mark it for restart */ | |
516 | if (p->wpid == pid) | |
517 | p->wpid = -1; | |
d0ca48ff SL |
518 | if (p->pid == pid) { |
519 | rmut(p); | |
520 | p->pid = -1; | |
521 | } | |
068e4187 RC |
522 | } |
523 | } | |
524 | } | |
525 | ||
526 | wterm(p) | |
527 | register struct tab *p; | |
528 | { | |
529 | if (p->wpid != 0) { | |
530 | kill(p->wpid, SIGKILL); | |
531 | } | |
532 | p->wpid = 0; | |
533 | } | |
534 | ||
535 | wstart(p) | |
536 | register struct tab *p; | |
537 | { | |
a936c74e MK |
538 | register pid; |
539 | time_t t; | |
540 | int dowait = 0; | |
068e4187 | 541 | |
a936c74e MK |
542 | time(&t); |
543 | p->windcnt++; | |
544 | if ((t - p->windtime) >= 60) { | |
545 | p->windtime = t; | |
546 | p->windcnt = 1; | |
547 | } else if (p->windcnt >= 5) { | |
548 | dowait = 1; | |
549 | p->windtime = t; | |
550 | p->windcnt = 1; | |
551 | } | |
552 | ||
553 | pid = fork(); | |
554 | ||
555 | if (pid == 0) { | |
068e4187 | 556 | signal(SIGTERM, SIG_DFL); |
a936c74e MK |
557 | signal(SIGHUP, SIG_IGN); |
558 | sigsetmask(0); /* since can be called from masked code */ | |
559 | if (dowait) { | |
560 | syslog(LOG_ERR, "'%s %s' failing, sleeping", p->wcmd, p->line); | |
561 | closelog(); | |
562 | sleep(30); | |
563 | } | |
068e4187 RC |
564 | execit(p->wcmd, p->line); |
565 | exit(0); | |
566 | } | |
a936c74e | 567 | p->wpid = pid; |
068e4187 RC |
568 | } |
569 | ||
a936c74e | 570 | #define NARGS 20 /* must be at least 4 */ |
068e4187 RC |
571 | #define ARGLEN 512 /* total size for all the argument strings */ |
572 | ||
573 | execit(s, arg) | |
574 | char *s; | |
575 | char *arg; /* last argument on line */ | |
576 | { | |
577 | char *argv[NARGS], args[ARGLEN], *envp[1]; | |
578 | register char *sp = s; | |
579 | register char *ap = args; | |
580 | register char c; | |
581 | register int i; | |
582 | ||
583 | /* | |
584 | * First we have to set up the argument vector. | |
585 | * "prog arg1 arg2" maps to exec("prog", "-", "arg1", "arg2"). | |
586 | */ | |
587 | for (i = 1; i < NARGS - 2; i++) { | |
588 | argv[i] = ap; | |
589 | for (EVER) { | |
590 | if ((c = *sp++) == '\0' || ap >= &args[ARGLEN-1]) { | |
591 | *ap = '\0'; | |
592 | goto done; | |
593 | } | |
594 | if (c == ' ') { | |
595 | *ap++ = '\0'; | |
596 | while (*sp == ' ') | |
597 | sp++; | |
598 | if (*sp == '\0') | |
599 | goto done; | |
600 | break; | |
601 | } | |
602 | *ap++ = c; | |
603 | } | |
f570e1ff | 604 | } |
068e4187 RC |
605 | done: |
606 | argv[0] = argv[1]; | |
607 | argv[1] = "-"; | |
608 | argv[i+1] = arg; | |
609 | argv[i+2] = 0; | |
610 | envp[0] = 0; | |
611 | execve(argv[0], &argv[1], envp); | |
612 | /* report failure of exec */ | |
613 | syslog(LOG_ERR, "%s: %m", argv[0]); | |
614 | closelog(); | |
615 | sleep(10); /* prevent failures from eating machine */ | |
f570e1ff | 616 | } |