Init - SCO Xenix System V replacement
John F. Haugh II
jfh at rpp386.Dallas.TX.US
Thu Mar 23 00:28:06 AEST 1989
This is the beta test release of the init I've been munging on.
It is currently being used on this site with some results. It
is not complete and does not contain a telinit. You have to
send it various signals to get things to happen ...
So far it seems to work.
Caveats -
- no telinit yet
- still flaky as a pie crust
- only tested on Xenix/386 2.2.1
- syscon and systty aren't implemented yet
Debugging an init is EXTREMELY troublesome. If you are unable
to reboot frequently and from a floppy, I would not suggest
getting involved just yet. This init is easier to debug in a
production setting than the real McCoy as this version can be
restarted without rebooting the system. Nice trick.
How to use this beasty -
Create your /etc/inittab just like normal. You need to have
some experience with inittabs. Here is mine as a starter:
--
id:S:initdefault:
rc:Ss2:wait:/etc/rc < /dev/console > /dev/console 2>&1
co:Ss:wait:/bin/su - root < /dev/console > /dev/console 2>&1
01:2:respawn:/etc/getty tty01 m # Screen 1
02:2:respawn:/etc/getty tty02 m # Screen 2
03:2:respawn:/etc/getty tty03 m # Screen 3
d1:2:respawn:/etc/getty tty1A v # Anchor Automation Modem
d2:2:respawn:/etc/getty tty2A v # Everex Modem
--
Create a new /etc/rc file. The old one is probably kinda
useless if you are running SCO Xenix. It doesn't know about
being called in single user mode.
Save your old init someplace handy and make and install
this version.
Reboot. You will now be in single user mode.
To change run levels, signal init with SIGUSR1 [ signal
16 ] and you will be prompted on the console for a new
run level. Enter the new runlevel at the prompt.
To restart init, signal init with SIGUSR2 [ signal 17 ]
and init will kill all active processes and re-exec
itself. This is very useful for replacing init without
rebooting.
To re-read the inittab, send init a signal 1, 2, or 3.
You might want to read the config.h file. There are only
a few options at this stage of the game.
If you aren't completely frightened, or REALLY DESPARATELY
need a real init, complete with source code, unwrap this
sucker and get on with the show ...
WARNING - SCREWING WITH INIT CAN GET YOUR MACHINE REAL
UNUSABLE REAL FAST. ALWAYS ALWAYS ALWAYS make plenty of
backups and sacrifice virgins to the computer gods before
screwing with this. Don't say I didn't warn you.
THIS POSTING COPYRIGHT, 1989, JOHN F. HAUGH II
ALL RIGHTS RESERVED.
Use and redistribution in a USENET-like manner permitted,
all other uses prohibited.
--
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
# Makefile
# error.c
# getlevel.c
# main.c
# process.c
# startup.c
# inittab.c
# spawn.c
# config.h
# inittab.h
# patchlevel.h
# This archive created: Wed Mar 22 08:07:05 1989
# By: John F. Haugh II (River Parishes Programming, Dallas TX)
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'Makefile'
then
echo shar: "will not over-write existing file 'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
#
# %Z%Init - System V compatible init
#
# %W% %U% %G%
#
SHELL = /bin/sh
CFLAGS = -O -M3 -g
SRCS = error.c getlevel.c main.c process.c startup.c inittab.c spawn.c
HDRS = config.h inittab.h patchlevel.h
OBJS = error.o getlevel.o main.o process.o startup.o inittab.o spawn.o
FILES = Makefile $(SRCS) $(HDRS)
init: $(OBJS)
cc -o init -g $(OBJS)
error.o: config.h
getlevel.o: inittab.h config.h
inittab.o: inittab.h config.h
main.o: inittab.h config.h
process.o: inittab.h config.h
spawn.o: inittab.h
startup.o: inittab.h config.h
shar: $(FILES)
shar $(FILES) > init.shar
clean:
rm -f *.o core
clobber: clean
rm -f init
SHAR_EOF
fi
if test -f 'error.c'
then
echo shar: "will not over-write existing file 'error.c'"
else
cat << \SHAR_EOF > 'error.c'
#include <fcntl.h>
#include <stdio.h>
#include "config.h"
#ifndef lint
static char _sccsid[] = "@(#)error.c 1.1 07:58:04 3/22/89";
#endif
extern int proc1;
extern int consolefd;
error (s)
char *s;
{
char buf[BUFSIZ];
sprintf (buf, "ERROR: %s\r\n", s);
#ifdef DEBUG
fputs (buf, stderr);
#else
if (proc1) {
if (fork () == 0) {
proc1 = 0;
consolefd = open (CONSOLE, O_RDWR|O_NDELAY);
write (consolefd, buf, strlen (buf));
_exit (0);
}
} else {
write (consolefd, buf, strlen (buf));
_exit (0);
}
#endif
}
msg (s)
char *s;
{
char buf[BUFSIZ];
sprintf (buf, "%s\r\n", s);
#ifdef DEBUG
fputs (buf, stderr);
#else
if (proc1) {
if (fork () == 0) {
proc1 = 0;
consolefd = open (CONSOLE, O_RDWR|O_NDELAY);
write (consolefd, buf, strlen (buf));
_exit (0);
}
} else {
write (consolefd, buf, strlen (buf));
_exit (0);
}
#endif
}
SHAR_EOF
fi
if test -f 'getlevel.c'
then
echo shar: "will not over-write existing file 'getlevel.c'"
else
cat << \SHAR_EOF > 'getlevel.c'
#include <stdio.h>
#include <fcntl.h>
#include <termio.h>
#include <signal.h>
#include "inittab.h"
#include "config.h"
#ifndef lint
static char _sccsid[] = "@(#)getlevel.c 1.1 07:58:04 3/22/89";
#endif
extern int proc1;
extern int consolefd;
extern int nproc;
extern struct inittab *proc;
/*
* getlevel - return new run level
*/
int getlevel ()
{
char buf[16];
int fd;
int status;
int pid;
int child;
int i;
struct termio termio;
for (i = 0;i < nproc;i++) {
if (proc[i].ini_pid > 1) {
kill (- proc[i].ini_pid, SIGKILL);
waitfor (&proc[i]);
}
}
kill (0, SIGKILL);
switch (child = fork ()) {
default: /* still proc1 ... */
while ((pid = wait (&status)) != child
&& pid != -1)
;
if ((status & 0377) != 0) {
error ("Can't get run-level, using S");
return ('S');
}
break;
case -1: /* couldn't fork */
error ("Can't get run-level, using S");
return ('S');
case 0: /* child process */
proc1 = 0;
if ((fd = open (CONSOLE, O_RDWR|O_NDELAY)) < 0)
_exit (0); /* assume 'S' ... */
#ifndef DEBUG
ioctl (fd, TCGETA, &termio);
termio.c_iflag = (ISTRIP|ICRNL|IXON);
termio.c_oflag = (OPOST|ONLCR);
termio.c_cflag &= CBAUD;
termio.c_cflag |= (CREAD|HUPCL);
termio.c_lflag = (ISIG|ICANON|ECHO|ECHOE|ECHOK);
ioctl (fd, TCSETA, &termio);
#endif
fcntl (fd, F_SETFL,
fcntl (fd, F_GETFL, 0) & ~O_NDELAY);
consolefd = fd;
do {
write (fd, "Enter run-level [Ss0123456]: ", 29);
i = read (fd, buf, sizeof buf);
if (i >= 0)
buf[i] = '\0';
} while (! (buf[0] == 's' || buf[0] == 'S'
|| (buf[0] >= '0' && buf[0] <= '6')));
if (buf[0] == 'S' || buf[0] == '0')
_exit (0);
else if (buf[0] == 's')
_exit (1);
else
_exit (buf[0] - '0' + 1);
}
status = (status >> 8) & 07;
return ("Ss123456"[status]);
}
SHAR_EOF
fi
if test -f 'main.c'
then
echo shar: "will not over-write existing file 'main.c'"
else
cat << \SHAR_EOF > 'main.c'
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <utmp.h>
#include <string.h>
#include "config.h"
#include "inittab.h"
#ifndef lint
static char _sccsid[] = "@(#)main.c 1.1 07:58:07 3/22/89";
#endif
char intrflag;
int proc1;
int runlevel;
int prevlevel;
int runcnt[8];
int consolefd;
int wtmpfd;
int nproc;
struct inittab *proc;
reinit ()
{
int i;
msg ("Reloading INIT");
#ifndef DEBUG
kill (-1, SIGKILL);
#endif
#ifdef DEBUG
execl ("./init", "init", "proc1", (char *) 0);
#else
execl ("/etc/init", "/etc/init", (char *) 0);
#endif
}
main (argc, argv)
int argc;
char **argv;
{
int newlevel;
char buf[BUFSIZ];
#ifdef DEBUG
if (proc1 = (argc > 1 && strcmp (argv[1], "proc1") == 0)) {
argv[1] = argv[0];
argc--;
argv++;
}
#else
proc1 = getpid () == 1;
#endif
if (proc1)
startup ();
while (1) {
process (runlevel);
newlevel = getlevel ();
if (newlevel != runlevel)
sprintf (buf, "INIT: New run-level: %c", newlevel);
else
sprintf (buf, "INIT: Run-level: %c", newlevel);
msg (buf);
runlevel = newlevel;
}
}
SHAR_EOF
fi
if test -f 'process.c'
then
echo shar: "will not over-write existing file 'process.c'"
else
cat << \SHAR_EOF > 'process.c'
#include <signal.h>
#include <sys/types.h>
#include <utmp.h>
#include <fcntl.h>
#include "config.h"
#include "inittab.h"
#ifndef lint
static char _sccsid[] = "@(#)process.c 1.1 07:58:08 3/22/89";
#endif
extern char intrflag;
extern int nproc;
extern int prevlevel;
extern int runlevel;
extern int runcnt[];
extern int wtmpfd;
extern struct inittab *proc;
/*
* process - perform entries specified in inittab
*
* perform respawn, wait, and once commands.
*/
process ()
{
int i;
int utmpfd;
int count;
struct inittab *ip;
struct utmp utmp;
struct utmp utent;
if (runlevel == 'S')
i = runcnt[0]++;
else if (runlevel == 's')
i = runcnt[1]++;
else
i = runcnt[runlevel - '0' + 1]++;
#ifdef DEBUG
utmpfd = -1;
#else
utmpfd = open ("/etc/utmp", O_RDWR|O_CREAT, 0644);
#endif
memset ((char *) &utmp, 0, sizeof utmp);
sprintf (utmp.ut_line, RUNLVL_MSG, runlevel);
utmp.ut_type = RUN_LVL;
utmp.ut_pid = i;
utmp.ut_exit.e_termination = runlevel;
utmp.ut_exit.e_exit = prevlevel;
utmp.ut_time = time ((time_t *) 0);
prevlevel = runlevel;
intrflag = 0;
if (utmpfd >= 0) {
while (read (utmpfd, &utent, sizeof utent) == sizeof utent)
if (utent.ut_type == RUN_LVL)
break;
if (utent.ut_type == RUN_LVL)
lseek (utmpfd, (off_t) - sizeof utent, 1);
write (utmpfd, &utmp, sizeof utmp);
close (utmpfd);
utmpfd = -1;
}
if (wtmpfd >= 0)
write (wtmpfd, &utmp, sizeof utmp);
again:
inittab (runlevel);
#ifdef DEBUG
prtab ();
#endif
for (count = 0, ip = proc;ip != &proc[nproc];ip++) {
if (ip->ini_pid && kill (ip->ini_pid, 0) != 0)
waitfor (ip);
if (! (ip->ini_pid && kill (ip->ini_pid, 0) == 0)) {
switch (ip->ini_action) {
case INIT_RESPAWN:
spawn (ip);
count++;
break;
case INIT_WAIT:
if (intrflag == 0)
spawn (ip);
count++;
break;
case INIT_ONCE:
if (ip->ini_count == 0)
spawn (ip);
count++;
break;
}
}
}
intrflag = 0;
if (count)
waitfor ((struct inittab *) 0);
if (intrflag && intrflag != SIGUSR1)
goto again;
}
SHAR_EOF
fi
if test -f 'startup.c'
then
echo shar: "will not over-write existing file 'startup.c'"
else
cat << \SHAR_EOF > 'startup.c'
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include <utmp.h>
#include "config.h"
#include "inittab.h"
extern void reread ();
extern void reinit ();
extern char intrflag;
extern int runlevel;
extern int prevlevel;
extern int nproc;
extern int wtmpfd;
extern struct inittab *proc;
#ifndef lint
static char _sccsid[] = "@(#)startup.c 1.1 07:58:09 3/22/89";
#endif
/*
* startup - set up the initial state
*/
void startup ()
{
int i;
int fd;
int utmpfd;
struct utmp utent;
struct utmp utmp;
wtmpfd = open ("/etc/wtmp", O_RDWR|O_APPEND|O_CREAT, 0644);
#ifdef DEBUG
utmpfd = -1;
#else
utmpfd = open ("/etc/utmp", O_RDWR|O_CREAT|O_TRUNC, 0644);
#endif
memset (utmp, sizeof utmp, 0);
strcpy (utmp.ut_line, BOOT_MSG);
utmp.ut_type = BOOT_TIME;
utmp.ut_time = time ((time_t *) 0);
if (utmpfd >= 0) {
while (read (utmpfd, &utent, sizeof utent) == sizeof utent)
if (utent.ut_type == BOOT_TIME)
break;
if (utent.ut_type == BOOT_TIME)
lseek (utmpfd, (off_t) - sizeof utent, 1);
write (utmpfd, &utmp, sizeof utmp);
}
if (wtmpfd >= 0)
write (wtmpfd, &utmp, sizeof utmp);
#ifndef DEBUG
for (i = 1;i < NSIG;i++)
signal (i, SIG_IGN);
#endif
signal (SIGHUP, reread);
signal (SIGINT, reread);
signal (SIGQUIT, reread);
signal (SIGUSR1, reread);
signal (SIGUSR2, reinit);
signal (SIGCLD, SIG_DFL);
inittab (-1);
#ifdef DEBUG
printf ("INIT: BOOT\n");
prtab ();
#endif
/*
* certain entries must be executed first. initdefault is
* the first one of them. if there is no initdefault entry,
* we assume 'S' for the initial run level.
*/
for (i = 0;i < nproc && ! runlevel;i++) /* scan for initdefault */
if (proc[i].ini_action == INIT_INITDEFAULT)
runlevel = proc[i].ini_levels[0];
if (! runlevel)
runlevel = 'S';
prevlevel = runlevel;
memset (utmp, sizeof utmp, 0);
sprintf (utmp.ut_line, RUNLVL_MSG, runlevel);
utmp.ut_type = RUN_LVL;
utmp.ut_pid = 0;
utmp.ut_exit.e_termination = utmp.ut_exit.e_exit = runlevel;
utmp.ut_time = time ((time_t *) 0);
if (utmpfd >= 0) {
while (read (utmpfd, &utent, sizeof utent) == sizeof utent)
if (utent.ut_type == RUN_LVL)
break;
if (utent.ut_type == RUN_LVL)
lseek (utmpfd, (off_t) - sizeof utent, 1);
write (utmpfd, &utmp, sizeof utmp);
}
if (wtmpfd >= 0)
write (wtmpfd, &utmp, sizeof utmp);
/*
* next we must exec all `sysinit' commands ...
*/
for (i = 0;i < nproc;i++) /* scan for sysinit */
if (proc[i].ini_action == INIT_SYSINIT)
spawn (&proc[i]);
/*
* now we execute the `boot time only' commands ...
*/
for (i = 0;i < nproc;i++)
if (proc[i].ini_action == INIT_BOOT
|| proc[i].ini_action == INIT_BOOTWAIT)
spawn (&proc[i]);
close (utmpfd);
}
SHAR_EOF
fi
if test -f 'inittab.c'
then
echo shar: "will not over-write existing file 'inittab.c'"
else
cat << \SHAR_EOF > 'inittab.c'
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include "inittab.h"
#include "config.h"
#ifndef lint
static char _sccsid[] = "@(#)inittab.c 1.1 07:58:06 3/22/89";
#endif
char *actions[] = {
"respawn",
"wait",
"once",
"boot",
"bootwait",
"powerfail",
"powerwait",
"off",
"ondemand",
"initdefault",
"sysinit"
};
struct inittab initdefault = {
"default",
"Ss123456",
INIT_ONCE,
"/etc/sulogin",
0
};
extern struct inittab *proc;
extern int nproc;
extern char intrflag;
extern char *malloc ();
extern char *realloc ();
struct inittab *getinit (fp, entry)
FILE *fp;
struct inittab *entry;
{
char *cp;
char buf[BUFSIZ];
char id[16];
char levels[16];
char actions[16];
char command[BUFSIZ];
while (fgets (buf, BUFSIZ, fp) != (char *) 0) {
if (buf[0] == '#')
continue;
if (cp = strtok (buf, ":"))
strcpy (id, cp);
else
continue;
if (cp = strtok ((char *) 0, ":"))
strcpy (levels, cp);
else
continue;
if (cp = strtok ((char *) 0, ":"))
strcpy (actions, cp);
else
continue;
if (cp = strtok ((char *) 0, ":"))
strcpy (command, cp);
else
continue;
if (cp = strchr (command, '\n'))
*cp = '\0';
if (strcmp (actions, "respawn") == 0)
entry->ini_action = INIT_RESPAWN;
else if (strcmp (actions, "wait") == 0)
entry->ini_action = INIT_WAIT;
else if (strcmp (actions, "once") == 0)
entry->ini_action = INIT_ONCE;
else if (strcmp (actions, "boot") == 0)
entry->ini_action = INIT_BOOT;
else if (strcmp (actions, "bootwait") == 0)
entry->ini_action = INIT_BOOTWAIT;
else if (strcmp (actions, "off") == 0)
entry->ini_action = INIT_OFF;
else if (strcmp (actions, "ondemand") == 0)
entry->ini_action = INIT_ONDEMAND;
else if (strcmp (actions, "initdefault") == 0)
entry->ini_action = INIT_INITDEFAULT;
else if (strcmp (actions, "sysinit") == 0)
entry->ini_action = INIT_SYSINIT;
else
continue;
entry->ini_id = strdup (id);
entry->ini_levels = strdup (levels);
entry->ini_command = strdup (command);
return (entry);
}
return ((struct inittab *) 0);
}
freeinit (entry)
struct inittab *entry;
{
free (entry->ini_id);
free (entry->ini_levels);
free (entry->ini_command);
}
struct inittab *findinit (id, table, entries)
char *id;
struct inittab *table;
int entries;
{
while (--entries >= 0) {
if (strcmp (id, table->ini_id) == 0)
return (table);
else
table++;
}
return ((struct inittab *) 0);
}
/*
* inittab - read the inittab
*/
inittab (runlevel)
int runlevel;
{
FILE *fp;
int i, j;
struct inittab it;
struct inittab *ip;
struct inittab *newproc;
int newprocs;
int kills;
if ((fp = fopen (INITTAB, "r")) == (FILE *) 0) {
nproc = 1;
proc = (struct inittab *) malloc (sizeof it);
proc[0] = initdefault;
return;
}
newprocs = 0;
if (runlevel != -1) {
for (kills = i = 0;i < nproc;i++) {
if (proc[i].ini_pid == 0)
continue;
if (strchr (proc[i].ini_levels, runlevel))
continue;
kill (proc[i].ini_pid, SIGTERM);
kills++;
}
if (kills)
sleep (10);
for (i = 0;i < nproc;i++) {
if (proc[i].ini_pid == 0)
continue;
if (strchr (proc[i].ini_levels, runlevel))
continue;
kill (proc[i].ini_pid, SIGKILL);
waitfor (&proc[i]);
}
}
while (getinit (fp, &it)) {
if (runlevel != -1
&& (it.ini_action == INIT_BOOT
|| it.ini_action == INIT_BOOTWAIT
|| it.ini_action == INIT_INITDEFAULT
|| it.ini_action == INIT_SYSINIT
|| ! strchr (it.ini_levels, runlevel))) {
freeinit (&it);
continue;
}
if (newprocs == 0)
newproc = (struct inittab *) malloc (sizeof it);
else
newproc = (struct inittab *) realloc (newproc, sizeof it * (newprocs + 1));
newproc[newprocs++] = it;
}
fclose (fp);
for (kills = i = 0;i < newprocs;i++) {
if (ip = findinit (newproc[i].ini_id, proc, nproc)) {
newproc[i].ini_pid = ip->ini_pid;
newproc[i].ini_count = ip->ini_count;
newproc[i].ini_status = ip->ini_status;
if (newproc[i].ini_action == ip->ini_action
&& strcmp (newproc[i].ini_levels, ip->ini_levels) == 0
&& strcmp (newproc[i].ini_command, ip->ini_command) == 0)
continue;
} else {
newproc[i].ini_pid = 0;
newproc[i].ini_count = 0;
newproc[i].ini_status = 0;
}
if (newproc[i].ini_pid == 0)
continue;
if (newproc[i].ini_action == INIT_OFF) {
kill (newproc[i].ini_pid, SIGTERM);
kills++;
}
}
if (kills)
sleep (10);
for (i = 0;i < newprocs;i++) {
if (ip = findinit (newproc[i].ini_id, proc, nproc)) {
if (newproc[i].ini_action == ip->ini_action
&& strcmp (newproc[i].ini_levels, ip->ini_levels) == 0
&& strcmp (newproc[i].ini_command, ip->ini_command) == 0)
continue;
}
if (newproc[i].ini_pid == 0)
continue;
if (newproc[i].ini_action == INIT_OFF) {
kill (newproc[i].ini_pid, SIGKILL);
waitfor (&newproc[i]);
}
}
for (i = 0;i < nproc;i++)
freeinit (&proc[i]);
proc = newproc;
nproc = newprocs;
}
void reread (sig)
int sig;
{
char buf[BUFSIZ];
signal (sig, reread);
intrflag = sig;
}
prtab ()
{
int i;
char buf[BUFSIZ];
for (i = 0;i < nproc;i++) {
sprintf (buf, "%s:%s:%s:%s",
proc[i].ini_id, proc[i].ini_levels,
actions[proc[i].ini_action], proc[i].ini_command);
msg (buf);
}
}
SHAR_EOF
fi
if test -f 'spawn.c'
then
echo shar: "will not over-write existing file 'spawn.c'"
else
cat << \SHAR_EOF > 'spawn.c'
#include <stdio.h>
#include <sys/types.h>
#include <utmp.h>
#include <signal.h>
#include "inittab.h"
#ifndef lint
static char _sccsid[] = "@(#)spawn.c 1.1 07:58:09 3/22/89";
#endif
extern int proc1;
extern int errno;
extern int nproc;
extern int wtmpfd;
extern struct inittab *proc;
struct utmp *getutent ();
extern void waitfor ();
time_t time ();
/*
* spawn - execute an entry
*/
spawn (entry)
struct inittab *entry;
{
int mustwait = 0;
int child;
int type;
int fd;
int sig;
char buf[BUFSIZ];
mustwait = (entry->ini_action == INIT_WAIT ||
entry->ini_action == INIT_BOOTWAIT ||
entry->ini_action == INIT_SYSINIT);
switch (child = fork ()) {
case 0:
proc1 = 0;
strcat (strcpy (buf, "exec "), entry->ini_command);
for (fd = 0;fd < _NFILE;fd++)
close (fd);
setpgrp ();
if (execl ("/bin/sh", "sh", "-c", buf, (char *) 0)) {
sprintf (buf, "INIT: Can't exec %s", buf);
error (buf);
_exit (errno);
}
break;
case -1:
return;
default:
entry->ini_count++;
entry->ini_pid = child;
birth (entry);
if (mustwait)
waitfor (entry);
break;
}
}
void waitfor (entry)
struct inittab *entry;
{
struct inittab *ip;
int pid;
int status;
int i;
int children;
if (entry && entry->ini_pid == 0)
return;
if (! entry) { /* count the children to wait for */
for (children = 0, ip = proc;ip != &proc[nproc];ip++)
if (ip->ini_pid)
children++;
} else { /* only have one to worry about */
children = 1;
}
while (children && (pid = wait (&status)) != -1) {
if (entry && pid == entry->ini_pid) {
entry->ini_status = status;
bury (entry);
entry->ini_pid = 0;
return;
}
/*
* find process in table and lay to rest. may require
* being restarted if action is respawn. entries not
* in the table are silently buried.
*/
for (ip = proc;ip != &proc[nproc];ip++) {
if (ip->ini_pid != pid)
continue;
ip->ini_status = status;
bury (ip);
children--;
ip->ini_pid = 0;
if (ip->ini_action == INIT_RESPAWN) {
spawn (ip);
children++;
}
break;
}
}
}
bury (entry)
struct inittab *entry;
{
struct utmp *utmp;
setutent ();
while (utmp = getutent ()) {
if (strcmp (utmp->ut_id, entry->ini_id) == 0)
break;
}
if (utmp) {
utmp->ut_pid = entry->ini_pid;
utmp->ut_type = DEAD_PROCESS;
utmp->ut_exit.e_termination = entry->ini_status & 0377;
utmp->ut_exit.e_exit = (entry->ini_status >> 8) & 0377;
pututline (utmp);
write (wtmpfd, (char *) utmp, sizeof *utmp);
}
endutent ();
}
birth (entry)
struct inittab *entry;
{
struct utmp *utmp;
struct utmp new;
setutent ();
while (utmp = getutent ()) {
if (strcmp (utmp->ut_id, entry->ini_id) == 0)
break;
}
if (! utmp) {
utmp = &new;
memset ((char *) utmp, 0, sizeof *utmp);
}
strncpy (utmp->ut_id, entry->ini_id, sizeof (utmp->ut_id));
if (entry->ini_action == INIT_RESPAWN)
strcpy (utmp->ut_user, "GETTY");
else
memset (utmp->ut_user, '\0', sizeof utmp->ut_user);
utmp->ut_pid = entry->ini_pid;
utmp->ut_type = INIT_PROCESS;
utmp->ut_exit.e_termination = 0;
utmp->ut_exit.e_exit = 0;
utmp->ut_time = time ((time_t *) 0);
pututline (utmp);
write (wtmpfd, (char *) utmp, sizeof *utmp);
endutent ();
}
SHAR_EOF
fi
if test -f 'config.h'
then
echo shar: "will not over-write existing file 'config.h'"
else
cat << \SHAR_EOF > 'config.h'
/*
* config.h - init configuration file
*
* @(#)config.h 1.1 07:58:03 3/22/89
*/
#ifndef DEBUG
#define CONSOLE "/dev/console"
#define NPROC 100
#define INITTAB "/etc/inittab"
#else
#define CONSOLE "/dev/tty"
#define NPROC 20
#define INITTAB "inittab"
#endif
SHAR_EOF
fi
if test -f 'inittab.h'
then
echo shar: "will not over-write existing file 'inittab.h'"
else
cat << \SHAR_EOF > 'inittab.h'
#include <stdio.h>
#include "config.h"
/*
* inittab - structure of the inittab file
*
* @(#)inittab.h 1.1 07:58:06 3/22/89
*/
struct inittab {
char *ini_id;
char *ini_levels;
int ini_action;
char *ini_command;
long ini_count;
int ini_pid;
int ini_status;
};
#define INIT_RESPAWN 0
#define INIT_WAIT 1
#define INIT_ONCE 2
#define INIT_BOOT 3
#define INIT_BOOTWAIT 4
#define INIT_POWERFAIL 5
#define INIT_POWERWAIT 6
#define INIT_OFF 7
#define INIT_ONDEMAND 8
#define INIT_INITDEFAULT 9
#define INIT_SYSINIT 10
SHAR_EOF
fi
if test -f 'patchlevel.h'
then
echo shar: "will not over-write existing file 'patchlevel.h'"
else
cat << \SHAR_EOF > 'patchlevel.h'
/*
* patchlevel.h - current patch level
*
* @(#)patchlevel.h 1.1 07:58:07 3/22/89
*/
#define PATCHLEVEL 1
SHAR_EOF
fi
exit 0
# End of shell archive
--
John F. Haugh II +-Quote of the Week:-------------------
VoiceNet: (214) 250-3311 Data: -6272 | "Do not drink and bake"
InterNet: jfh at rpp386.Dallas.TX.US | -- Arnold Swartzenegger
UucpNet : <backbone>!killer!rpp386!jfh +--------------------------------------
More information about the Alt.sources
mailing list