From af485f89cd5240df2f4fa72bd46465b0e38247d1 Mon Sep 17 00:00:00 2001
From: Matt Johnston <matt@ucc.asn.au>
Date: Tue, 28 Feb 2006 04:03:49 +0000
Subject: [PATCH] Merge of the uClinux-dist patch, should work in inetd mode

--HG--
extra : convert_revision : 976bfa569f133be97d6f57c89bffa0311a142be3
---
 scp.c             | 32 ++++++++++++++++++++++++++++++++
 svr-chansession.c | 13 +++++++++++++
 2 files changed, 45 insertions(+)

diff --git a/scp.c b/scp.c
index ccb6c2a3..ffc4deb4 100644
--- a/scp.c
+++ b/scp.c
@@ -166,8 +166,22 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc)
 	close(reserved[0]);
 	close(reserved[1]);
 
+    // uClinux needs to build the args here before vforking,
+    // otherwise we do it later on.
+#ifdef __uClinux__
+	args.list[0] = ssh_program;
+	if (remuser != NULL)
+		addargs(&args, "-l%s", remuser);
+	addargs(&args, "%s", host);
+	addargs(&args, "%s", cmd);
+#endif /* __uClinux__ */
+
 	/* Fork a child to execute the command on the remote host using ssh. */
+#ifdef __uClinux__
+	do_cmd_pid = vfork();
+#else
 	do_cmd_pid = fork();
+#endif /* __uClinux__ */
 	if (do_cmd_pid == 0) {
 		/* Child. */
 		close(pin[1]);
@@ -177,6 +191,7 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc)
 		close(pin[0]);
 		close(pout[1]);
 
+#ifndef __uClinux__
 		args.list[0] = ssh_program;
 		if (remuser != NULL) {
 			addargs(&args, "-l");
@@ -184,6 +199,7 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc)
 		}
 		addargs(&args, "%s", host);
 		addargs(&args, "%s", cmd);
+#endif
 
 		execvp(ssh_program, args.list);
 		perror(ssh_program);
@@ -192,6 +208,22 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc)
 		fprintf(stderr, "Fatal error: fork: %s\n", strerror(errno));
 		exit(1);
 	}
+
+#ifdef __uClinux__
+	/* clean up command */
+	/* pop cmd */
+	free(args->list[--args->num]);
+	args->list[args->num]=NULL;
+	/* pop host */
+	free(args->list[--args->num-1]);
+	args->list[args->num]=NULL;
+	/* pop user */
+	if (remuser != NULL) {
+		free(args->list[--args->num-1]);
+		args->list[args->num]=NULL;
+	}
+#endif /* __uClinux__
+	  
 	/* Parent.  Close the other side, and return the local side. */
 	close(pin[0]);
 	*fdout = pin[1];
diff --git a/svr-chansession.c b/svr-chansession.c
index 03ac40ac..9ea6ac5e 100644
--- a/svr-chansession.c
+++ b/svr-chansession.c
@@ -623,7 +623,12 @@ static int noptycommand(struct Channel *channel, struct ChanSess *chansess) {
 	if (pipe(errfds) != 0)
 		return DROPBEAR_FAILURE;
 
+#ifdef __uClinux__
+	pid = vfork();
+#else
 	pid = fork();
+#endif
+
 	if (pid < 0)
 		return DROPBEAR_FAILURE;
 
@@ -714,7 +719,11 @@ static int ptycommand(struct Channel *channel, struct ChanSess *chansess) {
 		return DROPBEAR_FAILURE;
 	}
 	
+#ifdef __uClinux__
+	pid = vfork();
+#else
 	pid = fork();
+#endif
 	if (pid < 0)
 		return DROPBEAR_FAILURE;
 
@@ -828,12 +837,16 @@ static void execchild(struct ChanSess *chansess) {
 	char * baseshell = NULL;
 	unsigned int i;
 
+    /* with uClinux we'll have vfork()ed, so don't want to overwrite the
+     * hostkey. can't think of a workaround to clear it */
+#ifndef __uClinux__
 	/* wipe the hostkey */
 	sign_key_free(svr_opts.hostkey);
 	svr_opts.hostkey = NULL;
 
 	/* overwrite the prng state */
 	seedrandom();
+#endif
 
 	/* close file descriptors except stdin/stdout/stderr
 	 * Need to be sure FDs are closed here to avoid reading files as root */
-- 
GitLab