summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJunweiZhang <junwei.zhang@6wind.com>2013-07-09 08:55:20 -0700
committerStephen Hemminger <stephen@networkplumber.org>2013-07-09 09:14:10 -0700
commit95592b47be09bd9347026ff9aa298fc097733e56 (patch)
tree451493b57766e7c96d1d35142355f11b418ea4bb
parent86c00faae20d0ec60c61a24eed905a0283cf2ac2 (diff)
ipbatch: fix use of 'ip netns exec'
execvp() does not return when the command succeed, hence all commands in the batch file after the line 'ip netns exec' are not executed. Let's fork before calling execvp() if batch mode is used.. Example: $ cat test.batch netns add netns1 netns exec netns1 ip l netns $ ip -b test.batch 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: sit0: <NOARP> mtu 1480 qdisc noop state DOWN mode DEFAULT link/sit 0.0.0.0 brd 0.0.0.0 All command after 'netns exec' are never executed. With the patch: $ ip -b test.batch 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: sit0: <NOARP> mtu 1480 qdisc noop state DOWN mode DEFAULT link/sit 0.0.0.0 brd 0.0.0.0 netns1 Now, existing netns are displayed. Signed-off-by: JunweiZhang <junwei.zhang@6wind.com> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
-rw-r--r--ip/ipnetns.c34
1 files changed, 33 insertions, 1 deletions
diff --git a/ip/ipnetns.c b/ip/ipnetns.c
index fa2b6810..d534fb69 100644
--- a/ip/ipnetns.c
+++ b/ip/ipnetns.c
@@ -42,6 +42,7 @@
#define MS_SHARED (1 << 20)
#endif
+extern char *batch_file;
#ifndef HAVE_SETNS
static int setns(int fd, int nstype)
@@ -185,10 +186,41 @@ static int netns_exec(int argc, char **argv)
/* Setup bind mounts for config files in /etc */
bind_etc(name);
+ fflush(stdout);
+
+ if (batch_file) {
+ int status;
+ pid_t pid;
+
+ pid = fork();
+ if (pid < 0) {
+ perror("fork");
+ return EXIT_FAILURE;
+ }
+
+ if (pid != 0) {
+ /* Parent */
+ if (waitpid(pid, &status, 0) < 0) {
+ perror("waitpid");
+ return EXIT_FAILURE;
+ }
+
+ if (WIFEXITED(status)) {
+ /* ip must returns the status of the child,
+ * but do_cmd() will add a minus to this,
+ * so let's add another one here to cancel it.
+ */
+ return -WEXITSTATUS(status);
+ }
+
+ return EXIT_FAILURE;
+ }
+ }
+
if (execvp(cmd, argv + 1) < 0)
fprintf(stderr, "exec of \"%s\" failed: %s\n",
cmd, strerror(errno));
- return EXIT_FAILURE;
+ _exit(EXIT_FAILURE);
}
static int is_pid(const char *str)