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