*** empty log message ***
This commit is contained in:
@@ -1,141 +0,0 @@
|
||||
/* 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>
|
||||
#include <minix/dmap.h>
|
||||
|
||||
extern int errno;
|
||||
|
||||
#define EXEC_FAILED 49 /* arbitrary, recognizable status */
|
||||
#define MAX_PATH_LEN 256 /* maximum path string length */
|
||||
#define MAX_ARGS_LEN 4096 /* maximum argument string length */
|
||||
#define MAX_ARG_COUNT 1 /* parsed arguments count */
|
||||
|
||||
PRIVATE char command[MAX_PATH_LEN+1];
|
||||
PRIVATE char arg_buf[MAX_ARGS_LEN+1];
|
||||
|
||||
/*===========================================================================*
|
||||
* do_start *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_start(message *m_ptr)
|
||||
{
|
||||
message m;
|
||||
int child_proc_nr;
|
||||
int major_nr;
|
||||
enum dev_style dev_style;
|
||||
pid_t child_pid;
|
||||
char *args[MAX_ARG_COUNT+1];
|
||||
int s;
|
||||
|
||||
/* Obtain command name and parameters. */
|
||||
if (m_ptr->SRV_PATH_LEN > MAX_PATH_LEN) return(E2BIG);
|
||||
if (OK != (s=sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->SRV_PATH_ADDR,
|
||||
SELF, (vir_bytes) command, m_ptr->SRV_PATH_LEN))) return(s);
|
||||
command[m_ptr->SRV_PATH_LEN] = '\0';
|
||||
if (command[0] != '/') return(EINVAL);
|
||||
|
||||
args[0] = command;
|
||||
if (m_ptr->SRV_ARGS_LEN > 0) {
|
||||
if (m_ptr->SRV_ARGS_LEN > MAX_ARGS_LEN) return(E2BIG);
|
||||
if (OK != (s=sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->SRV_ARGS_ADDR,
|
||||
SELF, (vir_bytes) arg_buf, m_ptr->SRV_ARGS_LEN))) return(s);
|
||||
arg_buf[m_ptr->SRV_ARGS_LEN] = '\0';
|
||||
args[1] = &arg_buf[0];
|
||||
args[2] = NULL;
|
||||
} else {
|
||||
args[1] = NULL;
|
||||
}
|
||||
|
||||
/* Now try to execute the new system service. Fork a new process. The child
|
||||
* process will be inhibited from running by the NO_PRIV flag. Only let the
|
||||
* child run once its privileges have been set by the parent.
|
||||
*/
|
||||
if ((s = _taskcall(PM_PROC_NR, FORK, &m)) < 0) /* use raw interface */
|
||||
report("SM", "_taskcall to PM failed", s); /* to get both */
|
||||
child_pid = m.m_type; /* - child's pid */
|
||||
child_proc_nr = m.PR_PROC_NR; /* - process nr */
|
||||
|
||||
/* Now branch for parent and child process, and check for error. */
|
||||
switch(child_pid) { /* see fork(2) */
|
||||
case 0: /* child process */
|
||||
execve(command, args, NULL); /* POSIX exec */
|
||||
report("SM", "warning, exec() failed", errno); /* shouldn't happen */
|
||||
exit(EXEC_FAILED); /* terminate child */
|
||||
break;
|
||||
case -1: /* fork failed */
|
||||
report("SM", "warning, fork() failed", errno); /* shouldn't happen */
|
||||
return(errno);
|
||||
default: /* parent process */
|
||||
if ((major_nr = m_ptr->SRV_DEV_MAJOR) > 0) { /* set driver map */
|
||||
dev_style = STYLE_DEV;
|
||||
if ((s=mapdriver(child_proc_nr, major_nr, dev_style)) < 0) {
|
||||
|
||||
#if VERBOSE
|
||||
printf("SM: '%s %s', major %d, pid %d, proc_nr %d",
|
||||
command, arg_buf, major_nr, child_pid, child_proc_nr);
|
||||
#endif
|
||||
report("SM", "couldn't map driver", errno);
|
||||
}
|
||||
}
|
||||
if ((s = _taskcall(SYSTEM, SYS_PRIVCTL, &m)) < 0) /* set privileges */
|
||||
report("SM", "_taskcall to SYSTEM failed", s); /* to let child run */
|
||||
#if VERBOSE
|
||||
printf("SM: started '%s %s', major %d, pid %d, proc_nr %d",
|
||||
command, arg_buf, major_nr, child_pid, child_proc_nr);
|
||||
#endif
|
||||
/* 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;
|
||||
|
||||
#if VERBOSE
|
||||
printf("SM: got SIGCHLD signal, doing wait to get exited child.\n");
|
||||
#endif
|
||||
|
||||
/* 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 ) {
|
||||
|
||||
#if VERBOSE
|
||||
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));
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
return(OK);
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
/* Function prototypes. */
|
||||
|
||||
/* sm.c */
|
||||
_PROTOTYPE( void main, (void));
|
||||
|
||||
/* manager.c */
|
||||
_PROTOTYPE( int do_exit, (message *m));
|
||||
_PROTOTYPE( int do_start, (message *m));
|
||||
_PROTOTYPE( int do_stop, (message *m));
|
||||
|
||||
@@ -1,179 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <minix/config.h>
|
||||
#include <minix/com.h>
|
||||
#include <minix/const.h>
|
||||
#include <minix/type.h>
|
||||
#include <minix/ipc.h>
|
||||
#include <minix/syslib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
/* This array defines all known requests. */
|
||||
PRIVATE char *known_requests[] = {
|
||||
"up",
|
||||
"down",
|
||||
"catch for illegal requests"
|
||||
};
|
||||
#define ILLEGAL_REQUEST sizeof(known_requests)/sizeof(char *)
|
||||
|
||||
/* Global error number set for failed system calls. */
|
||||
#define OK 0
|
||||
extern int errno;
|
||||
|
||||
/* Define names for arguments provided to this utility. The first few
|
||||
* arguments are required and have a known index. Thereafter, some optional
|
||||
* argument pairs like "-args arglist" follow.
|
||||
*/
|
||||
#define ARG_NAME 0 /* own application name */
|
||||
#define ARG_REQUEST 1 /* request to perform */
|
||||
#define ARG_PATH 2 /* binary of system service */
|
||||
|
||||
#define MIN_ARG_COUNT 3 /* minimum number of arguments */
|
||||
|
||||
#define ARG_ARGS "-args" /* list of arguments to be passed */
|
||||
#define ARG_DEV "-dev" /* major device number for drivers */
|
||||
#define ARG_PRIV "-priv" /* required privileges */
|
||||
|
||||
/* The function parse_arguments() verifies and parses the command line
|
||||
* parameters passed to this utility. Request parameters that are needed
|
||||
* are stored globally in the following variables:
|
||||
*/
|
||||
PRIVATE int req_type;
|
||||
PRIVATE char *req_path;
|
||||
PRIVATE char *req_args;
|
||||
PRIVATE int req_major;
|
||||
PRIVATE char *req_priv;
|
||||
|
||||
/* An error occurred. Report the problem, print the usage, and exit.
|
||||
*/
|
||||
PRIVATE void print_usage(char *app_name, char *problem)
|
||||
{
|
||||
printf("Warning, %s\n", problem);
|
||||
printf("Usage:\n");
|
||||
printf(" %s <request> <binary> [%s <args>] [%s <special>]\n",
|
||||
app_name, ARG_ARGS, ARG_DEV);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* An unexpected, unrecoverable error occurred. Report and exit.
|
||||
*/
|
||||
PRIVATE void panic(char *app_name, char *mess, int num)
|
||||
{
|
||||
printf("Panic in %s: %s", app_name, mess);
|
||||
if (num != NO_NUM) printf(": %d", num);
|
||||
printf("\n");
|
||||
exit(EGENERIC);
|
||||
}
|
||||
|
||||
/* Parse and verify correctness of arguments. Report problem and exit if an
|
||||
* error is found. Store needed parameters in global variables.
|
||||
*/
|
||||
PRIVATE int parse_arguments(int argc, char **argv)
|
||||
{
|
||||
struct stat stat_buf;
|
||||
int i;
|
||||
|
||||
/* Verify argument count. */
|
||||
if (! argc >= MIN_ARG_COUNT) {
|
||||
print_usage(argv[ARG_NAME], "wrong number of arguments");
|
||||
exit(EINVAL);
|
||||
}
|
||||
|
||||
/* Verify request type. */
|
||||
for (req_type=0; req_type< ILLEGAL_REQUEST; req_type++) {
|
||||
if (strcmp(known_requests[req_type],argv[ARG_REQUEST])==0) break;
|
||||
}
|
||||
if (req_type == ILLEGAL_REQUEST) {
|
||||
print_usage(argv[ARG_NAME], "illegal request type");
|
||||
exit(ENOSYS);
|
||||
}
|
||||
|
||||
/* Verify the name of the binary of the system service. */
|
||||
req_path = argv[ARG_PATH];
|
||||
if (req_path[0] != '/') {
|
||||
print_usage(argv[ARG_NAME], "binary should be absolute path");
|
||||
exit(EINVAL);
|
||||
}
|
||||
if (stat(req_path, &stat_buf) == -1) {
|
||||
print_usage(argv[ARG_NAME], "couldn't get status of binary");
|
||||
exit(errno);
|
||||
}
|
||||
if (! (stat_buf.st_mode & S_IFREG)) {
|
||||
print_usage(argv[ARG_NAME], "binary is not a regular file");
|
||||
exit(EINVAL);
|
||||
}
|
||||
|
||||
/* Check optional arguments that come in pairs like "-args arglist". */
|
||||
for (i=MIN_ARG_COUNT; i<argc; i=i+2) {
|
||||
if (! (i+1 < argc)) {
|
||||
print_usage(argv[ARG_NAME], "optional argument not complete");
|
||||
exit(EINVAL);
|
||||
}
|
||||
if (strcmp(argv[i], ARG_ARGS)==0) {
|
||||
req_args = argv[i+1];
|
||||
}
|
||||
else if (strcmp(argv[i], ARG_DEV)==0) {
|
||||
if (stat(argv[i+1], &stat_buf) == -1) {
|
||||
print_usage(argv[ARG_NAME], "couldn't get status of device node");
|
||||
exit(errno);
|
||||
}
|
||||
if ( ! (stat_buf.st_mode & (S_IFBLK | S_IFCHR))) {
|
||||
print_usage(argv[ARG_NAME], "special file is not a device node");
|
||||
exit(EINVAL);
|
||||
}
|
||||
req_major = (stat_buf.st_rdev >> MAJOR) & BYTE;
|
||||
}
|
||||
else if (strcmp(argv[i], ARG_ARGS)==0) {
|
||||
req_priv = argv[i+1];
|
||||
}
|
||||
else {
|
||||
print_usage(argv[ARG_NAME], "unknown optional argument given");
|
||||
exit(EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the request number if no error were found. */
|
||||
return(i);
|
||||
}
|
||||
|
||||
/* Main program.
|
||||
*/
|
||||
PUBLIC int main(int argc, char **argv)
|
||||
{
|
||||
message m;
|
||||
int result;
|
||||
int s;
|
||||
|
||||
/* Verify and parse the command line arguments. All arguments are checked
|
||||
* here. If an error occurs, the problem is reported and exit(2) is called.
|
||||
* all needed parameters to perform the request are extracted and stored
|
||||
* global variables.
|
||||
*/
|
||||
parse_arguments(argc, argv);
|
||||
|
||||
/* Arguments seem fine. Try to perform the request. Only valid requests
|
||||
* should end up here. The default is used for not yet supported requests.
|
||||
*/
|
||||
switch(req_type+SRV_RQ_BASE) {
|
||||
case SRV_UP:
|
||||
m.SRV_PATH_ADDR = req_path;
|
||||
m.SRV_PATH_LEN = strlen(req_path);
|
||||
m.SRV_ARGS_ADDR = req_args;
|
||||
m.SRV_ARGS_LEN = strlen(req_args);
|
||||
m.SRV_DEV_MAJOR = req_major;
|
||||
if (OK != (s=_taskcall(SM_PROC_NR, SRV_UP, &m)))
|
||||
panic(argv[ARG_NAME], "sendrec to manager server failed", s);
|
||||
result = m.m_type;
|
||||
break;
|
||||
case SRV_DOWN:
|
||||
case SRV_STATUS:
|
||||
default:
|
||||
print_usage(argv[ARG_NAME], "request is not yet supported");
|
||||
result = EGENERIC;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
130
servers/sm/sm.c
130
servers/sm/sm.c
@@ -1,130 +0,0 @@
|
||||
/* 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_SIG:
|
||||
/* 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 SRV_UP:
|
||||
result = do_start(&m_in);
|
||||
break;
|
||||
case SRV_DOWN:
|
||||
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);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* 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);
|
||||
}
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
/* Header file for the system service manager server.
|
||||
*
|
||||
* Created:
|
||||
* Jul 22, 2005 by Jorrit N. Herder
|
||||
*/
|
||||
|
||||
#define _SYSTEM 1 /* get OK and negative error codes */
|
||||
#define _MINIX 1 /* tell headers to include MINIX stuff */
|
||||
|
||||
#define VERBOSE 0 /* display diagnostics */
|
||||
|
||||
#include <ansi.h>
|
||||
#include <sys/types.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <minix/callnr.h>
|
||||
#include <minix/config.h>
|
||||
#include <minix/type.h>
|
||||
#include <minix/const.h>
|
||||
#include <minix/com.h>
|
||||
#include <minix/syslib.h>
|
||||
#include <minix/sysutil.h>
|
||||
#include <minix/keymap.h>
|
||||
#include <minix/bitmap.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "proto.h"
|
||||
|
||||
Reference in New Issue
Block a user