Annotation of prex-old/usr/server/exec/main.c, Revision 1.1.1.1.2.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: /*
1.1.1.1.2.1! nbrk 73: * Check the server existence. Timeout is 1sec.
1.1 nbrk 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;
1.1.1.1.2.1! nbrk 109: m.data[0] = (int)org_task;
! 110: m.data[1] = (int)new_task;
1.1 nbrk 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;
1.1.1.1.2.1! nbrk 117: m.data[0] = (int)org_task;
! 118: m.data[1] = (int)new_task;
1.1 nbrk 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:
1.1.1.1.2.1! nbrk 140: DPRINTF(("do_exec: path=%s task=%x\n", msg->path, msg->hdr.task));
1.1 nbrk 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: }
1.1.1.1.2.1! nbrk 177: for (ldr = loader_table; ldr->el_name != NULL; ldr++) {
! 178: if (ldr->el_probe(header) == 0)
1.1 nbrk 179: break;
180: /* Check next format */
181: }
1.1.1.1.2.1! nbrk 182: if (ldr->el_name == NULL) {
! 183: DPRINTF(("Unsupported file format\n"));
1.1 nbrk 184: err = ENOEXEC;
185: goto err2;
186: }
1.1.1.1.2.1! nbrk 187: DPRINTF(("exec loader=%s\n", ldr->el_name));
1.1 nbrk 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);
1.1.1.1.2.1! nbrk 213:
! 214: /*
! 215: * XXX: Temporary removed...
! 216: */
1.1 nbrk 217: /* cap &= CONFIG_CAP_MASK; */
1.1.1.1.2.1! nbrk 218:
1.1 nbrk 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: */
1.1.1.1.2.1! nbrk 236: if ((err = ldr->el_load(header, new_task, fd, (void **)&entry)) != 0)
1.1 nbrk 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);
1.1.1.1.2.1! nbrk 257: DPRINTF(("exec complete successfully\n"));
1.1 nbrk 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:
1.1.1.1.2.1! nbrk 268: DPRINTF(("exec failed err=%d\n", err));
1.1 nbrk 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:
1.1.1.1.2.1! nbrk 292: for (ldr = loader_table; ldr->el_name; ldr++) {
! 293: DPRINTF(("Initialize \'%s\' loader\n", ldr->el_name));
! 294: ldr->el_init();
1.1 nbrk 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)
1.1.1.1.2.1! nbrk 369: DPRINTF(("msg error=%d\n", err));
1.1 nbrk 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