[BACK]Return to main.c CVS log [TXT][DIR] Up to [local] / prex-old / usr / server / exec

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