1 static char *sccsid = "@(#)init.c 4.10 (Berkeley) 12/22/82"; 2 #include <signal.h> 3 #include <sys/types.h> 4 #include <utmp.h> 5 #include <setjmp.h> 6 #include <sys/reboot.h> 7 #include <errno.h> 8 9 #define LINSIZ sizeof(wtmp.ut_line) 10 #define TABSIZ 100 11 #define ALL p = &itab[0]; p < &itab[TABSIZ]; p++ 12 #define EVER ;; 13 #define SCPYN(a, b) strncpy(a, b, sizeof(a)) 14 #define SCMPN(a, b) strncmp(a, b, sizeof(a)) 15 16 char shell[] = "/bin/sh"; 17 char getty[] = "/etc/getty"; 18 char minus[] = "-"; 19 char runc[] = "/etc/rc"; 20 char ifile[] = "/etc/ttys"; 21 char utmp[] = "/etc/utmp"; 22 char wtmpf[] = "/usr/adm/wtmp"; 23 char ctty[] = "/dev/console"; 24 char dev[] = "/dev/"; 25 26 struct utmp wtmp; 27 struct 28 { 29 char line[LINSIZ]; 30 char comn; 31 char flag; 32 } line; 33 struct tab 34 { 35 char line[LINSIZ]; 36 char comn; 37 char xflag; 38 int pid; 39 time_t gettytime; 40 int gettycnt; 41 } itab[TABSIZ]; 42 43 int fi; 44 int mergflag; 45 char tty[20]; 46 jmp_buf sjbuf, shutpass; 47 time_t time0; 48 49 int reset(); 50 int idle(); 51 char *strcpy(), *strcat(); 52 long lseek(); 53 54 #ifndef sun 55 main() 56 { 57 register int r11; /* passed thru from boot */ 58 #else sun 59 main(argc, argv) 60 char **argv; 61 { 62 #endif sun 63 int howto, oldhowto; 64 65 time0 = time(0); 66 #ifndef sun 67 howto = r11; 68 #else sun 69 if (argc > 1 && argv[1][0] == '-') { 70 char *cp; 71 72 howto = 0; 73 cp = &argv[1][1]; 74 while (*cp) switch (*cp++) { 75 case 'a': 76 howto |= RB_ASKNAME; 77 break; 78 case 's': 79 howto |= RB_SINGLE; 80 break; 81 } 82 } else { 83 howto = RB_SINGLE; 84 } 85 #endif sun 86 setjmp(sjbuf); 87 signal(SIGTERM, reset); 88 signal(SIGTSTP, idle); 89 signal(SIGSTOP, SIG_IGN); 90 signal(SIGTTIN, SIG_IGN); 91 signal(SIGTTOU, SIG_IGN); 92 for(EVER) { 93 oldhowto = howto; 94 howto = RB_SINGLE; 95 if (setjmp(shutpass) == 0) 96 shutdown(); 97 if (oldhowto & RB_SINGLE) 98 single(); 99 if (runcom(oldhowto) == 0) 100 continue; 101 merge(); 102 multiple(); 103 } 104 } 105 106 int shutreset(); 107 108 shutdown() 109 { 110 register i; 111 register struct tab *p; 112 113 close(creat(utmp, 0644)); 114 signal(SIGHUP, SIG_IGN); 115 for(ALL) { 116 term(p); 117 p->line[0] = 0; 118 } 119 signal(SIGALRM, shutreset); 120 alarm(30); 121 for(i=0; i<5; i++) 122 kill(-1, SIGKILL); 123 while(wait((int *)0) != -1) 124 ; 125 alarm(0); 126 shutend(); 127 } 128 129 char shutfailm[] = "WARNING: Something is hung (wont die); ps axl advised\n"; 130 131 shutreset() 132 { 133 int status; 134 135 if (fork() == 0) { 136 int ct = open(ctty, 1); 137 write(ct, shutfailm, sizeof (shutfailm)); 138 sleep(5); 139 exit(1); 140 } 141 sleep(5); 142 shutend(); 143 longjmp(shutpass, 1); 144 } 145 146 shutend() 147 { 148 register i, f; 149 150 acct(0); 151 signal(SIGALRM, SIG_DFL); 152 for(i=0; i<10; i++) 153 close(i); 154 f = open(wtmpf, 1); 155 if (f >= 0) { 156 lseek(f, 0L, 2); 157 SCPYN(wtmp.ut_line, "~"); 158 SCPYN(wtmp.ut_name, "shutdown"); 159 time(&wtmp.ut_time); 160 write(f, (char *)&wtmp, sizeof(wtmp)); 161 close(f); 162 } 163 return(1); 164 } 165 166 single() 167 { 168 register pid; 169 register xpid; 170 extern errno; 171 172 do { 173 pid = fork(); 174 if(pid == 0) { 175 /* 176 alarm(300); 177 */ 178 signal(SIGTERM, SIG_DFL); 179 signal(SIGHUP, SIG_DFL); 180 signal(SIGALRM, SIG_DFL); 181 open(ctty, 2); 182 dup(0); 183 dup(0); 184 execl(shell, minus, (char *)0); 185 exit(0); 186 } 187 while((xpid = wait((int *)0)) != pid) 188 if (xpid == -1 && errno == ECHILD) 189 break; 190 } while (xpid == -1); 191 } 192 193 runcom(oldhowto) 194 int oldhowto; 195 { 196 register pid, f; 197 int status; 198 199 pid = fork(); 200 if(pid == 0) { 201 open("/", 0); 202 dup(0); 203 dup(0); 204 if (oldhowto & RB_SINGLE) 205 execl(shell, shell, runc, (char *)0); 206 else 207 execl(shell, shell, runc, "autoboot", (char *)0); 208 exit(1); 209 } 210 while(wait(&status) != pid) 211 ; 212 if(status) 213 return(0); 214 f = open(wtmpf, 1); 215 if (f >= 0) { 216 lseek(f, 0L, 2); 217 SCPYN(wtmp.ut_line, "~"); 218 SCPYN(wtmp.ut_name, "reboot"); 219 if (time0) { 220 wtmp.ut_time = time0; 221 time0 = 0; 222 } else 223 time(&wtmp.ut_time); 224 write(f, (char *)&wtmp, sizeof(wtmp)); 225 close(f); 226 } 227 return(1); 228 } 229 230 setmerge() 231 { 232 233 signal(SIGHUP, setmerge); 234 mergflag = 1; 235 } 236 237 multiple() 238 { 239 register struct tab *p; 240 register pid; 241 242 loop: 243 mergflag = 0; 244 signal(SIGHUP, setmerge); 245 for(EVER) { 246 pid = wait((int *)0); 247 if(mergflag) { 248 merge(); 249 goto loop; 250 } 251 if(pid == -1) 252 return; 253 for(ALL) 254 if(p->pid == pid || p->pid == -1) { 255 rmut(p); 256 dfork(p); 257 } 258 } 259 } 260 261 term(p) 262 register struct tab *p; 263 { 264 265 if(p->pid != 0) { 266 rmut(p); 267 kill(p->pid, SIGKILL); 268 } 269 p->pid = 0; 270 } 271 272 rline() 273 { 274 register c, i; 275 276 loop: 277 c = get(); 278 if(c < 0) 279 return(0); 280 if(c == 0) 281 goto loop; 282 line.flag = c; 283 c = get(); 284 if(c <= 0) 285 goto loop; 286 line.comn = c; 287 SCPYN(line.line, ""); 288 for (i=0; i<LINSIZ; i++) { 289 c = get(); 290 if(c <= 0) 291 break; 292 line.line[i] = c; 293 } 294 while(c > 0) 295 c = get(); 296 if(line.line[0] == 0) 297 goto loop; 298 if(line.flag == '0') 299 goto loop; 300 strcpy(tty, dev); 301 strncat(tty, line.line, LINSIZ); 302 if(access(tty, 06) < 0) 303 goto loop; 304 return(1); 305 } 306 307 get() 308 { 309 char b; 310 311 if(read(fi, &b, 1) != 1) 312 return(-1); 313 if(b == '\n') 314 return(0); 315 return(b); 316 } 317 318 #define FOUND 1 319 #define CHANGE 2 320 321 merge() 322 { 323 register struct tab *p; 324 325 fi = open(ifile, 0); 326 if(fi < 0) 327 return; 328 for(ALL) 329 p->xflag = 0; 330 while(rline()) { 331 for(ALL) { 332 if (SCMPN(p->line, line.line)) 333 continue; 334 p->xflag |= FOUND; 335 if(line.comn != p->comn) { 336 p->xflag |= CHANGE; 337 p->comn = line.comn; 338 } 339 goto contin1; 340 } 341 for(ALL) { 342 if(p->line[0] != 0) 343 continue; 344 SCPYN(p->line, line.line); 345 p->xflag |= FOUND|CHANGE; 346 p->comn = line.comn; 347 goto contin1; 348 } 349 contin1: 350 ; 351 } 352 close(fi); 353 for(ALL) { 354 if((p->xflag&FOUND) == 0) { 355 term(p); 356 p->line[0] = 0; 357 } 358 if((p->xflag&CHANGE) != 0) { 359 term(p); 360 dfork(p); 361 } 362 } 363 } 364 365 #include <sys/ioctl.h> 366 367 dfork(p) 368 struct tab *p; 369 { 370 register pid; 371 time_t t; 372 int dowait = 0; 373 extern char *sys_errlist[]; 374 375 time(&t); 376 p->gettycnt++; 377 if ((t - p->gettytime) >= 60) { 378 p->gettytime = t; 379 p->gettycnt = 1; 380 } else { 381 if (p->gettycnt >= 5) { 382 dowait = 1; 383 p->gettytime = t; 384 p->gettycnt = 1; 385 } 386 } 387 pid = fork(); 388 if(pid == 0) { 389 int oerrno, f; 390 extern int errno; 391 392 signal(SIGTERM, SIG_DFL); 393 signal(SIGHUP, SIG_IGN); 394 strcpy(tty, dev); 395 strncat(tty, p->line, LINSIZ); 396 if (dowait) { 397 f = open("/dev/console", 1); 398 write(f, "init: ", 6); 399 write(f, tty, strlen(tty)); 400 write(f, ": getty failing, sleeping\n\r", 27); 401 close(f); 402 sleep(30); 403 if ((f = open("/dev/tty", 2)) >= 0) { 404 ioctl(f, TIOCNOTTY, 0); 405 close(f); 406 } 407 } 408 chown(tty, 0, 0); 409 chmod(tty, 0622); 410 if (open(tty, 2) < 0) { 411 int repcnt = 0; 412 do { 413 oerrno = errno; 414 if (repcnt % 10 == 0) { 415 f = open("/dev/console", 1); 416 write(f, "init: ", 6); 417 write(f, tty, strlen(tty)); 418 write(f, ": ", 2); 419 write(f, sys_errlist[oerrno], 420 strlen(sys_errlist[oerrno])); 421 write(f, "\n", 1); 422 close(f); 423 if ((f = open("/dev/tty", 2)) >= 0) { 424 ioctl(f, TIOCNOTTY, 0); 425 close(f); 426 } 427 } 428 repcnt++; 429 sleep(60); 430 } while (open(tty, 2) < 0); 431 exit(0); /* have wrong control tty, start over */ 432 } 433 vhangup(); 434 signal(SIGHUP, SIG_DFL); 435 open(tty, 2); 436 close(0); 437 dup(1); 438 dup(0); 439 tty[0] = p->comn; 440 tty[1] = 0; 441 execl(getty, minus, tty, (char *)0); 442 exit(0); 443 } 444 p->pid = pid; 445 } 446 447 rmut(p) 448 register struct tab *p; 449 { 450 register f; 451 int found = 0; 452 453 f = open(utmp, 2); 454 if(f >= 0) { 455 while(read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) { 456 if (SCMPN(wtmp.ut_line, p->line) || wtmp.ut_name[0]==0) 457 continue; 458 lseek(f, -(long)sizeof(wtmp), 1); 459 SCPYN(wtmp.ut_name, ""); 460 time(&wtmp.ut_time); 461 write(f, (char *)&wtmp, sizeof(wtmp)); 462 found++; 463 } 464 close(f); 465 } 466 if (found) { 467 f = open(wtmpf, 1); 468 if (f >= 0) { 469 SCPYN(wtmp.ut_line, p->line); 470 SCPYN(wtmp.ut_name, ""); 471 time(&wtmp.ut_time); 472 lseek(f, (long)0, 2); 473 write(f, (char *)&wtmp, sizeof(wtmp)); 474 close(f); 475 } 476 } 477 } 478 479 reset() 480 { 481 longjmp(sjbuf, 1); 482 } 483 484 idle() 485 { 486 register struct tab *p; 487 register pid; 488 489 signal(SIGTSTP, idle); 490 for (;;) { 491 pid = wait((int *) 0); 492 if (mergflag) 493 return; 494 if (pid == -1) 495 pause(); 496 else { 497 for (ALL) 498 if (p->pid == pid) { 499 rmut(p); 500 p->pid = -1; 501 } 502 } 503 } 504 } 505