|
|||
Prex Home / Browse Source - Prex Version: 0.9.0 |
|||
root/usr/server/proc/main.c/* [<][>][^][v][top][bottom][index][help] */DEFINITIONSThis source file includes following definitions.
1 /* 2 * Copyright (c) 2005-2008, 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 * Process server: 32 * 33 * A process server is responsible to handle process ID, group 34 * ID, signal and fork()/exec() state. Since Prex microkernel 35 * does not have the concept about process or process group, the 36 * process server will map each Prex task to POSIX process. 37 * 38 * Prex does not support uid (user ID) and gid (group ID) because 39 * it runs only in a single user mode. The value of uid and gid is 40 * always returned as 1 for all process. These are handled by the 41 * library stubs, and it is out of scope in this server. 42 * 43 * Important Notice: 44 * This server is made as a single thread program to reduce many 45 * locks and to keep the code clean. So, we should not block in 46 * the kernel for any service. If some service must wait an 47 * event, it should wait within the library stub in the client 48 * application. 49 */ 50 51 #include <sys/prex.h> 52 #include <sys/param.h> 53 #include <ipc/proc.h> 54 #include <ipc/ipc.h> 55 #include <ipc/exec.h> 56 #include <sys/list.h> 57 58 #include <unistd.h> 59 #include <errno.h> 60 #include <stdlib.h> 61 #include <string.h> 62 63 #include "proc.h" 64 65 /* forward declarations */ 66 static int proc_getpid(struct msg *); 67 static int proc_getppid(struct msg *); 68 static int proc_getpgid(struct msg *); 69 static int proc_setpgid(struct msg *); 70 static int proc_getsid(struct msg *); 71 static int proc_setsid(struct msg *); 72 static int proc_fork(struct msg *); 73 static int proc_exit(struct msg *); 74 static int proc_stop(struct msg *); 75 static int proc_waitpid(struct msg *); 76 static int proc_kill(struct msg *); 77 static int proc_exec(struct msg *); 78 static int proc_pstat(struct msg *); 79 static int proc_register(struct msg *); 80 static int proc_setinit(struct msg *); 81 static int proc_trace(struct msg *); 82 static int proc_boot(struct msg *); 83 static int proc_shutdown(struct msg *); 84 static int proc_noop(struct msg *); 85 static int proc_debug(struct msg *); 86 87 /* 88 * Message mapping 89 */ 90 struct msg_map { 91 int code; 92 int (*func)(struct msg *); 93 }; 94 95 static const struct msg_map procmsg_map[] = { 96 {PS_GETPID, proc_getpid}, 97 {PS_GETPPID, proc_getppid}, 98 {PS_GETPGID, proc_getpgid}, 99 {PS_SETPGID, proc_setpgid}, 100 {PS_GETSID, proc_getsid}, 101 {PS_SETSID, proc_setsid}, 102 {PS_FORK, proc_fork}, 103 {PS_EXIT, proc_exit}, 104 {PS_STOP, proc_stop}, 105 {PS_WAITPID, proc_waitpid}, 106 {PS_KILL, proc_kill}, 107 {PS_EXEC, proc_exec}, 108 {PS_PSTAT, proc_pstat}, 109 {PS_REGISTER, proc_register}, 110 {PS_SETINIT, proc_setinit}, 111 {PS_TRACE, proc_trace}, 112 {STD_BOOT, proc_boot}, 113 {STD_SHUTDOWN, proc_shutdown}, 114 {STD_DEBUG, proc_debug}, 115 {0, proc_noop}, 116 }; 117 118 static struct proc proc0; /* process data of this server (pid=0) */ 119 static struct pgrp pgrp0; /* process group for first process */ 120 static struct session session0; /* session for first process */ 121 122 struct proc initproc; /* process slot for init process (pid=1) */ 123 struct proc *curproc; /* current (caller) process */ 124 struct list allproc; /* list of all processes */ 125 126 static int 127 proc_getpid(struct msg *msg) 128 { 129 pid_t pid; 130 131 pid = sys_getpid(); 132 133 msg->data[0] = (int)pid; 134 return 0; 135 } 136 137 static int 138 proc_getppid(struct msg *msg) 139 { 140 pid_t ppid; 141 142 ppid = sys_getppid(); 143 144 msg->data[0] = (int)ppid; 145 return 0; 146 } 147 148 static int 149 proc_getpgid(struct msg *msg) 150 { 151 pid_t pid, pgid; 152 int error; 153 154 pid = (pid_t)msg->data[0]; 155 156 error = sys_getpgid(pid, &pgid); 157 if (error) 158 return error; 159 160 msg->data[0] = (int)pgid; 161 return 0; 162 } 163 164 static int 165 proc_setpgid(struct msg *msg) 166 { 167 pid_t pid, pgid; 168 169 pid = (pid_t)msg->data[0]; 170 pgid = (pid_t)msg->data[1]; 171 172 return sys_setpgid(pid, pgid); 173 } 174 175 static int 176 proc_getsid(struct msg *msg) 177 { 178 pid_t pid, sid; 179 int error; 180 181 pid = (pid_t)msg->data[0]; 182 183 error = sys_getsid(pid, &sid); 184 if (error) 185 return error; 186 187 msg->data[0] = (int)sid; 188 return 0; 189 } 190 191 static int 192 proc_setsid(struct msg *msg) 193 { 194 pid_t sid; 195 int error; 196 197 error = sys_setsid(&sid); 198 if (error) 199 return error; 200 201 msg->data[0] = (int)sid; 202 return 0; 203 } 204 205 static int 206 proc_fork(struct msg *msg) 207 { 208 task_t child; 209 int vfork; 210 pid_t pid; 211 int error; 212 213 child = (task_t)msg->data[0]; 214 vfork = msg->data[1]; 215 216 error = sys_fork(child, vfork, &pid); 217 if (error) 218 return error; 219 220 msg->data[0] = (int)pid; 221 return 0; 222 } 223 224 static int 225 proc_exit(struct msg *msg) 226 { 227 int exitcode; 228 229 exitcode = msg->data[0]; 230 231 return sys_exit(exitcode); 232 } 233 234 static int 235 proc_stop(struct msg *msg) 236 { 237 int exitcode; 238 239 exitcode = msg->data[0]; 240 241 return stop(exitcode); 242 } 243 244 static int 245 proc_waitpid(struct msg *msg) 246 { 247 pid_t pid, pid_child; 248 int options, status, error; 249 250 pid = (pid_t)msg->data[0]; 251 options = msg->data[1]; 252 253 error = sys_waitpid(pid, &status, options, &pid_child); 254 if (error) 255 return error; 256 257 msg->data[0] = pid_child; 258 msg->data[1] = status; 259 260 return 0; 261 } 262 263 static int 264 proc_kill(struct msg *msg) 265 { 266 pid_t pid; 267 int sig; 268 269 pid = (pid_t)msg->data[0]; 270 sig = msg->data[1]; 271 272 return sys_kill(pid, sig); 273 } 274 275 /* 276 * exec() - Update pid to track the mapping with task id. 277 * The almost all work is done by a exec server for exec() 278 * emulation. So, there is not so many jobs here... 279 */ 280 static int 281 proc_exec(struct msg *msg) 282 { 283 task_t orgtask, newtask; 284 struct proc *p, *parent; 285 286 DPRINTF(("proc: exec pid=%x\n", curproc->p_pid)); 287 288 orgtask = (task_t)msg->data[0]; 289 newtask = (task_t)msg->data[1]; 290 if ((p = task_to_proc(orgtask)) == NULL) 291 return EINVAL; 292 293 p_remove(p); 294 p->p_task = newtask; 295 p_add(p); 296 p->p_invfork = 0; 297 p->p_stackbase = (void *)msg->data[2]; 298 299 if (p->p_flag & P_TRACED) { 300 DPRINTF(("proc: traced!\n")); 301 sys_debug(DBGC_TRACE, (void *)newtask); 302 } 303 304 parent = p->p_parent; 305 if (parent != NULL && parent->p_vforked) 306 vfork_end(parent); 307 308 return 0; 309 } 310 311 /* 312 * Get process status. 313 */ 314 static int 315 proc_pstat(struct msg *msg) 316 { 317 task_t task; 318 struct proc *p; 319 320 DPRINTF(("proc: pstat task=%x\n", msg->data[0])); 321 322 task = (task_t)msg->data[0]; 323 if ((p = task_to_proc(task)) == NULL) 324 return EINVAL; 325 326 msg->data[0] = (int)p->p_pid; 327 msg->data[2] = (int)p->p_stat; 328 if (p->p_parent == NULL) 329 msg->data[1] = (int)0; 330 else 331 msg->data[1] = (int)p->p_parent->p_pid; 332 return 0; 333 } 334 335 /* 336 * Set init process (pid=1). 337 */ 338 static int 339 proc_setinit(struct msg *msg) 340 { 341 342 DPRINTF(("proc: setinit task=%x\n", msg->hdr.task)); 343 344 /* Check client's capability. */ 345 if (task_chkcap(msg->hdr.task, CAP_PROTSERV) != 0) 346 return EPERM; 347 348 if (initproc.p_stat == SRUN) 349 return EPERM; 350 351 curproc = &proc0; 352 newproc(&initproc, 1, msg->hdr.task); 353 354 return 0; 355 } 356 357 /* 358 * Set trace flag 359 */ 360 static int 361 proc_trace(struct msg *msg) 362 { 363 task_t task = msg->hdr.task; 364 struct proc *p; 365 366 DPRINTF(("proc: trace task=%x\n", task)); 367 368 if ((p = task_to_proc(task)) == NULL) 369 return EINVAL; 370 371 /* Toggle trace flag */ 372 p->p_flag ^= P_TRACED; 373 return 0; 374 } 375 376 /* 377 * Register boot task. 378 */ 379 static int 380 proc_register(struct msg *msg) 381 { 382 struct proc *p; 383 384 DPRINTF(("proc: register task=%x\n", msg->hdr.task)); 385 386 /* Check client's capability. */ 387 if (task_chkcap(msg->hdr.task, CAP_PROTSERV) != 0) 388 return EPERM; 389 390 if ((p = malloc(sizeof(struct proc))) == NULL) 391 return ENOMEM; 392 memset(p, 0, sizeof(struct proc)); 393 394 curproc = &proc0; 395 if (newproc(p, 0, msg->hdr.task)) 396 sys_panic("proc: fail to register boot task"); 397 398 DPRINTF(("proc: register pid=%d\n", p->p_pid)); 399 return 0; 400 } 401 402 /* 403 * Ready to boot 404 */ 405 static int 406 proc_boot(struct msg *msg) 407 { 408 object_t obj; 409 struct bind_msg m; 410 411 DPRINTF(("proc: boot\n")); 412 413 /* Check client's capability. */ 414 if (task_chkcap(msg->hdr.task, CAP_PROTSERV) != 0) 415 return EPERM; 416 417 /* 418 * Request exec server to bind an appropriate 419 * capability for us. 420 */ 421 if (object_lookup("!exec", &obj) != 0) 422 sys_panic("proc: no exec found"); 423 m.hdr.code = EXEC_BINDCAP; 424 strlcpy(m.path, "/boot/proc", sizeof(m.path)); 425 msg_send(obj, &m, sizeof(m)); 426 427 return 0; 428 } 429 430 static int 431 proc_shutdown(struct msg *msg) 432 { 433 434 DPRINTF(("proc: shutdown\n")); 435 return 0; 436 } 437 438 static int 439 proc_noop(struct msg *msg) 440 { 441 442 return 0; 443 } 444 445 static int 446 proc_debug(struct msg *msg) 447 { 448 #ifdef DEBUG_PROC 449 struct proc *p; 450 list_t n; 451 char stat[][5] = { " ", "RUN ", "ZOMB", "STOP" }; 452 453 dprintf("<Process Server>\n"); 454 dprintf("Dump process\n"); 455 dprintf(" pid ppid pgid sid stat task\n"); 456 dprintf(" ------ ------ ------ ------ ---- --------\n"); 457 458 for (n = list_first(&allproc); n != &allproc; 459 n = list_next(n)) { 460 p = list_entry(n, struct proc, p_link); 461 dprintf(" %6d %6d %6d %6d %s %08x\n", p->p_pid, 462 p->p_parent->p_pid, p->p_pgrp->pg_pgid, 463 p->p_pgrp->pg_session->s_leader->p_pid, 464 stat[p->p_stat], p->p_task); 465 } 466 dprintf("\n"); 467 #endif 468 return 0; 469 } 470 471 static void 472 proc_init(void) 473 { 474 475 list_init(&allproc); 476 tty_init(); 477 table_init(); 478 } 479 480 481 /* 482 * Initialize process 0. 483 */ 484 static void 485 proc0_init(void) 486 { 487 struct proc *p; 488 struct pgrp *pg; 489 struct session *sess; 490 491 p = &proc0; 492 pg = &pgrp0; 493 sess = &session0; 494 495 pg->pg_pgid = 0; 496 list_init(&pg->pg_members); 497 pg_add(pg); 498 499 pg->pg_session = sess; 500 sess->s_refcnt = 1; 501 sess->s_leader = p; 502 sess->s_ttyhold = 0; 503 504 p->p_parent = 0; 505 p->p_pgrp = pg; 506 p->p_stat = SRUN; 507 p->p_exitcode = 0; 508 p->p_pid = 0; 509 p->p_task = task_self(); 510 p->p_vforked = 0; 511 p->p_invfork = 0; 512 513 list_init(&p->p_children); 514 p_add(p); 515 list_insert(&pg->pg_members, &p->p_pgrp_link); 516 } 517 518 /* 519 * Main routine for process service. 520 */ 521 int 522 main(int argc, char *argv[]) 523 { 524 static struct msg msg; 525 const struct msg_map *map; 526 object_t obj; 527 int error; 528 529 sys_log("Starting process server\n"); 530 531 /* Boost thread priority. */ 532 thread_setpri(thread_self(), PRI_PROC); 533 534 /* Initialize process and pgrp structures. */ 535 proc_init(); 536 537 /* Create process 0 (process server). */ 538 proc0_init(); 539 540 /* Create an object to expose our service. */ 541 if ((error = object_create("!proc", &obj)) != 0) 542 sys_panic("proc: fail to create object"); 543 544 /* 545 * Message loop 546 */ 547 for (;;) { 548 /* 549 * Wait for an incoming request. 550 */ 551 error = msg_receive(obj, &msg, sizeof(msg)); 552 if (error) 553 continue; 554 555 DPRINTF(("proc: msg code=%x task=%x\n", 556 msg.hdr.code, msg.hdr.task)); 557 558 error = EINVAL; 559 map = &procmsg_map[0]; 560 while (map->code != 0) { 561 if (map->code == msg.hdr.code) { 562 563 /* Get current process */ 564 curproc = task_to_proc(msg.hdr.task); 565 error = (*map->func)(&msg); 566 break; 567 } 568 map++; 569 } 570 /* 571 * Reply to the client. 572 */ 573 msg.hdr.status = error; 574 msg_reply(obj, &msg, sizeof(msg)); 575 #ifdef DEBUG_PROC 576 if (error) { 577 DPRINTF(("proc: msg code=%x error=%d\n", 578 map->code, error)); 579 } 580 #endif 581 } 582 } /* [<][>][^][v][top][bottom][index][help] */ | |||
Copyright© 2005-2009 Kohsuke Ohtani |