# This patchset implements the suggestion found in xsystem.c in the # original opkg sources -- use vfork and exec instead of system(). # # This, like the preceding patch in this patchset is vital to dodging # the OOM killer on small-memory machines. # # Mike Westerhof, Dec 2008 --- orig/libopkg/opkg.c 2008-12-20 15:07:04.000000000 -0600 +++ opkg/libopkg/opkg.c 2008-12-21 21:41:07.000000000 -0600 @@ -31,6 +31,7 @@ #include "sprintf_alloc.h" #include "file_util.h" +#include "xsystem.h" #include --- orig/libopkg/xsystem.h 2008-03-01 12:55:29.000000000 -0600 +++ opkg/libopkg/xsystem.h 2008-12-21 21:41:07.000000000 -0600 @@ -29,6 +29,7 @@ as defined in . */ int xsystem(const char *cmd); +int xvsystem(const char *cmd, char *const argv[]); #endif --- orig/libopkg/xsystem.c 2008-04-17 11:00:51.000000000 -0500 +++ opkg/libopkg/xsystem.c 2008-12-21 21:41:07.000000000 -0600 @@ -62,3 +62,58 @@ return -1; } +int xvsystem(const char *cmd, char *const argv[]) +{ + int err; + pid_t pid; + +#ifdef DO_DEBUG + int i = 0; + char *p; + printf("DEBUG: xvsystem: execute "); + while (p = argv[i++]) { + printf("\"%s\" ", p); + } + printf("\n"); +#endif + + pid = vfork(); + + if (pid == 0) { /* Child */ + execvp(cmd, argv); + _exit(1); + + } else if (pid == -1) { /* Error on fork() */ + perror("vfork()"); + fprintf(stderr, "%s: ERROR: fork failed before execution: `%s'\n", + __FUNCTION__, cmd); + return -1; + + } else { /* Parent */ + if (waitpid(pid, &err, 0) != pid) { /* wait for child */ + perror("waitpid()"); + fprintf(stderr, "%s: ERROR: failed to execute: `%s'\n", + __FUNCTION__, cmd); + return -1; + } + } + +#ifdef DO_DEBUG + printf("DEBUG: xvsystem: child exit status %d\n", err); +#endif + + if (WIFSIGNALED(err)) { + fprintf(stderr, "%s: ERROR: Child process died due to signal %d: `%s'\n", + __FUNCTION__, WTERMSIG(err), cmd); + return -1; + } + + if (WIFEXITED(err)) { + /* Normal child exit */ + return WEXITSTATUS(err); + } + + fprintf(stderr, "%s: ERROR: Received unintelligible return value from system: %d", + __FUNCTION__, err); + return -1; +} --- orig/libopkg/opkg_conf.c 2008-12-20 15:06:50.000000000 -0600 +++ opkg/libopkg/opkg_conf.c 2008-12-21 21:41:07.000000000 -0600 @@ -316,10 +320,8 @@ err = rmdir(conf->tmp_dir); if (err) { if (errno == ENOTEMPTY) { - char *cmd; - sprintf_alloc(&cmd, "rm -fr %s\n", conf->tmp_dir); - err = xsystem(cmd); - free(cmd); + char *argv[] = {"rm", "-fr", conf->tmp_dir, NULL}; + err = xvsystem(argv[0], argv); } if (err) fprintf(stderr, "WARNING: Unable to remove temporary directory: %s: %s\n", conf->tmp_dir, strerror(errno)); --- orig/libopkg/opkg_install.c 2008-12-20 15:06:51.000000000 -0600 +++ opkg/libopkg/opkg_install.c 2008-12-21 21:41:07.000000000 -0600 @@ -1617,13 +1617,9 @@ } if (strcmp(response, "d") == 0) { - char *cmd; - + char *argv[] = {"diff", "-u", backup, file_name, NULL}; free(response); - /* XXX: BUG rewrite to use exec or busybox's internal diff */ - sprintf_alloc(&cmd, "diff -u %s %s", backup, file_name); - xsystem(cmd); - free(cmd); + xvsystem(argv[0], argv); printf(" [Press ENTER to continue]\n"); response = file_read_line_alloc(stdin); free(response); --- orig/libopkg/pkg.c 2008-12-20 15:06:50.000000000 -0600 +++ opkg/libopkg/pkg.c 2008-12-21 23:31:39.000000000 -0600 @@ -1534,7 +1564,12 @@ sprintf_alloc(&cmd, "%s %s", path, args); free(path); - err = xsystem(cmd); +// err = xsystem(cmd); + { + char *argv[] = {"sh", "-c", cmd, NULL}; + err = xvsystem(argv[0], argv); + } + free(cmd); if (err) { --- orig/libopkg/opkg_cmd.c 2008-12-20 15:07:04.000000000 -0600 +++ opkg/libopkg/opkg_cmd.c 2008-12-21 21:41:07.000000000 -0600 @@ -33,6 +33,7 @@ #include "libbb/libbb.h" #include "opkg_utils.h" #include "opkg_defines.h" +#include "xsystem.h" #include @@ -371,7 +373,7 @@ sprintf_alloc (&path, "%s/%s", ctx->statedir, de->d_name); if (access (path, X_OK) == 0) { - if (system (path)) { + if (system (path)) { /* FIXME FIXME */ err = errno; perror (de->d_name); } --- orig/libopkg/opkg_download.c 2008-12-20 15:07:04.000000000 -0600 +++ opkg/libopkg/opkg_download.c 2008-12-21 21:44:30.000000000 -0600 @@ -129,16 +129,21 @@ #else { int res; - char *wgetcmd; - char *wgetopts; - wgetopts = getenv("OPKG_WGETOPTS"); - sprintf_alloc(&wgetcmd, "wget -q %s%s -O \"%s\" \"%s\"", - (conf->http_proxy || conf->ftp_proxy) ? "-Y on " : "", - (wgetopts!=NULL) ? wgetopts : "", - tmp_file_location, src); - opkg_message(conf, OPKG_INFO, "Executing: %s\n", wgetcmd); - res = xsystem(wgetcmd); - free(wgetcmd); + char *argv[16]; + int i = 0; + + argv[i++] = "wget"; + argv[i++] = "-q"; + if (conf->http_proxy || conf->ftp_proxy) { + argv[i++] = "-Y"; + argv[i++] = "on"; + } + argv[i++] = "-O"; + argv[i++] = tmp_file_location; + argv[i++] = src; + argv[i++] = NULL; + res = xvsystem(argv[0], argv); + if (res) { opkg_message(conf, OPKG_ERROR, "Failed to download %s, error %d\n", src, res); free(tmp_file_location);