From d4097ed3d55c2787ab2ec55270c652e94cf6e72d Mon Sep 17 00:00:00 2001 From: Justus Winter <4winter@informatik.uni-hamburg.de> Date: Tue, 23 Sep 2014 11:42:43 +0200 Subject: [PATCH] exec: add proper argument parsing, add --device-master-port If the device master port is given, a boot-time exec server can print diagnostic messages earlier. * exec/main.c (opt_device_master): New variable. (OPT_DEVICE_MASTER_PORT): New macro. (options): New set of options. (parse_opt): New function. (trivfs_append_args): Likewise. (argp): Pull the argp definition out of main. (trivfs_runtime_argp): Set, so that we respond properly to fsysopts. (open_console): Pull the code out of S_exec_init and generalize it. (main): Call open_console if a device master port is given. (S_exec_init): Call open_console. --- exec/main.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 93 insertions(+), 13 deletions(-) diff --git a/exec/main.c b/exec/main.c index 78faebd..784000b 100644 --- a/exec/main.c +++ b/exec/main.c @@ -45,6 +45,7 @@ int trivfs_cntl_nportclasses = 1; struct trivfs_control *fsys; char **save_argv; +mach_port_t opt_device_master; #include "exec_S.h" @@ -104,16 +105,104 @@ deadboot (void *p) ports_enable_class (trivfs_cntl_portclasses[0]); } +#define OPT_DEVICE_MASTER_PORT (-1) + +static const struct argp_option options[] = +{ + {"device-master-port", OPT_DEVICE_MASTER_PORT, "PORT", 0, + "If specified, a boot-time exec server can print " + "diagnostic messages earlier.", 0}, + {0} +}; + +static error_t +parse_opt (int opt, char *arg, struct argp_state *state) +{ + switch (opt) + { + default: + return ARGP_ERR_UNKNOWN; + case ARGP_KEY_INIT: + case ARGP_KEY_SUCCESS: + case ARGP_KEY_ERROR: + break; + + case OPT_DEVICE_MASTER_PORT: + opt_device_master = atoi (arg); + break; + } + return 0; +} + +/* This will be called from libtrivfs to help construct the answer + to an fsys_get_options RPC. */ +error_t +trivfs_append_args (struct trivfs_control *fsys, + char **argz, size_t *argz_len) +{ + error_t err = 0; + char *opt; + + if (MACH_PORT_VALID (opt_device_master)) + { + asprintf (&opt, "--device-master-port=%d", opt_device_master); + + if (opt) + { + err = argz_add (argz, argz_len, opt); + free (opt); + } + } + + return err; +} + +static struct argp argp = +{ options, parse_opt, 0, "Hurd standard exec server." }; + +/* Setting this variable makes libtrivfs use our argp to + parse options passed in an fsys_set_options RPC. */ +struct argp *trivfs_runtime_argp = &argp; + +/* Get our stderr set up to print on the console, in case we have to + panic or something. */ +error_t +open_console (mach_port_t device_master) +{ + static int got_console = 0; + mach_port_t cons; + error_t err; + + if (got_console) + return 0; + + err = device_open (device_master, D_READ|D_WRITE, "console", &cons); + if (err) + return err; + + stdin = mach_open_devstream (cons, "r"); + stdout = stderr = mach_open_devstream (cons, "w"); + + got_console = 1; + mach_port_deallocate (mach_task_self (), cons); + return 0; +} int main (int argc, char **argv) { error_t err; mach_port_t bootstrap; - struct argp argp = { 0, 0, 0, "Hurd standard exec server." }; argp_parse (&argp, argc, argv, 0, 0, 0); + if (MACH_PORT_VALID (opt_device_master)) + { + err = open_console (opt_device_master); + assert_perror (err); + mach_port_deallocate (mach_task_self (), opt_device_master); + } + save_argv = argv; task_get_bootstrap_port (mach_task_self (), &bootstrap); @@ -236,18 +325,9 @@ S_exec_init (struct trivfs_protid *protid, err = get_privileged_ports (&host_priv, &device_master); assert_perror (err); - { - /* Get our stderr set up to print on the console, in case we have - to panic or something. */ - mach_port_t cons; - error_t err; - err = device_open (device_master, D_READ|D_WRITE, "console", &cons); - assert_perror (err); - mach_port_deallocate (mach_task_self (), device_master); - stdin = mach_open_devstream (cons, "r"); - stdout = stderr = mach_open_devstream (cons, "w"); - mach_port_deallocate (mach_task_self (), cons); - } + err = open_console (device_master); + assert_perror (err); + mach_port_deallocate (mach_task_self (), device_master); proc_register_version (procserver, host_priv, "exec", "", HURD_VERSION); -- 2.1.0