git: 0a402ad2e6d6 - main - daemon: add long_opts

From: Kyle Evans <kevans_at_FreeBSD.org>
Date: Fri, 10 Feb 2023 04:37:59 UTC
The branch main has been updated by kevans:

URL: https://cgit.FreeBSD.org/src/commit/?id=0a402ad2e6d6014ed8c622a90153f53b99c1b482

commit 0a402ad2e6d6014ed8c622a90153f53b99c1b482
Author:     Ihor Antonov <ihor@antonovs.family>
AuthorDate: 2023-02-10 04:36:07 +0000
Commit:     Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2023-02-10 04:36:07 +0000

    daemon: add long_opts
    
    Long options improve readability of scripts, makes code comprehension
    easier.  This patch adds long options while preserving the existing CLI
    interface.
    
    Also --help/-h option is added.
    
    Reviewed by:    allanjude, pauamma (both earlier versions), kevans
    Differential Revision:  https://reviews.freebsd.org/D38244
---
 usr.sbin/daemon/daemon.8 | 71 +++++++++++++++++++++----------------------
 usr.sbin/daemon/daemon.c | 78 ++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 98 insertions(+), 51 deletions(-)

diff --git a/usr.sbin/daemon/daemon.8 b/usr.sbin/daemon/daemon.8
index c4f20548d4a2..3b91b9b20f3d 100644
--- a/usr.sbin/daemon/daemon.8
+++ b/usr.sbin/daemon/daemon.8
@@ -57,10 +57,10 @@ log file.
 .Pp
 The options are as follows:
 .Bl -tag -width indent
-.It Fl c
+.It Fl c , Fl -change-dir
 Change the current working directory to the root
 .Pq Dq Pa / .
-.It Fl f
+.It Fl f , Fl -close-fds
 Redirect standard input, standard output and standard error to
 .Pa /dev/null .
 When this option is used together with any of the options related to file
@@ -68,35 +68,35 @@ or syslog output, the standard file descriptors are first redirected to
 .Pa /dev/null ,
 then stdout and/or stderr is redirected to a file or to syslog as
 specified by the other options.
-.It Fl H
+.It Fl H , Fl -sighup
 Close
 .Pa output_file
 and re-open it when signal SIGHUP is received, for interoperability with
 .Xr newsyslog 1
 and similar log rotation / archival mechanisms.  If
-.Fl o
+.Fl -output-file
 is not specified, this flag is ignored.
-.It Fl S
+.It Fl S , Fl -syslog
 Enable syslog output.
 This is implicitly applied if other syslog parameters are provided.
 The default values are daemon, notice, and daemon for facility, priority, and
 tag, respectively.
-.It Fl o Ar output_file
+.It Fl o , Fl -output-file Ar output_file
 Append output from the daemonized process to
 .Pa output_file .
 If the file does not exist, it is created with permissions 0600.
 When this option is used together with options
-.Fl c
+.Fl -change-dir
 and
-.Fl H
+.Fl -sighup
 the absolute path needs to be provided to ensure
 .Nm
 can re-open the file after a SIGHUP.
-.It Fl m Ar output_mask
+.It Fl m , Fl -output-mask Ar output_mask
 Redirect output from the child process stdout (1), stderr (2), or both (3).
 This value specifies what is sent to syslog and the log file.
 The default is 3.
-.It Fl p Ar child_pidfile
+.It Fl p , Fl -child-pidfile Ar child_pidfile
 Write the ID of the created process into the
 .Ar child_pidfile
 using the
@@ -112,9 +112,9 @@ The
 owner is the user who runs the
 .Nm
 regardless of whether the
-.Fl u
+.Fl -user
 option is used or not.
-.It Fl P Ar supervisor_pidfile
+.It Fl P , Fl -supervisor-pidfile Ar supervisor_pidfile
 Write the ID of the
 .Nm
 process into the
@@ -132,45 +132,46 @@ The
 owner is the user who runs the
 .Nm
 regardless of whether the
-.Fl u
+.Fl -user
 option is used or not.
-.It Fl r
+.It Fl r , Fl -restart
 Supervise and restart the program after a one-second delay if it has
 been terminated.
-.It Fl R Ar restart_delay_seconds
+.It Fl R , Fl -restart-delay Ar restart_delay_seconds
 Supervise and restart the program after the specified delay
 if it has been terminated.
