aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2014-09-14 12:29:44 -0500
committerRob Landley <rob@landley.net>2014-09-14 12:29:44 -0500
commit360d57f843f5435a75270e54583430dcb8f62546 (patch)
tree2e043033414a0cb03b6eb86b3b662f7ca9571788
parente1366f02fea3cb035cc4ed0b59d12f1962b6ebfd (diff)
downloadtoybox-360d57f843f5435a75270e54583430dcb8f62546.tar.gz
Split xpopen() into xpopen_both(), xpopen(), and xrun() depending on whether we want to redirect both, one, or neither of stdin/stdout.
-rw-r--r--lib/lib.h8
-rw-r--r--lib/xwrap.c78
-rw-r--r--toys/lsb/mount.c19
-rw-r--r--toys/other/inotifyd.c2
-rw-r--r--toys/posix/cp.c3
-rw-r--r--toys/posix/find.c2
6 files changed, 78 insertions, 34 deletions
diff --git a/lib/lib.h b/lib/lib.h
index b93e19bc..887c1d57 100644
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -95,8 +95,12 @@ void xflush(void);
pid_t xfork(void);
void xexec_optargs(int skip);
void xexec(char **argv);
-pid_t xpopen(char **argv, int *pipes);
-int xpclose(pid_t pid, int *pipes);
+pid_t xpopen_both(char **argv, int *pipes);
+int xpclose_both(pid_t pid, int *pipes);
+pid_t xpopen(char **argv, int *pipe, int stdout);
+pid_t xpclose(pid_t pid, int pipe);
+int xrun(char **argv);
+int xpspawn(char **argv, int*pipes);
void xaccess(char *path, int flags);
void xunlink(char *path);
int xcreate(char *path, int flags, int mode);
diff --git a/lib/xwrap.c b/lib/xwrap.c
index c9d1876f..64b183ff 100644
--- a/lib/xwrap.c
+++ b/lib/xwrap.c
@@ -145,33 +145,41 @@ void xexec(char **argv)
// Spawn child process, capturing stdin/stdout.
// argv[]: command to exec. If null, child returns to original program.
-// pipes[]: stdin, stdout of new process. If null, block and wait for child.
+// pipes[2]: stdin, stdout of new process. If -1 will not have pipe allocated.
// return: pid of child process
-pid_t xpopen(char **argv, int *pipes)
+pid_t xpopen_both(char **argv, int *pipes)
{
int cestnepasun[4], pid;
- // Make the pipes?
+ // Make the pipes? Not this won't set either pipe to 0 because if fds are
+ // allocated in order and if fd0 was free it would go to cestnepasun[0]
if (pipes) {
- if (pipe(cestnepasun) || pipe(cestnepasun+2)) perror_exit("pipe");
- pipes[0] = cestnepasun[1];
- pipes[1] = cestnepasun[2];
+ for (pid = 0; pid < 2; pid++) {
+ if (pipes[pid] == -1) continue;
+ if (pipe(cestnepasun+(2*pid))) perror_exit("pipe");
+ pipes[pid] = cestnepasun[pid+1];
+ }
}
// Child process
if (!(pid = xfork())) {
// Dance of the stdin/stdout redirection.
if (pipes) {
- close(cestnepasun[1]);
- close(cestnepasun[2]);
- // if we had no stdin/out, pipe handles could overlap, so test for that
- if (cestnepasun[0]) {
- dup2(cestnepasun[0], 0);
- close(cestnepasun[0]);
+ // if we had no stdin/out, pipe handles could overlap, so test for it
+ // and free up potentially overlapping pipe handles before reuse
+ if (pipes[1] != -1) close(cestnepasun[2]);
+ if (pipes[0] != -1) {
+ close(cestnepasun[1]);
+ if (cestnepasun[0]) {
+ dup2(cestnepasun[0], 0);
+ close(cestnepasun[0]);
+ }
+ }
+ if (pipes[1] != -1) {
+ dup2(cestnepasun[3], 1);
+ dup2(cestnepasun[3], 2);
+ if (cestnepasun[3] > 2 || !cestnepasun[3]) close(cestnepasun[3]);
}
- dup2(cestnepasun[3], 1);
- dup2(cestnepasun[3], 2);
- if (cestnepasun[3] > 2) close(cestnepasun[3]);
}
if (argv) {
if (CFG_TOYBOX) toy_exec(argv);
@@ -180,18 +188,18 @@ pid_t xpopen(char **argv, int *pipes)
}
return 0;
- // Parent process
- } else {
- if (pipes) {
- close(cestnepasun[0]);
- close(cestnepasun[3]);
- }
+ }
- return pid;
+ // Parent process
+ if (pipes) {
+ if (pipes[0] != -1) close(cestnepasun[0]);
+ if (pipes[1] != -1) close(cestnepasun[3]);
}
+
+ return pid;
}
-int xpclose(pid_t pid, int *pipes)
+int xpclose_both(pid_t pid, int *pipes)
{
int rc = 127;
@@ -204,6 +212,30 @@ int xpclose(pid_t pid, int *pipes)
return WIFEXITED(rc) ? WEXITSTATUS(rc) : WTERMSIG(rc) + 127;
}
+// Wrapper to xpopen with a pipe for just one of stdin/stdout
+pid_t xpopen(char **argv, int *pipe, int stdout)
+{
+ int pipes[2];
+
+ pipe[!stdout] = -1;
+ pipe[!!stdout] = 0;
+
+ return xpopen_both(argv, pipes);
+}
+
+int xpclose(pid_t pid, int pipe)
+{
+ close(pipe);
+
+ return xpclose_both(pid, 0);
+}
+
+// Call xpopen and wait for it to finish, keeping existing stdin/stdout.
+int xrun(char **argv)
+{
+ return xpclose_both(xpopen_both(argv, 0), 0);
+}
+
void xaccess(char *path, int flags)
{
if (access(path, flags)) perror_exit("Can't access '%s'", path);
diff --git a/toys/lsb/mount.c b/toys/lsb/mount.c
index 949fb05d..39d98caf 100644
--- a/toys/lsb/mount.c
+++ b/toys/lsb/mount.c
@@ -7,6 +7,7 @@
* no mtab (/proc/mounts does it) so -n is NOP.
USE_MOUNT(NEWTOY(mount, "?O:afnrvwt:o*[-rw]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
+USE_NFSMOUNT(NEWTOY(nfsmount, "?<2>2", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
config MOUNT
bool "mount"
@@ -32,6 +33,14 @@ config MOUNT
bind mounts (file on file, directory on directory), so you don't need
to say --bind or --loop. You can also "mount -a /path" to mount everything
in /etc/fstab under /path, even if it's noauto.
+
+config NFSMOUNT
+ bool "nfsmount"
+ default n
+ help
+ usage: nfsmount SHARE DIR
+
+ Invoke an eldrich horror from the dawn of time.
*/
#define FOR_mount
@@ -155,7 +164,7 @@ static void mount_filesystem(char *dev, char *dir, char *type,
} else fp = xfopen("/proc/filesystems", "r");
} else if (!strcmp(type, "ignore")) return;
else if (!strcmp(type, "swap"))
- toys.exitval |= xpclose(xpopen((char *[]){"swapon", "--", dev, 0}, 0), 0);
+ toys.exitval |= xrun((char *[]){"swapon", "--", dev, 0});
for (;;) {
char *buf = 0;
@@ -204,13 +213,13 @@ static void mount_filesystem(char *dev, char *dir, char *type,
if (errno == ENOTBLK) {
char *losetup[] = {"losetup", "-fs", dev, 0};
- int pipes[2], len;
+ int pipe, len;
pid_t pid;
if (flags & MS_RDONLY) losetup[1] = "-fsr";
- pid = xpopen(losetup, pipes);
- len = readall(pipes[1], toybuf, sizeof(toybuf)-1);
- rc = xpclose(pid, pipes);
+ pid = xpopen(losetup, &pipe, 1);
+ len = readall(pipe, toybuf, sizeof(toybuf)-1);
+ rc = xpclose(pid, pipe);
if (!rc && len > 1) {
if (toybuf[len-1] == '\n') --len;
toybuf[len] = 0;
diff --git a/toys/other/inotifyd.c b/toys/other/inotifyd.c
index 59c9a50c..f2e11ca4 100644
--- a/toys/other/inotifyd.c
+++ b/toys/other/inotifyd.c
@@ -104,7 +104,7 @@ void inotifyd_main(void)
prog_args[1] = toybuf;
prog_args[2] = toys.optargs[event->wd];
prog_args[3] = event->len ? event->name : 0;
- xpclose(xpopen(prog_args, 0), 0);
+ xrun(prog_args);
}
if (event->mask & IN_IGNORED) {
diff --git a/toys/posix/cp.c b/toys/posix/cp.c
index d79819b2..d73b7229 100644
--- a/toys/posix/cp.c
+++ b/toys/posix/cp.c
@@ -341,8 +341,7 @@ static int install_node(struct dirtree *try)
// No -r so always one level deep, so destname as set by cp_node() is correct
if (toys.optflags & FLAG_s)
- if (xpclose(xpopen((char *[]){"strip", "-p", TT.destname, 0}, 0), 0))
- toys.exitval = 1;
+ if (xrun((char *[]){"strip", "-p", TT.destname, 0})) toys.exitval = 1;
return 0;
}
diff --git a/toys/posix/find.c b/toys/posix/find.c
index b74cb88e..9f679a02 100644
--- a/toys/posix/find.c
+++ b/toys/posix/find.c
@@ -102,7 +102,7 @@ static int flush_exec(struct dirtree *new, struct exec_range *aa)
newargs[pos+rest] = 0;
}
- rc = xpclose(xpopen(newargs, 0), 0);
+ rc = xrun(newargs);
llist_traverse(*dl, llist_free_double);
*dl = 0;