Prex Home / Browse Source - Prex Version: 0.9.0

root/usr/server/proc/main.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. proc_getpid
  2. proc_getppid
  3. proc_getpgid
  4. proc_setpgid
  5. proc_getsid
  6. proc_setsid
  7. proc_fork
  8. proc_exit
  9. proc_stop
  10. proc_waitpid
  11. proc_kill
  12. proc_exec
  13. proc_pstat
  14. proc_setinit
  15. proc_trace
  16. proc_register
  17. proc_boot
  18. proc_shutdown
  19. proc_noop
  20. proc_debug
  21. proc_init
  22. proc0_init
  23. main

   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] */