-.It Fl t Ar title
+.It Fl t , Fl -title Ar title
 Set the title for the daemon process.
 The default is the daemonized invocation.
-.It Fl u Ar user
+.It Fl u , Fl -user Ar user
 Login name of the user to execute the program under.
 Requires adequate superuser privileges.
-.It Fl s Ar syslog_priority
+.It Fl s , Fl -syslog-priority Ar syslog_priority
 These priorities are accepted: emerg, alert, crit, err, warning,
 notice, info, and debug.
 The default is notice.
-.It Fl l Ar syslog_facility
+.It Fl l , Fl -syslog-facility Ar syslog_facility
 These facilities are accepted: auth, authpriv, console, cron, daemon,
 ftp, kern, lpr, mail, news, ntp, security, syslog, user, uucp, and
 local0, ..., local7.
 The default is daemon.
-.It Fl T Ar syslog_tag
+.It Fl T , Fl -syslog-tag Ar syslog_tag
 Set the tag which is appended to all syslog messages.
 The default is daemon.
 .El
 .Pp
 If any of the options
-.Fl p ,
-.Fl P ,
-.Fl r ,
-.Fl o ,
-.Fl s ,
-.Fl T ,
-.Fl m ,
-.Fl S ,
+.Fl -child-pidfile ,
+.Fl -output-mask ,
+.Fl -restart ,
+.Fl -restart-delay ,
+.Fl -supervisor-pidfile ,
+.Fl -syslog ,
+.Fl -syslog-facility
+.Fl -syslog-priority ,
+.Fl -syslog-tag ,
 or
-.Fl l
+.Fl -output ,
 are specified, the program is executed in a spawned child process.
 The
 .Nm
@@ -187,21 +188,21 @@ If neither file or syslog output are selected, all output is redirected to the
 .Nm
 process and written to stdout.
 The
-.Fl f
+.Fl -close-fds
 option may be used to suppress the stdout output completely.
 .Pp
 The
-.Fl P
+.Fl -supervisor-pidfile
 option is useful combined with the
-.Fl r
+.Fl -restart
 option as
 .Ar supervisor_pidfile
 contains the ID of the supervisor
 not the child.
 This is especially important if you use
-.Fl r
+.Fl -restart
 in an rc script as the
-.Fl p
+.Fl -child-pidfile
 option will give you the child's ID to signal when you attempt to
 stop the service, causing
 .Nm
@@ -229,7 +230,7 @@ cannot be opened for appending, and otherwise 0.
 If the command cannot be executed, an error message is printed to
 standard error.
 The exact behavior depends on the logging parameters and the
-.Fl f
+.Fl -close-fds
 flag.
 .Sh SEE ALSO
 .Xr nohup 1 ,
diff --git a/usr.sbin/daemon/daemon.c b/usr.sbin/daemon/daemon.c
index e8cdaa230caa..edcdf3141fcc 100644
--- a/usr.sbin/daemon/daemon.c
+++ b/usr.sbin/daemon/daemon.c
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
 #include <fcntl.h>
 #include <err.h>
 #include <errno.h>
+#include <getopt.h>
 #include <libutil.h>
 #include <login_cap.h>
 #include <paths.h>
@@ -77,11 +78,64 @@ static void open_pid_files(const char *, const char *, struct pidfh **,
 			   struct pidfh **);
 static void do_output(const unsigned char *, size_t, struct log_params *);
 static void daemon_sleep(time_t, long);
-static void usage(void);
 
 static volatile sig_atomic_t terminate = 0, child_gone = 0, pid = 0,
   do_log_reopen = 0;
 
