diff --git a/src/include/66/ssexec.h b/src/include/66/ssexec.h index 6691708288e62cd1b28344bbd8d69168af622d7a..696dfaafa7444d34c4ee68ec0854293d17b947ef 100644 --- a/src/include/66/ssexec.h +++ b/src/include/66/ssexec.h @@ -116,6 +116,8 @@ extern ssexec_func_t ssexec_reconfigure ; extern ssexec_func_t ssexec_reload ; extern ssexec_func_t ssexec_restart ; extern ssexec_func_t ssexec_inresolve ; +extern ssexec_func_t ssexec_resolve_service ; +extern ssexec_func_t ssexec_resolve_tree ; extern ssexec_func_t ssexec_instate ; extern ssexec_func_t ssexec_intree ; extern ssexec_func_t ssexec_inservice ; @@ -123,6 +125,8 @@ extern ssexec_func_t ssexec_boot ; extern ssexec_func_t ssexec_scanctl ; extern ssexec_func_t ssexec_scandir ; extern ssexec_func_t ssexec_tree_wrapper ; +extern ssexec_func_t ssexec_service_wrapper ; +extern ssexec_func_t ssexec_service_admin ; extern char const *usage_parse ; extern char const *help_parse ; @@ -166,6 +170,10 @@ extern char const *usage_scanctl ; extern char const *help_scanctl ; extern char const *usage_scandir ; extern char const *help_scandir ; +extern char const *usage_service_wrapper ; +extern char const *help_service_wrapper ; +extern char const *usage_service_admin ; +extern char const *help_service_admin ; extern char const *usage_66 ; #define OPTS_SUBSTART "P" @@ -176,7 +184,7 @@ extern char const *usage_66 ; #define OPTS_INIT_LEN (sizeof OPTS_INIT - 1) #define OPTS_ENABLE "fFSI" #define OPTS_ENABLE_LEN (sizeof OPTS_ENABLE - 1) -#define OPTS_DISABLE "SFR" +#define OPTS_DISABLE "S" #define OPTS_DISABLE_LEN (sizeof OPTS_DISABLE - 1) #define OPTS_START "P" #define OPTS_START_LEN (sizeof OPTS_START - 1) @@ -204,6 +212,10 @@ extern char const *usage_66 ; #define OPTS_SCANCTL_LEN (sizeof OPTS_SCANCTL - 1) #define OPTS_SCANDIR "bl:s:o:L:cB" #define OPTS_SCANDIR_LEN (sizeof OPTS_SCANDIR - 1) +#define OPTS_SERVICE_WRAPPER "" +#define OPTS_SERVICE_WRAPPER_LEN (sizeof OPTS_SERVICE_WRAPPER - 1) +#define OPTS_SERVICE_ADMIN "" +#define OPTS_SERVICE_ADMIN_LEN (sizeof OPTS_SERVICE_ADMIN - 1) diff --git a/src/lib66/exec/deps-lib/deps b/src/lib66/exec/deps-lib/deps index 5570d296e1a0480df8ecd80215431cefa62e6fff..96614ae633152379f058168675a162816b0622e0 100644 --- a/src/lib66/exec/deps-lib/deps +++ b/src/lib66/exec/deps-lib/deps @@ -6,21 +6,24 @@ ssexec_env.o ssexec_free.o ssexec_help.o ssexec_init.o -ssexec_inresolve.o ssexec_inservice.o ssexec_instate.o ssexec_intree.o ssexec_parse.o ssexec_reconfigure.o ssexec_reload.o +ssexec_resolve_service.o +ssexec_resolve_tree.o ssexec_restart.o ssexec_scanctl.o ssexec_scandir.o +ssexec_service_wrapper.o ssexec_start.o ssexec_stop.o ssexec_svctl.o ssexec_tree.o ssexec_treectl.o +ssexec_service_admin.o ssexec_tree_wrapper.o -ls6 -loblibs diff --git a/src/lib66/exec/ssexec_help.c b/src/lib66/exec/ssexec_help.c index 0ee7956f310f4cf7989980971d1f2d828b61f35b..5f8de4de75b63d0ab84db71e1ce2cb781388436c 100644 --- a/src/lib66/exec/ssexec_help.c +++ b/src/lib66/exec/ssexec_help.c @@ -43,7 +43,7 @@ char const *help_enable = " -S: enable and start the service\n" ; -char const *usage_disable = "66 disable [ -h ] [ -z ] [ -v verbosity ] [ - l live ] [ -t tree ] [ -S ] [ -F ] [ -R ] service(s)" ; +char const *usage_disable = "66 disable [ -h ] [ -z ] [ -v verbosity ] [ - l live ] [ -t tree ] [ -S ] service(s)" ; char const *help_disable = "\n" @@ -53,9 +53,7 @@ char const *help_disable = " -v: increase/decrease verbosity\n" " -l: live directory\n" " -t: name of the tree to use\n" -" -S: disable and stop the service\n" -" -F: forces to disable the service\n" -" -R: disable the service and remove its configuration and logger files\n" +" -S: disable and stop/unsupervice the service if needed\n" ; char const *usage_init = "66 init [ -h ] [ -z ] [ -v verbosity ] [ -l live ] tree" ; @@ -311,6 +309,60 @@ char const *help_inservice = " logfile: displays the contents of the log file\n" ; +/** + * + * pass -g as default + * -d -g -p become -o depth=,graph=none,reverse=,nline= + * + * + * */ +char const *usage_service_wrapper = "66 service [ -h ] [ -z ] [ -v verbosity ] [ -t tree ] status|resolve|state|remove [ -n ] [ -o name,intree,status,... ] [ -g ] [ -d depth ] [ -r ] [ -p nline ] service" ; + +char const *help_service_wrapper = +"\n" +"options :\n" +" -h: print this help\n" +" -z: use color\n" +" -v: increase/decrease verbosity\n" +" -n: do not display the field name\n" +" -o: comma separated list of field to display\n" +" -g: displays the contents field as graph\n" +" -d: limit the depth of the contents field recursion\n" +" -r: reverse the contents field\n" +" -t: only search service at the specified tree\n" +" -p: print n last lines of the log file\n" +"\n" +"valid fields for -o options are:\n" +"\n" +" name: displays the name\n" +" version: displays the version of the service\n" +" intree: displays the service's tree name\n" +" status: displays the status\n" +" type: displays the service type\n" +" description: displays the description\n" +" source: displays the source of the service's frontend file\n" +" live: displays the service's live directory\n" +" depends: displays the service's dependencies\n" +" requiredby: displays the service(s) which depends on service\n" +" extdepends: displays the service's external dependencies\n" +" optsdepends: displays the service's optional dependencies\n" +" start: displays the service's start script\n" +" stop: displays the service's stop script\n" +" envat: displays the source of the environment file\n" +" envfile: displays the contents of the environment file\n" +" logname: displays the logger's name\n" +" logdst: displays the logger's destination\n" +" logfile: displays the contents of the log file\n" +; + +char const *usage_service_admin = "66 service remove [ -h ] service" ; + +char const *help_service_admin = +"\n" +"options :\n" +" -h: print this help\n" +; + char const *usage_boot = "66 boot [ -h ] [ -z ] [ -m ] [ -s skel ] [ -l log_user ] [ -e environment ] [ -d dev ] [ -b banner ]" ; char const *help_boot = @@ -358,4 +410,4 @@ char const *help_scandir = " -o: handles owner scandir\n" ; -char const *usage_66 = "66 start|stop|unsupervise|enable|disable|init|env|parse|svctl|tree|reconfigure|reload|restart|scanctl|scandir|boot service(s)|tree" ; +char const *usage_66 = "66 start|stop|reload|restart|unsupervise|reconfigure|enable|disable|env|service|tree|init|parse|svctl|scanctl|scandir|boot|version service(s)|tree" ; diff --git a/src/lib66/exec/ssexec_inresolve.c b/src/lib66/exec/ssexec_inresolve.c deleted file mode 100644 index 2ae548c905e0d50bc397d5f6f8050cfa4a59f1ff..0000000000000000000000000000000000000000 --- a/src/lib66/exec/ssexec_inresolve.c +++ /dev/null @@ -1,448 +0,0 @@ -/* - * ssexec_inresolve.c - * - * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org> - * - * All rights reserved. - * - * This file is part of Obarun. It is subject to the license terms in - * the LICENSE file found in the top-level directory of this - * distribution. - * This file may not be copied, modified, propagated, or distributed - * except according to the terms contained in the LICENSE file./ - */ - -#include <string.h> -#include <wchar.h> - -#include <oblibs/log.h> -#include <oblibs/sastr.h> -#include <oblibs/string.h> -#include <oblibs/types.h> - -#include <skalibs/types.h> -#include <skalibs/stralloc.h> -#include <skalibs/lolstdio.h> -#include <skalibs/buffer.h> - -#include <66/resolve.h> -#include <66/ssexec.h> -#include <66/tree.h> -#include <66/service.h> -#include <66/info.h> -#include <66/utils.h> -#include <66/constants.h> -#include <66/config.h> -#include <66/state.h> - -#define MAXOPTS 84 - -static wchar_t const field_suffix[] = L" :" ; -static char fields[INFO_NKEY][INFO_FIELD_MAXLEN] = {{ 0 }} ; - -static inline unsigned int lookup (char const *const *table, char const *data) -{ - log_flow() ; - - unsigned int i = 0 ; - for (; table[i] ; i++) if (!strcmp(data, table[i])) break ; - return i ; -} - -static inline unsigned int parse_what (char const *str) -{ - log_flow() ; - - static char const *const table[] = - { - "service", - "tree", - 0 - } ; - unsigned int i = lookup(table, str) ; - if (!table[i]) i = 2 ; - return i ; -} - -static void info_display_string(char const *field, char const *str, uint32_t element, uint8_t check) -{ - info_display_field_name(field) ; - - if (check && !element) { - - if (!bprintf(buffer_1,"%s%s", log_color->warning, "None")) - log_dieusys(LOG_EXIT_SYS, "write to stdout") ; - - } else { - - if (!buffer_puts(buffer_1, str + element)) - log_dieusys(LOG_EXIT_SYS, "write to stdout") ; - } - - if (buffer_putsflush(buffer_1, "\n") == -1) - log_dieusys(LOG_EXIT_SYS, "write to stdout") ; - - -} - -static void info_display_int(char const *field, uint32_t element) -{ - info_display_field_name(field) ; - - char ui[UINT_FMT] ; - ui[uint_fmt(ui, element)] = 0 ; - - if (!buffer_puts(buffer_1, ui)) - log_dieusys(LOG_EXIT_SYS, "write to stdout") ; - - if (buffer_putsflush(buffer_1, "\n") == -1) - log_dieusys(LOG_EXIT_SYS, "write to stdout") ; -} - -static void info_display_service_field(resolve_service_t *res) -{ - info_display_string(fields[0], res->sa.s, res->name, 0) ; - info_display_string(fields[1], res->sa.s, res->description, 1) ; - info_display_string(fields[2], res->sa.s, res->version, 1) ; - info_display_int(fields[3], res->type) ; - info_display_int(fields[4], res->notify) ; - info_display_int(fields[5], res->maxdeath) ; - info_display_int(fields[6], res->earlier) ; - info_display_string(fields[7], res->sa.s, res->hiercopy, 1) ; - info_display_string(fields[8], res->sa.s, res->intree, 1) ; - info_display_string(fields[9], res->sa.s, res->ownerstr, 1) ; - info_display_int(fields[10], res->owner) ; - info_display_string(fields[11], res->sa.s, res->treename, 1) ; - info_display_string(fields[12], res->sa.s, res->user, 1) ; - info_display_string(fields[13], res->sa.s, res->inmodule, 1) ; - - info_display_string(fields[14], res->sa.s, res->path.home, 1) ; - info_display_string(fields[15], res->sa.s, res->path.frontend, 1) ; - info_display_string(fields[16], res->sa.s, res->path.tree, 1) ; - info_display_string(fields[17], res->sa.s, res->path.status, 1) ; - - info_display_string(fields[18], res->sa.s, res->dependencies.depends, 1) ; - info_display_string(fields[19], res->sa.s, res->dependencies.requiredby, 1) ; - info_display_string(fields[20], res->sa.s, res->dependencies.optsdeps, 1) ; - info_display_int(fields[21], res->dependencies.ndepends) ; - info_display_int(fields[22], res->dependencies.nrequiredby) ; - info_display_int(fields[23], res->dependencies.noptsdeps) ; - - info_display_string(fields[24], res->sa.s, res->execute.run.run, 1) ; - info_display_string(fields[25], res->sa.s, res->execute.run.run_user, 1) ; - info_display_string(fields[26], res->sa.s, res->execute.run.build, 1) ; - info_display_string(fields[27], res->sa.s, res->execute.run.shebang, 1) ; - info_display_string(fields[28], res->sa.s, res->execute.run.runas, 1) ; - info_display_string(fields[29], res->sa.s, res->execute.finish.run, 1) ; - info_display_string(fields[30], res->sa.s, res->execute.finish.run_user, 1) ; - info_display_string(fields[31], res->sa.s, res->execute.finish.build, 1) ; - info_display_string(fields[32], res->sa.s, res->execute.finish.shebang, 1) ; - info_display_string(fields[33], res->sa.s, res->execute.finish.runas, 1) ; - info_display_int(fields[34], res->execute.timeout.kill) ; - info_display_int(fields[35], res->execute.timeout.finish) ; - info_display_int(fields[36], res->execute.timeout.up) ; - info_display_int(fields[37], res->execute.timeout.down) ; - info_display_int(fields[38], res->execute.down) ; - info_display_int(fields[39], res->execute.downsignal) ; - - info_display_string(fields[40], res->sa.s, res->live.livedir, 1) ; - info_display_string(fields[41], res->sa.s, res->live.scandir, 1) ; - info_display_string(fields[42], res->sa.s, res->live.statedir, 1) ; - info_display_string(fields[43], res->sa.s, res->live.eventdir, 1) ; - info_display_string(fields[44], res->sa.s, res->live.notifdir, 1) ; - info_display_string(fields[45], res->sa.s, res->live.supervisedir, 1) ; - info_display_string(fields[46], res->sa.s, res->live.fdholderdir, 1) ; - info_display_string(fields[47], res->sa.s, res->live.oneshotddir, 1) ; - - info_display_string(fields[48], res->sa.s, res->logger.name, 1) ; - info_display_string(fields[49], res->sa.s, res->logger.destination, 1) ; - info_display_int(fields[50], res->logger.backup) ; - info_display_int(fields[51], res->logger.maxsize) ; - info_display_int(fields[52], res->logger.timestamp) ; - info_display_string(fields[53], res->sa.s, res->logger.execute.run.run, 1) ; - info_display_string(fields[54], res->sa.s, res->logger.execute.run.run_user, 1) ; - info_display_string(fields[55], res->sa.s, res->logger.execute.run.build, 1) ; - info_display_string(fields[56], res->sa.s, res->logger.execute.run.shebang, 1) ; - info_display_string(fields[57], res->sa.s, res->logger.execute.run.runas, 1) ; - info_display_int(fields[58], res->logger.execute.timeout.kill) ; - info_display_int(fields[59], res->logger.execute.timeout.finish) ; - - info_display_string(fields[60], res->sa.s, res->environ.env, 1) ; - info_display_string(fields[61], res->sa.s, res->environ.envdir, 1) ; - info_display_int(fields[62], res->environ.env_overwrite) ; - - info_display_string(fields[63], res->sa.s, res->regex.configure, 1) ; - info_display_string(fields[64], res->sa.s, res->regex.directories, 1) ; - info_display_string(fields[65], res->sa.s, res->regex.files, 1) ; - info_display_string(fields[66], res->sa.s, res->regex.infiles, 1) ; - info_display_int(fields[67], res->regex.ndirectories) ; - info_display_int(fields[68], res->regex.nfiles) ; - info_display_int(fields[69], res->regex.ninfiles) ; - -} - -int ssexec_inresolve(int argc, char const *const *argv, ssexec_t *info) -{ - int found = 0, what = 0 ; - uint8_t master = 0 ; - - char const *svname = 0 ; - char const *treename = info->treename.s ; - char atree[SS_MAX_TREENAME + 1] ; - - argc-- ; - argv++ ; - - if (argc < 2) log_usage(usage_inresolve) ; - - what = parse_what(*argv) ; - if (what == 2) - log_usage(usage_inresolve) ; - - argv++; - argc--; - svname = *argv ; - - if (!what) { - - char service_buf[MAXOPTS][INFO_FIELD_MAXLEN] = { - "name", - "description" , - "version", - "type", - "notify", - "maxdeath", - "earlier", - "hiercopy", - "intree", - "ownerstr", - "owner", - "treename", - "user" , - "inmodule", // 14 - - "home", - "frontend", - "tree", - "status", //18 - - "depends", - "requiredby", - "optsdeps", - "ndepends", - "nrequiredby", - "noptsdeps", // 24 - - "run", - "run_user", - "run_build", - "run_shebang", - "run_runas", - "finish", - "finish_user", - "finish_build", - "finish_shebang", - "finish_runas", - "timeoutkill", - "timeoutfinish", - "timeoutup", - "timeoutdown", - "down", - "downsignal", // 40 - - "livedir", - "scandir", - "statedir", - "eventdir", - "notifdir", - "supervisedir", - "fdholderdir", - "oneshotddir", //48 - - "logname" , - "logdestination" , - "logbackup" , - "logmaxsize" , - "logtimestamp" , - "logrun" , - "logrun_user" , - "logrun_build" , - "logrun_shebang" , - "logrun_runas" , - "logtimeoutkill", - "logtimeoutfinish", // 60 - - "env", - "envdir", - "env_overwrite", // 63 - - "configure", - "directories", - "files", - "infiles", - "ndirectories", - "nfiles", - "ninfiles", // 70 - - "classic", - "bundle", - "oneshot", - "module", - "enabled", - "disabled", - "contents", - "nclassic", - "nbundle", - "noneshot", - "nmodule", - "nenabled", - "ndisabled", - "ncontents" // 84 - } ; - - resolve_wrapper_t_ref wres = 0 ; - resolve_service_t res = RESOLVE_SERVICE_ZERO ; - resolve_service_master_t mres = RESOLVE_SERVICE_MASTER_ZERO ; - - if (!strcmp(svname, SS_MASTER + 1)) { - - master = 1 ; - wres = resolve_set_struct(DATA_SERVICE_MASTER, &mres) ; - - } else { - - wres = resolve_set_struct(DATA_SERVICE, &res) ; - } - - if (!master) { - - found = service_is_g(atree, svname, STATE_FLAGS_ISPARSED) ; - if (found == -1) - log_dieu(LOG_EXIT_SYS, "get information of service: ", svname, " -- please a bug report") ; - else if (!found) - log_die(LOG_EXIT_USER, svname, " is not parsed -- try to parse it first") ; - - if (!resolve_read_g(wres, info->base.s, svname)) - log_dieusys(LOG_EXIT_SYS,"read resolve file") ; - - } else { - - char solve[info->base.len + SS_SYSTEM_LEN + 1 + strlen(treename) + SS_SVDIRS_LEN + 1] ; - auto_strings(solve, info->base.s, SS_SYSTEM, "/", treename, SS_SVDIRS) ; - - if (!resolve_read(wres, solve, SS_MASTER + 1)) - log_dieusys(LOG_EXIT_SYS,"read resolve file") ; - } - - info_field_align(service_buf, fields, field_suffix,MAXOPTS) ; - - if (!master) { - - info_display_service_field(&res) ; - - } else { - - info_display_string(fields[0], mres.sa.s, mres.name, 0) ; - info_display_string(fields[70], mres.sa.s, mres.classic, 1) ; - info_display_string(fields[71], mres.sa.s, mres.bundle, 1) ; - info_display_string(fields[72], mres.sa.s, mres.oneshot, 1) ; - info_display_string(fields[73], mres.sa.s, mres.module, 1) ; - info_display_string(fields[74], mres.sa.s, mres.enabled, 1) ; - info_display_string(fields[75], mres.sa.s, mres.disabled, 1) ; - info_display_string(fields[76], mres.sa.s, mres.contents, 1) ; - - info_display_int(fields[77], mres.nclassic) ; - info_display_int(fields[78], mres.nbundle) ; - info_display_int(fields[79], mres.noneshot) ; - info_display_int(fields[80], mres.nmodule) ; - info_display_int(fields[81], mres.nenabled) ; - info_display_int(fields[82], mres.ndisabled) ; - info_display_int(fields[83], mres.ncontents) ; - } - - resolve_free(wres) ; - - } else { - - char tree_buf[MAXOPTS][INFO_FIELD_MAXLEN] = { - "name", - "depends" , - "requiredby", - "allow", - "groups", - "contents", - "ndepends", - "nrequiredby", - "nallow", - "ngroups", - "ncontents", - "init" , - "supervised", - "disen", // 14 - // Master - "enabled", - "current", - "contents", - "nenabled", - "ncontents" // 19 - } ; - - resolve_wrapper_t_ref wres = 0 ; - resolve_tree_t tres = RESOLVE_TREE_ZERO ; - resolve_tree_master_t mres = RESOLVE_TREE_MASTER_ZERO ; - - if (!strcmp(argv[0], SS_MASTER + 1)) { - - master = 1 ; - wres = resolve_set_struct(DATA_TREE_MASTER, &mres) ; - - } else { - - wres = resolve_set_struct(DATA_TREE, &tres) ; - } - - found = tree_isvalid(info->base.s, svname) ; - if (found < 0) - log_diesys(LOG_EXIT_SYS, "invalid tree directory") ; - - if (!found) - log_dieusys(LOG_EXIT_SYS, "find tree: ", svname) ; - - if (!resolve_read_g(wres, info->base.s, svname)) - log_dieusys(LOG_EXIT_SYS, "read resolve file") ; - - info_field_align(tree_buf, fields, field_suffix,MAXOPTS) ; - - if (!master) { - - info_display_string(fields[0], tres.sa.s, tres.name, 0) ; - info_display_string(fields[1], tres.sa.s, tres.depends, 1) ; - info_display_string(fields[2], tres.sa.s, tres.requiredby, 1) ; - info_display_string(fields[3], tres.sa.s, tres.allow, 1) ; - info_display_string(fields[4], tres.sa.s, tres.groups, 1) ; - info_display_string(fields[5], tres.sa.s, tres.contents, 1) ; - info_display_int(fields[6], tres.ndepends) ; - info_display_int(fields[7], tres.nrequiredby) ; - info_display_int(fields[8], tres.nallow) ; - info_display_int(fields[9], tres.ngroups) ; - info_display_int(fields[10], tres.ncontents) ; - info_display_int(fields[11], tres.init) ; - info_display_int(fields[12], tres.supervised) ; - info_display_int(fields[13], tres.disen) ; - - } else { - - info_display_string(fields[0], mres.sa.s, mres.name, 1) ; - info_display_string(fields[3], mres.sa.s, mres.allow, 1) ; - info_display_string(fields[14], mres.sa.s, mres.enabled, 1) ; - info_display_string(fields[15], mres.sa.s, mres.current, 1) ; - info_display_string(fields[16], mres.sa.s, mres.contents, 1) ; - info_display_int(fields[17], mres.nenabled) ; - info_display_int(fields[18], mres.ncontents) ; - } - - resolve_free(wres) ; - } - - return 0 ; -} diff --git a/src/lib66/exec/ssexec_resolve_service.c b/src/lib66/exec/ssexec_resolve_service.c new file mode 100644 index 0000000000000000000000000000000000000000..adec8d4acb4f21ffd524489db92e69810d848b2b --- /dev/null +++ b/src/lib66/exec/ssexec_resolve_service.c @@ -0,0 +1,275 @@ +/* + * ssexec_resolve_service.c + * + * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org> + * + * All rights reserved. + * + * This file is part of Obarun. It is subject to the license terms in + * the LICENSE file found in the top-level directory of this + * distribution. + * This file may not be copied, modified, propagated, or distributed + * except according to the terms contained in the LICENSE file./ + */ + +#include <string.h> +#include <wchar.h> + +#include <oblibs/log.h> +#include <oblibs/sastr.h> +#include <oblibs/string.h> +#include <oblibs/types.h> + +#include <skalibs/types.h> +#include <skalibs/stralloc.h> +#include <skalibs/lolstdio.h> +#include <skalibs/buffer.h> + +#include <66/resolve.h> +#include <66/ssexec.h> +#include <66/service.h> +#include <66/info.h> +#include <66/utils.h> +#include <66/constants.h> +#include <66/config.h> +#include <66/state.h> + +#define MAXOPTS 70 + +static wchar_t const field_suffix[] = L" :" ; +static char fields[INFO_NKEY][INFO_FIELD_MAXLEN] = {{ 0 }} ; + +static void info_display_string(char const *field, char const *str, uint32_t element, uint8_t check) +{ + info_display_field_name(field) ; + + if (check && !element) { + + if (!bprintf(buffer_1,"%s%s", log_color->warning, "None")) + log_dieusys(LOG_EXIT_SYS, "write to stdout") ; + + } else { + + if (!buffer_puts(buffer_1, str + element)) + log_dieusys(LOG_EXIT_SYS, "write to stdout") ; + } + + if (buffer_putsflush(buffer_1, "\n") == -1) + log_dieusys(LOG_EXIT_SYS, "write to stdout") ; + + +} + +static void info_display_int(char const *field, uint32_t element) +{ + info_display_field_name(field) ; + + char ui[UINT_FMT] ; + ui[uint_fmt(ui, element)] = 0 ; + + if (!buffer_puts(buffer_1, ui)) + log_dieusys(LOG_EXIT_SYS, "write to stdout") ; + + if (buffer_putsflush(buffer_1, "\n") == -1) + log_dieusys(LOG_EXIT_SYS, "write to stdout") ; +} + +static void info_display_service_field(resolve_service_t *res) +{ + info_display_string(fields[0], res->sa.s, res->name, 0) ; + info_display_string(fields[1], res->sa.s, res->description, 1) ; + info_display_string(fields[2], res->sa.s, res->version, 1) ; + info_display_int(fields[3], res->type) ; + info_display_int(fields[4], res->notify) ; + info_display_int(fields[5], res->maxdeath) ; + info_display_int(fields[6], res->earlier) ; + info_display_string(fields[7], res->sa.s, res->hiercopy, 1) ; + info_display_string(fields[8], res->sa.s, res->intree, 1) ; + info_display_string(fields[9], res->sa.s, res->ownerstr, 1) ; + info_display_int(fields[10], res->owner) ; + info_display_string(fields[11], res->sa.s, res->treename, 1) ; + info_display_string(fields[12], res->sa.s, res->user, 1) ; + info_display_string(fields[13], res->sa.s, res->inmodule, 1) ; + + info_display_string(fields[14], res->sa.s, res->path.home, 1) ; + info_display_string(fields[15], res->sa.s, res->path.frontend, 1) ; + info_display_string(fields[16], res->sa.s, res->path.tree, 1) ; + info_display_string(fields[17], res->sa.s, res->path.status, 1) ; + + info_display_string(fields[18], res->sa.s, res->dependencies.depends, 1) ; + info_display_string(fields[19], res->sa.s, res->dependencies.requiredby, 1) ; + info_display_string(fields[20], res->sa.s, res->dependencies.optsdeps, 1) ; + info_display_int(fields[21], res->dependencies.ndepends) ; + info_display_int(fields[22], res->dependencies.nrequiredby) ; + info_display_int(fields[23], res->dependencies.noptsdeps) ; + + info_display_string(fields[24], res->sa.s, res->execute.run.run, 1) ; + info_display_string(fields[25], res->sa.s, res->execute.run.run_user, 1) ; + info_display_string(fields[26], res->sa.s, res->execute.run.build, 1) ; + info_display_string(fields[27], res->sa.s, res->execute.run.shebang, 1) ; + info_display_string(fields[28], res->sa.s, res->execute.run.runas, 1) ; + info_display_string(fields[29], res->sa.s, res->execute.finish.run, 1) ; + info_display_string(fields[30], res->sa.s, res->execute.finish.run_user, 1) ; + info_display_string(fields[31], res->sa.s, res->execute.finish.build, 1) ; + info_display_string(fields[32], res->sa.s, res->execute.finish.shebang, 1) ; + info_display_string(fields[33], res->sa.s, res->execute.finish.runas, 1) ; + info_display_int(fields[34], res->execute.timeout.kill) ; + info_display_int(fields[35], res->execute.timeout.finish) ; + info_display_int(fields[36], res->execute.timeout.up) ; + info_display_int(fields[37], res->execute.timeout.down) ; + info_display_int(fields[38], res->execute.down) ; + info_display_int(fields[39], res->execute.downsignal) ; + + info_display_string(fields[40], res->sa.s, res->live.livedir, 1) ; + info_display_string(fields[41], res->sa.s, res->live.scandir, 1) ; + info_display_string(fields[42], res->sa.s, res->live.statedir, 1) ; + info_display_string(fields[43], res->sa.s, res->live.eventdir, 1) ; + info_display_string(fields[44], res->sa.s, res->live.notifdir, 1) ; + info_display_string(fields[45], res->sa.s, res->live.supervisedir, 1) ; + info_display_string(fields[46], res->sa.s, res->live.fdholderdir, 1) ; + info_display_string(fields[47], res->sa.s, res->live.oneshotddir, 1) ; + + info_display_string(fields[48], res->sa.s, res->logger.name, 1) ; + info_display_string(fields[49], res->sa.s, res->logger.destination, 1) ; + info_display_int(fields[50], res->logger.backup) ; + info_display_int(fields[51], res->logger.maxsize) ; + info_display_int(fields[52], res->logger.timestamp) ; + info_display_string(fields[53], res->sa.s, res->logger.execute.run.run, 1) ; + info_display_string(fields[54], res->sa.s, res->logger.execute.run.run_user, 1) ; + info_display_string(fields[55], res->sa.s, res->logger.execute.run.build, 1) ; + info_display_string(fields[56], res->sa.s, res->logger.execute.run.shebang, 1) ; + info_display_string(fields[57], res->sa.s, res->logger.execute.run.runas, 1) ; + info_display_int(fields[58], res->logger.execute.timeout.kill) ; + info_display_int(fields[59], res->logger.execute.timeout.finish) ; + + info_display_string(fields[60], res->sa.s, res->environ.env, 1) ; + info_display_string(fields[61], res->sa.s, res->environ.envdir, 1) ; + info_display_int(fields[62], res->environ.env_overwrite) ; + + info_display_string(fields[63], res->sa.s, res->regex.configure, 1) ; + info_display_string(fields[64], res->sa.s, res->regex.directories, 1) ; + info_display_string(fields[65], res->sa.s, res->regex.files, 1) ; + info_display_string(fields[66], res->sa.s, res->regex.infiles, 1) ; + info_display_int(fields[67], res->regex.ndirectories) ; + info_display_int(fields[68], res->regex.nfiles) ; + info_display_int(fields[69], res->regex.ninfiles) ; + +} + +int ssexec_resolve_service(int argc, char const *const *argv, ssexec_t *info) +{ + int r = 0 ; + + char const *svname = 0 ; + char atree[SS_MAX_TREENAME + 1] ; + + resolve_service_t res = RESOLVE_SERVICE_ZERO ; + resolve_wrapper_t_ref wres = resolve_set_struct(DATA_SERVICE, &res) ; + + argc-- ; + argv++ ; + + if (argc < 1) + log_usage(usage_inresolve) ; + + svname = *argv ; + + char service_buf[MAXOPTS][INFO_FIELD_MAXLEN] = { + "name", + "description" , + "version", + "type", + "notify", + "maxdeath", + "earlier", + "hiercopy", + "intree", + "ownerstr", + "owner", + "treename", + "user" , + "inmodule", // 14 + + "home", + "frontend", + "tree", + "status", //18 + + "depends", + "requiredby", + "optsdeps", + "ndepends", + "nrequiredby", + "noptsdeps", // 24 + + "run", + "run_user", + "run_build", + "run_shebang", + "run_runas", + "finish", + "finish_user", + "finish_build", + "finish_shebang", + "finish_runas", + "timeoutkill", + "timeoutfinish", + "timeoutup", + "timeoutdown", + "down", + "downsignal", // 40 + + "livedir", + "scandir", + "statedir", + "eventdir", + "notifdir", + "supervisedir", + "fdholderdir", + "oneshotddir", //48 + + "logname" , + "logdestination" , + "logbackup" , + "logmaxsize" , + "logtimestamp" , + "logrun" , + "logrun_user" , + "logrun_build" , + "logrun_shebang" , + "logrun_runas" , + "logtimeoutkill", + "logtimeoutfinish", // 60 + + "env", + "envdir", + "env_overwrite", // 63 + + "configure", + "directories", + "files", + "infiles", + "ndirectories", + "nfiles", + "ninfiles" // 70 + + } ; + + + r = service_is_g(atree, svname, STATE_FLAGS_ISPARSED) ; + if (r == -1) + log_dieu(LOG_EXIT_SYS, "get information of service: ", svname, " -- please a bug report") ; + else if (!r) + log_die(LOG_EXIT_USER, svname, " is not parsed -- try to parse it first") ; + + if (!resolve_read_g(wres, info->base.s, svname)) + log_dieusys(LOG_EXIT_SYS, "read resolve file") ; + + info_field_align(service_buf, fields, field_suffix,MAXOPTS) ; + + info_display_service_field(&res) ; + + resolve_free(wres) ; + + return 0 ; +} diff --git a/src/lib66/exec/ssexec_resolve_tree.c b/src/lib66/exec/ssexec_resolve_tree.c new file mode 100644 index 0000000000000000000000000000000000000000..3298d7129174b83a5d1cad670eeb52a5e54fd8d3 --- /dev/null +++ b/src/lib66/exec/ssexec_resolve_tree.c @@ -0,0 +1,173 @@ +/* + * ssexec_resolve_tree.c + * + * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org> + * + * All rights reserved. + * + * This file is part of Obarun. It is subject to the license terms in + * the LICENSE file found in the top-level directory of this + * distribution. + * This file may not be copied, modified, propagated, or distributed + * except according to the terms contained in the LICENSE file./ + */ + +#include <string.h> +#include <wchar.h> + +#include <oblibs/log.h> +#include <oblibs/sastr.h> +#include <oblibs/string.h> +#include <oblibs/types.h> + +#include <skalibs/types.h> +#include <skalibs/stralloc.h> +#include <skalibs/lolstdio.h> +#include <skalibs/buffer.h> + +#include <66/resolve.h> +#include <66/ssexec.h> +#include <66/tree.h> +#include <66/info.h> +#include <66/utils.h> +#include <66/constants.h> +#include <66/config.h> +#include <66/state.h> + +#define MAXOPTS 19 + +static wchar_t const field_suffix[] = L" :" ; +static char fields[INFO_NKEY][INFO_FIELD_MAXLEN] = {{ 0 }} ; + +static void info_display_string(char const *field, char const *str, uint32_t element, uint8_t check) +{ + info_display_field_name(field) ; + + if (check && !element) { + + if (!bprintf(buffer_1,"%s%s", log_color->warning, "None")) + log_dieusys(LOG_EXIT_SYS, "write to stdout") ; + + } else { + + if (!buffer_puts(buffer_1, str + element)) + log_dieusys(LOG_EXIT_SYS, "write to stdout") ; + } + + if (buffer_putsflush(buffer_1, "\n") == -1) + log_dieusys(LOG_EXIT_SYS, "write to stdout") ; + + +} + +static void info_display_int(char const *field, uint32_t element) +{ + info_display_field_name(field) ; + + char ui[UINT_FMT] ; + ui[uint_fmt(ui, element)] = 0 ; + + if (!buffer_puts(buffer_1, ui)) + log_dieusys(LOG_EXIT_SYS, "write to stdout") ; + + if (buffer_putsflush(buffer_1, "\n") == -1) + log_dieusys(LOG_EXIT_SYS, "write to stdout") ; +} + +int ssexec_resolve_tree(int argc, char const *const *argv, ssexec_t *info) +{ + int r = 0 ; + uint8_t master = 0 ; + + char const *svname = 0 ; + char const *treename = info->treename.s ; + + resolve_wrapper_t_ref wres = 0 ; + resolve_tree_t tres = RESOLVE_TREE_ZERO ; + resolve_tree_master_t mres = RESOLVE_TREE_MASTER_ZERO ; + + argc-- ; + argv++ ; + + if (argc < 1) + log_usage(usage_inresolve) ; + + svname = *argv ; + + char tree_buf[MAXOPTS][INFO_FIELD_MAXLEN] = { + "name", + "depends" , + "requiredby", + "allow", + "groups", + "contents", + "ndepends", + "nrequiredby", + "nallow", + "ngroups", + "ncontents", + "init" , + "supervised", + "disen", // 14 + // Master + "enabled", + "current", + "contents", + "nenabled", + "ncontents" // 19 + } ; + + if (!strcmp(argv[0], SS_MASTER + 1)) { + + master = 1 ; + wres = resolve_set_struct(DATA_TREE_MASTER, &mres) ; + + } else { + + wres = resolve_set_struct(DATA_TREE, &tres) ; + } + + r = tree_isvalid(info->base.s, svname) ; + if (r < 0) + log_diesys(LOG_EXIT_SYS, "invalid tree directory") ; + + if (!r) + log_dieusys(LOG_EXIT_SYS, "find tree: ", svname) ; + + if (!resolve_read_g(wres, info->base.s, svname)) + log_dieusys(LOG_EXIT_SYS, "read resolve file") ; + + info_field_align(tree_buf, fields, field_suffix,MAXOPTS) ; + + if (!master) { + + info_display_string(fields[0], tres.sa.s, tres.name, 0) ; + info_display_string(fields[1], tres.sa.s, tres.depends, 1) ; + info_display_string(fields[2], tres.sa.s, tres.requiredby, 1) ; + info_display_string(fields[3], tres.sa.s, tres.allow, 1) ; + info_display_string(fields[4], tres.sa.s, tres.groups, 1) ; + info_display_string(fields[5], tres.sa.s, tres.contents, 1) ; + info_display_int(fields[6], tres.ndepends) ; + info_display_int(fields[7], tres.nrequiredby) ; + info_display_int(fields[8], tres.nallow) ; + info_display_int(fields[9], tres.ngroups) ; + info_display_int(fields[10], tres.ncontents) ; + info_display_int(fields[11], tres.init) ; + info_display_int(fields[12], tres.supervised) ; + info_display_int(fields[13], tres.disen) ; + + } else { + + info_display_string(fields[0], mres.sa.s, mres.name, 1) ; + info_display_string(fields[3], mres.sa.s, mres.allow, 1) ; + info_display_string(fields[14], mres.sa.s, mres.enabled, 1) ; + info_display_string(fields[15], mres.sa.s, mres.current, 1) ; + info_display_string(fields[16], mres.sa.s, mres.contents, 1) ; + info_display_int(fields[17], mres.nenabled) ; + info_display_int(fields[18], mres.ncontents) ; + } + + resolve_free(wres) ; + + return 0 ; +} diff --git a/src/lib66/exec/ssexec_service_admin.c b/src/lib66/exec/ssexec_service_admin.c new file mode 100644 index 0000000000000000000000000000000000000000..4e6dadb084c6b7c763c6b806d752cbcbaba851c6 --- /dev/null +++ b/src/lib66/exec/ssexec_service_admin.c @@ -0,0 +1,184 @@ +/* + * ssexec_service_admin.c + * + * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org> + * + * All rights reserved. + * + * This file is part of Obarun. It is subject to the license terms in + * the LICENSE file found in the top-level directory of this + * distribution. + * This file may not be copied, modified, propagated, or distributed + * except according to the terms contained in the LICENSE file./ + */ + +#include <string.h> + +#include <oblibs/log.h> + +#include <skalibs/sgetopt.h> + +#include <66/ssexec.h> +#include <66/config.h> + +static inline void info_help (char const *help,char const *usage) +{ + log_flow() ; + + DEFAULT_MSG = 0 ; + + log_info(usage,"\n", help) ; +} + +int ssexec_service_admin(int argc, char const *const *argv, ssexec_t *info) +{ + log_flow() ; + + if (!argv[1]) { + PROG = "service" ; + log_usage(usage_service_wrapper) ; + } + + int r, n = 0, i = 0 ; + uint8_t ctl = 0 ; + ssexec_func_t_ref func = 0 ; + char const *nargv[argc + 1] ; + + if (!strcmp(argv[1], "status")) { + + nargv[n++] = PROG ; + + info->prog = PROG ; + info->help = help_inservice ; + info->usage = usage_inservice ; + func = &ssexec_inservice ; + + argc-- ; + argv++ ; + + } else if (!strcmp(argv[1], "resolve")) { + + nargv[n++] = PROG ; + + info->prog = PROG ; + info->help = help_inresolve ; + info->usage = usage_inresolve ; + func = &ssexec_resolve_service ; + + argc-- ; + argv++ ; + + } else if (!strcmp(argv[1], "state")) { + + nargv[n++] = PROG ; + + info->prog = PROG ; + info->help = help_instate ; + info->usage = usage_instate ; + func = &ssexec_instate ; + + argc-- ; + argv++ ; + + } else if (!strcmp(argv[1], "remove")) { + + nargv[n++] = PROG ; + + info->prog = PROG ; + info->help = help_instate ; + info->usage = usage_instate ; + func = &ssexec_service_admin ; + + argc-- ; + argv++ ; + + } else { + + log_usage(usage_tree) ; + } + + { + subgetopt l = SUBGETOPT_ZERO ; + + int f = 0 ; + for (;;) { + + int opt = subgetopt_r(argc, argv, "-h", &l) ; + if (opt == -1) break ; + switch (opt) { + + case 'h' : + + info_help(info->help, info->usage) ; + return 0 ; + + default: + + for (i = 0 ; i < n ; i++) { + + if (!argv[l.ind]) + log_usage(info->usage) ; + + if (l.arg) { + + if (!strcmp(nargv[i],argv[l.ind - 2]) || !strcmp(nargv[i],l.arg)) + f = 1 ; + + } else { + + if (!strcmp(nargv[i],argv[l.ind])) + f = 1 ; + } + } + + if (!f) { + + if (l.arg) { + // distinction between e.g -enano and -e nano + if (argv[l.ind - 1][0] != '-') + nargv[n++] = argv[l.ind - 2] ; + + nargv[n++] = argv[l.ind - 1] ; + + } else { + + nargv[n++] = argv[l.ind] ; + } + } + f = 0 ; + break ; + } + } + argc -= l.ind ; argv += l.ind ; + } + + for (i = 0 ; i < argc ; i++ , argv++) + nargv[n++] = *argv ; + + nargv[n] = 0 ; + + if (ctl) { + /* swap the command and options e.g. + * down -f <treename> <-> -f down <treename> */ + if (n > 2) { + /* swap the command and options e.g. + * down -f <-> -f down */ + nargv[n] = nargv[n-1] ; + nargv[n-1] = nargv[0] ; + nargv[++n] = 0 ; + + } else if (nargv[n-1][0] == '-') { + nargv[n++] = nargv[0] ; + nargv[n] = 0 ; + } else { + nargv[n] = nargv[n-1] ; + nargv[n-1] = nargv[0] ; + nargv[++n] = 0 ; + } + + } + + r = (*func)(n, nargv, info) ; + + return r ; +} diff --git a/src/lib66/exec/ssexec_service_wrapper.c b/src/lib66/exec/ssexec_service_wrapper.c new file mode 100644 index 0000000000000000000000000000000000000000..26e8407dd44fdeec09bd9bbb774dfb77082a8266 --- /dev/null +++ b/src/lib66/exec/ssexec_service_wrapper.c @@ -0,0 +1,184 @@ +/* + * ssexec_service_wrapper.c + * + * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org> + * + * All rights reserved. + * + * This file is part of Obarun. It is subject to the license terms in + * the LICENSE file found in the top-level directory of this + * distribution. + * This file may not be copied, modified, propagated, or distributed + * except according to the terms contained in the LICENSE file./ + */ + +#include <string.h> + +#include <oblibs/log.h> + +#include <skalibs/sgetopt.h> + +#include <66/ssexec.h> +#include <66/config.h> + +static inline void info_help (char const *help,char const *usage) +{ + log_flow() ; + + DEFAULT_MSG = 0 ; + + log_info(usage,"\n", help) ; +} + +int ssexec_service_wrapper(int argc, char const *const *argv, ssexec_t *info) +{ + log_flow() ; + + if (!argv[1]) { + PROG = "service" ; + log_usage(usage_service_wrapper) ; + } + + int r, n = 0, i = 0 ; + uint8_t ctl = 0 ; + ssexec_func_t_ref func = 0 ; + char const *nargv[argc + 1] ; + + if (!strcmp(argv[1], "status")) { + + nargv[n++] = PROG ; + + info->prog = PROG ; + info->help = help_inservice ; + info->usage = usage_inservice ; + func = &ssexec_inservice ; + + argc-- ; + argv++ ; + + } else if (!strcmp(argv[1], "resolve")) { + + nargv[n++] = PROG ; + + info->prog = PROG ; + info->help = help_inresolve ; + info->usage = usage_inresolve ; + func = &ssexec_resolve_service ; + + argc-- ; + argv++ ; + + } else if (!strcmp(argv[1], "state")) { + + nargv[n++] = PROG ; + + info->prog = PROG ; + info->help = help_instate ; + info->usage = usage_instate ; + func = &ssexec_instate ; + + argc-- ; + argv++ ; + + } else if (!strcmp(argv[1], "remove")) { + + nargv[n++] = PROG ; + + info->prog = PROG ; + info->help = help_instate ; + info->usage = usage_instate ; + func = &ssexec_service_admin ; + + argc-- ; + argv++ ; + + } else { + + log_usage(usage_tree) ; + } + + { + subgetopt l = SUBGETOPT_ZERO ; + + int f = 0 ; + for (;;) { + + int opt = subgetopt_r(argc, argv, "-h", &l) ; + if (opt == -1) break ; + switch (opt) { + + case 'h' : + + info_help(info->help, info->usage) ; + return 0 ; + + default: + + for (i = 0 ; i < n ; i++) { + + if (!argv[l.ind]) + log_usage(info->usage) ; + + if (l.arg) { + + if (!strcmp(nargv[i],argv[l.ind - 2]) || !strcmp(nargv[i],l.arg)) + f = 1 ; + + } else { + + if (!strcmp(nargv[i],argv[l.ind])) + f = 1 ; + } + } + + if (!f) { + + if (l.arg) { + // distinction between e.g -enano and -e nano + if (argv[l.ind - 1][0] != '-') + nargv[n++] = argv[l.ind - 2] ; + + nargv[n++] = argv[l.ind - 1] ; + + } else { + + nargv[n++] = argv[l.ind] ; + } + } + f = 0 ; + break ; + } + } + argc -= l.ind ; argv += l.ind ; + } + + for (i = 0 ; i < argc ; i++ , argv++) + nargv[n++] = *argv ; + + nargv[n] = 0 ; + + if (ctl) { + /* swap the command and options e.g. + * down -f <treename> <-> -f down <treename> */ + if (n > 2) { + /* swap the command and options e.g. + * down -f <-> -f down */ + nargv[n] = nargv[n-1] ; + nargv[n-1] = nargv[0] ; + nargv[++n] = 0 ; + + } else if (nargv[n-1][0] == '-') { + nargv[n++] = nargv[0] ; + nargv[n] = 0 ; + } else { + nargv[n] = nargv[n-1] ; + nargv[n-1] = nargv[0] ; + nargv[++n] = 0 ; + } + + } + + r = (*func)(n, nargv, info) ; + + return r ; +} diff --git a/src/lib66/exec/ssexec_tree_wrapper.c b/src/lib66/exec/ssexec_tree_wrapper.c index e0f80ec56cd24aed0821466f899964d15792639e..bc3235244af0bf226e4ba433ef4523972f1ea450 100644 --- a/src/lib66/exec/ssexec_tree_wrapper.c +++ b/src/lib66/exec/ssexec_tree_wrapper.c @@ -1,5 +1,5 @@ /* - * ssexec_reload.c + * ssexec_tree_wrapper.c * * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org> * @@ -21,6 +21,15 @@ #include <66/ssexec.h> #include <66/config.h> +static inline void info_help (char const *help,char const *usage) +{ + log_flow() ; + + DEFAULT_MSG = 0 ; + + log_info(usage,"\n", help) ; +} + int ssexec_tree_wrapper(int argc, char const *const *argv, ssexec_t *info) { log_flow() ; @@ -113,6 +122,32 @@ int ssexec_tree_wrapper(int argc, char const *const *argv, ssexec_t *info) argc-- ; argv++ ; + } else if (!strcmp(argv[1], "resolve")) { + + nargv[n++] = PROG ; + + info->prog = PROG ; + info->help = help_inresolve ; + info->usage = usage_inresolve ; + + func = &ssexec_resolve_tree ; + + argc-- ; + argv++ ; + + } else if (!strcmp(argv[1], "status")) { + + nargv[n++] = PROG ; + + info->prog = PROG ; + info->help = help_intree ; + info->usage = usage_intree ; + + func = &ssexec_intree ; + + argc-- ; + argv++ ; + } else if (!strcmp(argv[1], "up")) { info->prog = PROG ; @@ -148,41 +183,51 @@ int ssexec_tree_wrapper(int argc, char const *const *argv, ssexec_t *info) int f = 0 ; for (;;) { - int opt = subgetopt_r(argc, argv, "", &l) ; + int opt = subgetopt_r(argc, argv, "-h", &l) ; if (opt == -1) break ; + switch (opt) { - for (i = 0 ; i < n ; i++) { + case 'h' : - if (!argv[l.ind]) - log_usage(info->usage) ; + info_help(info->help, info->usage) ; + return 0 ; - if (l.arg) { + default: - if (!strcmp(nargv[i],argv[l.ind - 2]) || !strcmp(nargv[i],l.arg)) - f = 1 ; + for (i = 0 ; i < n ; i++) { - } else { + if (!argv[l.ind]) + log_usage(info->usage) ; - if (!strcmp(nargv[i],argv[l.ind])) - f = 1 ; - } - } + if (l.arg) { + + if (!strcmp(nargv[i],argv[l.ind - 2]) || !strcmp(nargv[i],l.arg)) + f = 1 ; + + } else { + + if (!strcmp(nargv[i],argv[l.ind])) + f = 1 ; + } + } - if (!f) { + if (!f) { - if (l.arg) { - // distinction between e.g -enano and -e nano - if (argv[l.ind - 1][0] != '-') - nargv[n++] = argv[l.ind - 2] ; + if (l.arg) { + // distinction between e.g -enano and -e nano + if (argv[l.ind - 1][0] != '-') + nargv[n++] = argv[l.ind - 2] ; - nargv[n++] = argv[l.ind - 1] ; + nargv[n++] = argv[l.ind - 1] ; - } else { + } else { - nargv[n++] = argv[l.ind] ; - } + nargv[n++] = argv[l.ind] ; + } + } + f = 0 ; + break ; } - f = 0 ; } argc -= l.ind ; argv += l.ind ; }