Prex Home / Browse Source - Prex Version: 0.9.0

root/usr/server/boot/boot.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wait_server
  2. send_bootmsg
  3. mount_fs
  4. exec_init
  5. copy_file
  6. main

   1 /*-
   2  * Copyright (c) 2005-2007, Kohsuke Ohtani
   3  * All rights reserved.
   4  *
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions
   7  * are met:
   8  * 1. Redistributions of source code must retain the above copyright
   9  *    notice, this list of conditions and the following disclaimer.
  10  * 2. Redistributions in binary form must reproduce the above copyright
  11  *    notice, this list of conditions and the following disclaimer in the
  12  *    documentation and/or other materials provided with the distribution.
  13  * 3. Neither the name of the author nor the names of any co-contributors
  14  *    may be used to endorse or promote products derived from this software
  15  *    without specific prior written permission.
  16  *
  17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27  * SUCH DAMAGE.
  28  */
  29 
  30 /*
  31  * main.c - bootstrap server
  32  */
  33 
  34 /*
  35  * A bootstrap server works to setup the POSIX environment for
  36  * 'init' process. It sends a setup message to other servers in
  37  * order to let them know that this task becomes 'init' process.
  38  * The bootstrap server is gone after it launches (exec) the
  39  * 'init' process.
  40  */
  41 
  42 #include <sys/prex.h>
  43 #include <sys/mount.h>
  44 #include <sys/stat.h>
  45 #include <sys/fcntl.h>
  46 #include <sys/syslog.h>
  47 
  48 #include <ipc/fs.h>
  49 #include <ipc/exec.h>
  50 #include <ipc/proc.h>
  51 #include <ipc/ipc.h>
  52 
  53 #include <unistd.h>
  54 #include <string.h>
  55 #include <stdlib.h>
  56 #include <stdio.h>
  57 #include <signal.h>
  58 #include <errno.h>
  59 
  60 #ifdef DEBUG
  61 #define DPRINTF(a) sys_log a
  62 #else
  63 #define DPRINTF(a)
  64 #endif
  65 
  66 static const char *initargs[] = { "1", NULL };
  67 static const char *initenvs[] = { "TERM=vt100", "USER=root", NULL };
  68 
  69 static char iobuf[BUFSIZ];
  70 
  71 /*
  72  * Base directories at root.
  73  */
  74 static char *base_dir[] = {
  75         "/bin",         /* applications */
  76         "/boot",        /* system servers */
  77         "/dev",         /* device files */
  78         "/etc",         /* shareable read-only data */
  79         "/mnt",         /* mount point for file systems */
  80         "/private",     /* user's private data */
  81         "/tmp",         /* temporary files */
  82         NULL
  83 };
  84 
  85 static void
  86 wait_server(const char *name, object_t *pobj)
  87 {
  88         int i, error = 0;
  89 
  90         /* Give chance to run other servers. */
  91         thread_yield();
  92 
  93         /*
  94          * Wait for server loading. timeout is 1 sec.
  95          */
  96         for (i = 0; i < 100; i++) {
  97                 error = object_lookup((char *)name, pobj);
  98                 if (error == 0)
  99                         break;
 100 
 101                 /* Wait 10msec */
 102                 timer_sleep(10, 0);
 103                 thread_yield();
 104         }
 105         if (error)
 106                 sys_panic("boot: server not found");
 107 }
 108 
 109 static void
 110 send_bootmsg(object_t obj)
 111 {
 112         struct msg m;
 113         int error;
 114 
 115         m.hdr.code = STD_BOOT;
 116         error = msg_send(obj, &m, sizeof(m));
 117         if (error)
 118                 sys_panic("boot: server error");
 119 }
 120 
 121 static void
 122 mount_fs(void)
 123 {
 124         char line[128];
 125         FILE *fp;
 126         char *spec, *file, *type, *p;
 127         char nodev[] = "";
 128         int i;
 129 
 130         DPRINTF(("boot: mounting file systems\n"));
 131 
 132         /*
 133          * Mount root.
 134          */
 135         if (mount("", "/", "ramfs", 0, NULL) < 0)
 136                 sys_panic("boot: mount failed");
 137 
 138         /*
 139          * Create some default directories.
 140          */
 141         i = 0;
 142         while (base_dir[i] != NULL) {
 143                 if (mkdir(base_dir[i], 0) == -1)
 144                         sys_panic("boot: mkdir failed");
 145                 i++;
 146         }
 147 
 148         /*
 149          * Mount file system for /boot.
 150          */
 151         if (mount("/dev/ram0", "/boot", "arfs", 0, NULL) < 0)
 152                 sys_panic("boot: mount failed");
 153 
 154         /*
 155          * Mount file systems described in fstab.
 156          */
 157         if ((fp = fopen("/boot/fstab", "r")) == NULL)
 158                 sys_panic("boot: no fstab");
 159 
 160         for (;;) {
 161                 if ((p = fgets(line, sizeof(line), fp)) == NULL)
 162                         break;
 163                 spec = strtok(p, " \t\n");
 164                 if (spec == NULL || *spec == '#')
 165                         continue;
 166                 file = strtok(NULL, " \t\n");
 167                 type = strtok(NULL, " \t\n");
 168                 if (!strcmp(file, "/") || !strcmp(file, "/boot"))
 169                         continue;
 170                 if (!strcmp(spec, "none"))
 171                         spec = nodev;
 172 
 173                 /* We create the mount point automatically */
 174                 mkdir(file, 0);
 175                 mount(spec, file, type, 0, 0);
 176         }
 177         fclose(fp);
 178 }
 179 
 180 static int
 181 exec_init(object_t execobj)
 182 {
 183         struct exec_msg msg;
 184         int error, i, argc, envc;
 185         size_t bufsz;
 186         char *dest;
 187         char const *src;
 188 
 189         DPRINTF(("boot: execute init\n"));
 190 
 191         /* Get arg/env buffer size */
 192         bufsz = 0;
 193         argc = 0;
 194         while (initargs[argc]) {
 195                 bufsz += (strlen(initargs[argc]) + 1);
 196                 argc++;
 197         }
 198         envc = 0;
 199         while (initenvs[envc]) {
 200                 bufsz += (strlen(initenvs[envc]) + 1);
 201                 envc++;
 202         }
 203         if (bufsz >= ARG_MAX)
 204                 sys_panic("boot: args too long");
 205 
 206         /*
 207          * Build exec message.
 208          */
 209         dest = msg.buf;
 210         for (i = 0; i < argc; i++) {
 211                 src = initargs[i];
 212                 while ((*dest++ = *src++) != 0);
 213         }
 214         for (i = 0; i < envc; i++) {
 215                 src = initenvs[i];
 216                 while ((*dest++ = *src++) != 0);
 217         }
 218         msg.hdr.code = EXEC_EXECVE;
 219         msg.argc = argc;
 220         msg.envc = envc;
 221         msg.bufsz = bufsz;
 222         strlcpy(msg.cwd, "/", sizeof(msg.cwd));
 223         strlcpy(msg.path, "/boot/init", sizeof(msg.path));
 224 
 225         do {
 226                 error = msg_send(execobj, &msg, sizeof(msg));
 227                 /*
 228                  * If exec server can execute new process
 229                  * properly, it will terminate the caller task
 230                  * automatically. So, the control never comes
 231                  * here in that case.
 232                  */
 233         } while (error == EINTR);
 234         return -1;
 235 }
 236 
 237 static void
 238 copy_file(char *src, char *dest)
 239 {
 240         int fold, fnew, n;
 241         struct stat stbuf;
 242         mode_t mode;
 243 
 244         if ((fold = open(src, O_RDONLY)) == -1)
 245                 return;
 246 
 247         fstat(fold, &stbuf);
 248         mode = stbuf.st_mode;
 249 
 250         if ((fnew = creat(dest, mode)) == -1) {
 251                 close(fold);
 252                 return;
 253         }
 254         while ((n = read(fold, iobuf, BUFSIZ)) > 0) {
 255                 if (write(fnew, iobuf, (size_t)n) != n) {
 256                         close(fold);
 257                         close(fnew);
 258                         return;
 259                 }
 260         }
 261         close(fold);
 262         close(fnew);
 263 }
 264 
 265 int
 266 main(int argc, char *argv[])
 267 {
 268         object_t execobj, procobj, fsobj;
 269         struct bind_msg bm;
 270         struct msg m;
 271 
 272         sys_log("Starting bootstrap server\n");
 273 
 274         thread_setpri(thread_self(), PRI_DEFAULT);
 275 
 276         /*
 277          * Wait until all required system servers
 278          * become available.
 279          */
 280         wait_server("!proc", &procobj);
 281         wait_server("!fs", &fsobj);
 282         wait_server("!exec", &execobj);
 283 
 284         /*
 285          * Send boot message to all servers.
 286          * This is required to synchronize the server
 287          * initialization without deadlock.
 288          */
 289         send_bootmsg(execobj);
 290         send_bootmsg(procobj);
 291         send_bootmsg(fsobj);
 292 
 293         /*
 294          * Request to bind a new capabilities for us.
 295          */
 296         bm.hdr.code = EXEC_BINDCAP;
 297         strlcpy(bm.path, "/boot/boot", sizeof(bm.path));
 298         msg_send(execobj, &bm, sizeof(bm));
 299 
 300         /*
 301          * Register this process as 'init'.
 302          * We will become an init process later.
 303          */
 304         m.hdr.code = PS_SETINIT;
 305         msg_send(procobj, &m, sizeof(m));
 306 
 307         /*
 308          * Initialize a library for file I/O.
 309          */
 310         fslib_init();
 311 
 312         /*
 313          * Mount file systems.
 314          */
 315         mount_fs();
 316 
 317         /*
 318          * Copy some files.
 319          * Note that almost applications including 'init'
 320          * does not have an access right to /boot directory...
 321          */
 322         copy_file("/boot/rc", "/etc/rc");
 323         copy_file("/boot/fstab", "/etc/fstab");
 324 
 325         /*
 326          * Exec first application.
 327          */
 328         exec_init(execobj);
 329 
 330         sys_panic("boot: failed to exec init");
 331 
 332         /* NOTREACHED */
 333         return 0;
 334 }

/* [<][>][^][v][top][bottom][index][help] */