summaryrefslogtreecommitdiffhomepage
path: root/dbutil.c
diff options
context:
space:
mode:
authorMatt Johnston <matt@ucc.asn.au>2008-09-15 14:04:55 +0000
committerMatt Johnston <matt@ucc.asn.au>2008-09-15 14:04:55 +0000
commit12929e8cf09bf16ad59e04eaa20f31282bd58e30 (patch)
treebec557b58d2251467eddfc6eede4b7667f57b387 /dbutil.c
parent7ac24b10b9967e396d5c97395eb70084e1697947 (diff)
- Add run_shell_command() function to run a "sh -c" command, handling
lots of the work that exechild did (and can be shared by client -J option) --HG-- extra : convert_revision : a15dfd8017af8212b3b227f18ce2539dd471f7f6
Diffstat (limited to 'dbutil.c')
-rw-r--r--dbutil.c45
1 files changed, 43 insertions, 2 deletions
diff --git a/dbutil.c b/dbutil.c
index d10a651..2dcae6b 100644
--- a/dbutil.c
+++ b/dbutil.c
@@ -393,8 +393,7 @@ int connect_remote(const char* remotehost, const char* remoteport,
* and the pid. exec_fn is the function that will actually execute the child process,
* it will be run after the child has fork()ed, and is passed exec_data. */
int spawn_command(void(*exec_fn)(void *user_data), void *exec_data,
- int *ret_writefd, int *ret_readfd, int *ret_errfd, pid_t *ret_pid)
-{
+ int *ret_writefd, int *ret_readfd, int *ret_errfd, pid_t *ret_pid) {
int infds[2];
int outfds[2];
int errfds[2];
@@ -466,6 +465,48 @@ int spawn_command(void(*exec_fn)(void *user_data), void *exec_data,
}
}
+/* Runs a command with "sh -c". Will close FDs (except stdin/stdout/stderr) and
+ * re-enabled SIGPIPE. If cmd is NULL, will run a login shell.
+ */
+void run_shell_command(const char* cmd, unsigned int maxfd, char* usershell) {
+ char * argv[4];
+ char * baseshell = NULL;
+ unsigned int i;
+
+ baseshell = basename(usershell);
+
+ if (cmd != NULL) {
+ argv[0] = baseshell;
+ } else {
+ /* a login shell should be "-bash" for "/bin/bash" etc */
+ int len = strlen(baseshell) + 2; /* 2 for "-" */
+ argv[0] = (char*)m_malloc(len);
+ snprintf(argv[0], len, "-%s", baseshell);
+ }
+
+ if (cmd != NULL) {
+ argv[1] = "-c";
+ argv[2] = cmd;
+ argv[3] = NULL;
+ } else {
+ /* construct a shell of the form "-bash" etc */
+ argv[1] = NULL;
+ }
+
+ /* Re-enable SIGPIPE for the executed process */
+ if (signal(SIGPIPE, SIG_DFL) == SIG_ERR) {
+ dropbear_exit("signal() error");
+ }
+
+ /* close file descriptors except stdin/stdout/stderr
+ * Need to be sure FDs are closed here to avoid reading files as root */
+ for (i = 3; i <= maxfd; i++) {
+ m_close(i);
+ }
+
+ execv(usershell, argv);
+}
+
/* Return a string representation of the socket address passed. The return
* value is allocated with malloc() */
unsigned char * getaddrstring(struct sockaddr_storage* addr, int withport) {