]> git.ipfire.org Git - thirdparty/iproute2.git/commitdiff
ipbatch: fix use of 'ip netns exec'
authorJunweiZhang <junwei.zhang@6wind.com>
Tue, 9 Jul 2013 15:55:20 +0000 (08:55 -0700)
committerStephen Hemminger <stephen@networkplumber.org>
Tue, 9 Jul 2013 16:14:10 +0000 (09:14 -0700)
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>
ip/ipnetns.c

index fa2b6810b0ba8b71c5b7a7a49e4c13804a352c29..d534fb694daab8e5ea6df4f09330a1b42fd6880b 100644 (file)
@@ -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)