--- /dev/null
+/* This file contains procedures to manage the system processes.
+ *
+ * The entry points into this file are
+ * do_start:
+ * do_stop:
+ * do_exit: a child of this server exited
+ *
+ * Changes:
+ * Jul 22, 2005: Created (Jorrit N. Herder)
+ */
+
+#include "sm.h"
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+extern int errno;
+
+#define EXEC_FAILED 49 /* recognizable exit status */
+
+/*===========================================================================*
+ * do_start *
+ *===========================================================================*/
+PUBLIC int do_start(message *m_ptr)
+{
+ pid_t child_pid;
+ char command[255] = "/usr/sbin/is";
+
+ /* Obtain command name and parameters. */
+
+
+ /* Now try to execute the new system service. */
+ child_pid = fork(); /* normal POSIX fork */
+ switch(child_pid) {
+ case 0: /* child process, start system service */
+ execve(command, NULL, NULL); /* POSIX exec */
+ report("SM", "warning, exec() failed", errno); /* shouldn't happen */
+ exit(EXEC_FAILED); /* terminate child */
+ break;
+ case -1: /* fork failed, report error */
+ report("SM", "warning, fork() failed", errno); /* shouldn't happen */
+ return(errno);
+ default: /* parent process */
+ report("SM", "new process forked, pid", child_pid);
+ /* update tables */
+ }
+ return(OK);
+}
+
+
+/*===========================================================================*
+ * do_stop *
+ *===========================================================================*/
+PUBLIC int do_stop(message *m_ptr)
+{
+ return(ENOSYS);
+}
+
+/*===========================================================================*
+ * do_exit *
+ *===========================================================================*/
+PUBLIC int do_exit(message *m_ptr)
+{
+ pid_t exit_pid;
+ int exit_status;
+
+ printf("SM: got SIGCHLD signal, doing wait to get exited child.\n");
+
+ /* See which child exited and what the exit status is. This is done in a
+ * loop because multiple childs may have exited, all reported by one
+ * SIGCHLD signal. The WNOHANG options is used to prevent blocking if,
+ * somehow, no exited child can be found.
+ */
+ while ( (exit_pid = waitpid(-1, &exit_status, WNOHANG)) != 0 ) {
+
+ printf("SM: pid %d,", exit_pid);
+ if (WIFSIGNALED(exit_status)) {
+ printf("killed, signal number %d\n", WTERMSIG(exit_status));
+ } else if (WIFEXITED(exit_status)) {
+ printf("normal exit, status %d\n", WEXITSTATUS(exit_status));
+ }
+ }
+ return(OK);
+}
+
+
--- /dev/null
+/* System Process Manager.
+ *
+ * Created:
+ * Jul 22, 2005 by Jorrit N. Herder
+ */
+
+#include "sm.h"
+
+/* Set debugging level to 0, 1, or 2 to see no, some, all debug output. */
+#define DEBUG_LEVEL 1
+#define DPRINTF if (DEBUG_LEVEL > 0) printf
+
+/* Allocate space for the global variables. */
+message m_in; /* the input message itself */
+message m_out; /* the output message used for reply */
+int who; /* caller's proc number */
+int callnr; /* system call number */
+
+/* Declare some local functions. */
+FORWARD _PROTOTYPE(void init_server, (void) );
+FORWARD _PROTOTYPE(void get_work, (void) );
+FORWARD _PROTOTYPE(void reply, (int whom, int result) );
+
+/*===========================================================================*
+ * main *
+ *===========================================================================*/
+PUBLIC void main(void)
+{
+/* This is the main routine of this service. The main loop consists of
+ * three major activities: getting new work, processing the work, and
+ * sending the reply. The loop never terminates, unless a panic occurs.
+ */
+ int result;
+ sigset_t sigset;
+
+ /* Initialize the server, then go to work. */
+ init_server();
+
+ /* Main loop - get work and do it, forever. */
+ while (TRUE) {
+
+ /* Wait for incoming message, sets 'callnr' and 'who'. */
+ get_work();
+
+ switch (callnr) {
+ case SYS_EVENT:
+ /* Signals are passed by means of a notification message from SYSTEM.
+ * Extract the map of pending signals from the notification argument.
+ */
+ sigset = (sigset_t) m_in.NOTIFY_ARG;
+
+ if (sigismember(&sigset, SIGCHLD)) {
+ /* A child of this server exited. Take action. */
+ do_exit(&m_in);
+ }
+ if (sigismember(&sigset, SIGUSR1)) {
+ do_start(&m_in);
+ }
+ if (sigismember(&sigset, SIGTERM)) {
+ /* Nothing to do on shutdown. */
+ }
+ if (sigismember(&sigset, SIGKSTOP)) {
+ /* Nothing to do on shutdown. */
+ }
+ continue;
+ case START_SERVICE:
+ result = do_start(&m_in);
+ break;
+ case STOP_SERVICE:
+ result = do_stop(&m_in);
+ break;
+ default:
+ printf("Warning, SM got unexpected request %d from %d\n",
+ m_in.m_type, m_in.m_source);
+ result = EINVAL;
+ }
+
+ /* Finally send reply message, unless disabled. */
+ if (result != EDONTREPLY) {
+ reply(who, result);
+ }
+ }
+}
+
+
+/*===========================================================================*
+ * init_server *
+ *===========================================================================*/
+PRIVATE void init_server(void)
+{
+/* Initialize the information service. */
+ int i, s;
+ struct sigaction sa;
+
+ /* Install signal handlers. Ask PM to transform signal into message. */
+ sa.sa_handler = SIG_MESS;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ if (sigaction(SIGCHLD, &sa, NULL)<0) panic("SM","sigaction failed", errno);
+ if (sigaction(SIGTERM, &sa, NULL)<0) panic("SM","sigaction failed", errno);
+ if (sigaction(SIGABRT, &sa, NULL)<0) panic("SM","sigaction failed", errno);
+ if (sigaction(SIGHUP, &sa, NULL)<0) panic("SM","sigaction failed", errno);
+
+ /* Report successfull start. */
+ report("SM","system service manager successfully initialized", NO_NUM);
+}
+
+
+/*===========================================================================*
+ * get_work *
+ *===========================================================================*/
+PRIVATE void get_work()
+{
+ int status = 0;
+ status = receive(ANY, &m_in); /* this blocks until message arrives */
+ if (OK != status)
+ panic("SM","failed to receive message!", status);
+ who = m_in.m_source; /* message arrived! set sender */
+ callnr = m_in.m_type; /* set function call number */
+}
+
+
+/*===========================================================================*
+ * reply *
+ *===========================================================================*/
+PRIVATE void reply(who, result)
+int who; /* destination */
+int result; /* report result to replyee */
+{
+ int send_status;
+ m_out.m_type = result; /* build reply message */
+ send_status = send(who, &m_out); /* send the message */
+ if (OK != send_status)
+ panic("SM", "unable to send reply!", send_status);
+}
+
+
+