int main(int argc, char **argv) { char *Argv0 = *argv; int rc; int lfd; pid_t childpid; time_t starttime; int attempts = 0; UNUSED_PARAMETER(argc); time(&starttime); for ( argv++ ; *argv ; argv++ ) { char *arg = *argv; char *opt = strchr(arg, '='); /* the -- token marks the end of the list */ if ( strcmp(*argv, "--") == 0 ) { argv++; break; } if (opt) *opt++ = '\0'; /* pick off the =VALUE part */ if ( STRMATCH(arg, "--version") ) { puts(Version); exit(EXIT_SUCCESS); } else if ( STRMATCH(arg, "--help")) { show_help(helptext); exit(EXIT_SUCCESS); } else if ( STRMATCH(arg, "-L") || STRMATCH(arg, "--lockfile")) { lockfile = getarg(opt, &argv); } else if ( STRMATCH(arg, "-W") || STRMATCH(arg, "--wait")) { wait_for_lock = TRUE; } else if ( STRMATCH(arg, "-S") || STRMATCH(arg, "--sleep")) { sleeptime = atoi(getarg(opt, &argv)); } else if ( STRMATCH(arg, "-R") || STRMATCH(arg, "--retries")) { retries = atoi(getarg(opt, &argv)); } else if ( STRMATCH(arg, "-T") || STRMATCH(arg, "--maxtime")) { Maxtime = atoi(getarg(opt, &argv)); } else if ( STRMATCH(arg, "-V") || STRMATCH(arg, "--verbose")) { Verbose++; } else if ( STRMATCH(arg, "-Q") || STRMATCH(arg, "-q") || STRMATCH(arg, "--quiet") || STRMATCH(arg, "-I") || STRMATCH(arg, "--idempotent")) { Quiet = TRUE; } else { die("ERROR: \"%s\" is an invalid cmdline param", arg); } } /*---------------------------------------------------------------- * SANITY CHECKING * * Make sure that we have all the parameters we require */ if (*argv == 0) die("ERROR: missing command to %s (must follow \"--\" marker) ", Argv0); if (lockfile == 0) die("ERROR: missing --lockfile=F parameter"); /*---------------------------------------------------------------- * Open or create the lockfile, then try to acquire the lock. If * the lock is acquired immediately (==0), then we're done, but * if the lock is not available, we have to wait for it. * * We can either loop trying for the lock (for --wait), or exit * with error. */ if ( (lfd = open(lockfile, O_RDWR|O_CREAT, openmode)) < 0) die("ERROR: cannot open(%s) [err=%s]", lockfile, strerror(errno)); while ( WAIT_AND_LOCK(lfd) != 0 ) { attempts++; if ( ! wait_for_lock ) { if ( Quiet) exit(EXIT_SUCCESS); else die("ERROR: cannot launch %s - run is locked", argv[0]); } if ( retries > 0 && attempts >= retries ) { die("ERROR: cannot launch %s - run is locked (after %d attempts)", argv[0], attempts); } /* waiting */ if ( Verbose ) printf("(locked: sleeping %d secs, after attempt #%d)\n", sleeptime, attempts); sleep(sleeptime); } fflush(stdout); /* run the child */ if ( (childpid = fork()) == 0 ) { /* IN THE CHILD */ close(lfd); /* don't need the lock file */ /* Make ourselves a process group leader so that this and all * child processes can be sent a signal as a group. This may * be used someday to support a --kill option, though this is * is still tricky. * * PORTING NOTE: if "setsid" is undefined on your platform, * just comment it out and send me an email with info about * the build environment. */ (void) setsid(); /* Set rc to the result of execvp. This lets the parent know we failed. */ rc = execvp(argv[0], argv); } else if ( childpid > 0 ) { /* IN THE PARENT */ time_t endtime; pid_t pid; int status; if ( Verbose ) printf("Waiting for process %ld\n", (long) childpid); pid = waitpid(childpid, &status, 0); rc = WEXITSTATUS(status); time(&endtime); endtime -= starttime; if ( Verbose || (Maxtime > 0 && endtime > Maxtime) ) printf("pid %d exited with status %d, exit code: %d (time=%ld sec)\n", pid, status, rc, endtime); } else { die("ERROR: cannot fork [%s]", strerror(errno)); } exit(rc); }
int main(int argc, char **argv) { char *Argv0 = *argv; int rc; int lfd; pid_t childpid; time_t starttime; UNUSED_PARAMETER(argc); time(&starttime); for ( argv++ ; *argv ; argv++ ) { char *arg = *argv; char *opt = strchr(arg, '='); /* the -- token marks the end of the list */ if ( strcmp(*argv, "--") == 0 ) { argv++; break; } if (opt) *opt++ = '\0'; /* pick off the =VALUE part */ if ( STRMATCH(arg, "-L") || STRMATCH(arg, "--lockfile")) { lockfile = getarg(opt, &argv); } else if ( STRMATCH(arg, "-W") || STRMATCH(arg, "--wait")) { wait_for_lock = TRUE; } else if ( STRMATCH(arg, "-S") || STRMATCH(arg, "--sleep")) { sleeptime = atoi(getarg(opt, &argv)); } else if ( STRMATCH(arg, "-T") || STRMATCH(arg, "--maxtime")) { Maxtime = atoi(getarg(opt, &argv)); } else if ( STRMATCH(arg, "-V") || STRMATCH(arg, "--verbose")) { Verbose++; } else { die("ERROR: \"%s\" is an invalid cmdline param", arg); } } /*---------------------------------------------------------------- * SANITY CHECKING * * Make sure that we have all the parameters we require */ if (*argv == 0) die("ERROR: missing command to %s (must follow \"--\" marker) ", Argv0); if (lockfile == 0) die("ERROR: missing --lockfile=F parameter"); /*---------------------------------------------------------------- * Open or create the lockfile, then try to acquire the lock. If * the lock is acquired immediately (==0), then we're done, but * if the lock is not available, we have to wait for it. * * We can either loop trying for the lock (for --wait), or exit * with error. */ if ( (lfd = open(lockfile, O_RDWR|O_CREAT, openmode)) < 0) die("ERROR: cannot open(%s) [err=%s]", lockfile, strerror(errno)); while ( WAIT_AND_LOCK(lfd) != 0 ) { if ( ! wait_for_lock ) { die("ERROR: cannot launch %s - run is locked", argv[0]); } /* waiting */ if ( Verbose ) printf("(locked: sleeping %d secs)\n", sleeptime); sleep(sleeptime); } fflush(stdout); /* run the child */ if ( (childpid = fork()) == 0 ) { close(lfd); // don't need the lock file execvp(argv[0], argv); } else if ( childpid > 0 ) { time_t endtime; pid_t pid; if ( Verbose ) printf("Waiting for process %ld\n", (long) childpid); pid = waitpid(childpid, &rc, 0); time(&endtime); endtime -= starttime; if ( Verbose || (Maxtime > 0 && endtime > Maxtime) ) printf("pid %d exited with status %d (time=%ld sec)\n", pid, rc, endtime); } else { die("ERROR: cannot fork [%s]", strerror(errno)); } exit(rc); }