On Wed, Nov 1, 2023 at 11:53 PM Louai Al-Khanji <[email protected]> wrote:
>
> Hi,
>
> I am interested in implementing the -o|--output option that the Debian 
> start-stop-daemon supports. Might such a patch be considered for upstreaming?
>
> Thanks,
> Louai

Hello,

Attached is a proposed patch. Any feedback would be appreciated.

Thank you,
Louai

-- 


________
This email and any attachments may contain Astranis confidential 
and/or proprietary information governed by a non-disclosure agreement, and 
are intended solely for the individual or entity specified by the message.
From 310c6137f05d1d21b2f06ce17b33a808a520b97f Mon Sep 17 00:00:00 2001
From: Louai Al-Khanji <[email protected]>
Date: Fri, 3 Nov 2023 14:36:23 -0700
Subject: [PATCH] start-stop-daemon: implement option -O|--output

If specified redirect command stdout and stderr to given pathname.
---
 debianutils/start_stop_daemon.c | 27 +++++++++++++++++++++++++--
 include/libbb.h                 |  1 +
 libbb/xfuncs_printf.c           |  7 +++++++
 3 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/debianutils/start_stop_daemon.c b/debianutils/start_stop_daemon.c
index 3e5dd9faa..ff886362e 100644
--- a/debianutils/start_stop_daemon.c
+++ b/debianutils/start_stop_daemon.c
@@ -77,6 +77,7 @@ Misc options:
 //config:	-o|--oknodo ignored since we exit with 0 anyway
 //config:	-v|--verbose
 //config:	-N|--nicelevel N
+//config:	-O|--output pathname
 
 //applet:IF_START_STOP_DAEMON(APPLET_ODDNAME(start-stop-daemon, start_stop_daemon, BB_DIR_SBIN, BB_SUID_DROP, start_stop_daemon))
 /* not NOEXEC: uses bb_common_bufsiz1 */
@@ -113,8 +114,9 @@ Misc options:
 //usage:	IF_FEATURE_START_STOP_DAEMON_FANCY(
 //usage:     "\n	-o		Exit with status 0 if nothing is done"
 //usage:     "\n	-v		Verbose"
-//usage:	)
 //usage:     "\n	-q		Quiet"
+//usage:     "\n	-O pathname	Redirect stdout and stderr to pathname"
+//usage:	)
 
 /* Override ENABLE_FEATURE_PIDFILE */
 #define WANT_PIDFILE 1
@@ -143,6 +145,7 @@ enum {
 	OPT_OKNODO     = (1 << 13) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -o
 	OPT_VERBOSE    = (1 << 14) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -v
 	OPT_NICELEVEL  = (1 << 15) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -N
+	OPT_OUTPUT     = (1 << 16) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -O
 };
 #define QUIET (option_mask32 & OPT_QUIET)
 #define TEST  (option_mask32 & OPT_TEST)
@@ -154,6 +157,7 @@ struct globals {
 	char *execname;
 	char *pidfile;
 	char *execname_cmpbuf;
+	char *output;
 	unsigned execname_sizeof;
 	int user_id;
 	smallint signal_nr;
@@ -168,6 +172,7 @@ struct globals {
 #define pidfile           (G.pidfile             )
 #define user_id           (G.user_id             )
 #define signal_nr         (G.signal_nr           )
+#define output            (G.output              )
 #define INIT_G() do { \
 	setup_common_bufsiz(); \
 	user_id = -1; \
@@ -385,6 +390,7 @@ static const char start_stop_daemon_longopts[] ALIGN1 =
 	"oknodo\0"       No_argument       "o"
 	"verbose\0"      No_argument       "v"
 	"nicelevel\0"    Required_argument "N"
+	"output\0"       Required_argument "O"
 # endif
 	"startas\0"      Required_argument "a"
 	"name\0"         Required_argument "n"
@@ -415,13 +421,14 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv)
 //	char *retry_arg = NULL;
 //	int retries = -1;
 	char *opt_N;
+	int original_stdout, original_stderr;
 #endif
 
 	INIT_G();
 
 	opt = GETOPT32(argv, "^"
 		"KSbqtma:n:s:u:c:x:p:"
-		IF_FEATURE_START_STOP_DAEMON_FANCY("ovN:R:")
+		IF_FEATURE_START_STOP_DAEMON_FANCY("ovN:O:R:")
 			/* -K or -S is required; they are mutually exclusive */
 			/* -p is required if -m is given */
 			/* -xpun (at least one) is required if -K is given */
@@ -434,6 +441,7 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv)
 		LONGOPTS
 		&startas, &cmdname, &signame, &userspec, &chuid, &execname, &pidfile
 		IF_FEATURE_START_STOP_DAEMON_FANCY(,&opt_N)
+		IF_FEATURE_START_STOP_DAEMON_FANCY(,&output)
 		/* We accept and ignore -R <param> / --retry <param> */
 		IF_FEATURE_START_STOP_DAEMON_FANCY(,NULL)
 	);
@@ -560,10 +568,25 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv)
 			setgroups(1, &ugid.gid);
 		}
 	}
+#if ENABLE_FEATURE_START_STOP_DAEMON_FANCY
+	if (opt & OPT_OUTPUT) {
+		int output_fd = xopen(output, O_CREAT | O_WRONLY);
+		original_stdout = xdup(STDOUT_FILENO);
+		original_stderr = xdup(STDERR_FILENO);
+		xdup2(output_fd, STDOUT_FILENO);
+		xdup2(output_fd, STDERR_FILENO);
+	}
+#endif
 	/* Try:
 	 * strace -oLOG start-stop-daemon -S -x /bin/usleep -a qwerty 500000
 	 * should exec "/bin/usleep", but argv[0] should be "qwerty":
 	 */
 	execvp(execname, argv);
+#if ENABLE_FEATURE_START_STOP_DAEMON_FANCY
+	if (opt & OPT_OUTPUT) {
+		xdup2(original_stdout, STDOUT_FILENO);
+		xdup2(original_stderr, STDERR_FILENO);
+	}
+#endif
 	bb_perror_msg_and_die("can't execute '%s'", startas);
 }
diff --git a/include/libbb.h b/include/libbb.h
index 0883fb565..436a55914 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -570,6 +570,7 @@ char *is_suffixed_with(const char *string, const char *key) FAST_FUNC;
 int ndelay_on(int fd) FAST_FUNC;
 int ndelay_off(int fd) FAST_FUNC;
 void close_on_exec_on(int fd) FAST_FUNC;
+int xdup(int) FAST_FUNC;
 void xdup2(int, int) FAST_FUNC;
 void xmove_fd(int, int) FAST_FUNC;
 
diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c
index 842d10cd2..49b6b35ef 100644
--- a/libbb/xfuncs_printf.c
+++ b/libbb/xfuncs_printf.c
@@ -227,6 +227,13 @@ void FAST_FUNC xpipe(int *filedes)
 		bb_simple_perror_msg_and_die("can't create pipe");
 }
 
+int FAST_FUNC xdup(int fd)
+{
+	int newfd = dup(fd);
+	if (newfd < 0) bb_simple_perror_msg_and_die("can't duplicate file descriptor");
+	return newfd;
+}
+
 void FAST_FUNC xdup2(int from, int to)
 {
 	if (dup2(from, to) != to)
-- 
2.25.1

_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to