home *** CD-ROM | disk | FTP | other *** search
- /*
- * Init.c for MiNT version 0.5 (c) S.R.Usher 1991/92.
- *
- * Changelog
- *
- * 21/09/91 0.1 S.R.Usher Original version.
- *
- * 20/10/91 0.2 S.R.Usher Added support for BSD style
- * utmp/wtmp and made it able to be
- * shutdown!
- *
- * 29/11/91 0.3 S.R.Usher Make sure the ttytab file is closed
- * after reading it!
- *
- * 27/12/91 0.4 S.R.Usher Kill all processes except MiNT &
- * init(8) when doing a shutdown or
- * reboot as single user. Fix code for
- * re-reading ttytab.
- *
- * 18/1/92 0.5 S.R.Usher Following suggestions from Dave Gymer
- * the Pdomain call was removed as was
- * the call to putenv to set up the TTY
- * variable. Also, the presents of the
- * rc files is checked before sh is run
- * with them.
- *
- */
-
- #include <stdio.h>
- #include <fcntl.h>
- #include <signal.h>
- #include <sys/wait.h>
- #include <sys/errno.h>
- #include <ttyent.h>
- #include <sys/time.h>
- #include <sys/resource.h>
-
- #ifdef MINT
- #include <sys/dir.h>
- #include <mintbind.h>
-
- extern char *strchr();
- #endif
-
- #define SKIP_RC_BOOT 0x01
- #define SINGLE_USER 0x02
- #define HALT 0x10
-
- static int slowdown = 0;
- static int shutdown = 0;
- static int exit_anyway = 0;
-
- int flags;
-
- void reread_ttys(), do_single_user(), cease_new_ttys(), generic(), do_shutdown();
- void handle_sigalrm();
-
- main(argc, argv, envp)
- int argc;
- char *argv[];
- char *envp[];
- {
- register FILE *fp;
- register int i;
-
- signal(SIGHUP, reread_ttys);
- signal(SIGINT, do_single_user);
- signal(SIGTERM, do_shutdown);
- signal(SIGTSTP, cease_new_ttys);
- signal(SIGALRM, handle_sigalrm);
-
- signal(SIGTTOU, generic);
- signal(SIGTTIN, generic);
-
- sigblock(sigmask(SIGPIPE));
- sigblock(sigmask(SIGURG));
- sigblock(sigmask(SIGSTOP));
- sigblock(sigmask(SIGTTOU));
- sigblock(sigmask(SIGTTIN));
- sigblock(sigmask(SIGCONT));
- sigblock(sigmask(SIGCHLD));
- sigblock(sigmask(SIGIO));
- sigblock(sigmask(SIGXCPU));
- sigblock(sigmask(SIGXFSZ));
- sigblock(sigmask(SIGVTALRM));
- sigblock(sigmask(SIGPROF));
- sigblock(sigmask(SIGWINCH));
- sigblock(sigmask(SIGUSR1));
- sigblock(sigmask(SIGUSR2));
-
- flags = parse_opts(argc, argv);
-
- reboot:
-
- write_wtmp("~", "reboot", "\0", time(0L));
-
- /*
- * Clear out the utmp file...
- */
- unlink("/etc/utmp");
-
- /*
- * Re-create it... this is cludge... I don't know why, but creat() produces a
- * file of zero length which acts rather like /dev/null, the only thing which
- * gets bigger when you write to it is the size given by ls(1)!
- */
- if ((fp = fopen("/etc/utmp", "w")) != NULL)
- {
- fclose(fp);
- }
-
- if (SINGLE_USER & flags)
- single_user();
-
- if (!(SKIP_RC_BOOT & flags) && !access("/etc/rc.boot", F_OK))
- system("/bin/sh /etc/rc.boot");
- #ifdef DEBUG
- else
- printf("Can't access /etc/rc.boot\n");
- #endif
-
- if (!access("/etc/rc", F_OK))
- system("/bin/sh /etc/rc");
- #ifdef DEBUG
- else
- printf("Can't access /etc/rc\n");
- #endif
-
- get_tty_setup();
-
- run_ttys();
-
- if ((flags & HALT) != HALT)
- {
- shutdown = 0;
- goto reboot;
- }
-
- write_wtmp("~", "shutdown", "\0", time(0L));
- exit(0);
- }
-
- parse_opts(argc, argv)
- int argc;
- char *argv[];
- {
- int flag = 0;
- int i, j;
-
- if (argc < 2)
- return flag;
-
- for (i = 0; i < argc; i++)
- {
- if (argv[i][0] == '-')
- for (j = 1; argv[i][j] != '\0'; j++)
- switch (argv[i][j])
- {
- case 'b':
- flag |= SKIP_RC_BOOT;
- break;
-
- case 's':
- flag |= SINGLE_USER;
- break;
-
- default:
- fprintf(stderr, "init: unknown option\n");
- }
- }
-
- return flag;
- }
-
- single_user()
- {
- if (!access("/etc/rc.single", F_OK))
- system("/bin/sh /etc/rc.single");
- system("/bin/sh");
- }
-
- struct my_tty {
- char mtt_name[32];
- int mtt_pid;
- int mtt_flag;
- };
-
- #define MAXENTS 32
-
- static struct my_tty myttys[MAXENTS];
- static entries[MAXENTS];
- static num_of_ents = 0;
-
- get_tty_setup()
- {
- register int i;
- struct ttyent *entry;
-
- setttyent();
-
- num_of_ents = 0;
-
- for (i = 0; ((entry = getttyent()) != NULL) && (i < MAXENTS); i++, num_of_ents++)
- {
- #ifdef DEBUG
- printf("init: get_tty_setup: getttyent returned entry for %s.\n", entry->ty_name);
- #endif
- entries[i] = 1;
- strcpy(myttys[i].mtt_name, entry->ty_name);
- myttys[i].mtt_pid = 0;
- myttys[i].mtt_flag = entry->ty_status;
- }
- #ifdef DEBUG
- printf("num_of_ents = %d\n", num_of_ents);
- #endif
- endttyent();
- }
-
- void reread_ttys()
- {
- register int i;
- struct ttyent *entry;
-
- setttyent();
-
- num_of_ents = 0;
-
- for (i = 0; (((entry = getttyent()) != NULL) && (i < MAXENTS)); i++, num_of_ents++)
- {
- #ifdef DEBUG
- printf("init: reread_ttys: getttyent returned entry for %s.\n", entry->ty_name);
- #endif
- if ((myttys[i].mtt_flag & TTY_ON) && !(entry->ty_status & TTY_ON))
- {
- #ifdef DEBUG
- printf("init: reread_ttys: killing %s (pid %d)\n", myttys[i].mtt_name, myttys[i].mtt_pid);
- #endif
- killpg(myttys[i].mtt_pid, SIGKILL);
- myttys[i].mtt_pid = 0;
- }
-
- if (((myttys[i].mtt_flag & TTY_ON) == 0) && ((entry->ty_status & TTY_ON) > 0))
- {
- strcpy(myttys[i].mtt_name, entry->ty_name);
- #ifdef DEBUG
- printf("init: reread_ttys: Starting new tty, %s... flag = %d (%d).\n", myttys[i].mtt_name, (entry->ty_status & TTY_ON), i);
- #endif
- myttys[i].mtt_pid = start_getty_entry(entry, myttys[i].mtt_name);
- }
-
- myttys[i].mtt_flag = entry->ty_status;
- }
- endttyent();
- }
-
- run_ttys()
- {
- register int i;
- int pid;
-
- for (i = 0; i < MAXENTS; i++)
- if (myttys[i].mtt_flag & TTY_ON)
- myttys[i].mtt_pid = start_getty(myttys[i].mtt_name);
-
- while(shutdown != 1)
- {
- while ((pid = wait4tty()) == -1)
- {
- if (shutdown == 1)
- return;
- }
-
- if (slowdown != 1)
- for (i = 0; i < num_of_ents; i++)
- if (myttys[i].mtt_flag & TTY_ON)
- if (myttys[i].mtt_pid == pid)
- {
- write_utmp(myttys[i].mtt_name, "\0", "\0", time(0L));
- write_wtmp(myttys[i].mtt_name, "\0", "\0", time(0L));
- #ifdef DEBUG
- printf("init: run_ttys: Starting tty %s.\n", myttys[i].mtt_name);
- #endif
- myttys[i].mtt_pid = start_getty(myttys[i].mtt_name);
- }
- }
- }
-
- wait4tty()
- {
- int pid;
- union wait status;
- struct rusage usage;
-
- while (1)
- {
- pid = wait3(&status, 0, &usage);
- if ((!WIFSTOPPED(status)) || (pid == -1))
- return pid;
- }
- }
-
- void do_single_user()
- {
- register int i;
-
- do_killprocs();
-
- shutdown = 1;
- slowdown = 0;
-
- flags = SINGLE_USER;
- }
-
- void cease_new_ttys()
- {
- slowdown = 1;
- }
-
- void do_shutdown()
- {
- do_killprocs();
-
- printf("Syncing file systems...");
- fflush(stdout);
-
- #ifdef SYNC_FILESYS
- sync();
- sync();
- sync();
-
- sleep(1);
- #endif
-
- printf("done.\n");
-
- shutdown = 1;
- slowdown = 0;
-
- flags = HALT;
- }
-
- do_killprocs()
- {
- register int i, j, doit, waitpid, wontdie = 0;
- static union wait status;
- static struct rusage usage;
- #ifdef MINT
- int pid, deadpid;
- DIR *procdir;
- struct direct *entry;
- char *pointer;
- #endif
-
- printf("\nProcesses killed... ");
-
- for (i = 0; i <= num_of_ents; i++)
- if (myttys[i].mtt_pid != 0)
- {
- myttys[i].mtt_flag = 0;
- killpg(myttys[i].mtt_pid, SIGHUP);
- for (j = 0, waitpid = 0; (j < 20) && (waitpid == 0) ; j++)
- {
- waitpid = wait3(&status, 1, &usage);
- }
- if ((waitpid == 0) && (j >= 19))
- killpg(myttys[i].mtt_pid, SIGQUIT);
-
- printf("%d ", myttys[i].mtt_pid);
- fflush(stdout);
- }
-
- #ifdef MINT
- if ((procdir = opendir("u:/proc")) == NULL)
- {
- perror("opendir: u:/proc");
- }
- else
- {
- while ((entry = readdir(procdir)) != NULL)
- {
- entry->d_name[entry->d_namlen] = '\0';
- pointer = strchr(entry->d_name, '.');
- sscanf(++pointer, "%3d", &pid);
- if (pid > 1)
- {
- kill(pid, SIGTERM);
- deadpid = wait(0);
- printf("%d ", pid);
- }
- }
- closedir(procdir);
- }
- #endif
- printf("done!\n");
-
- if (wontdie > 0)
- printf("init: A process won't die.\n");
- }
-
- static char ttyenv[256];
-
- start_getty(name)
- char *name;
- {
- struct ttyent *entry;
-
- setttyent();
-
- if ((entry = getttynam(name)) == NULL)
- return;
-
- endttyent();
-
- return start_getty_entry(entry, name);
- }
-
- start_getty_entry(entry, name)
- struct ttyent *entry;
- char *name;
- {
- char ttyname[32];
- char **argv, **envp;
- int pid, tty;
- char *getty_cmd, *args[256];
- char *parse_getty();
-
- #ifdef NEED_TRANSLATED_CONSOLE
- if (!strcmp(name, "console"))
- {
- sprintf(ttyname, "/dev/con");
- }
- else
- #endif
- sprintf(ttyname, "/dev/%s", name);
-
- getty_cmd = parse_getty(entry, args);
-
- if ((pid = vfork()) == 0)
- {
- setpgrp(getpid(), getpid());
-
- tty = open(ttyname, O_RDWR);
-
- #ifdef MINT
- dup2(tty, -1); /* set controlling terminal */
- #endif
- dup2(tty, 0);
- dup2(tty, 1);
- dup2(tty, 2);
-
- close(tty);
-
- execv(getty_cmd, args);
-
- perror("init");
- _exit(0);
- }
-
- return pid;
- }
-
- char *parse_getty(entry, argv)
- struct ttyent *entry;
- char *argv[];
- {
- char *pointer;
- int i = 1;
-
- pointer = entry->ty_getty;
-
- argv[0] = pointer;
-
- for (; *pointer != '\0'; pointer++)
- if (*pointer == ' ')
- {
- *pointer = '\0';
- argv[i++] = pointer + 1L;
- }
-
- argv[i] = NULL;
- #ifdef environment
- envp[0] = entry->ty_type;
- envp[1] = NULL;
- #endif
- return entry->ty_getty;
- }
-
- void generic(int signum)
- {
- printf("Signal no. %d caught.\n", signum);
- }
-
- void handle_sigalrm(int signum)
- {
- printf("A process failed to halt, exitting.\n");
- }
-