From 8dc4626e1b6b9336a351dc55aa1e748435759094 Mon Sep 17 00:00:00 2001 From: "Anna (navi) Figueiredo Gomes" Date: Thu, 8 May 2025 01:27:04 +0200 Subject: [PATCH 1/2] *: unify commandline arguments in macro call this ties together the short and long flags, with the argument spec and description. this avoids mismatches between all 3 variables (getoptstring, longopts, longopts_help) --- src/checkpath/checkpath.c | 37 +++---- src/fstabinfo/fstabinfo.c | 30 ++---- src/kill_all/kill_all.c | 16 +-- src/mountinfo/mountinfo.c | 48 +++------ src/openrc-run/openrc-run.c | 29 ++--- src/openrc-shutdown/openrc-shutdown.c | 40 +++---- src/openrc/rc.c | 26 ++--- src/rc-depend/rc-depend.c | 30 ++---- src/rc-service/rc-service.c | 46 +++----- src/rc-status/rc-status.c | 39 +++---- src/rc-update/rc-update.c | 18 +--- src/seedrng/seedrng.c | 15 +-- src/shared/_usage.h | 65 ++++++------ src/start-stop-daemon/start-stop-daemon.c | 122 +++++++--------------- src/supervise-daemon/supervise-daemon.c | 103 ++++++------------ src/swclock/swclock.c | 15 +-- 16 files changed, 223 insertions(+), 456 deletions(-) diff --git a/src/checkpath/checkpath.c b/src/checkpath/checkpath.c index ebc65cb23..f4b2a8125 100644 --- a/src/checkpath/checkpath.c +++ b/src/checkpath/checkpath.c @@ -42,33 +42,20 @@ typedef enum { inode_fifo = 3, } inode_t; +#define opts(opt, opt_long) \ + opt(d, directory, no_argument, "Create a directory if not exists") \ + opt(D, directory-truncate, no_argument, "Create/empty directory") \ + opt(f, file, no_argument, "Create a file if not exists") \ + opt(F, file-truncate, no_argument, "Truncate file") \ + opt(p, pipe, no_argument, "Create a named pipe (FIFO) if not exists") \ + opt(m, mode, required_argument, "Mode to check") \ + opt(o, owner, required_argument, "Owner to check (user:group)") \ + opt(s, symlinks, no_argument, "follow symbolic links (irrelevant on linux)") \ + opt(W, writable, no_argument, "Check whether the path is writable or not") +cmdline_opts(opts) + const char *applet = NULL; const char *extraopts ="path1 [path2] [...]"; -const char getoptstring[] = "dDfFpm:o:sW" getoptstring_COMMON; -const struct option longopts[] = { - { "directory", 0, NULL, 'd'}, - { "directory-truncate", 0, NULL, 'D'}, - { "file", 0, NULL, 'f'}, - { "file-truncate", 0, NULL, 'F'}, - { "pipe", 0, NULL, 'p'}, - { "mode", 1, NULL, 'm'}, - { "owner", 1, NULL, 'o'}, - { "symlinks", 0, NULL, 's'}, - { "writable", 0, NULL, 'W'}, - longopts_COMMON -}; -const char * const longopts_help[] = { - "Create a directory if not exists", - "Create/empty directory", - "Create a file if not exists", - "Truncate file", - "Create a named pipe (FIFO) if not exists", - "Mode to check", - "Owner to check (user:group)", - "follow symbolic links (irrelevant on linux)", - "Check whether the path is writable or not", - longopts_help_COMMON -}; const char *usagestring = NULL; static int get_dirfd(char *path, bool symlinks) diff --git a/src/fstabinfo/fstabinfo.c b/src/fstabinfo/fstabinfo.c index 43ee822c2..c9d2cf062 100644 --- a/src/fstabinfo/fstabinfo.c +++ b/src/fstabinfo/fstabinfo.c @@ -68,28 +68,16 @@ extern char **environ; const char *applet = NULL; const char *extraopts = NULL; -const char getoptstring[] = "MRbmop:t:" getoptstring_COMMON; -const struct option longopts[] = { - { "mount", 0, NULL, 'M' }, - { "remount", 0, NULL, 'R' }, - { "blockdevice", 0, NULL, 'b' }, - { "mountargs", 0, NULL, 'm' }, - { "options", 0, NULL, 'o' }, - { "passno", 1, NULL, 'p' }, - { "fstype", 1, NULL, 't' }, - longopts_COMMON -}; -const char * const longopts_help[] = { - "Mounts the filesystem from the mountpoint", - "Remounts the filesystem based on the information in fstab", - "Extract the block device", - "Show arguments needed to mount the entry", - "Extract the options field", - "Extract or query the pass number field", - "List entries with matching file system type", - longopts_help_COMMON -}; const char *usagestring = NULL; +#define opts(opt, opt_long) \ + opt(M, mount, no_argument, "Mounts the filesystem from the mountpoint") \ + opt(R, remount, no_argument, "Remounts the filesystem based on the information in fstab") \ + opt(b, blockdevice, no_argument, "Extract the block device") \ + opt(m, mountargs, no_argument, "Show arguments needed to mount the entry") \ + opt(o, options, no_argument, "Extract the options field") \ + opt(p, passno, required_argument, "Extract or query the pass number field") \ + opt(t, fstype, required_argument, "List entries with matching file system type") +cmdline_opts(opts) #ifdef HAVE_GETMNTENT static struct mntent * diff --git a/src/kill_all/kill_all.c b/src/kill_all/kill_all.c index e19b95fe9..65de7f88e 100644 --- a/src/kill_all/kill_all.c +++ b/src/kill_all/kill_all.c @@ -37,19 +37,13 @@ const char *applet = NULL; const char *extraopts = "[signal number]"; -const char getoptstring[] = "do:" getoptstring_COMMON; -const struct option longopts[] = { - { "dry-run", 0, NULL, 'd' }, - { "omit", 1, NULL, 'o' }, - longopts_COMMON -}; -const char * const longopts_help[] = { - "print what would be done", - "omit this pid (can be repeated)", - longopts_help_COMMON -}; const char *usagestring = NULL; +#define opts(opt, opt_long) \ + opt(d, dry-run, no_argument, "print what would be done") \ + opt(o, omit, required_argument, "omit this pid (can be repeated)") +cmdline_opts(opts) + static int mount_proc(void) { pid_t rc; diff --git a/src/mountinfo/mountinfo.c b/src/mountinfo/mountinfo.c index 001fe08ae..7bdc90e39 100644 --- a/src/mountinfo/mountinfo.c +++ b/src/mountinfo/mountinfo.c @@ -49,40 +49,22 @@ const char *applet = NULL; const char *procmounts = "/proc/mounts"; const char *extraopts = "[mount1] [mount2] ..."; -const char getoptstring[] = "f:F:n:N:o:O:p:P:iste:E:" getoptstring_COMMON; -const struct option longopts[] = { - { "fstype-regex", 1, NULL, 'f'}, - { "skip-fstype-regex", 1, NULL, 'F'}, - { "node-regex", 1, NULL, 'n'}, - { "skip-node-regex", 1, NULL, 'N'}, - { "options-regex", 1, NULL, 'o'}, - { "skip-options-regex", 1, NULL, 'O'}, - { "point-regex", 1, NULL, 'p'}, - { "skip-point-regex", 1, NULL, 'P'}, - { "options", 0, NULL, 'i'}, - { "fstype", 0, NULL, 's'}, - { "node", 0, NULL, 't'}, - { "netdev", 0, NULL, 'e'}, - { "nonetdev", 0, NULL, 'E'}, - longopts_COMMON -}; -const char * const longopts_help[] = { - "fstype regex to find", - "fstype regex to skip", - "node regex to find", - "node regex to skip", - "options regex to find", - "options regex to skip", - "point regex to find", - "point regex to skip", - "print options", - "print fstype", - "print node", - "is it a network device", - "is it not a network device", - longopts_help_COMMON -}; const char *usagestring = NULL; +#define opts(opt, opt_long) \ + opt(f, fstype-regex, required_argument, "fstype regex to find") \ + opt(F, skip-fstype-regex, required_argument, "fstype regex to skip") \ + opt(n, node-regex, required_argument, "node regex to find") \ + opt(N, skip-node-regex, required_argument, "node regex to skip") \ + opt(o, options-regex, required_argument, "options regex to find") \ + opt(O, skip-options-regex, required_argument, "options regex to skip") \ + opt(p, point-regex, required_argument, "point regex to find") \ + opt(P, skip-point-regex, required_argument, "point regex to skip") \ + opt(i, options, no_argument, "print options") \ + opt(s, fstype, no_argument, "print fstype") \ + opt(t, node, no_argument, "print node") \ + opt(e, netdev, no_argument, "is it a network device") \ + opt(E, nonetdev, no_argument, "is it not a network device") +cmdline_opts(opts) typedef enum { mount_from, diff --git a/src/openrc-run/openrc-run.c b/src/openrc-run/openrc-run.c index 9ad19bfe8..ac24d7136 100644 --- a/src/openrc-run/openrc-run.c +++ b/src/openrc-run/openrc-run.c @@ -61,27 +61,16 @@ #define WARN_TIMEOUT 10 /* warn about this every N seconds */ const char *applet = NULL; -const char *extraopts = "stop | start | restart | status | describe | zap"; -const char getoptstring[] = "dDsSvl:Z" getoptstring_COMMON; -const struct option longopts[] = { - { "debug", 0, NULL, 'd'}, - { "dry-run", 0, NULL, 'Z'}, - { "ifstarted", 0, NULL, 's'}, - { "ifstopped", 0, NULL, 'S'}, - { "nodeps", 0, NULL, 'D'}, - { "lockfd", 1, NULL, 'l'}, - longopts_COMMON -}; -const char *const longopts_help[] = { - "set xtrace when running the script", - "show what would be done", - "only run commands when started", - "only run commands when stopped", - "ignore dependencies", - "fd of the exclusive lock from rc", - longopts_help_COMMON -}; const char *usagestring = NULL; +const char *extraopts = "stop | start | restart | status | describe | zap"; +#define opts(opt, opt_long) \ + opt(d, debug, no_argument, "set xtrace when running the script") \ + opt(Z, dry-run, no_argument, "show what would be done") \ + opt(s, ifstarted, no_argument, "only run commands when started") \ + opt(S, ifstopped, no_argument, "only run commands when stopped") \ + opt(D, nodeps, no_argument, "ignore dependencies") \ + opt(l, lockfd, required_argument, "fd of the exclusive lock from rc") +cmdline_opts(opts) static char *service, *runlevel, *ibsave, *prefix; static RC_DEPTREE *deptree; diff --git a/src/openrc-shutdown/openrc-shutdown.c b/src/openrc-shutdown/openrc-shutdown.c index ada2bdac6..4b0cb7447 100644 --- a/src/openrc-shutdown/openrc-shutdown.c +++ b/src/openrc-shutdown/openrc-shutdown.c @@ -44,33 +44,19 @@ const char *applet = NULL; const char *extraopts = NULL; -const char getoptstring[] = "cdDfFHKpRrsw" getoptstring_COMMON; -const struct option longopts[] = { - { "cancel", no_argument, NULL, 'c'}, - { "no-write", no_argument, NULL, 'd'}, - { "dry-run", no_argument, NULL, 'D'}, - { "halt", no_argument, NULL, 'H'}, - { "kexec", no_argument, NULL, 'K'}, - { "poweroff", no_argument, NULL, 'p'}, - { "reexec", no_argument, NULL, 'R'}, - { "reboot", no_argument, NULL, 'r'}, - { "single", no_argument, NULL, 's'}, - { "write-only", no_argument, NULL, 'w'}, - longopts_COMMON -}; -const char * const longopts_help[] = { - "cancel a pending shutdown", - "do not write wtmp record", - "print actions instead of executing them", - "halt the system", - "reboot the system using kexec", - "power off the system", - "re-execute init (use after upgrading)", - "reboot the system", - "single user mode", - "write wtmp boot record and exit", - longopts_help_COMMON -}; +#define opts(opt, opt_long) \ + opt(c, cancel, no_argument, "cancel a pending shutdown") \ + opt(d, no-write, no_argument, "do not write wtmp record") \ + opt(D, dry-run, no_argument, "print actions instead of executing them") \ + opt(H, halt, no_argument, "halt the system") \ + opt(K, kexec, no_argument, "reboot the system using kexec") \ + opt(p, poweroff, no_argument, "power off the system") \ + opt(R, reexec, no_argument, "re-execute init (use after upgrading)") \ + opt(r, reboot, no_argument, "reboot the system") \ + opt(s, single, no_argument, "single user mode") \ + opt(w, write-only, no_argument, "write wtmp boot record and exit") +cmdline_opts(opts) + const char *usagestring = "" "Usage: openrc-shutdown -c | --cancel\n" " or: openrc-shutdown -R | --reexec\n" diff --git a/src/openrc/rc.c b/src/openrc/rc.c index 6e1c4e246..0d851387f 100644 --- a/src/openrc/rc.c +++ b/src/openrc/rc.c @@ -49,24 +49,16 @@ #include "_usage.h" #include "helpers.h" +#define opts(opt, opt_long) \ + opt(n, no-stop, no_argument, "do not stop any services") \ + opt(o, override, required_argument, "override the next runlevel to change into\n" \ + "when leaving single user or boot runlevels") \ + opt(s, service, required_argument, "runs the service specified with the rest of the arguments") \ + opt(S, sys, no_argument, "output the RC system type, if any") +cmdline_opts(opts) + const char *extraopts = NULL; -const char getoptstring[] = "a:no:s:S" getoptstring_COMMON; -const struct option longopts[] = { - { "no-stop", 0, NULL, 'n' }, - { "override", 1, NULL, 'o' }, - { "service", 1, NULL, 's' }, - { "sys", 0, NULL, 'S' }, - longopts_COMMON -}; -const char * const longopts_help[] = { - "do not stop any services", - "override the next runlevel to change into\nwhen leaving single user or boot runlevels", - "runs the service specified with the rest\nof the arguments", - "output the RC system type, if any", - longopts_help_COMMON -}; -const char *usagestring = "" - "Usage: openrc [options] []"; +const char *usagestring = "Usage: openrc [options] []"; #define INITSH RC_LIBEXECDIR "/sh/init.sh" #define INITEARLYSH RC_LIBEXECDIR "/sh/init-early.sh" diff --git a/src/rc-depend/rc-depend.c b/src/rc-depend/rc-depend.c index 791bddc87..4736cc123 100644 --- a/src/rc-depend/rc-depend.c +++ b/src/rc-depend/rc-depend.c @@ -32,27 +32,15 @@ const char *applet = NULL; const char *extraopts = NULL; -const char getoptstring[] = "aot:suTF:" getoptstring_COMMON; -const struct option longopts[] = { - { "starting", 0, NULL, 'a'}, - { "stopping", 0, NULL, 'o'}, - { "type", 1, NULL, 't'}, - { "notrace", 0, NULL, 'T'}, - { "strict", 0, NULL, 's'}, - { "update", 0, NULL, 'u'}, - { "deptree-file", 1, NULL, 'F'}, - longopts_COMMON -}; -const char * const longopts_help[] = { - "Order services as if runlevel is starting", - "Order services as if runlevel is stopping", - "Type(s) of dependency to list", - "Don't trace service dependencies", - "Only use what is in the runlevels", - "Force an update of the dependency tree", - "File to load cached deptree from", - longopts_help_COMMON -}; +#define opts(opt, opt_long) \ + opt(a, starting, no_argument, "Order services as if runlevel is starting") \ + opt(o, stopping, no_argument, "Order services as if runlevel is stopping") \ + opt(t, type, required_argument, "Type(s) of dependency to list") \ + opt(T, notrace, no_argument, "Don't trace service dependencies") \ + opt(s, strict, no_argument, "Only use what is in the runlevels") \ + opt(u, update, no_argument, "Force an update of the dependency tree") \ + opt(F, deptree-file, required_argument, "File to load cached deptree from") +cmdline_opts(opts) const char *usagestring = NULL; int main(int argc, char **argv) diff --git a/src/rc-service/rc-service.c b/src/rc-service/rc-service.c index 08cba9a6b..bfd78e943 100644 --- a/src/rc-service/rc-service.c +++ b/src/rc-service/rc-service.c @@ -31,37 +31,21 @@ const char *applet = NULL; const char *extraopts = NULL; -const char getoptstring[] = "cdDe:ilr:INsSZ" getoptstring_COMMON; -const struct option longopts[] = { - { "debug", 0, NULL, 'd' }, - { "nodeps", 0, NULL, 'D' }, - { "exists", 1, NULL, 'e' }, - { "ifcrashed", 0, NULL, 'c' }, - { "ifexists", 0, NULL, 'i' }, - { "ifinactive", 0, NULL, 'I' }, - { "ifnotstarted", 0, NULL, 'N' }, - { "ifstarted", 0, NULL, 's' }, - { "ifstopped", 0, NULL, 'S' }, - { "list", 0, NULL, 'l' }, - { "resolve", 1, NULL, 'r' }, - { "dry-run", 0, NULL, 'Z' }, - longopts_COMMON -}; -const char * const longopts_help[] = { - "set xtrace when running the command", - "ignore dependencies", - "tests if the service exists or not", - "if the service is crashed run the command", - "if the service exists run the command", - "if the service is inactive run the command", - "if the service is not started run the command", - "if the service is started run the command", - "if the service is stopped run the command", - "list all available services", - "resolve the service name to an init script", - "dry run (show what would happen)", - longopts_help_COMMON -}; +#define opts(opt, opt_long) \ + opt(d, debug, no_argument, "set xtrace when running the command") \ + opt(D, nodeps, no_argument, "ignore dependencies") \ + opt(e, exists, required_argument, "tests if the service exists or not") \ + opt(c, ifcrashed, no_argument, "if the service is crashed run the command") \ + opt(i, ifexists, no_argument, "if the service exists run the command") \ + opt(I, ifinactive, no_argument, "if the service is inactive run the command") \ + opt(N, ifnotstarted, no_argument, "if the service is not started run the command") \ + opt(s, ifstarted, no_argument, "if the service is started run the command") \ + opt(S, ifstopped, no_argument, "if the service is stopped run the command") \ + opt(l, list, no_argument, "list all available services") \ + opt(r, resolve, required_argument, "resolve the service name to an init script") \ + opt(Z, dry-run, no_argument, "dry run (show what would happen)") +cmdline_opts(opts) + const char *usagestring = "" "Usage: rc-service [options] [-i] ...\n" " or: rc-service [options] -e \n" diff --git a/src/rc-status/rc-status.c b/src/rc-status/rc-status.c index b3f800cda..1dd74730b 100644 --- a/src/rc-status/rc-status.c +++ b/src/rc-status/rc-status.c @@ -39,33 +39,18 @@ enum format_t { const char *applet = NULL; const char *extraopts = NULL; -const char getoptstring[] = "acf:i:lmrsSu" getoptstring_COMMON; -const struct option longopts[] = { - {"all", 0, NULL, 'a'}, - {"crashed", 0, NULL, 'c'}, - {"format", 1, NULL, 'f'}, - {"in-state", 1, NULL, 'i'}, - {"list", 0, NULL, 'l'}, - {"manual", 0, NULL, 'm'}, - {"runlevel", 0, NULL, 'r'}, - {"servicelist", 0, NULL, 's'}, - {"supervised", 0, NULL, 'S'}, - {"unused", 0, NULL, 'u'}, - longopts_COMMON -}; -const char * const longopts_help[] = { - "Show services from all run levels", - "Show crashed services", - "format status to be parsable (currently arg must be ini)", - "Show services which are in this state", - "Show list of run levels", - "Show manually started services", - "Show the name of the current runlevel", - "Show service list", - "show supervised services", - "Show services not assigned to any runlevel", - longopts_help_COMMON -}; +#define opts(opt, opt_long) \ + opt(a, all, no_argument, "Show services from all run levels") \ + opt(c, crashed, no_argument, "Show crashed services") \ + opt(f, format, required_argument, "format status to be parsable (currently arg must be ini)") \ + opt(i, in-state, required_argument, "Show services which are in this state") \ + opt(l, list, no_argument, "Show list of run levels") \ + opt(m, manual, no_argument, "Show manually started services") \ + opt(r, runlevel, no_argument, "Show the name of the current runlevel") \ + opt(s, servicelist, no_argument, "Show service list") \ + opt(S, supervised, no_argument, "show supervised services") \ + opt(u, unused, no_argument, "Show services not assigned to any runlevel") +cmdline_opts(opts) const char *usagestring = "" "Usage: rc-status [-C] [-f ini] [-i state] [runlevel]\n" " or: rc-status [-C] [-f ini] [-a | -m | -S | -s | -u]\n" diff --git a/src/rc-update/rc-update.c b/src/rc-update/rc-update.c index 7ff004dc5..43ea50c24 100644 --- a/src/rc-update/rc-update.c +++ b/src/rc-update/rc-update.c @@ -36,19 +36,11 @@ const char *usagestring = "" "Usage: rc-update [options] add [...]\n" " or: rc-update [options] del [...]\n" " or: rc-update [options] [show [...]]"; -const char getoptstring[] = "asu" getoptstring_COMMON; -const struct option longopts[] = { - { "all", 0, NULL, 'a' }, - { "stack", 0, NULL, 's' }, - { "update", 0, NULL, 'u' }, - longopts_COMMON -}; -const char * const longopts_help[] = { - "Process all runlevels", - "Stack a runlevel instead of a service", - "Force an update of the dependency tree", - longopts_help_COMMON -}; +#define opts(opt, opt_long) \ + opt(a, all, no_argument, "Process all runlevels") \ + opt(s, stack, no_argument, "Stack a runlevel instead of a service") \ + opt(u, update, no_argument, "Force an update of the dependency tree") +cmdline_opts(opts) /* Return the number of changes made: * -1 = no changes (error) diff --git a/src/seedrng/seedrng.c b/src/seedrng/seedrng.c index ca6810531..d707275f5 100644 --- a/src/seedrng/seedrng.c +++ b/src/seedrng/seedrng.c @@ -61,18 +61,11 @@ enum long_opts { const char *applet = NULL; const char *extraopts = NULL; -const char getoptstring[] = getoptstring_COMMON; -const struct option longopts[] = { - { "seed-dir", 1, NULL, LONGOPT_SEED_DIR }, - { "skip-credit", 0, NULL, LONGOPT_SKIP_CREDIT }, - longopts_COMMON -}; -const char * const longopts_help[] = { - "Directory for seed files (default: " DEFAULT_SEED_DIR ")", - "Skip crediting entropy of seeds", - longopts_help_COMMON -}; const char *usagestring = NULL; +#define opts(opt, opt_long) \ + opt_long(LONGOPT_SEED_DIR, seed-dir, required_argument, "Directory for seed files (default: " DEFAULT_SEED_DIR ")") \ + opt_long(LONGOPT_SKIP_CREDIT, skip-credit, no_argument, "Skip crediting entropy of seeds") +cmdline_opts(opts) enum blake2s_lengths { BLAKE2S_BLOCK_LEN = 64, diff --git a/src/shared/_usage.h b/src/shared/_usage.h index c66b792e7..fff757f32 100644 --- a/src/shared/_usage.h +++ b/src/shared/_usage.h @@ -14,41 +14,36 @@ #include #include "librc.h" -#define getoptstring_COMMON "ChqVvU" - -#define longopts_COMMON \ - { "help", 0, NULL, 'h'}, \ - { "nocolor", 0, NULL, 'C'}, \ - { "version", 0, NULL, 'V'}, \ - { "verbose", 0, NULL, 'v'}, \ - { "quiet", 0, NULL, 'q'}, \ - { "user", 0, NULL, 'U'}, \ - { NULL, 0, NULL, 0 } - -#define longopts_help_COMMON \ - "Display this help output", \ - "Disable color output", \ - "Display software version", \ - "Run verbosely", \ - "Run quietly (repeat to suppress errors)", \ - "Run in user mode" - -#define case_RC_COMMON_getopt_case_C setenv ("EINFO_COLOR", "NO", 1); -#define case_RC_COMMON_getopt_case_h usage (EXIT_SUCCESS); -#define case_RC_COMMON_getopt_case_V if (argc == 2) show_version(); -#define case_RC_COMMON_getopt_case_v setenv ("EINFO_VERBOSE", "YES", 1); -#define case_RC_COMMON_getopt_case_q set_quiet_options(); -#define case_RC_COMMON_getopt_case_U rc_set_user(); -#define case_RC_COMMON_getopt_default usage (EXIT_FAILURE); - -#define case_RC_COMMON_GETOPT \ - case 'C': case_RC_COMMON_getopt_case_C; break; \ - case 'h': case_RC_COMMON_getopt_case_h; break; \ - case 'V': case_RC_COMMON_getopt_case_V; break; \ - case 'v': case_RC_COMMON_getopt_case_v; break; \ - case 'q': case_RC_COMMON_getopt_case_q; break; \ - case 'U': case_RC_COMMON_getopt_case_U; break; \ - default: case_RC_COMMON_getopt_default; break; +#define longopt(short, long, args, help) { #long, args, NULL, #short[0] }, +#define longopt_only(short, long, args, help) { #long, args, NULL, short }, +#define shortopt_no_argument +#define shortopt_required_argument ":" +#define shortopt_optional_argument "::" +#define shortopt(short, long, args, help) #short shortopt_##args +#define opt_null(short, long, args, help) +#define helpstring(short, long, args, help) #help, + +#define common_opts(opt) \ + opt(h, help, no_argument, "Display this help output") \ + opt(C, nocolor, no_argument, "Disable color output") \ + opt(V, version, no_argument, "Display software version") \ + opt(v, verbose, no_argument, "Run verbosely") \ + opt(q, quiet, no_argument, "Run quietly (repeat to suppress errors)") \ + opt(U, user, no_argument, "Run in user mode") + +#define cmdline_opts(opts) \ + const struct option longopts[] = { opts(longopt, longopt_only) common_opts(longopt) }; \ + const char getoptstring[] = opts(shortopt, opt_null) common_opts(shortopt); \ + const char * const longopts_help[] = { opts(helpstring, opt_null) common_opts(helpstring) }; \ + +#define case_RC_COMMON_GETOPT \ + case 'C': setenv("EINFO_COLOR", "NO", 1); break; \ + case 'h': usage(EXIT_SUCCESS); break; \ + case 'V': if (argc == 2) show_version(); break; \ + case 'v': setenv("EINFO_VERBOSE", "YES", 1); break; \ + case 'q': set_quiet_options(); break; \ + case 'U': rc_set_user(); break; \ + default: usage(EXIT_FAILURE); break; extern const char *applet; extern const char *extraopts; diff --git a/src/start-stop-daemon/start-stop-daemon.c b/src/start-stop-daemon/start-stop-daemon.c index 57aea70c1..cb2bd8da5 100644 --- a/src/start-stop-daemon/start-stop-daemon.c +++ b/src/start-stop-daemon/start-stop-daemon.c @@ -96,92 +96,48 @@ enum { const char *applet = NULL; const char *extraopts = NULL; -const char getoptstring[] = "I:KN:PR:Sa:bc:d:e:g:ik:mn:op:s:tu:r:w:x:0:1:2:3:4:" \ - getoptstring_COMMON; -const struct option longopts[] = { - { "capabilities", 1, NULL, LONGOPT_CAPABILITIES}, - { "secbits", 1, NULL, LONGOPT_SECBITS}, - { "no-new-privs", 0, NULL, LONGOPT_NO_NEW_PRIVS}, - { "ionice", 1, NULL, 'I'}, - { "stop", 0, NULL, 'K'}, - { "nicelevel", 1, NULL, 'N'}, - { "oom-score-adj",1, NULL, LONGOPT_OOM_SCORE_ADJ}, - { "retry", 1, NULL, 'R'}, - { "start", 0, NULL, 'S'}, - { "startas", 1, NULL, 'a'}, - { "background", 0, NULL, 'b'}, - { "chuid", 1, NULL, 'c'}, - { "chdir", 1, NULL, 'd'}, - { "env", 1, NULL, 'e'}, - { "umask", 1, NULL, 'k'}, - { "group", 1, NULL, 'g'}, - { "interpreted", 0, NULL, 'i'}, - { "make-pidfile", 0, NULL, 'm'}, - { "name", 1, NULL, 'n'}, - { "oknodo", 0, NULL, 'o'}, - { "pidfile", 1, NULL, 'p'}, - { "signal", 1, NULL, 's'}, - { "test", 0, NULL, 't'}, - { "user", 1, NULL, 'u'}, - { "chroot", 1, NULL, 'r'}, - { "wait", 1, NULL, 'w'}, - { "exec", 1, NULL, 'x'}, - { "stdin", 1, NULL, '0'}, - { "stdout", 1, NULL, '1'}, - { "stderr", 1, NULL, '2'}, - { "stdout-logger",1, NULL, '3'}, - { "stderr-logger",1, NULL, '4'}, - { "progress", 0, NULL, 'P'}, - { "scheduler", 1, NULL, LONGOPT_SCHEDULER}, - { "scheduler-priority", 1, NULL, LONGOPT_SCHEDULER_PRIO}, - { "notify", 1, NULL, LONGOPT_NOTIFY}, - longopts_COMMON -}; -const char * const longopts_help[] = { - "Set the inheritable, ambient and bounding capabilities", - "Set the security-bits for the program", - "Set the No New Privs flag for the program", - "Set an ionice class:data when starting", - "Stop daemon", - "Set a nicelevel when starting", - "Set OOM score adjustment when starting", - "Retry schedule to use when stopping", - "Start daemon", - "deprecated, use --exec or --name", - "Force daemon to background", - "deprecated, use --user", - "Change the PWD", - "Set an environment string", - "Set the umask for the daemon", - "Change the process group", - "Match process name by interpreter", - "Create a pidfile", - "Match process name", - "deprecated", - "Match pid found in this file", - "Send a different signal", - "Test actions, don't do them", - "Change the process user", - "Chroot to this directory", - "Milliseconds to wait for daemon start", - "Binary to start/stop", - "Redirect stdin to file", - "Redirect stdout to file", - "Redirect stderr to file", - "Redirect stdout to process", - "Redirect stderr to process", - "Print dots each second while waiting", - "Set process scheduler", - "Set process scheduler priority", - "Configures experimental notification behaviour", - longopts_help_COMMON -}; -const char *usagestring = NULL; +#define opts(opt, opt_long) \ + opt(I, ionice, required_argument, "Set an ionice class:data when starting") \ + opt(K, stop, no_argument, "Stop daemon") \ + opt(N, nicelevel, required_argument, "Set a nicelevel when starting") \ + opt(R, retry, required_argument, "Retry schedule to use when stopping") \ + opt(S, start, no_argument, "Start daemon") \ + opt(a, startas, required_argument, "deprecated, use --exec or --name") \ + opt(b, background, no_argument, "Force daemon to background") \ + opt(c, chuid, required_argument, "deprecated, use --user") \ + opt(d, chdir, required_argument, "Change the PWD") \ + opt(e, env, required_argument, "Set an environment string") \ + opt(k, umask, required_argument, "Set the umask for the daemon") \ + opt(g, group, required_argument, "Change the process group") \ + opt(i, interpreted, no_argument, "Match process name by interpreter") \ + opt(m, make-pidfile, no_argument, "Create a pidfile") \ + opt(n, name, required_argument, "Match process name") \ + opt(o, oknodo, no_argument, "deprecated") \ + opt(p, pidfile, required_argument, "Match pid found in this file") \ + opt(s, signal, required_argument, "Send a different signal") \ + opt(t, test, no_argument, "Test actions, don't do them") \ + opt(u, user, required_argument, "Change the process user") \ + opt(r, chroot, required_argument, "Chroot to this directory") \ + opt(w, wait, required_argument, "Milliseconds to wait for daemon start") \ + opt(x, exec, required_argument, "Binary to start/stop") \ + opt(no_argument, stdin, required_argument, "Redirect stdin to file") \ + opt(required_argument, stdout, required_argument, "Redirect stdout to file") \ + opt(2, stderr, required_argument, "Redirect stderr to file") \ + opt(3, stdout-logger, required_argument, "Redirect stdout to process") \ + opt(4, stderr-logger, required_argument, "Redirect stderr to process") \ + opt(P, progress, no_argument, "Print dots each second while waiting") \ + opt_long(LONGOPT_CAPABILITIES, "capabilities", required_argument, "Set the inheritable, ambient and bounding capabilities") \ + opt_long(LONGOPT_SECBITS, "secbits", required_argument, "Set the security-bits for the program") \ + opt_long(LONGOPT_NO_NEW_PRIVS, "no-new-privs", no_argument, "Set the No New Privs flag for the program") \ + opt_long(LONGOPT_OOM_SCORE_ADJ, "oom-score-adj",required_argument, "Set OOM score adjustment when starting") \ + opt_long(LONGOPT_SCHEDULER, "scheduler", required_argument, "Set process scheduler") \ + opt_long(LONGOPT_SCHEDULER_PRIO, "scheduler-priority", required_argument, "Set process scheduler priority") \ + opt_long(LONGOPT_NOTIFY, "notify", required_argument, "Configures experimental notification behaviour") +cmdline_opts(opts) +const char *usagestring = NULL; static char **nav; - static char *changeuser, *ch_root, *ch_dir; - extern char **environ; #if !defined(SYS_ioprio_set) && defined(__NR_ioprio_set) diff --git a/src/supervise-daemon/supervise-daemon.c b/src/supervise-daemon/supervise-daemon.c index cfce8c01d..9ef024fbb 100644 --- a/src/supervise-daemon/supervise-daemon.c +++ b/src/supervise-daemon/supervise-daemon.c @@ -85,76 +85,39 @@ enum { const char *applet = NULL; const char *extraopts = NULL; -const char getoptstring[] = "A:a:D:d:e:g:I:Kk:m:N:p:R:r:s:Su:0:1:2:3" \ - getoptstring_COMMON; -const struct option longopts[] = { - { "healthcheck-timer", 1, NULL, 'a'}, - { "healthcheck-delay", 1, NULL, 'A'}, - { "capabilities", 1, NULL, LONGOPT_CAPABILITIES}, - { "secbits", 1, NULL, LONGOPT_SECBITS}, - { "no-new-privs", 0, NULL, LONGOPT_NO_NEW_PRIVS}, - { "respawn-delay", 1, NULL, 'D'}, - { "respawn-delay-step", 1, NULL, LONGOPT_RESPAWN_DELAY_STEP}, - { "respawn-delay-cap", 1, NULL, LONGOPT_RESPAWN_DELAY_CAP}, - { "chdir", 1, NULL, 'd'}, - { "env", 1, NULL, 'e'}, - { "group", 1, NULL, 'g'}, - { "ionice", 1, NULL, 'I'}, - { "stop", 0, NULL, 'K'}, - { "umask", 1, NULL, 'k'}, - { "respawn-max", 1, NULL, 'm'}, - { "nicelevel", 1, NULL, 'N'}, - { "oom-score-adj",1, NULL, LONGOPT_OOM_SCORE_ADJ}, - { "pidfile", 1, NULL, 'p'}, - { "respawn-period", 1, NULL, 'P'}, - { "retry", 1, NULL, 'R'}, - { "chroot", 1, NULL, 'r'}, - { "signal", 1, NULL, 's'}, - { "start", 0, NULL, 'S'}, - { "user", 1, NULL, 'u'}, - { "stdin", 1, NULL, '0'}, - { "stdout", 1, NULL, '1'}, - { "stderr", 1, NULL, '2'}, - { "stdout-logger",1, NULL, LONGOPT_STDOUT_LOGGER}, - { "stderr-logger",1, NULL, LONGOPT_STDERR_LOGGER}, - { "reexec", 0, NULL, '3'}, - { "notify", 1, NULL, LONGOPT_NOTIFY}, - longopts_COMMON -}; -const char * const longopts_help[] = { - "set an initial health check delay", - "set a health check timer", - "Set the inheritable, ambient and bounding capabilities", - "Set the security-bits for the program", - "Set the No New Privs flag for the program", - "Set a respawn delay", - "Increase the respawn delay by this amount for every retry", - "Set maximum respawn delay when respawn-delay-step is also active", - "Change the PWD", - "Set an environment string", - "Change the process group", - "Set an ionice class:data when starting", - "Stop daemon", - "Set the umask for the daemon", - "set maximum number of respawn attempts", - "Set a nicelevel when starting", - "Set OOM score adjustment when starting", - "Match pid found in this file", - "Set respawn time period", - "Retry schedule to use when stopping", - "Chroot to this directory", - "Send a signal to the daemon", - "Start daemon", - "Change the process user", - "Redirect stdin to file", - "Redirect stdout to file", - "Redirect stderr to file", - "Redirect stdout to process", - "Redirect stderr to process", - "reexec (used internally)", - "Configures experimental notification behaviour", - longopts_help_COMMON -}; +#define opts(opt, opt_long) \ + opt(a, healthcheck-timer, required_argument, "set an initial health check delay") \ + opt(A, healthcheck-delay, required_argument, "set a health check timer") \ + opt(D, respawn-delay, required_argument, "Set a respawn delay") \ + opt(d, chdir, required_argument, "Change the PWD") \ + opt(e, env, required_argument, "Set an environment string") \ + opt(g, group, required_argument, "Change the process group") \ + opt(I, ionice, required_argument, "Set an ionice class:data when starting") \ + opt(K, stop, no_argument, "Stop daemon") \ + opt(k, umask, required_argument, "Set the umask for the daemon") \ + opt(m, respawn-max, required_argument, "set maximum number of respawn attempts") \ + opt(N, nicelevel, required_argument, "Set a nicelevel when starting") \ + opt(p, pidfile, required_argument, "Match pid found in this file") \ + opt(P, respawn-period, required_argument, "Set respawn time period") \ + opt(R, retry, required_argument, "Retry schedule to use when stopping") \ + opt(r, chroot, required_argument, "Chroot to this directory") \ + opt(s, signal, required_argument, "Send a signal to the daemon") \ + opt(S, start, no_argument, "Start daemon") \ + opt(u, user, required_argument, "Change the process user") \ + opt(no_argument, stdin, required_argument, "Redirect stdin to file") \ + opt(required_argument, stdout, required_argument, "Redirect stdout to file") \ + opt(2, stderr, required_argument, "Redirect stderr to file") \ + opt(3, reexec, no_argument, "reexec (used internally)") \ + opt_long(LONGOPT_CAPABILITIES, "capabilities", required_argument, "Set the inheritable, ambient and bounding capabilities") \ + opt_long(LONGOPT_SECBITS, "secbits", required_argument, "Set the security-bits for the program") \ + opt_long(LONGOPT_NO_NEW_PRIVS, "no-new-privs", no_argument, "Set the No New Privs flag for the program") \ + opt_long(LONGOPT_RESPAWN_DELAY_STEP, "respawn-delay-step", required_argument, "Increase the respawn delay by this amount for every retry") \ + opt_long(LONGOPT_RESPAWN_DELAY_CAP, "respawn-delay-cap", required_argument, "Set maximum respawn delay when respawn-delay-step is also active") \ + opt_long(LONGOPT_OOM_SCORE_ADJ, "oom-score-adj",required_argument, "Set OOM score adjustment when starting") \ + opt_long(LONGOPT_STDOUT_LOGGER, "stdout-logger",required_argument, "Redirect stdout to process") \ + opt_long(LONGOPT_STDERR_LOGGER, "stderr-logger",required_argument, "Redirect stderr to process") \ + opt_long(LONGOPT_NOTIFY, "notify", required_argument, "Configures experimental notification behaviour") +cmdline_opts(opts) const char *usagestring = NULL; static int healthcheckdelay = 0; diff --git a/src/swclock/swclock.c b/src/swclock/swclock.c index 6c2cbc595..4bb9a13f3 100644 --- a/src/swclock/swclock.c +++ b/src/swclock/swclock.c @@ -34,17 +34,10 @@ const char *applet = NULL; const char *extraopts = "file"; -const char getoptstring[] = "sw" getoptstring_COMMON; -const struct option longopts[] = { - { "save", 0, NULL, 's' }, - { "warn", 0, NULL, 'w' }, - longopts_COMMON -}; -const char * const longopts_help[] = { - "saves the time", - "no error if no reference file", - longopts_help_COMMON -}; +#define opts(opt, opt_long) \ + opt(s, save, no_argument, "saves the time") \ + opt(w, warn, no_argument, "no error if no reference file") +cmdline_opts(opts) const char *usagestring = NULL; int main(int argc, char **argv) From ba618fd0a5232d0e2f681c269e527067681080ae Mon Sep 17 00:00:00 2001 From: "Anna (navi) Figueiredo Gomes" Date: Thu, 8 May 2025 01:34:48 +0200 Subject: [PATCH 2/2] *: move --user flags to only the programs that it makes sense checkpath and other helpers shouldn't really get called with --user --- src/openrc-run/openrc-run.c | 3 ++- src/openrc/rc.c | 3 ++- src/rc-depend/rc-depend.c | 3 ++- src/rc-service/rc-service.c | 3 ++- src/rc-status/rc-status.c | 3 ++- src/rc-update/rc-update.c | 3 ++- src/shared/_usage.h | 1 - 7 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/openrc-run/openrc-run.c b/src/openrc-run/openrc-run.c index ac24d7136..fc0f25658 100644 --- a/src/openrc-run/openrc-run.c +++ b/src/openrc-run/openrc-run.c @@ -69,7 +69,8 @@ const char *extraopts = "stop | start | restart | status | describe | zap"; opt(s, ifstarted, no_argument, "only run commands when started") \ opt(S, ifstopped, no_argument, "only run commands when stopped") \ opt(D, nodeps, no_argument, "ignore dependencies") \ - opt(l, lockfd, required_argument, "fd of the exclusive lock from rc") + opt(l, lockfd, required_argument, "fd of the exclusive lock from rc") \ + opt(U, user, no_argument, "Run in user mode") cmdline_opts(opts) static char *service, *runlevel, *ibsave, *prefix; diff --git a/src/openrc/rc.c b/src/openrc/rc.c index 0d851387f..bc1bb58df 100644 --- a/src/openrc/rc.c +++ b/src/openrc/rc.c @@ -54,7 +54,8 @@ opt(o, override, required_argument, "override the next runlevel to change into\n" \ "when leaving single user or boot runlevels") \ opt(s, service, required_argument, "runs the service specified with the rest of the arguments") \ - opt(S, sys, no_argument, "output the RC system type, if any") + opt(S, sys, no_argument, "output the RC system type, if any") \ + opt(U, user, no_argument, "Run in user mode") cmdline_opts(opts) const char *extraopts = NULL; diff --git a/src/rc-depend/rc-depend.c b/src/rc-depend/rc-depend.c index 4736cc123..2a9c374bd 100644 --- a/src/rc-depend/rc-depend.c +++ b/src/rc-depend/rc-depend.c @@ -39,7 +39,8 @@ const char *extraopts = NULL; opt(T, notrace, no_argument, "Don't trace service dependencies") \ opt(s, strict, no_argument, "Only use what is in the runlevels") \ opt(u, update, no_argument, "Force an update of the dependency tree") \ - opt(F, deptree-file, required_argument, "File to load cached deptree from") + opt(F, deptree-file, required_argument, "File to load cached deptree from") \ + opt(U, user, no_argument, "Run in user mode") cmdline_opts(opts) const char *usagestring = NULL; diff --git a/src/rc-service/rc-service.c b/src/rc-service/rc-service.c index bfd78e943..3eb84f00c 100644 --- a/src/rc-service/rc-service.c +++ b/src/rc-service/rc-service.c @@ -43,7 +43,8 @@ const char *extraopts = NULL; opt(S, ifstopped, no_argument, "if the service is stopped run the command") \ opt(l, list, no_argument, "list all available services") \ opt(r, resolve, required_argument, "resolve the service name to an init script") \ - opt(Z, dry-run, no_argument, "dry run (show what would happen)") + opt(Z, dry-run, no_argument, "dry run (show what would happen)") \ + opt(U, user, no_argument, "Run in user mode") cmdline_opts(opts) const char *usagestring = "" diff --git a/src/rc-status/rc-status.c b/src/rc-status/rc-status.c index 1dd74730b..21a0ccd18 100644 --- a/src/rc-status/rc-status.c +++ b/src/rc-status/rc-status.c @@ -49,7 +49,8 @@ const char *extraopts = NULL; opt(r, runlevel, no_argument, "Show the name of the current runlevel") \ opt(s, servicelist, no_argument, "Show service list") \ opt(S, supervised, no_argument, "show supervised services") \ - opt(u, unused, no_argument, "Show services not assigned to any runlevel") + opt(u, unused, no_argument, "Show services not assigned to any runlevel") \ + opt(U, user, no_argument, "Run in user mode") cmdline_opts(opts) const char *usagestring = "" "Usage: rc-status [-C] [-f ini] [-i state] [runlevel]\n" diff --git a/src/rc-update/rc-update.c b/src/rc-update/rc-update.c index 43ea50c24..41b1fb79f 100644 --- a/src/rc-update/rc-update.c +++ b/src/rc-update/rc-update.c @@ -39,7 +39,8 @@ const char *usagestring = "" #define opts(opt, opt_long) \ opt(a, all, no_argument, "Process all runlevels") \ opt(s, stack, no_argument, "Stack a runlevel instead of a service") \ - opt(u, update, no_argument, "Force an update of the dependency tree") + opt(u, update, no_argument, "Force an update of the dependency tree") \ + opt(U, user, no_argument, "Run in user mode") cmdline_opts(opts) /* Return the number of changes made: diff --git a/src/shared/_usage.h b/src/shared/_usage.h index fff757f32..f4b1df58e 100644 --- a/src/shared/_usage.h +++ b/src/shared/_usage.h @@ -29,7 +29,6 @@ opt(V, version, no_argument, "Display software version") \ opt(v, verbose, no_argument, "Run verbosely") \ opt(q, quiet, no_argument, "Run quietly (repeat to suppress errors)") \ - opt(U, user, no_argument, "Run in user mode") #define cmdline_opts(opts) \ const struct option longopts[] = { opts(longopt, longopt_only) common_opts(longopt) }; \