Module Name: src Committed By: pooka Date: Wed Feb 16 15:33:47 UTC 2011
Modified Files: src/lib/librumpclient: rumpclient.c rumpclient.h src/lib/librumphijack: hijack.c Log Message: Push the fiddly tasks for exec and fork from rumphijack to rumpclient. This makes it possible easily execute those operations also from non-hijacked rump clients (plus fixes one memory leak in an error branch). To generate a diff of this commit: cvs rdiff -u -r1.29 -r1.30 src/lib/librumpclient/rumpclient.c cvs rdiff -u -r1.6 -r1.7 src/lib/librumpclient/rumpclient.h cvs rdiff -u -r1.41 -r1.42 src/lib/librumphijack/hijack.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/librumpclient/rumpclient.c diff -u src/lib/librumpclient/rumpclient.c:1.29 src/lib/librumpclient/rumpclient.c:1.30 --- src/lib/librumpclient/rumpclient.c:1.29 Tue Feb 15 10:37:07 2011 +++ src/lib/librumpclient/rumpclient.c Wed Feb 16 15:33:47 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: rumpclient.c,v 1.29 2011/02/15 10:37:07 pooka Exp $ */ +/* $NetBSD: rumpclient.c,v 1.30 2011/02/16 15:33:47 pooka Exp $ */ /* * Copyright (c) 2010, 2011 Antti Kantee. All Rights Reserved. @@ -74,6 +74,8 @@ int (*host_kevent)(int, const struct kevent *, size_t, struct kevent *, size_t, const struct timespec *); +int (*host_execve)(const char *, char *const[], char *const[]); + #include "sp_common.c" static struct spclient clispc = { @@ -748,6 +750,7 @@ FINDSYM(setsockopt); FINDSYM(dup); FINDSYM(kqueue); + FINDSYM(execve); #if !__NetBSD_Prereq__(5,99,7) FINDSYM(kevent); #else @@ -813,7 +816,7 @@ pthread_sigmask(SIG_SETMASK, &fullset, &omask); rpf = malloc(sizeof(*rpf)); if (rpf == NULL) - return NULL; + goto out; if ((rv = prefork_req(&clispc, &omask, &resp)) != 0) { free(rpf); @@ -926,6 +929,30 @@ return 0; } +pid_t +rumpclient_fork(pid_t (*forkfn)(void)) +{ + struct rumpclient_fork *rf; + pid_t rv; + + if ((rf = rumpclient_prefork()) == NULL) + return -1; + + switch ((rv = forkfn())) { + case -1: + /* XXX: cancel rf */ + break; + case 0: + if (rumpclient_fork_init(rf) == -1) + rv = -1; + break; + default: + break; + } + + return rv; +} + /* * Process is about to exec. Save info about our existing connection * in the env. rumpclient will check for this info in init(). @@ -933,13 +960,13 @@ * may use it as well. */ int -rumpclient__exec_augmentenv(char *const oenv1[], char *const oenv2[], - char ***newenvp) +rumpclient_exec(const char *path, char *const argv[], char *const envp[]) { char buf[4096]; char **newenv; char *envstr, *envstr2; - size_t nelem1, nelem2; + size_t nelem; + int rv, sverrno; snprintf(buf, sizeof(buf), "RUMPCLIENT__EXECFD=%d,%d", clispc.spc_fd, kq); @@ -963,31 +990,28 @@ envstr2 = NULL; } - nelem1 = 0; - if (oenv1) { - for (; oenv1[nelem1]; nelem1++) - continue; - } - nelem2 = 0; - if (oenv2) { - for (; oenv2[nelem2]; nelem2++) - continue; - } + for (nelem = 0; envp && envp[nelem]; nelem++) + continue; - newenv = malloc(sizeof(*newenv) * nelem1+nelem2+3); + newenv = malloc(sizeof(*newenv) * nelem+3); if (newenv == NULL) { free(envstr2); free(envstr); return ENOMEM; } - memcpy(&newenv[0], oenv1, sizeof(*oenv1) * nelem1); - memcpy(&newenv[nelem1], oenv2, sizeof(*oenv2) * nelem2); - - newenv[nelem1+nelem2] = envstr; - newenv[nelem1+nelem2+1] = envstr2; - newenv[nelem1+nelem2+2] = NULL; - - *newenvp = newenv; + memcpy(&newenv[0], envp, nelem*sizeof(*envp)); - return 0; + newenv[nelem] = envstr; + newenv[nelem+1] = envstr2; + newenv[nelem+2] = NULL; + + rv = host_execve(path, argv, newenv); + + _DIAGASSERT(rv != 0); + sverrno = errno; + free(envstr2); + free(envstr); + free(newenv); + errno = sverrno; + return rv; } Index: src/lib/librumpclient/rumpclient.h diff -u src/lib/librumpclient/rumpclient.h:1.6 src/lib/librumpclient/rumpclient.h:1.7 --- src/lib/librumpclient/rumpclient.h:1.6 Mon Feb 14 14:56:23 2011 +++ src/lib/librumpclient/rumpclient.h Wed Feb 16 15:33:47 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: rumpclient.h,v 1.6 2011/02/14 14:56:23 pooka Exp $ */ +/* $NetBSD: rumpclient.h,v 1.7 2011/02/16 15:33:47 pooka Exp $ */ /*- * Copyright (c) 2010 Antti Kantee. All Rights Reserved. @@ -39,6 +39,9 @@ struct rumpclient_fork *rumpclient_prefork(void); int rumpclient_fork_init(struct rumpclient_fork *); +int rumpclient_fork(pid_t (*forkfn)(void)); +int rumpclient_exec(const char *, char *const [], char *const[]); + #define RUMPCLIENT_RETRYCONN_INFTIME ((time_t)-1) #define RUMPCLIENT_RETRYCONN_ONCE ((time_t)-2) #define RUMPCLIENT_RETRYCONN_DIE ((time_t)-3) @@ -50,7 +53,6 @@ RUMPCLIENT_CLOSE_FCLOSEM }; int rumpclient__closenotify(int *, enum rumpclient_closevariant); -int rumpclient__exec_augmentenv(char *const[], char *const[], char ***); __END_DECLS Index: src/lib/librumphijack/hijack.c diff -u src/lib/librumphijack/hijack.c:1.41 src/lib/librumphijack/hijack.c:1.42 --- src/lib/librumphijack/hijack.c:1.41 Tue Feb 15 14:01:52 2011 +++ src/lib/librumphijack/hijack.c Wed Feb 16 15:33:46 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: hijack.c,v 1.41 2011/02/15 14:01:52 pooka Exp $ */ +/* $NetBSD: hijack.c,v 1.42 2011/02/16 15:33:46 pooka Exp $ */ /*- * Copyright (c) 2011 Antti Kantee. All Rights Reserved. @@ -26,7 +26,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: hijack.c,v 1.41 2011/02/15 14:01:52 pooka Exp $"); +__RCSID("$NetBSD: hijack.c,v 1.42 2011/02/16 15:33:46 pooka Exp $"); #define __ssp_weak_name(fun) _hijack_ ## fun @@ -594,33 +594,14 @@ return dodup(oldd, 0); } -/* - * We just wrap fork the appropriate rump client calls to preserve - * the file descriptors of the forked parent in the child, but - * prevent double use of connection fd. - */ pid_t fork() { - struct rumpclient_fork *rf; pid_t rv; DPRINTF(("fork\n")); - if ((rf = rumpclient_prefork()) == NULL) - return -1; - - switch ((rv = host_fork())) { - case -1: - /* XXX: cancel rf */ - break; - case 0: - if (rumpclient_fork_init(rf) == -1) - rv = -1; - break; - default: - break; - } + rv = rumpclient_fork(host_fork); DPRINTF(("fork returns %d\n", rv)); return rv; @@ -644,31 +625,38 @@ } int -execve(const char *path, char *const argv[], char *const oenvp[]) +execve(const char *path, char *const argv[], char *const envp[]) { char buf[128]; - char **env; - char *dup2maskenv[2]; char *dup2str; - int rv; + char **newenv; + size_t nelem; + int rv, sverrno; snprintf(buf, sizeof(buf), "RUMPHIJACK__DUP2MASK=%u", dup2mask); dup2str = malloc(strlen(buf)+1); if (dup2str == NULL) return ENOMEM; strcpy(dup2str, buf); - dup2maskenv[0] = dup2str; - dup2maskenv[1] = NULL; - rv = rumpclient__exec_augmentenv(oenvp, dup2maskenv, &env); - if (rv) - return rv; - - rv = host_execve(path, argv, env); - if (rv != 0) { + for (nelem = 0; envp && envp[nelem]; nelem++) + continue; + newenv = malloc(sizeof(*newenv) * nelem+2); + if (newenv == NULL) { free(dup2str); - free(env); /* XXX missing some strings within env */ + return ENOMEM; } + memcpy(newenv, envp, nelem*sizeof(*newenv)); + newenv[nelem] = dup2str; + newenv[nelem+1] = NULL; + + rv = rumpclient_exec(path, argv, newenv); + + _DIAGASSERT(rv != 0); + sverrno = errno; + free(newenv); + free(dup2str); + errno = sverrno; return rv; }