home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / mint / init_5 / init.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-03  |  9.2 KB  |  497 lines

  1. /*
  2.  * Init.c for MiNT version 0.5 (c) S.R.Usher 1991/92.
  3.  *
  4.  * Changelog
  5.  *
  6.  * 21/09/91    0.1    S.R.Usher    Original version.
  7.  *
  8.  * 20/10/91    0.2    S.R.Usher    Added support for BSD style
  9.  *                     utmp/wtmp and made it able to be
  10.  *                    shutdown!
  11.  *
  12.  * 29/11/91    0.3    S.R.Usher    Make sure the ttytab file is closed
  13.  *                    after reading it!
  14.  *
  15.  * 27/12/91    0.4    S.R.Usher    Kill all processes except MiNT &
  16.  *                    init(8) when doing a shutdown or
  17.  *                    reboot as single user. Fix code for
  18.  *                    re-reading ttytab.
  19.  *
  20.  * 18/1/92    0.5    S.R.Usher    Following suggestions from Dave Gymer
  21.  *                    the Pdomain call was removed as was
  22.  *                    the call to putenv to set up the TTY
  23.  *                    variable. Also, the presents of the
  24.  *                    rc files is checked before sh is run
  25.  *                    with them.
  26.  *
  27.  */
  28.  
  29. #include <stdio.h>
  30. #include <fcntl.h>
  31. #include <signal.h>
  32. #include <sys/wait.h>
  33. #include <sys/errno.h>
  34. #include <ttyent.h>
  35. #include <sys/time.h>
  36. #include <sys/resource.h>
  37.  
  38. #ifdef MINT
  39. #include <sys/dir.h>
  40. #include <mintbind.h>
  41.  
  42. extern char *strchr();
  43. #endif
  44.  
  45. #define SKIP_RC_BOOT    0x01
  46. #define SINGLE_USER    0x02
  47. #define HALT        0x10
  48.  
  49. static int slowdown = 0;
  50. static int shutdown = 0;
  51. static int exit_anyway = 0;
  52.  
  53. int flags;
  54.  
  55. void reread_ttys(), do_single_user(), cease_new_ttys(), generic(), do_shutdown();
  56. void handle_sigalrm();
  57.  
  58. main(argc, argv, envp)
  59. int argc;
  60. char *argv[];
  61. char *envp[];
  62. {
  63.     register FILE *fp;
  64.     register int i;
  65.  
  66.     signal(SIGHUP, reread_ttys);
  67.     signal(SIGINT, do_single_user);
  68.     signal(SIGTERM, do_shutdown);
  69.     signal(SIGTSTP, cease_new_ttys);
  70.     signal(SIGALRM, handle_sigalrm);
  71.  
  72.     signal(SIGTTOU, generic);
  73.     signal(SIGTTIN, generic);
  74.  
  75.     sigblock(sigmask(SIGPIPE));
  76.     sigblock(sigmask(SIGURG));
  77.     sigblock(sigmask(SIGSTOP));
  78.     sigblock(sigmask(SIGTTOU));
  79.     sigblock(sigmask(SIGTTIN));
  80.     sigblock(sigmask(SIGCONT));
  81.     sigblock(sigmask(SIGCHLD));
  82.     sigblock(sigmask(SIGIO));
  83.     sigblock(sigmask(SIGXCPU));
  84.     sigblock(sigmask(SIGXFSZ));
  85.     sigblock(sigmask(SIGVTALRM));
  86.     sigblock(sigmask(SIGPROF));
  87.     sigblock(sigmask(SIGWINCH));
  88.     sigblock(sigmask(SIGUSR1));
  89.     sigblock(sigmask(SIGUSR2));
  90.  
  91.     flags = parse_opts(argc, argv);
  92.  
  93. reboot:
  94.  
  95.     write_wtmp("~", "reboot", "\0", time(0L));
  96.  
  97. /*
  98.  * Clear out the utmp file...
  99.  */
  100.     unlink("/etc/utmp");
  101.     
  102. /*
  103.  * Re-create it... this is cludge... I don't know why, but creat() produces a
  104.  * file of zero length which acts rather like /dev/null, the only thing which
  105.  * gets bigger when you write to it is the size given by ls(1)!
  106.  */
  107.     if ((fp = fopen("/etc/utmp", "w")) != NULL)
  108.     {
  109.         fclose(fp);
  110.     }
  111.  
  112.     if (SINGLE_USER & flags)
  113.         single_user();
  114.  
  115.     if (!(SKIP_RC_BOOT & flags) && !access("/etc/rc.boot", F_OK))
  116.         system("/bin/sh /etc/rc.boot");
  117. #ifdef DEBUG
  118.     else
  119.         printf("Can't access /etc/rc.boot\n");
  120. #endif
  121.         
  122.     if (!access("/etc/rc", F_OK))
  123.         system("/bin/sh /etc/rc");
  124. #ifdef DEBUG
  125.     else
  126.         printf("Can't access /etc/rc\n");
  127. #endif
  128.  
  129.     get_tty_setup();
  130.  
  131.     run_ttys();
  132.  
  133.     if ((flags & HALT) != HALT)
  134.     {
  135.         shutdown = 0;
  136.         goto reboot;
  137.     }
  138.  
  139.     write_wtmp("~", "shutdown", "\0", time(0L));
  140.     exit(0);
  141. }
  142.  
  143. parse_opts(argc, argv)
  144. int argc;
  145. char *argv[];
  146. {
  147.     int flag = 0;
  148.     int i, j;
  149.     
  150.     if (argc < 2)
  151.         return flag;
  152.  
  153.     for (i = 0; i < argc; i++)
  154.     {
  155.         if (argv[i][0] == '-')
  156.             for (j = 1; argv[i][j] != '\0'; j++)
  157.                 switch (argv[i][j])
  158.                 {
  159.                 case 'b':
  160.                     flag |= SKIP_RC_BOOT;
  161.                     break;
  162.  
  163.                 case 's':
  164.                     flag |= SINGLE_USER;
  165.                     break;
  166.  
  167.                 default:
  168.                     fprintf(stderr, "init: unknown option\n");
  169.                 }
  170.     }
  171.  
  172.     return flag;
  173. }
  174.  
  175. single_user()
  176. {
  177.     if (!access("/etc/rc.single", F_OK))
  178.         system("/bin/sh /etc/rc.single");
  179.     system("/bin/sh");
  180. }
  181.  
  182. struct my_tty {
  183.     char mtt_name[32];
  184.     int mtt_pid;
  185.     int mtt_flag;
  186. };
  187.  
  188. #define MAXENTS 32
  189.  
  190. static struct my_tty myttys[MAXENTS];
  191. static entries[MAXENTS];
  192. static num_of_ents = 0;
  193.  
  194. get_tty_setup()
  195. {
  196.     register int i;
  197.     struct ttyent *entry;
  198.     
  199.     setttyent();
  200.  
  201.     num_of_ents = 0;
  202.  
  203.     for (i = 0; ((entry = getttyent()) != NULL) && (i < MAXENTS); i++, num_of_ents++)
  204.     {
  205. #ifdef DEBUG
  206.         printf("init: get_tty_setup: getttyent returned entry for %s.\n", entry->ty_name);
  207. #endif
  208.         entries[i] = 1;
  209.         strcpy(myttys[i].mtt_name, entry->ty_name);
  210.         myttys[i].mtt_pid = 0;
  211.         myttys[i].mtt_flag = entry->ty_status;
  212.     }
  213. #ifdef DEBUG
  214.     printf("num_of_ents = %d\n", num_of_ents);
  215. #endif
  216.     endttyent();
  217. }
  218.  
  219. void reread_ttys()
  220. {
  221.     register int i;
  222.     struct ttyent *entry;
  223.     
  224.     setttyent();
  225.  
  226.     num_of_ents = 0;
  227.  
  228.     for (i = 0; (((entry = getttyent()) != NULL) && (i < MAXENTS)); i++, num_of_ents++)
  229.     {
  230. #ifdef DEBUG
  231.         printf("init: reread_ttys: getttyent returned entry for %s.\n", entry->ty_name);
  232. #endif
  233.         if ((myttys[i].mtt_flag & TTY_ON) && !(entry->ty_status & TTY_ON))
  234.         {
  235. #ifdef DEBUG
  236.             printf("init: reread_ttys: killing %s (pid %d)\n", myttys[i].mtt_name, myttys[i].mtt_pid);
  237. #endif
  238.             killpg(myttys[i].mtt_pid, SIGKILL);
  239.             myttys[i].mtt_pid = 0;
  240.         }
  241.  
  242.         if (((myttys[i].mtt_flag & TTY_ON) == 0) && ((entry->ty_status & TTY_ON) > 0))
  243.         {
  244.             strcpy(myttys[i].mtt_name, entry->ty_name);
  245. #ifdef DEBUG
  246.             printf("init: reread_ttys: Starting new tty, %s... flag = %d (%d).\n", myttys[i].mtt_name, (entry->ty_status & TTY_ON), i);
  247. #endif
  248.             myttys[i].mtt_pid = start_getty_entry(entry, myttys[i].mtt_name);
  249.         }
  250.         
  251.         myttys[i].mtt_flag = entry->ty_status;
  252.     }
  253.     endttyent();
  254. }
  255.  
  256. run_ttys()
  257. {
  258.     register int i;
  259.     int pid;
  260.  
  261.     for (i = 0; i < MAXENTS; i++)
  262.         if (myttys[i].mtt_flag & TTY_ON)
  263.             myttys[i].mtt_pid = start_getty(myttys[i].mtt_name);
  264.  
  265.     while(shutdown != 1)
  266.     {
  267.         while ((pid = wait4tty()) == -1)
  268.         {
  269.             if (shutdown == 1)
  270.                 return;
  271.         }
  272.  
  273.         if (slowdown != 1)
  274.             for (i = 0; i < num_of_ents; i++)
  275.                 if (myttys[i].mtt_flag & TTY_ON)
  276.                     if (myttys[i].mtt_pid == pid)
  277.                     {
  278.                         write_utmp(myttys[i].mtt_name, "\0", "\0", time(0L));
  279.                         write_wtmp(myttys[i].mtt_name, "\0", "\0", time(0L));
  280. #ifdef DEBUG
  281.                         printf("init: run_ttys: Starting tty %s.\n", myttys[i].mtt_name);
  282. #endif
  283.                         myttys[i].mtt_pid = start_getty(myttys[i].mtt_name);
  284.                     }
  285.     }
  286. }
  287.  
  288. wait4tty()
  289. {
  290.     int pid;
  291.     union wait status;
  292.     struct rusage usage;
  293.  
  294.     while (1)
  295.     {
  296.         pid = wait3(&status, 0, &usage);
  297.         if ((!WIFSTOPPED(status)) || (pid == -1))
  298.             return pid;
  299.     }
  300. }
  301.  
  302. void do_single_user()
  303. {
  304.     register int i;
  305.  
  306.     do_killprocs();
  307.     
  308.     shutdown = 1;
  309.     slowdown = 0;
  310.  
  311.     flags = SINGLE_USER;
  312. }
  313.  
  314. void cease_new_ttys()
  315. {
  316.     slowdown = 1;
  317. }
  318.  
  319. void do_shutdown()
  320. {
  321.     do_killprocs();
  322.  
  323.     printf("Syncing file systems...");
  324.     fflush(stdout);
  325.  
  326. #ifdef SYNC_FILESYS
  327.     sync();
  328.     sync();
  329.     sync();
  330.  
  331.     sleep(1);
  332. #endif
  333.  
  334.     printf("done.\n");
  335.  
  336.     shutdown = 1;
  337.     slowdown = 0;
  338.  
  339.     flags = HALT;
  340. }
  341.  
  342. do_killprocs()
  343. {
  344.     register int i, j, doit, waitpid, wontdie = 0;
  345.     static union wait status;
  346.     static struct rusage usage;
  347. #ifdef MINT
  348.     int pid, deadpid;
  349.     DIR *procdir;
  350.     struct direct *entry;
  351.     char *pointer;
  352. #endif
  353.  
  354.     printf("\nProcesses killed... ");
  355.  
  356.     for (i = 0; i <= num_of_ents; i++)
  357.         if (myttys[i].mtt_pid != 0)
  358.         {
  359.             myttys[i].mtt_flag = 0;
  360.             killpg(myttys[i].mtt_pid, SIGHUP);
  361.             for (j = 0, waitpid = 0; (j < 20) && (waitpid == 0) ; j++)
  362.             {
  363.                 waitpid = wait3(&status, 1, &usage);
  364.             }
  365.             if ((waitpid == 0) && (j >= 19))
  366.                 killpg(myttys[i].mtt_pid, SIGQUIT);
  367.  
  368.             printf("%d ", myttys[i].mtt_pid);
  369.             fflush(stdout);
  370.         }
  371.  
  372. #ifdef MINT
  373.     if ((procdir = opendir("u:/proc")) == NULL)
  374.     {
  375.         perror("opendir: u:/proc");
  376.     }
  377.     else
  378.     {
  379.         while ((entry = readdir(procdir)) != NULL)
  380.         {
  381.             entry->d_name[entry->d_namlen] = '\0';
  382.             pointer = strchr(entry->d_name, '.');
  383.             sscanf(++pointer, "%3d", &pid);
  384.             if (pid > 1)
  385.             {
  386.                 kill(pid, SIGTERM);
  387.                 deadpid = wait(0);
  388.                 printf("%d ", pid);
  389.             }
  390.         }
  391.         closedir(procdir);
  392.     }
  393. #endif
  394.     printf("done!\n");
  395.  
  396.     if (wontdie > 0)
  397.         printf("init: A process won't die.\n");
  398. }
  399.  
  400. static char ttyenv[256];
  401.  
  402. start_getty(name)
  403. char *name;
  404. {
  405.     struct ttyent *entry;
  406.  
  407.     setttyent();
  408.  
  409.     if ((entry = getttynam(name)) == NULL)
  410.         return;
  411.  
  412.     endttyent();
  413.  
  414.     return start_getty_entry(entry, name);
  415. }
  416.  
  417. start_getty_entry(entry, name)
  418. struct ttyent *entry;
  419. char *name;
  420. {
  421.     char ttyname[32];
  422.     char **argv, **envp;
  423.     int pid, tty;
  424.     char *getty_cmd, *args[256];
  425.     char *parse_getty();
  426.  
  427. #ifdef NEED_TRANSLATED_CONSOLE
  428.     if (!strcmp(name, "console"))
  429.     {
  430.         sprintf(ttyname, "/dev/con");
  431.     }
  432.     else
  433. #endif
  434.         sprintf(ttyname, "/dev/%s", name);
  435.  
  436.     getty_cmd = parse_getty(entry, args);
  437.  
  438.     if ((pid = vfork()) == 0)
  439.     {
  440.         setpgrp(getpid(), getpid());
  441.  
  442.         tty = open(ttyname, O_RDWR);
  443.  
  444. #ifdef MINT
  445.         dup2(tty, -1);        /* set controlling terminal */
  446. #endif
  447.         dup2(tty, 0);
  448.         dup2(tty, 1);
  449.         dup2(tty, 2);
  450.  
  451.         close(tty);
  452.  
  453.         execv(getty_cmd, args);
  454.  
  455.         perror("init");
  456.         _exit(0);
  457.     }
  458.  
  459.     return pid;
  460. }
  461.  
  462. char *parse_getty(entry, argv)
  463. struct ttyent *entry;
  464. char *argv[];
  465. {
  466.     char *pointer;
  467.     int i = 1;
  468.  
  469.     pointer = entry->ty_getty;
  470.  
  471.     argv[0] = pointer;
  472.     
  473.     for (; *pointer != '\0'; pointer++)
  474.         if (*pointer == ' ')
  475.         {
  476.             *pointer = '\0';
  477.             argv[i++] = pointer + 1L;
  478.         }
  479.  
  480.     argv[i] = NULL;
  481. #ifdef environment
  482.     envp[0] = entry->ty_type;
  483.     envp[1] = NULL;
  484. #endif
  485.     return entry->ty_getty;
  486. }
  487.  
  488. void generic(int signum)
  489. {
  490.     printf("Signal no. %d caught.\n", signum);
  491. }
  492.  
  493. void handle_sigalrm(int signum)
  494. {
  495.     printf("A process failed to halt, exitting.\n");
  496. }
  497.