Annotation of prex/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: * Check the server existence. Timeout is 1sec.
! 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] = (int)org_task;
! 110: m.data[1] = (int)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] = (int)org_task;
! 118: m.data[1] = (int)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->el_name != NULL; ldr++) {
! 178: if (ldr->el_probe(header) == 0)
! 179: break;
! 180: /* Check next format */
! 181: }
! 182: if (ldr->el_name == NULL) {
! 183: DPRINTF(("Unsupported file format\n"));
! 184: err = ENOEXEC;
! 185: goto err2;
! 186: }
! 187: DPRINTF(("exec loader=%s\n", ldr->el_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:
! 214: /*
! 215: * XXX: Temporary removed...
! 216: */
! 217: /* cap &= CONFIG_CAP_MASK; */
! 218:
! 219: task_setcap(new_task, &cap);
! 220:
! 221: if ((err = thread_create(new_task, &th)) != 0)
! 222: goto err3;
! 223:
! 224: /*
! 225: * Allocate stack and build arguments on it.
! 226: */
! 227: err = vm_allocate(new_task, &stack, USTACK_SIZE, 1);
! 228: if (err)
! 229: goto err4;
! 230: if ((err = build_args(new_task, stack, msg, &sp)) != 0)
! 231: goto err5;
! 232:
! 233: /*
! 234: * Load file image.
! 235: */
! 236: if ((err = ldr->el_load(header, new_task, fd, (void **)&entry)) != 0)
! 237: goto err5;
! 238: if ((err = thread_load(th, entry, sp)) != 0)
! 239: goto err5;
! 240:
! 241: /*
! 242: * Notify to servers.
! 243: */
! 244: notify_server(old_task, new_task, stack);
! 245:
! 246: /*
! 247: * Terminate old task.
! 248: */
! 249: task_terminate(old_task);
! 250:
! 251: /*
! 252: * Set him running.
! 253: */
! 254: thread_resume(th);
! 255:
! 256: close(fd);
! 257: DPRINTF(("exec complete successfully\n"));
! 258: return 0;
! 259: err5:
! 260: vm_free(new_task, stack);
! 261: err4:
! 262: thread_terminate(th);
! 263: err3:
! 264: task_terminate(new_task);
! 265: err2:
! 266: close(fd);
! 267: err1:
! 268: DPRINTF(("exec failed err=%d\n", err));
! 269: return err;
! 270: }
! 271:
! 272: /*
! 273: * Debug
! 274: */
! 275: static void
! 276: exec_debug(void)
! 277: {
! 278:
! 279: #ifdef DEBUG
! 280: /* mstat(); */
! 281: #endif
! 282: }
! 283:
! 284: /*
! 285: * Initialize all exec loaders
! 286: */
! 287: static void
! 288: exec_init(void)
! 289: {
! 290: struct exec_loader *ldr;
! 291:
! 292: for (ldr = loader_table; ldr->el_name; ldr++) {
! 293: DPRINTF(("Initialize \'%s\' loader\n", ldr->el_name));
! 294: ldr->el_init();
! 295: }
! 296: }
! 297:
! 298: /*
! 299: * Main routine for exec service.
! 300: */
! 301: int
! 302: main(int argc, char *argv[])
! 303: {
! 304: struct exec_msg msg;
! 305: object_t obj;
! 306: int err;
! 307:
! 308: sys_log("Starting Exec Server\n");
! 309:
! 310: /*
! 311: * Boost current priority
! 312: */
! 313: thread_setprio(thread_self(), PRIO_EXEC);
! 314:
! 315: /*
! 316: * Wait until system server becomes available.
! 317: */
! 318: wait_server(OBJNAME_PROC, &proc_obj);
! 319: wait_server(OBJNAME_FS, &fs_obj);
! 320:
! 321: /*
! 322: * Register to process server
! 323: */
! 324: process_init();
! 325:
! 326: /*
! 327: * Register to file server
! 328: */
! 329: fslib_init();
! 330:
! 331: /*
! 332: * Initialize everything
! 333: */
! 334: exec_init();
! 335:
! 336: /*
! 337: * Create an object to expose our service.
! 338: */
! 339: err = object_create(OBJNAME_EXEC, &obj);
! 340: if (err)
! 341: sys_panic("fail to create object");
! 342:
! 343: /*
! 344: * Message loop
! 345: */
! 346: for (;;) {
! 347: /*
! 348: * Wait for an incoming request.
! 349: */
! 350: err = msg_receive(obj, &msg, sizeof(struct exec_msg));
! 351: if (err)
! 352: continue;
! 353: /*
! 354: * Process request.
! 355: */
! 356: err = EINVAL;
! 357: switch (msg.hdr.code) {
! 358: case STD_DEBUG:
! 359: exec_debug();
! 360: err = 0;
! 361: break;
! 362:
! 363: case EX_EXEC:
! 364: err = do_exec(&msg);
! 365: break;
! 366: }
! 367: #ifdef DEBUG_EXEC
! 368: if (err)
! 369: DPRINTF(("msg error=%d\n", err));
! 370: #endif
! 371: /*
! 372: * Reply to the client.
! 373: */
! 374: msg.hdr.status = err;
! 375: err = msg_reply(obj, &msg, sizeof(struct exec_msg));
! 376: }
! 377: return 0;
! 378: }
CVSweb