1: /*
   2:  *	init.c
   3:  */
   4: #include "whoami.h"
   5: #include <signal.h>
   6: #include <sys/types.h>
   7: #include <utmp.h>
   8: #include <setjmp.h>
   9: #ifdef  UCB_AUTOBOOT
  10: #include <sys/reboot.h>
  11: #endif
  12: #include <errno.h>
  13: #include <sys/autoconfig.h>
  14: 
  15: #define VHANGUP         /* undefine if you don't have vhangup */
  16: #define CONFIGOPTS  "-vc"
  17: 
  18: #define LINSIZ  sizeof(wtmp.ut_line)
  19: #define TABSIZ  100
  20: #define ALL p = &itab[0]; p < &itab[TABSIZ]; p++
  21: #define EVER    ;;
  22: #define SCPYN(a, b) strncpy(a, b, sizeof(a))
  23: #define SCMPN(a, b) strncmp(a, b, sizeof(a))
  24: 
  25: char    shell[] = "/bin/sh";
  26: char    getty[]  = "/etc/getty";
  27: char    minus[] = "-";
  28: char    plus[] = "+";       /* this tells getty we are in sp. sess. */
  29: char    runc[]  = "/etc/rc";
  30: char    ifile[] = "/etc/ttys";
  31: char    utmp[]  = "/etc/utmp";
  32: char    wtmpf[] = "/usr/adm/wtmp";
  33: char    ctty[]  = "/dev/console";
  34: char    dev[]   = "/dev/";
  35: char    config[]= "/etc/autoconfig";
  36: 
  37: struct utmp wtmp;
  38: struct
  39: {
  40:     char    line[LINSIZ];
  41:     char    comn;
  42:     char    flag;
  43: } line;
  44: struct  tab
  45: {
  46:     char    line[LINSIZ];
  47:     char    comn;
  48:     char    xflag;
  49:     int pid;
  50: } itab[TABSIZ];
  51: 
  52: extern  errno;
  53: 
  54: int fi;
  55: int mergflag;
  56: int multiuser;
  57: /*
  58:  *  Modes: bits in first char of /etc/ttys line
  59:  */
  60: #define NORMAL  1       /* anyone can login */
  61: #define SP_SESS 2       /* only root can login */
  62: int mode = NORMAL;
  63: 
  64: char    tty[20];
  65: jmp_buf sjbuf, shutpass;
  66: time_t  time0;
  67: 
  68: time_t  time();
  69: int reset();
  70: int idle(), sp_ss(), setmerge();
  71: char    *strcpy(), *strcat();
  72: long    lseek();
  73: 
  74: #ifdef  UCB_AUTOBOOT
  75: main(ac, av)
  76: char    **av;
  77: #else
  78: main ()
  79: #endif
  80: {
  81:     int howto, oldhowto;
  82: 
  83:     time0 = time((time_t *) 0);
  84: #ifdef  UCB_AUTOBOOT
  85:     signal(SIGQUIT, idle);
  86: 
  87:     if (ac > 1) {
  88:         howto = * ((int *) av[1]);
  89:         * ((int *) av[1]) = 0;  /* don't confuse ps with binary args */
  90:      } else
  91:         howto = RB_SINGLE;
  92:     if (autoconfig() == 0)
  93:         howto = RB_SINGLE;
  94: #else
  95:     autoconfig();
  96: #endif
  97:     setjmp(sjbuf);
  98:     signal(SIGTERM, reset);
  99:     signal(SIGINT, sp_ss);
 100:     signal(SIGHUP, setmerge);
 101:     for(EVER) {
 102:         shutdown();
 103: #ifdef  UCB_AUTOBOOT
 104:         oldhowto = howto;
 105:         howto = RB_SINGLE;
 106:         if (oldhowto & RB_SINGLE)
 107:             single();
 108:         if (runcom(oldhowto) == 0)
 109:             mode = SP_SESS;
 110: #else
 111:         single();
 112:         runcom();
 113: #endif
 114:         merge();
 115:         multiple();
 116:     }
 117: }
 118: 
 119: int shutreset();
 120: 
 121: shutdown()
 122: {
 123:     register i, f;
 124:     register struct tab *p;
 125: 
 126:     multiuser = 0;
 127:     for(ALL) {
 128:         term(p);
 129:         p->line[0] = 0;
 130:     }
 131:     close(creat(utmp, 0644));
 132:     signal(SIGALRM, shutreset);
 133:     if (setjmp(shutpass) == 0) {
 134:         alarm(30);
 135:         for(i=0; i<5; i++)
 136:             kill(-1, SIGKILL);
 137:         while(wait((int *)0) != -1)
 138:             ;
 139:         alarm(0);
 140:     }
 141:     acct(0);
 142:     signal(SIGALRM, SIG_DFL);
 143:     for(i=0; i<10; i++)
 144:         close(i);
 145:     f = open(wtmpf, 1);
 146:     if (f >= 0) {
 147:         lseek(f, 0L, 2);
 148:         SCPYN(wtmp.ut_line, "~");
 149:         SCPYN(wtmp.ut_name, "shutdown");
 150:         time(&wtmp.ut_time);
 151:         write(f, (char *)&wtmp, sizeof(wtmp));
 152:         close(f);
 153:     }
 154: }
 155: 
 156: shutreset()
 157: {
 158:     cmesg("WARNING: Something is hung (won't die); ps axl advised\n", 0, 0);
 159:     longjmp(shutpass, 1);
 160: }
 161: 
 162: single()
 163: {
 164:     register pid;
 165:     register xpid;
 166:     extern  errno;
 167: 
 168:     multiuser = 0;
 169:    do {
 170:     pid = fork();
 171:     if(pid == 0) {
 172: /*
 173: 		alarm(300);
 174: */
 175:         signal(SIGTERM, SIG_DFL);
 176:         signal(SIGHUP, SIG_DFL);
 177:         signal(SIGALRM, SIG_DFL);
 178:         open(ctty, 2);
 179:         dup(0);
 180:         dup(0);
 181:         execl(shell, minus, (char *)0);
 182:         cmesg("Init: can't exec ", shell, "\r\n");
 183:         exit(0);
 184:     }
 185:     while((xpid = wait((int *)0)) != pid)
 186:         if (xpid == -1 && errno == ECHILD)
 187:             break;
 188:    } while (xpid == -1);
 189: }
 190: 
 191: #ifdef  UCB_AUTOBOOT
 192: runcom(howto)
 193: int howto;
 194: #else
 195: runcom()
 196: #endif
 197: {
 198:     register pid, f;
 199:     int status;
 200:     char *arg1, *arg2;
 201: 
 202:     pid = fork();
 203:     if(pid == 0) {
 204:         open("/", 0);
 205:         dup(0);
 206:         dup(0);
 207: #ifdef  UCB_AUTOBOOT
 208:         if ((howto & RB_SINGLE) || (howto & RB_NOFSCK))
 209:             arg1 = "fastboot";
 210:         else
 211:             arg1 = "autoboot";
 212:         if (howto & RB_POWRFAIL)
 213:             arg2 = "powerfail";
 214:         else
 215:             arg2 = (char *)0;
 216:         execl(shell, shell, runc, arg1, arg2, (char *)0);
 217:         exit(1);
 218: #else
 219:         execl(shell, shell, runc, (char *)0);
 220:         exit(1);
 221: #endif
 222:     }
 223:     while(wait(&status) != pid)
 224:         ;
 225: #ifdef  UCB_AUTOBOOT
 226:     if(status)
 227:         return(0);
 228: #endif
 229:     f = open(wtmpf, 1);
 230:     if (f >= 0) {
 231:         lseek(f, 0L, 2);
 232:         SCPYN(wtmp.ut_line, "~");
 233:         SCPYN(wtmp.ut_name, "reboot");
 234:         if (time0) {
 235:             wtmp.ut_time = time0;
 236:             time0 = 0;
 237:         } else
 238:             time(&wtmp.ut_time);
 239:         write(f, (char *)&wtmp, sizeof(wtmp));
 240:         close(f);
 241:     }
 242:     return(1);
 243: }
 244: 
 245: setmerge()
 246: {
 247:     signal(SIGHUP, SIG_IGN);
 248:     mergflag = 1;
 249: }
 250: 
 251: multiple()
 252: {
 253:     register struct tab *p;
 254:     register pid;
 255: 
 256: loop:
 257:     multiuser = 1;
 258:     mergflag = 0;
 259:     signal(SIGHUP, setmerge);
 260:     for(EVER) {
 261:         pid = wait((int *)0);
 262:         if(mergflag) {
 263:             merge();
 264:             goto loop;
 265:         }
 266:         if(pid == -1) {
 267:             if (errno == ECHILD) {
 268:                 cmesg("Init: ", "no children left", "\r\n");
 269:                 return;
 270:             }
 271:             goto loop;
 272:         }
 273:         for(ALL)
 274:             if(p->pid == pid || p->pid == -1) {
 275: #ifdef  UCB_SUBMIT
 276:                 if (p->pid != -1)
 277:                     killbkg(p->pid, SIGKILL);
 278: #endif
 279:                 rmut(p);
 280:                 dfork(p);
 281:             }
 282:     }
 283: }
 284: 
 285: term(p)
 286: register struct tab *p;
 287: {
 288: 
 289:     if(p->pid != 0 && p->pid != -1) {
 290:         rmut(p);
 291:         kill(p->pid, SIGKILL);
 292: #ifdef  UCB_SUBMIT
 293:         killbkg(p->pid, SIGKILL);
 294: #endif
 295:     }
 296:     p->pid = 0;
 297: }
 298: 
 299: rline()
 300: {
 301:     register c, i;
 302: 
 303: loop:
 304:     c = get();
 305:     if(c < 0)
 306:         return(0);
 307:     if(c == 0)
 308:         goto loop;
 309:     line.flag = c;
 310:     c = get();
 311:     if(c <= 0)
 312:         goto loop;
 313:     line.comn = c;
 314:     SCPYN(line.line, "");
 315:     for (i=0; i<LINSIZ; i++) {
 316:         c = get();
 317:         /*
 318: 		 * If a blank, newline, or end of file, or tab,
 319: 		 * cease accumulating line name
 320: 		 */
 321:         if(c <= 0 || c == ' ' || c == '\t')
 322:             break;
 323:         line.line[i] = c;
 324:     }
 325:     while(c > 0)
 326:         c = get();
 327:     if(line.line[0] == 0)
 328:         goto loop;
 329:     if(line.flag == '0')
 330:         goto loop;
 331:     strcpy(tty, dev);
 332:     strncat(tty, line.line, LINSIZ);
 333:     if(access(tty, 06) < 0)
 334:         goto loop;
 335:     return(1);
 336: }
 337: 
 338: get()
 339: {
 340:     char b;
 341: 
 342:     if(read(fi, &b, 1) != 1)
 343:         return(-1);
 344:     if(b == '\n')
 345:         return(0);
 346:     return(b);
 347: }
 348: 
 349: #define FOUND   1
 350: #define CHANGE  2
 351: 
 352: merge()
 353: {
 354:     register struct tab *p;
 355: 
 356:     fi = open(ifile, 0);
 357:     if(fi < 0)
 358:         return;
 359:     for(ALL)
 360:         p->xflag = 0;
 361:     while(rline()) {
 362:         if ((line.flag < '1') || (line.flag > '9'))
 363:             continue;
 364:         if (((line.flag-'0') & mode) == 0)
 365:             continue;
 366:         for(ALL) {
 367:             if (SCMPN(p->line, line.line))
 368:                 continue;
 369:             p->xflag |= FOUND;
 370:             if(line.comn != p->comn) {
 371:                 p->xflag |= CHANGE;
 372:                 p->comn = line.comn;
 373:             }
 374:             goto contin1;
 375:         }
 376:         for(ALL) {
 377:             if(p->line[0] != 0)
 378:                 continue;
 379:             SCPYN(p->line, line.line);
 380:             p->xflag |= FOUND|CHANGE;
 381:             p->comn = line.comn;
 382:             goto contin1;
 383:         }
 384:     contin1:
 385:         ;
 386:     }
 387:     close(fi);
 388:     for(ALL) {
 389:         if((p->xflag&FOUND) == 0) {
 390:             term(p);
 391:             p->line[0] = 0;
 392:         }
 393:         if((p->xflag&CHANGE) != 0) {
 394:             term(p);
 395:             dfork(p);
 396:         }
 397: #ifdef  UCB_AUTOBOOT
 398:         /*
 399: 		 * If we are resuming after an idle (possibly a failed reboot)
 400: 		 * we need to restart the lines that shut down.
 401: 		 */
 402:         if (p->pid == -1)
 403:             dfork(p);
 404: #endif
 405:     }
 406: }
 407: 
 408: dfork(p)
 409: struct tab *p;
 410: {
 411:     register pid;
 412: 
 413:     pid = fork();
 414:     if(pid == 0) {
 415:         signal(SIGTERM, SIG_DFL);
 416:         signal(SIGHUP, SIG_IGN);
 417:         strcpy(tty, dev);
 418:         strncat(tty, p->line, LINSIZ);
 419:         chown(tty, 0, 0);
 420:         chmod(tty, 0622);
 421:         if (open(tty, 2) < 0) {
 422:             int repcnt = 0;
 423:             do {
 424:                 if (repcnt % 10 == 0)
 425:                     cmesg("init: ",tty,": cannot open\n\r");
 426:                 repcnt++;
 427:                 sleep(60);
 428:             } while (open(tty, 2) < 0);
 429:         }
 430: #ifdef  VHANGUP
 431:         vhangup();
 432: #endif
 433:         signal(SIGHUP, SIG_DFL);
 434:         open(tty, 2);
 435:         close(0);
 436:         dup(1);
 437:         dup(0);
 438:         tty[0] = p->comn;
 439:         tty[1] = 0;
 440:         if(mode == SP_SESS)
 441:             execl(getty, plus, tty, (char *)0);
 442:         else
 443:             execl(getty, minus, tty, (char *)0);
 444:         exit(0);
 445:     }
 446:     p->pid = pid;
 447: }
 448: 
 449: rmut(p)
 450: register struct tab *p;
 451: {
 452:     register f;
 453:     int found = 0;
 454: 
 455:     f = open(utmp, 2);
 456:     if(f >= 0) {
 457:         while(read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) {
 458:             if (SCMPN(wtmp.ut_line, p->line) || wtmp.ut_name[0]==0)
 459:                 continue;
 460:             lseek(f, -(long)sizeof(wtmp), 1);
 461:             SCPYN(wtmp.ut_name, "");
 462:             time(&wtmp.ut_time);
 463:             write(f, (char *)&wtmp, sizeof(wtmp));
 464:             found++;
 465:         }
 466:         close(f);
 467:     }
 468:     if (found) {
 469:         f = open(wtmpf, 1);
 470:         if (f >= 0) {
 471:             SCPYN(wtmp.ut_line, p->line);
 472:             SCPYN(wtmp.ut_name, "");
 473:             time(&wtmp.ut_time);
 474:             lseek(f, (long)0, 2);
 475:             write(f, (char *)&wtmp, sizeof(wtmp));
 476:             close(f);
 477:         }
 478:     }
 479: }
 480: 
 481: reset()
 482: {
 483:     longjmp(sjbuf, 1);
 484: }
 485: 
 486: /*
 487:  *  Toggle special-session mode.
 488:  *  Do a shutdown() so that getty's are reissued in the new mode.
 489:  */
 490: sp_ss()
 491: {
 492:     signal(SIGINT, SIG_IGN);
 493:     mergflag++;
 494:     shutdown();
 495:     if (mode == NORMAL)
 496:         mode = SP_SESS;
 497:     else {
 498:         /*
 499: 		 * Returning to normal operation.
 500: 		 * Run the rc file; either it hasn't been finished
 501: 		 * since we failed a filesystem check, or we shut down.
 502: 		 */
 503: #ifdef  UCB_AUTOBOOT
 504:         (void) runcom(RB_NOFSCK);
 505: #else
 506:         (void) runcom();
 507: #endif
 508:         mode = NORMAL;
 509:     }
 510:     signal(SIGINT, sp_ss);
 511: }
 512: 
 513: #ifdef  UCB_AUTOBOOT
 514: idle()
 515: {
 516:     register struct tab *p;
 517:     register pid;
 518: 
 519:     signal(SIGQUIT,idle);
 520:     for (;;) {
 521:         pid = wait((int *) 0);
 522:         if (mergflag) {
 523:             if (!multiuser)
 524:                 reset();
 525:             else
 526:                 return;
 527:         }
 528:         if (pid == -1)
 529:             pause();
 530:         else {
 531:             for (ALL)
 532:                 if (p->pid == pid) {
 533:                     rmut(p);
 534:                     p->pid = -1;
 535:                 }
 536:         }
 537:     }
 538: }
 539: #endif
 540: 
 541: cmesg(s1, s2, s3)
 542: char *s1, *s2, *s3;
 543: {
 544:     register int pid;
 545: 
 546:     pid = fork();
 547:     if (pid == 0) {
 548:         int fd = open(ctty, 2);
 549:         write(fd, s1, strlen(s1));
 550:         if (s2)
 551:             write(fd, s2, strlen(s2));
 552:         if (s3)
 553:             write(fd, s3, strlen(s3));
 554:         close(fd);
 555:         exit(0);
 556:     }
 557:     while (wait((int *)0) != pid)
 558:         ;
 559: }
 560: 
 561: autoconfig()
 562: {
 563:     int pid, status;
 564: 
 565:     cmesg("\r\nCONFIGURE SYSTEM:\n", 0, 0);
 566:     if ((pid = fork()) == 0) {
 567:         open(ctty, 2);
 568:         dup(0);
 569:         dup(0);
 570:         execl(config, "autoconfig", CONFIGOPTS, 0);
 571:         printf("Couldn't exec %s\n", config);
 572:         exit(AC_SETUP);
 573:     }
 574:     while (wait(&status) != pid)
 575:         ;
 576:     if ((status & 0377) == 0)
 577:         status >>= 8;
 578:     else
 579:         status = AC_SINGLE;
 580:     switch (status) {
 581:         case AC_SETUP:
 582:             cmesg("Configuration setup error\n", 0, 0);
 583:             return 0;
 584:         case AC_SINGLE:
 585:             cmesg("SERIOUS CONFIGURATION ERROR\n", 0, 0);
 586:             return 0;
 587:         case AC_OK:
 588:             return 1;
 589:         default:
 590:             cmesg("Unrecognized return from configure\n", 0, 0);
 591:             return 0;
 592:     }
 593: }

