Annotation of prex-old/usr/server/exec/main.c, Revision 1.1
1.1 ! nbrk 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: * Exec server - Execute various types of image files.
! 32: */
! 33:
! 34: #include <prex/prex.h>
! 35: #include <prex/capability.h>
! 36: #include <server/fs.h>
! 37: #include <server/proc.h>
! 38: #include <server/stdmsg.h>
! 39: #include <server/object.h>
! 40: #include <sys/list.h>
! 41:
! 42: #include <limits.h>
! 43: #include <unistd.h>
! 44: #include <stdlib.h>
! 45: #include <string.h>
! 46: #include <stdio.h>
! 47: #include <fcntl.h>
! 48: #include <unistd.h>
! 49: #include <errno.h>
! 50:
! 51: #include "exec.h"
! 52:
! 53: /*
! 54: * Object for system server
! 55: */
! 56: object_t proc_obj; /* Process server */
! 57: object_t fs_obj; /* File system server */
! 58:
! 59: /*
! 60: * File header
! 61: */
! 62: static char header[HEADER_SIZE];
! 63:
! 64: /*
! 65: * Wait until specified server starts.
! 66: */
! 67: static void
! 68: wait_server(const char *name, object_t *obj)
! 69: {
! 70: int i, err = 0;
! 71:
! 72: /*
! 73: * Wait 1sec for loading server.
! 74: */
! 75: for (i = 0; i < 100; i++) {
! 76: err = object_lookup((char *)name, obj);
! 77: if (err == 0)
! 78: break;
! 79:
! 80: /* Wait 10msec */
! 81: timer_sleep(10, 0);
! 82: thread_yield();
! 83: }
! 84: if (err)
! 85: sys_panic("exec: server not found");
! 86: }
! 87:
! 88: static void
! 89: process_init(void)
! 90: {
! 91: struct msg m;
! 92:
! 93: m.hdr.code = PS_REGISTER;
! 94: msg_send(proc_obj, &m, sizeof(m));
! 95: }
! 96:
! 97: /*
! 98: * Notify exec() to servers.
! 99: */
! 100: static void
! 101: notify_server(task_t org_task, task_t new_task, void *stack)
! 102: {
! 103: struct msg m;
! 104: int err;
! 105:
! 106: /* Notify to file system server */
! 107: do {
! 108: m.hdr.code = FS_EXEC;
! 109: m.data[0] = org_task;
! 110: m.data[1] = new_task;
! 111: err = msg_send(fs_obj, &m, sizeof(m));
! 112: } while (err == EINTR);
! 113:
! 114: /* Notify to process server */
! 115: do {
! 116: m.hdr.code = PS_EXEC;
! 117: m.data[0] = org_task;
! 118: m.data[1] = new_task;
! 119: m.data[2] = (int)stack;
! 120: err = msg_send(proc_obj, &m, sizeof(m));
! 121: } while (err == EINTR);
! 122: }
! 123:
! 124: /*
! 125: * Execute program
! 126: */
! 127: static int
! 128: do_exec(struct exec_msg *msg)
! 129: {
! 130: struct exec_loader *ldr;
! 131: char *name;
! 132: int err, fd, count;
! 133: struct stat st;
! 134: task_t old_task, new_task;
! 135: thread_t th;
! 136: void *stack, *sp;
! 137: void (*entry)(void);
! 138: cap_t cap;
! 139:
! 140: dprintf("do_exec: path=%s task=%x\n", msg->path, msg->hdr.task);
! 141:
! 142: old_task = msg->hdr.task;
! 143:
! 144: /*
! 145: * Check capability of caller task.
! 146: */
! 147: if (task_getcap(old_task, &cap)) {
! 148: err = EINVAL;
! 149: goto err1;
! 150: }
! 151: if ((cap & CAP_EXEC) == 0) {
! 152: err = EPERM;
! 153: goto err1;
! 154: }
! 155: /*
! 156: * Check target file
! 157: */
! 158: if ((fd = open(msg->path, O_RDONLY)) == -1) {
! 159: err = ENOENT;
! 160: goto err1;
! 161: }
! 162: if (fstat(fd, &st) == -1) {
! 163: err = EIO;
! 164: goto err2;
! 165: }
! 166: if (!S_ISREG(st.st_mode)) {
! 167: err = EACCES; /* must be regular file */
! 168: goto err2;
! 169: }
! 170: /*
! 171: * Find file loader from the file header.
! 172: */
! 173: if ((count = read(fd, header, HEADER_SIZE)) == -1) {
! 174: err = EIO;
! 175: goto err2;
! 176: }
! 177: for (ldr = loader_table; ldr->name != NULL; ldr++) {
! 178: if (ldr->probe(header) == 0)
! 179: break;
! 180: /* Check next format */
! 181: }
! 182: if (ldr->name == NULL) {
! 183: dprintf("Unsupported file format\n");
! 184: err = ENOEXEC;
! 185: goto err2;
! 186: }
! 187: dprintf("exec loader=%s\n", ldr->name);
! 188:
! 189: /*
! 190: * Suspend old task
! 191: */
! 192: if ((err = task_suspend(old_task)) != 0)
! 193: goto err2;
! 194:
! 195: /*
! 196: * Create new task
! 197: */
! 198: if ((err = task_create(old_task, VM_NEW, &new_task)) != 0)
! 199: goto err2;
! 200:
! 201: if (msg->path[0] != '\0') {
! 202: name = strrchr(msg->path, '/');
! 203: if (name)
! 204: name++;
! 205: else
! 206: name = msg->path;
! 207: task_name(new_task, name);
! 208: }
! 209: /*
! 210: * Copy capabilities
! 211: */
! 212: task_getcap(old_task, &cap);
! 213: /* cap &= CONFIG_CAP_MASK; */
! 214: task_setcap(new_task, &cap);
! 215:
! 216: if ((err = thread_create(new_task, &th)) != 0)
! 217: goto err3;
! 218:
! 219: /*
! 220: * Allocate stack and build arguments on it.
! 221: */
! 222: err = vm_allocate(new_task, &stack, USTACK_SIZE, 1);
! 223: if (err)
! 224: goto err4;
! 225: if ((err = build_args(new_task, stack, msg, &sp)) != 0)
! 226: goto err5;
! 227:
! 228: /*
! 229: * Load file image.
! 230: */
! 231: if ((err = ldr->load(header, new_task, fd, (void **)&entry)) != 0)
! 232: goto err5;
! 233: if ((err = thread_load(th, entry, sp)) != 0)
! 234: goto err5;
! 235:
! 236: /*
! 237: * Notify to servers.
! 238: */
! 239: notify_server(old_task, new_task, stack);
! 240:
! 241: /*
! 242: * Terminate old task.
! 243: */
! 244: task_terminate(old_task);
! 245:
! 246: /*
! 247: * Set him running.
! 248: */
! 249: thread_resume(th);
! 250:
! 251: close(fd);
! 252: dprintf("exec complete successfully\n");
! 253: return 0;
! 254: err5:
! 255: vm_free(new_task, stack);
! 256: err4:
! 257: thread_terminate(th);
! 258: err3:
! 259: task_terminate(new_task);
! 260: err2:
! 261: close(fd);
! 262: err1:
! 263: dprintf("exec failed err=%d\n", err);
! 264: return err;
! 265: }
! 266:
! 267: /*
! 268: * Debug
! 269: */
! 270: static void
! 271: exec_debug(void)
! 272: {
! 273:
! 274: #ifdef DEBUG
! 275: /* mstat(); */
! 276: #endif
! 277: }
! 278:
! 279: /*
! 280: * Initialize all exec loaders
! 281: */
! 282: static void
! 283: exec_init(void)
! 284: {
! 285: struct exec_loader *ldr;
! 286:
! 287: for (ldr = loader_table; ldr->name; ldr++) {
! 288: dprintf("Initialize \'%s\' loader\n", ldr->name);
! 289: ldr->init();
! 290: }
! 291: }
! 292:
! 293: /*
! 294: * Main routine for exec service.
! 295: */
! 296: int
! 297: main(int argc, char *argv[])
! 298: {
! 299: struct exec_msg msg;
! 300: object_t obj;
! 301: int err;
! 302:
! 303: sys_log("Starting Exec Server\n");
! 304:
! 305: /*
! 306: * Boost current priority
! 307: */
! 308: thread_setprio(thread_self(), PRIO_EXEC);
! 309:
! 310: /*
! 311: * Wait until system server becomes available.
! 312: */
! 313: wait_server(OBJNAME_PROC, &proc_obj);
! 314: wait_server(OBJNAME_FS, &fs_obj);
! 315:
! 316: /*
! 317: * Register to process server
! 318: */
! 319: process_init();
! 320:
! 321: /*
! 322: * Register to file server
! 323: */
! 324: fslib_init();
! 325:
! 326: /*
! 327: * Initialize everything
! 328: */
! 329: exec_init();
! 330:
! 331: /*
! 332: * Create an object to expose our service.
! 333: */
! 334: err = object_create(OBJNAME_EXEC, &obj);
! 335: if (err)
! 336: sys_panic("fail to create object");
! 337:
! 338: /*
! 339: * Message loop
! 340: */
! 341: for (;;) {
! 342: /*
! 343: * Wait for an incoming request.
! 344: */
! 345: err = msg_receive(obj, &msg, sizeof(struct exec_msg));
! 346: if (err)
! 347: continue;
! 348: /*
! 349: * Process request.
! 350: */
! 351: err = EINVAL;
! 352: switch (msg.hdr.code) {
! 353: case STD_DEBUG:
! 354: exec_debug();
! 355: err = 0;
! 356: break;
! 357:
! 358: case EX_EXEC:
! 359: err = do_exec(&msg);
! 360: break;
! 361: }
! 362: #ifdef DEBUG_EXEC
! 363: if (err)
! 364: dprintf("msg error=%d\n", err);
! 365: #endif
! 366: /*
! 367: * Reply to the client.
! 368: */
! 369: msg.hdr.status = err;
! 370: err = msg_reply(obj, &msg, sizeof(struct exec_msg));
! 371: }
! 372: return 0;
! 373: }
CVSweb