Path: utzoo!utgpu!water!watmath!clyde!att!pacbell!lll-tis!helios.ee.lbl.gov!pasteur!ucbvax!decwrl!sun!pitstop!sundc!seismo!uunet!mcvax!hp4nl!botter!star.cs.vu.nl!ast@cs.vu.nl From: ast@cs.vu.nl (Andy Tanenbaum) Newsgroups: comp.os.minix Subject: (re)posting of tools/init.c Message-ID: <928@ast.cs.vu.nl> Date: 23 Jul 88 07:48:35 GMT Sender: ast@cs.vu.nl Reply-To: ast@cs.vu.nl (Andy Tanenbaum) Organization: VU Informatica, Amsterdam Lines: 203 /* This process is the father (mother) of all MINIX user processes. When * MINIX comes up, this is process 2. It executes the /etc/rc shell file and * then reads the /etc/ttys file to find out which terminals need a login * process. The ttys file consists of 3-character lines as follows: * abc * where * a = 0 (line disabled = no shell), 1 (enabled = shell started) * b = a-r defines UART paramers (baud, bits, parity), 0 for console * c = line number * * The letters a-r correspond to the 18 entries of the uart table below. * For example, 'a' is 110 baud, 8 bits, no parity; 'b' is 300 baud, 8 bits, * no parity; 'j' is 2400 baud, 7 bits, even parity; etc. * * If the file /usr/adm/wtmp exists and is writable, init (with help from * login) maintains login accounting used by who(1). */ #include "../h/signal.h" #include "../h/sgtty.h" #define PIDSLOTS 10 #define NPARAMSETS 18 #define STACKSIZE 256 #define DIGIT 8 #define OFFSET 5 #define SHELL 1 #define NOPARAMS -100 #define WTMPSIZE 8 struct uart { int baud; int flags; } uart[NPARAMSETS] = { B110, BITS8, /* 110 baud, 8 bits, no parity */ B300, BITS8, /* 300 baud, 8 bits, no parity */ B1200, BITS8, /* 1200 baud, 8 bits, no parity */ B2400, BITS8, /* 2400 baud, 8 bits, no parity */ B4800, BITS8, /* 4800 baud, 8 bits, no parity */ B9600, BITS8, /* 9600 baud, 8 bits, no parity */ B110, BITS7 | EVENP, /* 110 baud, 7 bits, even parity */ B300, BITS7 | EVENP, /* 300 baud, 7 bits, even parity */ B1200, BITS7 | EVENP, /* 1200 baud, 7 bits, even parity */ B2400, BITS7 | EVENP, /* 2400 baud, 7 bits, even parity */ B4800, BITS7 | EVENP, /* 4800 baud, 7 bits, even parity */ B9600, BITS7 | EVENP, /* 9600 baud, 7 bits, even parity */ B110, BITS7 | ODDP, /* 110 baud, 7 bits, odd parity */ B300, BITS7 | ODDP, /* 300 baud, 7 bits, odd parity */ B1200, BITS7 | ODDP, /* 1200 baud, 7 bits, odd parity */ B2400, BITS7 | ODDP, /* 2400 baud, 7 bits, odd parity */ B4800, BITS7 | ODDP, /* 4800 baud, 7 bits, odd parity */ B9600, BITS7 | ODDP /* 9600 baud, 7 bits, odd parity */ }; char wtmpfile[] = {"/usr/adm/wtmp"}; char name[] = {"/dev/tty?"}; /* terminal names */ int pid[PIDSLOTS]; /* pids of init's own children */ int save_params[PIDSLOTS]; int pidct; extern int errno; char stack[STACKSIZE]; char *stackpt = &stack[STACKSIZE]; char **environ; /* declaration required by library routines */ struct sgttyb args; main() { char line[10]; /* /etc/ttys lines should be 3 chars */ int rc, tty, k, status, ttynr, ct, i, params, shell; /* Carry out /etc/rc. */ sync(); /* force buffers out onto RAM disk */ /* Execute the /etc/rc file. */ if (fork()) { /* Parent just waits. */ wait(&k); } else { /* Child exec's the shell to do the work. */ if (open("/etc/rc", 0) < 0) exit(-1); open("/dev/tty0", 1); /* std output */ open("/dev/tty0", 1); /* std error */ execn("/bin/sh"); exit(-2); /* impossible */ } /* Make the /usr/adm/wtmp entry. */ wtmp("~",""); /* log system reboot */ /* Read the /etc/ttys file and fork off login processes. */ if ( (tty = open("/etc/ttys", 0)) == 0) { /* Process /etc/ttys file. */ while ( (ct = read(0, line, 4)) == 4) { /* Extract and check the 3 characters on each line. */ shell = line[0] - '0'; /* 0, 1, 2 for disabled, sh, no sh */ params = line[1] - 'a'; /* selects UART parameters */ ttynr = line[2] - '0'; /* line number */ if (shell <= 0 || shell > 1) continue; if (line[1] == '0') params = NOPARAMS; else if (params < 0 || params > NPARAMSETS) continue; if (ttynr < 0 || ttynr > PIDSLOTS) continue; save_params[ttynr] = params; startup(ttynr, params); } } else { tty = open("/dev/tty0", 1); write(tty, "Init can't open /etc/ttys\n", 26); while (1) ; /* just hang -- system cannot be started */ } close(tty); /* All the children have been forked off. Wait for someone to terminate. * Note that it might be a child, in which case a new login process must be * spawned off, or it might be somebody's orphan, in which case ignore it. * First ignore all signals. */ for (i = 1; i <= NR_SIGS; i++) signal(i, SIG_IGN); while (1) { k = wait(&status); pidct--; /* Search to see which line terminated. */ for (i = 0; i < PIDSLOTS; i++) { if (pid[i] == k) { name[DIGIT] = '0' + i; wtmp(&name[OFFSET], ""); startup(i, save_params[i]); } } } } startup(linenr, params) int linenr, params; { /* Fork off a process for the indicated line. */ int k, n; if ( (k = fork()) != 0) { /* Parent */ pid[linenr] = k; pidct++; } else { /* Child */ close(0); /* /etc/ttys may be open */ name[DIGIT] = '0' + linenr; if (open(name, 0) != 0) exit(-3); /* standard input */ if (open(name, 1) != 1) exit(-3); /* standard output */ if (open(name, 1) != 2) exit(-3); /* standard error */ /* Set line parameters. */ if (params != NOPARAMS) { n = ioctl(0, TIOCGETP, &args); /* get parameters */ args.sg_ispeed = uart[params].baud; args.sg_ospeed = uart[params].baud; args.sg_flags = CRMOD | XTABS | ECHO | uart[params].flags; n = ioctl(0, TIOCSETP, &args); } /* Try to exec login, or in an emergency, exec the shell. */ execn("/usr/bin/login"); execn("/bin/login"); execn("/bin/sh"); /* last resort, if mount of /usr failed */ execn("/usr/bin/sh"); /* last resort, if mount of /usr failed */ return; /* impossible */ } } wtmp(tty, name) { /* Make an entry in /usr/adm/wtmp. */ int i, fd; long t, time(); char ttybuff[WTMPSIZE], namebuff[WTMPSIZE]; fd = open(wtmpfile, 2); if (fd < 0) return; /* if wtmp does not exist, no accounting */ i =lseek(fd, 0L, 2); /* append to file */ for (i = 0; i < WTMPSIZE; i++) { ttybuff[i] = 0; namebuff[i] = 0; } strncpy(ttybuff, tty, 8); strncpy(namebuff, name, 8); time(&t); write(fd, ttybuff, WTMPSIZE); write(fd, namebuff, WTMPSIZE); write(fd, &t, sizeof(t)); close(fd); }