From c81e058bb05b274b9a88e684ffd95a03a0ac4377 Mon Sep 17 00:00:00 2001
From: Matt Johnston <matt@ucc.asn.au>
Date: Wed, 7 Jun 2006 15:47:04 +0000
Subject: [PATCH] add -f background option to dbclient

--HG--
extra : convert_revision : 5ef61c30c0a634ac0da22a8c694ce235690e8170
---
 cli-runopts.c | 10 ++++++++++
 cli-session.c | 17 +++++++++++++++++
 dbclient.1    |  4 ++++
 runopts.h     |  1 +
 4 files changed, 32 insertions(+)

diff --git a/cli-runopts.c b/cli-runopts.c
index 2e7c0aca..a4a8a58c 100644
--- a/cli-runopts.c
+++ b/cli-runopts.c
@@ -51,6 +51,7 @@ static void printhelp() {
 					"-t    Allocate a pty\n"
 					"-T    Don't allocate a pty\n"
 					"-N    Don't run a remote command\n"
+					"-f    Run in background after auth\n"
 #ifdef ENABLE_CLI_PUBKEY_AUTH
 					"-i <identityfile>   (multiple allowed)\n"
 #endif
@@ -90,6 +91,7 @@ void cli_getopts(int argc, char ** argv) {
 	cli_opts.username = NULL;
 	cli_opts.cmd = NULL;
 	cli_opts.no_cmd = 0;
+	cli_opts.backgrounded = 0;
 	cli_opts.wantpty = 9; /* 9 means "it hasn't been touched", gets set later */
 #ifdef ENABLE_CLI_PUBKEY_AUTH
 	cli_opts.privkeys = NULL;
@@ -168,6 +170,9 @@ void cli_getopts(int argc, char ** argv) {
 				case 'N':
 					cli_opts.no_cmd = 1;
 					break;
+				case 'f':
+					cli_opts.backgrounded = 1;
+					break;
 #ifdef ENABLE_CLI_LOCALTCPFWD
 				case 'L':
 					nextislocal = 1;
@@ -274,6 +279,11 @@ void cli_getopts(int argc, char ** argv) {
 			cli_opts.wantpty = 0;
 		}
 	}
+
+	if (cli_opts.backgrounded && cli_opts.cmd == NULL
+			&& cli_opts.no_cmd == 0) {
+		dropbear_exit("command required for -f");
+	}
 }
 
 #ifdef ENABLE_CLI_PUBKEY_AUTH
diff --git a/cli-session.c b/cli-session.c
index c47bd3bc..be36becc 100644
--- a/cli-session.c
+++ b/cli-session.c
@@ -212,6 +212,23 @@ static void cli_sessionloop() {
 			*/
 
 		case USERAUTH_SUCCESS_RCVD:
+
+			if (cli_opts.backgrounded) {
+				int devnull;
+				// keeping stdin open steals input from the terminal and
+				// is confusing, though stdout/stderr could be useful.
+				devnull = open(_PATH_DEVNULL, O_RDONLY);
+				if (devnull < 0) {
+					dropbear_exit("opening /dev/null: %d %s",
+							errno, strerror(errno));
+				}
+				dup2(devnull, STDIN_FILENO);
+				if (daemon(0, 1) < 0) {
+					dropbear_exit("Backgrounding failed: %d %s", 
+							errno, strerror(errno));
+				}
+			}
+			
 #ifdef ENABLE_CLI_LOCALTCPFWD
 			setup_localtcp();
 #endif
diff --git a/dbclient.1 b/dbclient.1
index 27e2d201..acff59d3 100644
--- a/dbclient.1
+++ b/dbclient.1
@@ -63,6 +63,10 @@ Don't allocate a pty.
 .B \-N
 Don't request a remote shell or run any commands. Any command arguments are ignored.
 .TP
+.B \-f
+Fork into the background after authentication. A command argument (or -N) is required.
+This is useful when using password authentication.
+.TP
 .B \-g
 Allow non-local hosts to connect to forwarded ports. Applies to -L and -R
 forwarded ports, though remote connections to -R forwarded ports may be limited
diff --git a/runopts.h b/runopts.h
index cb5e4ca8..c3db42c7 100644
--- a/runopts.h
+++ b/runopts.h
@@ -103,6 +103,7 @@ typedef struct cli_runopts {
 	char *cmd;
 	int wantpty;
 	int no_cmd;
+	int backgrounded;
 #ifdef ENABLE_CLI_PUBKEY_AUTH
 	struct SignKeyList *privkeys; /* Keys to use for public-key auth */
 #endif
-- 
GitLab