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