Statistics
| Branch: | Tag: | Revision:

mininet / mnexec.c @ 51a14824

History | View | Annotate | Download (2.05 KB)

1
/* mnexec: execution utility for mininet
2
 *
3
 * Starts up programs and does things that are slow or
4
 * difficult in Python, including:
5
 *
6
 *  - closing all file descriptors except stdin/out/error
7
 *  - detaching from a controlling tty using setsid
8
 *  - running in a network namespace
9
 *  - printing out the pid of a process so we can identify it later
10
 *
11
 * Partially based on public domain setsid(1)
12
*/
13

    
14
#include <stdio.h>
15
#include <linux/sched.h>
16
#include <unistd.h>
17

    
18
void usage(char *name) 
19
{
20
    printf("Execution utility for Mininet.\n"
21
           "usage: %s [-cdnp]\n"
22
           "-c: close all file descriptors except stdin/out/error\n"
23
           "-d: detach from tty by calling setsid()\n"
24
           "-n: run in new network namespace\n"
25
           "-p: print ^A + pid\n", name);
26
}
27

    
28
int main(int argc, char *argv[])
29
{
30
    char c;
31
    int fd;
32
    
33
    while ((c = getopt(argc, argv, "+cdnp")) != -1)
34
        switch(c) {
35
        case 'c':
36
            /* close file descriptors except stdin/out/error */
37
            for (fd = getdtablesize(); fd > 2; fd--)
38
                close(fd);
39
            break;
40
        case 'd':
41
            /* detach from tty */
42
            if (getpgrp() == getpid()) {
43
                switch(fork()) {
44
                    case -1:
45
                        perror("fork");
46
                        return 1;
47
                    case 0:                /* child */
48
                        break;
49
                    default:        /* parent */
50
                        return 0;
51
                }
52
            }
53
            setsid();
54
            break;
55
        case 'n':
56
            /* run in network namespace */
57
            if (unshare(CLONE_NEWNET) == -1) {
58
                perror("unshare");
59
                return 1;
60
            }
61
            break;
62
        case 'p':
63
            /* print pid */
64
            printf("\001%d\n", getpid());
65
            fflush(stdout);
66
            break;
67
        default:
68
            usage(argv[0]);
69
            break;
70
        }
71

    
72
    if (optind < argc) {
73
                execvp(argv[optind], &argv[optind]);
74
                perror(argv[optind]);
75
                return 1;
76
        }
77
    
78
    usage(argv[0]);
79
}