+static const char shortopts[] = "+cfHSp:P:ru:o:s:l:t:m:R:T:h";
+
+static const struct option longopts[] = {
+        { "change-dir",         no_argument,            NULL,           'c' },
+        { "close-fds",          no_argument,            NULL,           'f' },
+        { "sighup",             no_argument,            NULL,           'H' },
+        { "syslog",             no_argument,            NULL,           'S' },
+        { "output-file",        required_argument,      NULL,           'o' },
+        { "output-mask",        required_argument,      NULL,           'm' },
+        { "child-pidfile",      required_argument,      NULL,           'p' },
+        { "supervisor-pidfile", required_argument,      NULL,           'P' },
+        { "restart",            no_argument,            NULL,           'r' },
+        { "restart-delay",      required_argument,      NULL,           'R' },
+        { "title",              required_argument,      NULL,           't' },
+        { "user",               required_argument,      NULL,           'u' },
+        { "syslog-priority",    required_argument,      NULL,           's' },
+        { "syslog-facility",    required_argument,      NULL,           'l' },
+        { "syslog-tag",         required_argument,      NULL,           'T' },
+        { "help",               no_argument,            NULL,           'h' },
+        { NULL,                 0,                      NULL,            0  }
+};
+
+static _Noreturn void
+usage(int exitcode)
+{
+	(void)fprintf(stderr,
+	    "usage: daemon [-cfHrS] [-p child_pidfile] [-P supervisor_pidfile]\n"
+	    "              [-u user] [-o output_file] [-t title]\n"
+	    "              [-l syslog_facility] [-s syslog_priority]\n"
+	    "              [-T syslog_tag] [-m output_mask] [-R restart_delay_secs]\n"
+	    "command arguments ...\n");
+
+	(void)fprintf(stderr,
+	    "  --change-dir         -c         Change the current working directory to root\n"
+	    "  --close-fds          -f         Set stdin, stdout, stderr to /dev/null\n"
+	    "  --sighup             -H         Close and re-open output file on SIGHUP\n"
+	    "  --syslog             -S         Send output to syslog\n"
+	    "  --output-file        -o <file>  Append output of the child process to file\n"
+	    "  --output-mask        -m <mask>  What to send to syslog/file\n"
+	    "                                  1=stdout, 2=stderr, 3=both\n"
+	    "  --child-pidfile      -p <file>  Write PID of the child process to file\n"
+	    "  --supervisor-pidfile -P <file>  Write PID of the supervisor process to file\n"
+	    "  --restart            -r         Restart child if it terminates (1 sec delay)\n"
+	    "  --restart-delay      -R <N>     Restart child if it terminates after N sec\n"
+	    "  --title              -t <title> Set the title of the supervisor process\n"
+	    "  --user               -u <user>  Drop privileges, run as given user\n"
+	    "  --syslog-priority    -s <prio>  Set syslog priority\n"
+	    "  --syslog-facility    -l <flty>  Set syslog facility\n"
+	    "  --syslog-tag         -T <tag>   Set syslog tag\n"
+	    "  --help               -h         Show this help\n");
+
+        exit(exitcode);
+}
+
 int
 main(int argc, char *argv[])
 {
@@ -106,7 +160,7 @@ main(int argc, char *argv[])
 	log_reopen = 0;
 	outfn = NULL;
 	title = NULL;
-	while ((ch = getopt(argc, argv, "cfHSp:P:ru:o:s:l:t:l:m:R:T:")) != -1) {
+	while ((ch = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) {
 		switch (ch) {
 		case 'c':
 			nochdir = 0;
@@ -164,15 +218,18 @@ main(int argc, char *argv[])
 		case 'u':
 			user = optarg;
 			break;
+                case 'h':
+			usage(0);
+                        __builtin_unreachable();
 		default:
-			usage();
+			usage(1);
 		}
 	}
 	argc -= optind;
 	argv += optind;
 
 	if (argc == 0)
-		usage();
+		usage(1);
 
 	if (!title)
 		title = argv[0];
@@ -182,7 +239,7 @@ main(int argc, char *argv[])
 		if (outfd == -1)
 			err(7, "open");
 	}
-	
+
 	if (dosyslog)
 		openlog(logtag, LOG_PID | LOG_NDELAY, logfac);
 
@@ -610,14 +667,3 @@ reopen_log(struct log_params *lpp)
 	lpp->outfd = outfd;
 }
 
-static void
-usage(void)
-{
-	(void)fprintf(stderr,
-	    "usage: daemon [-cfHrS] [-p child_pidfile] [-P supervisor_pidfile]\n"
-	    "              [-u user] [-o output_file] [-t title]\n"
-	    "              [-l syslog_facility] [-s syslog_priority]\n"
-	    "              [-T syslog_tag] [-m output_mask] [-R restart_delay_secs]\n"
-	    "command arguments ...\n");
-	exit(1);
-}