diff --git a/bbs/system.c b/bbs/system.c index 939f8f3..6464d92 100644 --- a/bbs/system.c +++ b/bbs/system.c @@ -423,53 +423,6 @@ int bbs_argv_from_str(char **argv, int argc, char *s) return c; } -/* Forward declaration */ -static int __bbs_execvpe_fd(struct bbs_node *node, int usenode, int fdin, int fdout, const char *filename, char *const argv[], char *const envp[], int isolated); - -int bbs_execvp(struct bbs_node *node, const char *filename, char *const argv[]) -{ - return __bbs_execvpe_fd(node, 1, -1, -1, filename, argv, NULL, 0); -} - -int bbs_execvp_isolated(struct bbs_node *node, const char *filename, char *const argv[]) -{ - return __bbs_execvpe_fd(node, 1, -1, -1, filename, argv, NULL, 1); -} - -int bbs_execvp_isolated_networked(struct bbs_node *node, const char *filename, char *const argv[]) -{ - return __bbs_execvpe_fd(node, 1, -1, -1, filename, argv, NULL, 2); -} - -int bbs_execvp_headless(struct bbs_node *node, const char *filename, char *const argv[]) -{ - if (!node) { - bbs_warning("It is not necessary to use %s if node is NULL\n", __func__); - } - return __bbs_execvpe_fd(node, 0, -1, -1, filename, argv, NULL, 0); -} - -int bbs_execvp_fd(struct bbs_node *node, int fdin, int fdout, const char *filename, char *const argv[]) -{ - return __bbs_execvpe_fd(node, 1, fdin, fdout, filename, argv, NULL, 0); -} - -int bbs_execvp_fd_headless(struct bbs_node *node, int fdin, int fdout, const char *filename, char *const argv[]) -{ - if (!node) { - bbs_warning("It is not necessary to use %s if node is NULL\n", __func__); - } - return __bbs_execvpe_fd(node, 0, fdin, fdout, filename, argv, NULL, 0); -} - -int bbs_execvpe_fd_headless(struct bbs_node *node, int fdin, int fdout, const char *filename, char *const argv[], char *const envp[]) -{ - if (!node) { - bbs_warning("It is not necessary to use %s if node is NULL\n", __func__); - } - return __bbs_execvpe_fd(node, 0, fdin, fdout, filename, argv, envp, 0); -} - #ifdef ISOEXEC_SUPPORTED static int update_map(const char *mapping, const char *map_file, int map_len) { @@ -728,9 +681,7 @@ static ssize_t full_read(int fd, char *restrict buf, size_t len) /*! * \brief Execute an external program. Most calls to exec() should funnel through this function... * \param node - * \param usenode - * \param fdin - * \param fdout + * \param e * \param filename Program name to execute * \param argv Arguments * \param envp Environment (optional) @@ -738,10 +689,12 @@ static ssize_t full_read(int fd, char *restrict buf, size_t len) * \retval -1 on failure * \return Result of program execution */ -static int __bbs_execvpe_fd(struct bbs_node *node, int usenode, int fdin, int fdout, const char *filename, char *const argv[], char *const envp[], int isolated) +int __bbs_execvpe(struct bbs_node *node, struct bbs_exec_params *e, const char *filename, char *const argv[], char *const envp[], const char *file, int lineno, const char *func) { pid_t pid; struct termios term; + int usenode = e->usenode; + int fdin = e->fdin, fdout = e->fdout; int fd = fdout; int res = -1; int pfd[2], procpipe[2]; @@ -755,8 +708,12 @@ static int __bbs_execvpe_fd(struct bbs_node *node, int usenode, int fdin, int fd #define MYENVP_SIZE 5 /* End with 3 NULLs so we can add up to 2 env vars if needed */ char *myenvp[MYENVP_SIZE] = { fullpath, fullterm, NULL, NULL, NULL }; /* Last NULL is always the sentinel */ + if (e->usenode) { + bbs_soft_assert(node != NULL); + } + #ifdef __FreeBSD__ - if (isolated) { + if (e->isolated) { /* The mount() API is not implemented in clone_container for FreeBSD. * Additionally, CLONE_NEW... is not available for FreeBSD. * As such, these preclude isoexec from being used on that platform. */ @@ -774,7 +731,7 @@ static int __bbs_execvpe_fd(struct bbs_node *node, int usenode, int fdin, int fd snprintf(fullpath, sizeof(fullpath), "PATH=%s", parentpath); } - bbs_debug(6, "node: %p, usenode: %d, fdin: %d, fdout: %d, filename: %s, isolated: %s\n", node, usenode, fdin, fdout, filename, isolated ? "yes" : "no"); + bbs_debug(6, "%s:%d (%s) node: %p, usenode: %d, fdin: %d, fdout: %d, filename: %s, isolated: %s\n", file, lineno, func, node, usenode, fdin, fdout, filename, e->isolated ? "yes" : "no"); if (node && usenode && (fdin != -1 || fdout != -1)) { bbs_warning("fdin/fdout should not be provided if usenode == 1 (node is preferred, fdin/fdout will be ignored)\n"); } @@ -821,11 +778,11 @@ static int __bbs_execvpe_fd(struct bbs_node *node, int usenode, int fdin, int fd #ifdef ISOEXEC_SUPPORTED /* If we have flags, we need to use clone(2). Otherwise, just use fork(2) */ - if (isolated) { + if (e->isolated) { int flags = 0; /* We need to do more than fork() allows */ flags |= SIGCHLD | CLONE_NEWIPC | CLONE_NEWNS | CLONE_NEWPID | CLONE_NEWUTS | CLONE_NEWNET | CLONE_NEWUSER; /* fork() sets SIGCHLD implicitly. */ - if (isolated == 2) { + if (e->net) { /* Keep network connectivity */ flags &= ~CLONE_NEWNET; } @@ -864,14 +821,14 @@ static int __bbs_execvpe_fd(struct bbs_node *node, int usenode, int fdin, int fd } if (pid == -1) { - bbs_error("%s failed (%s): %s\n", isolated ? "clone" : "fork", filename, strerror(errno)); - if (isolated) { + bbs_error("%s failed (%s): %s\n", e->isolated ? "clone" : "fork", filename, strerror(errno)); + if (e->isolated) { close(procpipe[0]); close(procpipe[1]); } return -1; } else if (pid == 0) { /* Child */ - if (!isolated) { + if (!e->isolated) { /* Immediately install a dummy signal handler for SIGWINCH. * Until we call exec, the child retains the parent's signal handlers. * However, if we have a node, we immediately call bbs_node_update_winsize @@ -904,7 +861,7 @@ static int __bbs_execvpe_fd(struct bbs_node *node, int usenode, int fdin, int fd fd = pfd[1]; /* Use write end of pipe */ fdout = fd; } - exec_pre(fdin, fdout, isolated ? procpipe[0] : -1); /* If we still need procpipe, don't close that */ + exec_pre(fdin, fdout, e->isolated ? procpipe[0] : -1); /* If we still need procpipe, don't close that */ if (node && usenode) { /* Set controlling terminal, or otherwise shells don't fully work properly. */ if (set_controlling_term(STDIN_FILENO)) { /* we dup2'd this to the slavefd. This is NOT the parent's STDIN. */ @@ -921,7 +878,7 @@ static int __bbs_execvpe_fd(struct bbs_node *node, int usenode, int fdin, int fd #ifndef pivot_root #define pivot_root(new, old) syscall(SYS_pivot_root, new, old) #endif - if (isolated) { + if (e->isolated) { struct utsname uts; char pidbuf[15]; char oldroot[384 + STRLEN("/.old")], newroot[384]; @@ -1109,7 +1066,7 @@ static int __bbs_execvpe_fd(struct bbs_node *node, int usenode, int fdin, int fd * But the parent will know that we failed since we return errno, and parent can log it. */ /* Also, use _exit, not exit, since exit will execute the parent's atexit function, etc. * That matters because exec failed, so atexit is still registered. */ - if (isolated) { + if (e->isolated) { int saved_errno = errno; fprintf(stderr, "%s: %s\n", filename, strerror(errno)); #ifdef DEBUG_NEW_FS @@ -1131,7 +1088,7 @@ static int __bbs_execvpe_fd(struct bbs_node *node, int usenode, int fdin, int fd } /* else, parent */ #ifdef ISOEXEC_SUPPORTED - if (isolated) { + if (e->isolated) { close(procpipe[0]); res = setup_namespace(pid); if (!res) { @@ -1205,7 +1162,7 @@ static int __bbs_execvpe_fd(struct bbs_node *node, int usenode, int fdin, int fd } #ifdef ISOEXEC_SUPPORTED - if (isolated) { + if (e->isolated) { char rootdir[268]; /* Clean up the temporary container, if one was created */ temp_container_root(rootdir, sizeof(rootdir), pid); diff --git a/bbs/transfer.c b/bbs/transfer.c index 94328f1..f39b3a8 100644 --- a/bbs/transfer.c +++ b/bbs/transfer.c @@ -199,6 +199,7 @@ int transfer_make_longname(const char *file, struct stat *st, char *buf, size_t static int recursive_copy(const char *srcfiles, const char *dest) { + struct bbs_exec_params x; /* It can probably do a better job than we can */ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdiscarded-qualifiers" @@ -207,7 +208,8 @@ static int recursive_copy(const char *srcfiles, const char *dest) * we don't want to overwrite all the user's existing files. */ char *const argv[] = { "cp", "-r", "-n", (char*) srcfiles, (char*) dest, NULL }; #pragma GCC diagnostic pop - return bbs_execvp(NULL, argv[0], argv); + EXEC_PARAMS_INIT_HEADLESS(x); + return bbs_execvp(NULL, &x, argv[0], argv); } int bbs_transfer_home_dir(unsigned int userid, char *buf, size_t len) diff --git a/doors/door_evergreen.c b/doors/door_evergreen.c index 85dbe2e..77208d8 100644 --- a/doors/door_evergreen.c +++ b/doors/door_evergreen.c @@ -30,6 +30,7 @@ static int evergreen_exec(struct bbs_node *node, const char *args) { + struct bbs_exec_params x; char username[64]; char fromname[64]; char fromaddr[64]; @@ -61,7 +62,8 @@ static int evergreen_exec(struct bbs_node *node, const char *args) return 0; } - bbs_execvp(node, "evergreen", argv); + EXEC_PARAMS_INIT(x); + bbs_execvp(node, &x, "evergreen", argv); bbs_user_semiperm_authorization_token_purge(passwordbuf); return 0; /* Don't return -1 or the node will abort */ } diff --git a/doors/door_ibbs.c b/doors/door_ibbs.c index d9f1481..8995cbb 100644 --- a/doors/door_ibbs.c +++ b/doors/door_ibbs.c @@ -53,6 +53,7 @@ static int ibbs_exec(struct bbs_node *node, const char *args) #pragma GCC diagnostic ignored "-Wdiscarded-qualifiers" if (access(listfile, R_OK)) { + struct bbs_exec_params x; char *const argv[] = { "unzip", tmpzip, "-d", "/tmp", NULL }; if (access(tmpzip, R_OK)) { char url[54]; @@ -72,7 +73,8 @@ static int ibbs_exec(struct bbs_node *node, const char *args) * Even though we have a handle to the node, pass NULL for node since we don't need to link STDIN/STDOUT to the unzip command. * We just need it to execute, and this is more efficient (and safer!) than using system() */ - if (bbs_execvp_headless(node, "unzip", argv)) { + EXEC_PARAMS_INIT_HEADLESS(x); + if (bbs_execvp(node, &x, "unzip", argv)) { return 0; /* Don't return -1 or the node will abort */ } } /* else, file already exists */ diff --git a/doors/door_utilities.c b/doors/door_utilities.c index ea8ee2e..d18f967 100644 --- a/doors/door_utilities.c +++ b/doors/door_utilities.c @@ -46,12 +46,6 @@ static int calc_exec(struct bbs_node *node, const char *args) return 0; } -#if 0 - /* Just use the bc shell */ - char *argv[3] = { "bc", "-q", NULL }; /* -q = quiet: disable initial banner */ - return bbs_execvp(node, "bc", argv); -#endif - /* Create a pipe for passing input and output to/from bc */ if (pipe(stdin)) { bbs_error("pipe failed: %s\n", strerror(errno)); @@ -67,6 +61,7 @@ static int calc_exec(struct bbs_node *node, const char *args) bbs_node_buffer(node); bbs_node_writef(node, "\r"); for (;;) { + struct bbs_exec_params x; #pragma GCC diagnostic ignored "-Wdiscarded-qualifiers" char *argv[3] = { "bc", "-q", NULL }; /* -q = quiet: disable initial banner */ bbs_node_writef(node, "EQ> "); @@ -100,7 +95,8 @@ static int calc_exec(struct bbs_node *node, const char *args) bbs_error("write failed: %s\n", strerror(errno)); continue; } - res = bbs_execvp_fd_headless(node, stdin[0], stdout[1], "bc", argv); + EXEC_PARAMS_INIT_FD(x, stdin[0], stdout[1]); + res = bbs_execvp(node, &x, "bc", argv); #pragma GCC diagnostic pop if (res) { bbs_node_writef(node, "Execution Error\n"); diff --git a/include/system.h b/include/system.h index a3423dc..29e116a 100644 --- a/include/system.h +++ b/include/system.h @@ -16,59 +16,69 @@ /* Forward declarations */ struct bbs_node; -/*! - * \brief Parse a string into an argv. Similar to wordexp, but without the unnecessary (and insecure?) shell expansion overhead - * This function will separate on spaces, but keep a quoted argument together as a single argument. - * \param[out] argv - * \param argc Size of argv - * \param s String to parse - * \retval Value of argc (new argc + 1) - */ -int bbs_argv_from_str(char **argv, int argc, char *s); +/* Execution settings */ +struct bbs_exec_params { + /* File descriptor priority is as follows, independently for STDIN/STDOUT: + * 1. If custom file descriptor provided (not -1), use that + * 2. If usenode is TRUE, use node file descriptor + * 3. Create pipes to discard STDIN/STDOUT, akin to /dev/null. */ + int fdin; /* Custom file descriptor for STDIN to created process, node->fdin or -1 otherwise */ + int fdout; /* Custom file descriptor for STDOUT from created process, node->fdout or -1 otherwise */ + int priority; /* CPU priority */ + unsigned int usenode:1; /* Whether to use the node for I/O. If FALSE, node will not be used for I/O */ + unsigned int isolated:1; /* Whether to create the process in an isolated container */ + /* Container parameters */ + unsigned int net:1; /* Retain network connectivity through the host, inside the container. Only applicable if isolated is TRUE. */ +}; -/*! - * \brief Wrapper around execvpe(). This will fork(), then call execvp(), then wait for the child to exit. - * \param node Node to use for I/O. If NULL, output will be written to a temporary pipe and logged, but otherwise discarded - * \param filename Filename of program to execute (path is optional) - * \param argv - * \retval 0 on success, -1 on failure - * \warning Do not call bbs_execvp from a node thread with NULL for node. Use bbs_execvp_headless. - */ -int bbs_execvp(struct bbs_node *node, const char *filename, char *const argv[]); +/* _HEADLESS suffix = Don't use node for I/O + * _FD suffix = Use custom file descriptors for I/O */ -/*! - * \brief Wrapper around execvpe() that creates a process in an isolated container. This will clone(), then call execvp(), then wait for the child to exit. - * \param node Node to use for I/O. If NULL, output will be written to a temporary pipe and logged, but otherwise discarded - * \param filename Filename of program to execute (path is optional) - * \param argv - * \retval 0 on success, -1 on failure - * \warning Do not call bbs_execvp from a node thread with NULL for node. Use bbs_execvp_headless. - */ -int bbs_execvp_isolated(struct bbs_node *node, const char *filename, char *const argv[]); +/* Normal init, use node for I/O */ +#define EXEC_PARAMS_INIT(x) \ + memset(&x, 0, sizeof(struct bbs_exec_params)); \ + x.usenode = 1; \ + x.fdin = -1; \ + x.fdout = -1; \ + +/* Running on a node, but use custom file descriptors for I/O */ +#define EXEC_PARAMS_INIT_FD(x, in, out) \ + EXEC_PARAMS_INIT(x); \ + x.usenode = 0; /* Setting to 0 is still important, since if fdin or fdout is -1, we don't want to default to using node->fdin or node->fdout */ \ + x.fdin = in; \ + x.fdout = out; -/*! \brief Same as bbs_execvp_isolated, but retains network connectivity through the host, inside the container */ -int bbs_execvp_isolated_networked(struct bbs_node *node, const char *filename, char *const argv[]); +/* No I/O whatsoever (effectively equivalent to > /dev/null < /dev/null) */ +#define EXEC_PARAMS_INIT_HEADLESS(x) \ + EXEC_PARAMS_INIT(x); \ + x.usenode = 0; -/*! \brief Same as bbs_execvp, but node will not be used for I/O. */ -int bbs_execvp_headless(struct bbs_node *node, const char *filename, char *const argv[]); +/*! \brief Same as bbs_execvpe, but with no custom envp */ +#define bbs_execvp(node, e, filename, argv) bbs_execvpe(node, e, filename, argv, NULL) /*! * \brief Wrapper around execvpe(). This will fork(), then call execvp(), then wait for the child to exit. - * \param node Node to use for I/O. If NULL and fdout == -1, output will be written to a temporary pipe and logged, but otherwise discarded - * \param fdin If node is NULL, file descriptor to use for STDIN. If -1, there will be no standard input available to the executed program. - * \param fdout If node is NULL, file descriptor to use for STDOUT/STDERR. If -1, output will be written to a temporary pipe and logged, but otherwise discarded. + * \param node Node to use for I/O. If NULL, output will be written to a temporary pipe and logged, but otherwise discarded + * \param e Execution parameters * \param filename Filename of program to execute (path is optional) * \param argv + * \param envp Custom environment (optional) * \retval 0 on success, -1 on failure - * \warning Do not call bbs_execvp_fd from a node thread with NULL for node. Use bbs_execvp_fd_headless. + * \warning Do not call bbs_execvp from a node thread with NULL for node. Provide the node but set e->usenode to 0. */ -int bbs_execvp_fd(struct bbs_node *node, int fdin, int fdout, const char *filename, char *const argv[]); +#define bbs_execvpe(node, e, filename, argv, envp) __bbs_execvpe(node, e, filename, argv, envp, __FILE__, __LINE__, __func__) -/*! \brief Same as bbs_execvp_fd, but node will not be used for I/O. */ -int bbs_execvp_fd_headless(struct bbs_node *node, int fdin, int fdout, const char *filename, char *const argv[]); +int __bbs_execvpe(struct bbs_node *node, struct bbs_exec_params *e, const char *filename, char *const argv[], char *const envp[], const char *file, int lineno, const char *func) __attribute__((nonnull (2, 3))); -/*! \brief Same as bbs_execvp_fd_headless, but allow passing an envp */ -int bbs_execvpe_fd_headless(struct bbs_node *node, int fdin, int fdout, const char *filename, char *const argv[], char *const envp[]); +/*! + * \brief Parse a string into an argv. Similar to wordexp, but without the unnecessary (and insecure?) shell expansion overhead + * This function will separate on spaces, but keep a quoted argument together as a single argument. + * \param[out] argv + * \param argc Size of argv + * \param s String to parse + * \retval Value of argc (new argc + 1) + */ +int bbs_argv_from_str(char **argv, int argc, char *s); /*! \brief Load system.conf config at startup */ int bbs_init_system(void); diff --git a/modules/mod_http.c b/modules/mod_http.c index 10940dd..6d1021d 100644 --- a/modules/mod_http.c +++ b/modules/mod_http.c @@ -2416,7 +2416,7 @@ static int cgi_run(struct http_session *http, const char *filename, char *const #pragma GCC diagnostic pop /* -Wdiscarded-qualifiers */ /* Because we need to run our own logic while the child is running, - * fork and wait on the child directly here, rather than using bbs_execvpe_fd_headless. + * fork and wait on the child directly here, rather than using BBS exec APIs. * It's just easier in this case. */ /* Create pipes for the CGI's STDIN and STDOUT */ diff --git a/modules/mod_ip_blocker.c b/modules/mod_ip_blocker.c index 3b2cb37..09c4af9 100755 --- a/modules/mod_ip_blocker.c +++ b/modules/mod_ip_blocker.c @@ -65,19 +65,21 @@ static RWLIST_HEAD_STATIC(ipblocks, ip_block); #pragma GCC diagnostic ignored "-Wdiscarded-qualifiers" static void ban_ip(const char *addr) { + struct bbs_exec_params x; int res; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" char *ipaddr = (char*) addr; + EXEC_PARAMS_INIT_FD(x, -1, -1); if (is_root()) { char *argv[] = { "/usr/sbin/iptables", "-A", "INPUT", "-s", ipaddr, "-j", "DROP", NULL }; - res = bbs_execvp_fd(NULL, -1, -1, "/usr/sbin/iptables", argv); + res = bbs_execvp(NULL, &x, "/usr/sbin/iptables", argv); } else { /* There's no guarantee that the BBS user is in the sudoers file for this command, or even that sudo is installed, * but this is the only way it could even work, so give it a try. */ char *argv[] = { "/usr/bin/sudo", "-n", "/usr/sbin/iptables", "-A", "INPUT", "-s", ipaddr, "-j", "DROP", NULL }; - res = bbs_execvp_fd(NULL, -1, -1, "/usr/bin/sudo", argv); + res = bbs_execvp(NULL, &x, "/usr/bin/sudo", argv); } if (res) { bbs_warning("Failed to block %s using iptables: %s\n", ipaddr, strerror(res)); diff --git a/modules/mod_irc_client.c b/modules/mod_irc_client.c index 7967e9d..143890c 100644 --- a/modules/mod_irc_client.c +++ b/modules/mod_irc_client.c @@ -446,6 +446,7 @@ static void __bot_handler(struct bbs_irc_client *client, enum relay_flags flags, #pragma GCC diagnostic pop int res; int stdout[2]; + struct bbs_exec_params x; if (strlen_zero(client->msgscript)) { return; @@ -469,7 +470,8 @@ static void __bot_handler(struct bbs_irc_client *client, enum relay_flags flags, */ bbs_readline_init(&rldata, buf, sizeof(buf)); - res = bbs_execvp_fd(NULL, -1, stdout[1], client->msgscript, argv); /* No STDIN, only STDOUT */ + EXEC_PARAMS_INIT_FD(x, -1, stdout[1]); + res = bbs_execvp(NULL, &x, client->msgscript, argv); /* No STDIN, only STDOUT */ bbs_debug(5, "Script '%s' returned %d\n", client->msgscript, res); if (res) { goto cleanup; /* Ignore non-zero return values */ diff --git a/modules/mod_mailscript.c b/modules/mod_mailscript.c index 8ca2fd6..92e74c8 100644 --- a/modules/mod_mailscript.c +++ b/modules/mod_mailscript.c @@ -298,6 +298,7 @@ static int do_action(struct smtp_msg_process *mproc, int lineno, char *s) char subbuf[1024]; char *argv[32]; int argc; + struct bbs_exec_params x; REQUIRE_ARG(s); if (strstr(s, "${MAILFILE}")) { /* This rule wants the message as a file */ bbs_node_var_set(mproc->node, "MAILFILE", mproc->datafile); @@ -309,7 +310,8 @@ static int do_action(struct smtp_msg_process *mproc, int lineno, char *s) bbs_warning("Invalid EXEC action\n"); return -1; /* Rules may rely on a return code of 0 for success, so don't return 0 if we didn't do anything */ } - res = bbs_execvp_headless(mproc->node, argv[0], argv); /* Directly return the exit code */ + EXEC_PARAMS_INIT_HEADLESS(x); + res = bbs_execvp(mproc->node, &x, argv[0], argv); /* Directly return the exit code */ return res; } else if (!strcasecmp(next, "FORWARD")) { REQUIRE_ARG(s); diff --git a/modules/mod_menu_handlers.c b/modules/mod_menu_handlers.c index a4c1fee..a37dd46 100644 --- a/modules/mod_menu_handlers.c +++ b/modules/mod_menu_handlers.c @@ -85,9 +85,11 @@ static int __exec_handler(struct bbs_node *node, char *args, int isolated) { int res; time_t execstart, execend; + struct bbs_exec_params x; char *argv[32]; /* 32 arguments ought to be enough for anybody. */ bbs_assert_exists(args); /* We registered with needargs, so args should never be NULL */ + EXEC_PARAMS_INIT(x); /* Parse a string (delimiting on spaces) into arguments for argv */ res = bbs_argv_from_str(argv, ARRAY_LEN(argv), args); @@ -101,17 +103,16 @@ static int __exec_handler(struct bbs_node *node, char *args, int isolated) /* Prog name is simply argv[0]. */ switch (isolated) { case 2: - res = bbs_execvp_isolated_networked(node, argv[0], argv); - break; + x.net = 1; + /* Fall through */ case 1: - res = bbs_execvp_isolated(node, argv[0], argv); - break; - default: - bbs_warning("Invalid value %d\n", isolated); + x.isolated = 1; /* Fall through */ case 0: - res = bbs_execvp(node, argv[0], argv); + res = bbs_execvp(node, &x, argv[0], argv); break; + default: + bbs_warning("Invalid value %d\n", isolated); } execend = time(NULL); bbs_debug(6, "res: %d, exec time: %lu\n", res, execend - execstart); diff --git a/modules/mod_sendmail.c b/modules/mod_sendmail.c index cd01fc0..7d563db 100644 --- a/modules/mod_sendmail.c +++ b/modules/mod_sendmail.c @@ -42,6 +42,7 @@ static int sendmail_helper(const char *tmp, FILE *p, int async) { + struct bbs_exec_params x; int res; /* XXX We could be calling this function from a node thread. @@ -60,13 +61,15 @@ static int sendmail_helper(const char *tmp, FILE *p, int async) /* Run it in the background using a shell */ fclose(p); snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", SENDMAIL_CMD, tmp, tmp); - res = bbs_execvp(NULL, "/bin/sh", argv); + EXEC_PARAMS_INIT_HEADLESS(x); + res = bbs_execvp(NULL, &x, "/bin/sh", argv); } else { /* Call sendmail synchronously. */ char *argv[3] = { SENDMAIL, SENDMAIL_ARG, NULL }; /* Have sendmail read STDIN from the file itself */ rewind(p); - res = bbs_execvp_fd(NULL, fileno(p), -1, SENDMAIL, argv); + EXEC_PARAMS_INIT_FD(x, fileno(p), -1); + res = bbs_execvp(NULL, &x, SENDMAIL, argv); fclose(p); if (remove(tmp)) { bbs_error("Failed to delete temporary email file '%s'\n", tmp); diff --git a/modules/mod_spamassassin.c b/modules/mod_spamassassin.c index 641f3ac..96eb316 100644 --- a/modules/mod_spamassassin.c +++ b/modules/mod_spamassassin.c @@ -39,6 +39,7 @@ static int spam_filter_cb(struct smtp_filter_data *f) int input[2], output[2]; char buf[1024]; struct readline_data rldata; + struct bbs_exec_params x; /* The only thing that this module really does is * execute the SpamAssassin binary, passing it the email message on STDIN, @@ -80,7 +81,8 @@ static int spam_filter_cb(struct smtp_filter_data *f) } CLOSE(input[1]); /* Close write end of STDIN */ - res = bbs_execvp_fd_headless(f->node, input[0], output[1], argv[0], argv); + EXEC_PARAMS_INIT_FD(x, input[0], output[1]); + res = bbs_execvp(f->node, &x, argv[0], argv); if (res) { res = -1; goto cleanup;