home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 13 / CDA13.ISO / MISC / SRC / INIT / INIT.C next >
Encoding:
C/C++ Source or Header  |  1996-12-20  |  10.5 KB  |  490 lines

  1. /*
  2.  * init.c
  3.  * 
  4.  * This is the install type init 
  5.  *
  6.  * Erik Troan (ewt@redhat.com)
  7.  *
  8.  * Copyright 1996 Red Hat Software 
  9.  *
  10.  * This software may be freely redistributed under the terms of the GNU
  11.  * public license.
  12.  *
  13.  * You should have received a copy of the GNU General Public License
  14.  * along with this program; if not, write to the Free Software
  15.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16.  *
  17.  */
  18.  
  19. #include <fcntl.h>
  20. #include <linux/fs.h>
  21. #include <linux/if.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <sys/ioctl.h>
  26. #include <sys/mount.h>
  27. #include <sys/socket.h>
  28. #include <sys/stat.h>
  29. #include <sys/time.h>
  30. #include <sys/types.h>
  31. #include <sys/un.h>
  32. #include <sys/wait.h>
  33. #include <unistd.h>
  34. #include <sys/ioctl.h>
  35. #include <termios.h>
  36.  
  37. #ifdef __alpha__
  38. #include <sys/reboot.h>
  39. #endif
  40.  
  41. /* 
  42.  * this needs to handle the following cases:
  43.  *
  44.  *    1) run from a CD root filesystem
  45.  *    2) run from a read only nfs rooted filesystem
  46.  *      3) run from a floppy
  47.  *    4) run from a floppy that's been loaded into a ramdisk 
  48.  *
  49.  */
  50.  
  51. int doShutdown;
  52.  
  53. #define __LIBRARY__
  54. #include <linux/unistd.h>
  55. #ifndef __alpha__
  56. # define __NR_sys_syslog __NR_syslog
  57. _syscall3(int,syslog,int, type, char *, buf, int, len);
  58. #else
  59. # define syslog klogctl
  60. #endif
  61.  
  62. void fatal_error(int usePerror) {
  63.     if (usePerror) 
  64.     perror("failed:");
  65.     else
  66.     fprintf(stderr, "failed.\n");
  67.  
  68.     fprintf(stderr, "\nI can't recover from this.\n");
  69.     while (1) ;
  70. }
  71.  
  72. int doMke2fs(char * device, char * size) {
  73.     char * args[] = { "/usr/bin/mke2fs", NULL, NULL, NULL };
  74.     int pid, status;
  75.  
  76.     args[1] = device;
  77.     args[2] = size;
  78.  
  79.     if (!(pid = fork())) {
  80.     execv("/usr/bin/mke2fs", args);
  81.     fatal_error(1);
  82.     }
  83.  
  84.     wait(&status);
  85.     
  86.     return 0;
  87. }
  88.  
  89. int hasNetConfiged(void) {
  90.     int rc;
  91.     int s;
  92.     struct ifconf configs;
  93.     struct ifreq devs[10];
  94.  
  95.     #ifdef __i386__
  96.     return 0;
  97.     #endif
  98.  
  99.     s = socket(AF_INET, SOCK_STREAM, 0);
  100.     if (s < 0) {
  101.     perror("socket");
  102.     return 0;
  103.     } else {
  104.     /* this is just good enough to tell us if we have anything 
  105.        configured */
  106.     configs.ifc_len = sizeof(devs);
  107.     configs.ifc_buf = (void *) devs;
  108.  
  109.     rc = ioctl(s, SIOCGIFCONF, &configs);
  110.     if (rc < 0) {
  111.         perror("SIOCGIFCONF");
  112.         return 0;
  113.     }
  114.     if (configs.ifc_len == 0) {
  115.         return 0;
  116.     }
  117.  
  118.     return 1;
  119.     }
  120.  
  121.     return 0;
  122. }
  123.  
  124. void doklog(char * fn) {
  125.     fd_set readset, unixs;
  126.     int in, out, i;
  127.     size_t s;
  128.     int sock;
  129.     struct sockaddr_un sockaddr;
  130.     char buf[1024];
  131.     int readfd;
  132.  
  133.     if (!fork())
  134.     return;
  135.  
  136.     in = open("/proc/kmsg", O_RDONLY);
  137.     if (in < 0) {
  138.     perror("open /proc/kmsg");
  139.     return;
  140.     }
  141.  
  142.     out = open(fn, O_WRONLY);
  143.     if (out < 0) {
  144.     printf("couldn't open %s for syslog -- trying /tmp/syslog\n", fn);
  145.  
  146.     out = open("/tmp/syslog", O_WRONLY | O_CREAT | 0644);
  147.     if (out < 0) {
  148.         perror("open kmsg log");
  149.         
  150.         close(in);
  151.         return;
  152.     }
  153.     }
  154.  
  155.     /* if we get this far, we should be in good shape */
  156.  
  157.     if (!fork) {
  158.     close(in);
  159.     close(out);
  160.     return;
  161.     }
  162.  
  163.     /* now open the syslog socket */
  164.     sockaddr.sun_family = AF_UNIX;
  165.     strcpy(sockaddr.sun_path, "/dev/log");
  166.     sock = socket(AF_UNIX, SOCK_STREAM, 0);
  167.     if (sock < 1) {
  168.     write(out, "socket error\n", 13);
  169.     }
  170.     if (bind(sock, (struct sockaddr *) &sockaddr, sizeof(sockaddr.sun_family) + 
  171.             strlen(sockaddr.sun_path))) {
  172.     write(out, "bind error\n", 11);
  173.     }
  174.     chmod("/dev/log", 0666);
  175.     if (listen(sock, 5)) {
  176.     write(out, "listen error\n", 13);
  177.     }
  178.     syslog(8, NULL, 1);
  179.  
  180.     FD_ZERO(&unixs);
  181.     while (1) {
  182.     memcpy(&readset, &unixs, sizeof(unixs));
  183.  
  184.     FD_SET(sock, &readset);
  185.     FD_SET(in, &readset);
  186.  
  187.     i = select(FD_SETSIZE, &readset, NULL, NULL, NULL);
  188.     if (i <= 0) continue;
  189.  
  190.     if (FD_ISSET(in, &readset)) {
  191.         i = read(in, buf, sizeof(buf));
  192.         if (i > 0) write(out, buf, i);
  193.     } 
  194.  
  195.     for (readfd = 0; readfd < FD_SETSIZE; ++readfd) {
  196.         if (FD_ISSET(readfd, &readset) && FD_ISSET(readfd, &unixs)) {
  197.         i = read(readfd, buf, sizeof(buf));
  198.         if (i > 0) {
  199.             write(out, buf, i);
  200.             write(out, "\n", 1);
  201.         } else if (i == 0) {
  202.             /* socket closed */
  203.             close(readfd);
  204.             FD_CLR(readfd, &unixs);
  205.         }
  206.         }
  207.     }
  208.  
  209.     if (FD_ISSET(sock, &readset)) {
  210.         i = sizeof(sockaddr);
  211.         readfd = accept(sock, (struct sockaddr *) &sockaddr, &s);
  212.         if (readfd < 0) {
  213.         /*write(out, "error in accept\n", 16);*/
  214.         } else {
  215.         FD_SET(readfd, &unixs);
  216.         }
  217.     }
  218.     }    
  219. }
  220.  
  221. #if defined(__alpha__)
  222. char * findKernel(void) {
  223.     char * dev, * file;
  224.     struct stat sb;
  225.  
  226.     dev = getenv("bootdevice");
  227.     file = getenv("bootfile");
  228.  
  229.     if (!dev || !file) {
  230.     printf("I can't find your kernel. When you are booting"
  231.         " from a CDROM, you must pass\n");
  232.     printf("the bootfile argument to the kernel if your"
  233.         " boot loader doesn't do so automatically.\n");
  234.     printf("\n");
  235.     printf("You should now reboot your system and try "    
  236.         "again\n");
  237.  
  238.     while (1) ;
  239.     }
  240.  
  241.     if (!strcmp(dev, "fd0")) {
  242.     if (!strcmp(file, "vmlinux.gz")) {
  243.         printf("The kernel on a boot floppy must be named vmlinux.gz. "
  244.                "You\n");
  245.         printf("are using a kernel named %s instead. You'll have "
  246.            "to\n", file);
  247.         printf("fix this and try again.\n");
  248.  
  249.         while (1) ;
  250.     }
  251.  
  252.     return NULL;
  253.     } else {
  254.     if (stat(file, &sb)) {
  255.         printf("I can't find your kernel. When you are booting"
  256.             " from a CDROM, you must pass\n");
  257.         printf("the bootfile argument to the kernel if your"
  258.             " boot loader doesn't do so automatically.\n");
  259.         printf("\n");
  260.         printf("You should now reboot your system and try "    
  261.             "again\n");
  262.  
  263.         while (1) ;
  264.     }
  265.  
  266.     return file;
  267.     }
  268. }
  269. #endif
  270.  
  271. int setupTerminal(int fd) {
  272.     struct winsize winsize;
  273.  
  274.     if (ioctl(fd, TIOCGWINSZ, &winsize)) {
  275.     printf("failed to get winsize");
  276.     fatal_error(1);
  277.     }
  278.  
  279.     winsize.ws_row = 24;
  280.     winsize.ws_col = 80;
  281.  
  282.     if (ioctl(fd, TIOCSWINSZ, &winsize)) {
  283.     printf("failed to set winsize");
  284.     fatal_error(1);
  285.     }
  286.  
  287.     putenv("TERM=vt100");
  288.  
  289.     return 0;
  290. }
  291.  
  292. void main(int argc, char ** argv) {
  293.     pid_t installpid, childpid;
  294.     int waitStatus;
  295.     int fd;
  296.     int i;
  297.     int nfsRoot = 0;
  298.     int roRoot = 0;
  299.     int cdRoot = 0;
  300.     int isRescue = 0;
  301.     int isSerial = 0;
  302.     char * kernel;
  303.  
  304.     /* turn off screen blanking */
  305.     printf("\033[9;0]");
  306.     printf("\033[8]");
  307.  
  308.     printf("Red Hat install init version %s starting\n", VERSION);
  309.  
  310.     putenv("PATH=/usr/bin:/bin:/sbin:/usr/sbin:/mnt/sbin:/mnt/usr/sbin:"
  311.            "/mnt/bin:/mnt/usr/bin");
  312.     putenv("LD_LIBRARY_PATH=/lib:/usr/lib:/mnt/lib:/mnt/usr/lib");
  313.     putenv("HOME=/");
  314.  
  315.     printf("checking command line arguments..."); fflush(stdout);
  316.     for (i = 1; i < argc; i++) {
  317.     /* the SPARC bootloader likes to pass an empty argument if no
  318.        arguments were given */
  319.     if (!strlen(argv[i])) return;
  320.  
  321.     if (!strcmp(argv[i], "auto")) {
  322.         /* lilo does this for us -- we don't care */
  323.     } else if (!strcmp(argv[i], "rescue")) {
  324.         printf("\n\trescue disk mode enabled"); fflush(stdout);
  325.         isRescue = 1;
  326.     } else if (!strcmp(argv[i], "serial")) {
  327.         printf("\n\tserial mode enabled (you probably don't see this!)"); 
  328.         fflush(stdout);
  329.         isSerial = 1;
  330.     } else {
  331.         printf("\n\tunknown option '%s'!", argv[i]); fflush(stdout);
  332.         sleep(5);
  333.         break;
  334.     }
  335.     }
  336.     printf("\n");
  337.  
  338.     if (isSerial) {
  339.     fd = open("/dev/cua0", O_RDWR);
  340.     if (fd < 0) {
  341.         printf("failed to open /dev/cua0");
  342.         fatal_error(1);
  343.     }
  344.     write(fd, "Switching to serial console...", 29);
  345.  
  346.     /* gulp */
  347.     fflush(stdout);
  348.     fflush(stderr);
  349.     dup2(fd, 0);
  350.     dup2(fd, 1);
  351.     dup2(fd, 2);
  352.  
  353.     printf("done\n\n"); fflush(stdout);
  354.  
  355.     printf("Red Hat install init version %s using a serial console\n", 
  356.         VERSION);
  357.  
  358.     printf("remember, cereal is an important part of a nutritionally "
  359.            "balanced breakfast.\n\n");
  360.  
  361.     putenv("SERIALCON=yes");
  362.  
  363.     setupTerminal(0);
  364.  
  365.     close(fd);
  366.     }
  367.  
  368.     sethostname("localhost", 9);
  369.  
  370.     printf("mounting /proc filesystem... "); fflush(stdout);
  371.     if (mount("/proc", "/proc", "proc", 0, NULL))
  372.     fatal_error(1);
  373.  
  374.     printf("done\n");
  375.  
  376.     doklog("/dev/tty4");
  377.  
  378.     printf("checking for NFS root filesystem..."); fflush(stdout);
  379.     if (hasNetConfiged()) {
  380.     printf("yes\n");
  381.     roRoot = nfsRoot = 1;
  382.     } else {
  383.     printf("no\n");
  384.     }
  385.  
  386.     if (!nfsRoot) {
  387.     printf("trying to remount root filesystem read write... ");
  388.     if (mount("/", "/", NULL, MS_REMOUNT | MS_MGC_VAL, NULL)) {
  389.         printf("failed (but that's okay)\n");
  390.     
  391.         roRoot = 1;
  392.     } else {
  393.         printf("done\n");
  394.  
  395.         /* 2.0.18 (at least) lets us remount a CD r/w!! */
  396.         printf("checking for writeable /tmp... ");
  397.         fd = open("/tmp/tmp", O_WRONLY | O_CREAT, 0644);
  398.         if (fd < 0) {
  399.         printf("no (probably a CD rooted install)\n");
  400.         roRoot = 1;
  401.         } else {
  402.         close(fd);
  403.         unlink("/tmp/tmp");
  404.         printf("yes\n");
  405.         }
  406.     }
  407.     }
  408.  
  409.     if (roRoot) {
  410.     printf("creating 100k of ramdisk space... "); fflush(stdout);
  411.     if (doMke2fs("/dev/ram", "100"))
  412.         fatal_error(0);
  413.  
  414.     printf("done\n");
  415.     
  416.     printf("mounting /tmp from ramdisk... "); fflush(stdout);
  417.     if (mount("/dev/ram", "/tmp", "ext2", 0, NULL))
  418.         fatal_error(1);
  419.  
  420.     printf("done\n");
  421.  
  422.     if (!nfsRoot) cdRoot = 1;
  423.     }
  424.  
  425.     /* Now we have some /tmp space set up, and /etc and /dev point to
  426.        it. We should be in pretty good shape. */
  427.  
  428.     /* Go into normal init mode - keep going, and then do a orderly shutdown
  429.        when:
  430.  
  431.     1) /bin/install exits
  432.     2) we receive a SIGHUP 
  433.     */
  434.  
  435.     printf("running install...\n");
  436.     if (!(installpid = fork())) {
  437.     if (nfsRoot) {
  438.         symlink("/", "/tmp/rhimage");
  439.         symlink("/", "/tmp/image");
  440.         execl("/usr/bin/runinstall2", "/usr/bin/runinstall2", "--method",
  441.           "nfs", isRescue ? "--rescue" : NULL, NULL);
  442.     } else if (cdRoot) {
  443.         symlink("/", "/tmp/rhimage");
  444.         symlink("/", "/tmp/image");
  445.  
  446. #        if defined(__alpha__)
  447.         kernel = findKernel();
  448.  
  449.         if (kernel) 
  450.             execl("/usr/bin/runinstall2", "/usr/bin/runinstall2", 
  451.                 "--method", "cdrom", "--kernel", kernel, 
  452.                 isRescue ? "--rescue" : NULL, NULL);
  453.         else
  454.             execl("/usr/bin/runinstall2", "/usr/bin/runinstall2", 
  455.                 "--method", "cdrom", 
  456.                 isRescue ? "--rescue" : NULL, NULL);
  457. #        else
  458.         execl("/usr/bin/runinstall2", "/usr/bin/runinstall2", 
  459.                 "--method", "cdrom", 
  460.                   isRescue ? "--rescue" : NULL, NULL);
  461. #        endif
  462.     } else {
  463.         execl("/bin/install", "/bin/install", 
  464.            isRescue ? "--rescue" : NULL, NULL);
  465.     }
  466.  
  467.     exit(0);
  468.     }
  469.  
  470.     while (!doShutdown) {
  471.     childpid = wait(&waitStatus);
  472.  
  473.     if (childpid == installpid) 
  474.         doShutdown = 1;
  475.     }
  476.  
  477.     sync(); sync();
  478.  
  479.     printf("rebooting system\n");
  480.  
  481.     /* this should unmount filesystems, kill processes, etc */
  482.     sleep(2);
  483.  
  484.     #ifdef __alpha__
  485.     reboot(RB_AUTOBOOT);
  486.     #else
  487.     reboot(0xfee1dead, 672274793, 0x1234567);
  488.     #endif
  489. }
  490.