Annotation of prex-old/usr/server/exec/main.c, Revision 1.1.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