/* mnexec: execution utility for mininet * * Starts up programs and does things that are slow or * difficult in Python, including: * * - closing all file descriptors except stdin/out/error * - detaching from a controlling tty using setsid * - running in a network namespace * - printing out the pid of a process so we can identify it later * * Partially based on public domain setsid(1) */ #include <stdio.h> #include <linux/sched.h> #include <unistd.h> void usage(char *name) { printf("Execution utility for Mininet.\n" "usage: %s [-cdnp]\n" "-c: close all file descriptors except stdin/out/error\n" "-d: detach from tty by calling setsid()\n" "-n: run in new network namespace\n" "-p: print ^A + pid\n", name); } int main(int argc, char *argv[]) { char c; int fd; while ((c = getopt(argc, argv, "+cdnp")) != -1) switch(c) { case 'c': /* close file descriptors except stdin/out/error */ for (fd = getdtablesize(); fd > 2; fd--) close(fd); break; case 'd': /* detach from tty */ if (getpgrp() == getpid()) { switch(fork()) { case -1: perror("fork"); return 1; case 0: /* child */ break; default: /* parent */ return 0; } } setsid(); break; case 'n': /* run in network namespace */ if (unshare(CLONE_NEWNET) == -1) { perror("unshare"); return 1; } break; case 'p': /* print pid */ printf("\001%d\n", getpid()); fflush(stdout); break; default: usage(argv[0]); break; } if (optind < argc) { execvp(argv[optind], &argv[optind]); perror(argv[optind]); return 1; } usage(argv[0]); }