/***********************/ /* run.c 1.00 */ /* by Adam M. Costello */ /* */ /* **************************/ /* Completely detaches itself from its caller */ /* by forking, letting the parent terminate, */ /* changing the child's process group ID to its */ /* PID, and closing all descriptors except 0, */ /* 1, and 2, which are closed and reopened to */ /* /dev/null. Calls execvp() using the first */ /* argument as the filename and the remaining */ /* arguments as the arguments. */ /* */ /* If the name by which run is called ends with */ /* a `d', run will print the PID of the child */ /* process, in decimal, on stdout. */ /* */ /* The exit status is 0 if the fork succeeds */ /* and 1 if it doesn't. The fork won't even be */ /* attempted if there are no arguments. */ /************************************************/ #include #include #include #include #include #ifdef NO_SETSID #include #include #endif main(argc,argv) int argc; char *argv[]; { int pid, n, d; struct rlimit rl; if (argc <= 1) exit(1); pid = fork(); if (pid < 0) exit(1); if (pid) { if ((*argv)[strlen(*argv) - 1] == 'd') printf("%d\n", pid); exit(0); } #ifndef NO_SETSID setsid(); #else setpgrp(0,0); d = open("/dev/tty"); if (d >= 0) ioctl(d, TIOCNOTTY, NULL); #endif #ifndef NO_RLIMIT_NOFILE if (getrlimit(RLIMIT_NOFILE, &rl)) exit(1); n = rl.rlim_max; #else n = getdtablesize(); #endif for (d = 3; d < n; ++d) close(d); d = open("/dev/null", O_RDWR); dup2(d,0); dup2(d,1); dup2(d,2); if (d > 2) close(d); execvp(argv[1], argv + 1); }