Defined functions

autoconfig defined in line 561; used 2 times
cmesg defined in line 541; used 8 times
dfork defined in line 408; used 3 times
get defined in line 338; used 4 times
idle defined in line 514; used 3 times
main defined in line 78; never used
merge defined in line 352; used 2 times
multiple defined in line 251; used 1 times
reset defined in line 481; used 3 times
rline defined in line 299; used 1 times
rmut defined in line 449; used 3 times
runcom defined in line 195; used 4 times
setmerge defined in line 245; used 3 times
shutdown defined in line 121; used 2 times
shutreset defined in line 156; used 2 times
single defined in line 162; used 2 times
sp_ss defined in line 490; used 3 times
term defined in line 285; used 3 times

Defined variables

config defined in line 35; used 2 times
ctty defined in line 33; used 3 times
dev defined in line 34; used 2 times
fi defined in line 54; used 4 times
getty defined in line 26; used 2 times
ifile defined in line 30; used 1 times
itab defined in line 50; used 2 times
  • in line 20(2)
mergflag defined in line 55; used 5 times
minus defined in line 27; used 2 times
mode defined in line 62; used 6 times
multiuser defined in line 56; used 4 times
plus defined in line 28; used 1 times
runc defined in line 29; used 2 times
shell defined in line 25; used 6 times
shutpass defined in line 65; used 2 times
sjbuf defined in line 65; used 2 times
time0 defined in line 66; used 4 times
tty defined in line 64; used 15 times
utmp defined in line 31; used 2 times
wtmp defined in line 37; used 27 times
wtmpf defined in line 32; used 3 times

Defined struct's

tab defined in line 44; used 14 times

Defined macros

ALL defined in line 20; used 7 times
CHANGE defined in line 350; used 3 times
CONFIGOPTS defined in line 16; used 1 times
EVER defined in line 21; used 2 times
FOUND defined in line 349; used 3 times
LINSIZ defined in line 18; used 5 times
NORMAL defined in line 60; used 3 times
SCMPN defined in line 23; used 2 times
SCPYN defined in line 22; used 9 times
SP_SESS defined in line 61; used 3 times
TABSIZ defined in line 19; used 2 times
VHANGUP defined in line 15; used 1 times
Last modified: 1983-05-18
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1752
Valid CSS Valid XHTML 1.0 Strict