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