Files
oldlinux-files/bin/qpl-init/init/init.c
2024-02-19 00:21:52 -05:00

278 lines
5.7 KiB
C

/*
init.c does some of the stuff /etc/init should do.
by qpliu@phoenix.princeton.edu 1992
run /etc/rc,
then run getty for each entry in /etc/ttytab
SIGHUP makes it reread /etc/ttytab
SIGTSTP makes it stop forking
SIGTERM is ignored
ugly error messages might get stuck on console, syslog stuff?
imported stuff from original init function
*/
/*
my computer is a puny 2meg 386sx, and can't run gcc.
so I made cc1 on my account on a sun 4/490
and compile to .s on the sun. however, cc1 dies with
SIGIOT when trying to optimize some of the inlined string.h stuff
when used in a big function.
*/
#define GCC_O_BUSTED
#include <unistd.h>
#include <time.h>
#include <linux/tty.h>
#include <linux/sched.h>
#include <linux/head.h>
#include <asm/system.h>
#include <asm/io.h>
#include <stddef.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <linux/fs.h>
#include <ttyent.h>
#include <signal.h>
#include <string.h>
struct ttytablist {
int pid;
char *dev, *getty;
struct ttytablist *next;
};
static struct ttyent *ent;
static struct ttytablist *tablist0, *tablist;
static char **getty_argv;
#ifdef GCC_O_BUSTED
static char *strtok1 (char *, const char *);
#else
#define strtok1 strtok
#endif GCC_O_BUSTED
static char * argv_rc[] = { "/bin/bash", NULL };
static char * envp_rc[] = { "HOME=/", NULL };
static char * argv[] = { "-bash", NULL };
static char * envp[] = { "HOME=/", NULL };
static char got_tstp = 0;
#define GETTY_RETRY_DLAY 30
static void rc ();
static void child ();
static void read_ttytab ();
static void free_ttytab (struct ttytablist *);
static void single_user ();
static void hup_handler ();
static void tstp_handler ();
void
main (void)
{
rc ();
read_ttytab (); /* initially, tablist->pid = 0 if off, -1 if on */
/* run getty */
tablist = tablist0;
while (tablist) {
if (tablist->pid) {
if (!(tablist->pid = fork()))
child ();
if (tablist->pid == -1) {
printf ("Fork failed in init for %s\n\r",
tablist->dev);
tablist->pid = 0; /* waste memory */
}
}
tablist = tablist->next;
}
signal (SIGHUP, hup_handler);
signal (SIGTERM, single_user);
signal (SIGTSTP, tstp_handler);
/* reap children, restart getty unless got_tstp */
for (;;) {
int pid, i;
pid = wait (&i);
if (!got_tstp) {
tablist = tablist0;
while (tablist) {
if (tablist->pid == pid) {
if (!(tablist->pid = fork()))
child ();
if (tablist->pid == -1) {
printf ("Fork failed in init for %s\n\r", tablist->dev);
tablist->pid = 0; /* waste memory */
}
}
tablist = tablist->next;
}
}
sync();
}
_exit(0); /* NOTE! _exit, not exit() */
}
static void
rc ()
{
int i, pid;
if (!(pid=fork())) {
close(0);
if (open("/etc/rc",O_RDONLY,0))
_exit(1);
execve("/bin/bash",argv_rc,envp_rc);
_exit(2);
}
if (pid>0)
while (pid != wait(&i))
/* nothing */;
}
static void
free_ttytab (struct ttytablist *t)
{
struct ttytablist *u;
/* free all that malloced stuff */
endttyent ();
do {
u = t->next;
free (t->dev);
free (t->getty);
free (t);
} while (t = u);
}
static void
read_ttytab ()
{
tablist0 = (struct ttytablist *)malloc (sizeof (struct ttytablist));
if (!tablist0) {
printf ("Malloc failed in init\n\r");
_exit (0);
}
tablist0->next = (struct ttytablist *)0;
tablist = tablist0;
ent = getttyent ();
if (!ent) {
printf ("Getttyent failed in init, check /etc/ttytab\n\r");
/* should probably enter single-user mode */
_exit (0);
}
/* assume first entry is on, if it's off, waste some memory */
tablist->pid = 0;
for (;;) {
tablist->next = (struct ttytablist *)0;
tablist->dev = (char *)malloc (5 + strlen (ent->ty_name));
strcpy (tablist->dev, "/dev/");
strcat (tablist->dev, ent->ty_name);
tablist->getty = (char *)malloc (strlen (ent->ty_getty));
strcpy (tablist->getty, ent->ty_getty);
if (ent->ty_status & TTY_ON) tablist->pid = -1;
else tablist->pid = 0;
/* don't waste memory to store off entries */
do {
ent = getttyent ();
if (!ent) {
endttyent ();
break;
}
} while (ent->ty_status & TTY_ON);
if (!ent) break;
tablist->next = (struct ttytablist *)malloc (sizeof (struct ttytablist));
tablist = tablist->next;
}
}
static void
child ()
{
int i;
char *c, *g = (char *)malloc (strlen (tablist->getty) * sizeof (char));
close(0);close(1);close(2);
setsid();
(void) open(tablist->dev,O_RDWR,0);
(void) dup(0);
(void) dup(0);
/* find argc for getty */
strcpy (g, tablist->getty);
i = 1; strtok1 (g, " \t\n");
while (strtok1 ((char *)0, " \t\n")) ++i;
getty_argv = (char **)malloc (i * sizeof (char **));
strcpy (g, tablist->getty);
i = 1; c = strtok1 (g, " \t\n"); *getty_argv = c;
while (c = strtok1 ((char *)NULL, " \t\n"))
*(getty_argv + i++) = c;
free_ttytab (tablist0);
execve (*getty_argv, getty_argv, envp);
sleep (GETTY_RETRY_DLAY); /* don't hog system */
_exit (0);
}
static void
hup_handler ()
{
struct ttytablist *t = tablist0, *u, *v;
got_tstp = 0;
signal (SIGHUP, SIG_IGN);
read_ttytab ();
/* copy running pids that still map onto enabled terminals */
for (u = tablist0; u; u = u->next)
if (u->pid) {
for (v = t; v; v = v->next) /* simple-minded */
if (!strcmp (v->dev, u->dev)) {
u->pid = v->pid;
break;
}
/* check if new terminal enabled */
if (!v) {
if (!(u->pid = fork()))
child ();
if (u->pid == -1) {
printf ("Fork failed in init for %s\n\r", tablist->dev);
u->pid = 0; /* waste memory */
}
}
}
free_ttytab (t);
signal (SIGHUP, hup_handler);
}
static void
tstp_handler ()
{
got_tstp = 1;
}
static void
single_user ()
{
}
/* don't want this inlined with -finline-functions, so put it last */
#ifdef GCC_O_BUSTED
static char *strtok1 (char *a, const char *b)
{
return strtok (a, b);
}
#endif GCC_O_BUSTED