Created
November 22, 2016 20:32
-
-
Save syntactician/5a96d86caab8f0fce5dc7e51ed0c81ca to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <errno.h> | |
| #include <stdarg.h> | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <unistd.h> | |
| #include <sys/time.h> | |
| #include <sys/wait.h> | |
| /* sysexits.h conventions */ | |
| #define EX_OK 0 | |
| #define EX_USAGE 64 | |
| #define EX_UNAVAILABLE 69 | |
| #define EX_OSERR 71 | |
| static int qflag = 0; | |
| static long int tvalue = -1; | |
| static void die(const int, const char *, ...); | |
| static int getyes(void); | |
| static int respawn(void); | |
| void | |
| die(const int ret, const char *errstr, ...) | |
| { | |
| va_list ap; | |
| va_start(ap, errstr); | |
| vfprintf(stderr, errstr, ap); | |
| va_end(ap); | |
| exit(ret); | |
| } | |
| int | |
| getyes(void) | |
| { | |
| int yes; | |
| char *line = NULL; | |
| size_t len = 0; | |
| getline(&line, &len, stdin); | |
| yes = !strcmp(line, "yes\n"); | |
| free(line); | |
| return yes; | |
| } | |
| int | |
| respawn(void) | |
| { | |
| if (!qflag) { | |
| printf("The command finished. " | |
| "Please enter \"yes\" if you want to exit: "); | |
| fflush(stdout); | |
| } | |
| if (!tvalue) { | |
| printf("\n"); | |
| return 0; | |
| } else if (tvalue < 0) { | |
| return getyes(); | |
| } else { | |
| fd_set rfds; | |
| int retval; | |
| struct timeval tv; | |
| tv.tv_sec = tvalue; | |
| tv.tv_usec = 0; | |
| FD_ZERO(&rfds); | |
| FD_SET(0, &rfds); | |
| if ((retval = select(1, &rfds, NULL, NULL, &tv)) < 0) { | |
| die(EX_OSERR, "Unable to read input\n"); | |
| /* NOTREACHED */ | |
| return 0; | |
| } else if (retval) { | |
| return getyes(); | |
| } else { | |
| printf("\n"); | |
| return 0; | |
| } | |
| } | |
| } | |
| int | |
| main(int argc, char **argv) | |
| { | |
| char *cmd = NULL; | |
| char *ptr = NULL; | |
| int c, i, returnStatus; | |
| int mvalue = -1; | |
| pid_t pid; | |
| if (!isatty(1)) | |
| die(EX_UNAVAILABLE, "%s: not connected to a terminal", argv[0]); | |
| while ((c = getopt(argc, argv, "+hm:qst:Vy")) != -1) { | |
| switch(c) { | |
| case 'h': | |
| die(EX_USAGE, | |
| "%s: [-hqVy] [-m max] [-t timeout] " | |
| "utility [argument...]\n", argv[0]); | |
| case 'm': | |
| if ((mvalue = strtol(optarg, &ptr, 10)) < 1) | |
| die(EX_USAGE, "-m value must be positive\n"); | |
| if (!strcmp(optarg, ptr) || errno == EINVAL) | |
| die(EX_USAGE, "-m value must be a number\n"); | |
| if (errno == ERANGE) | |
| die(EX_USAGE, "-m value out of range\n"); | |
| break; | |
| case 'q': | |
| qflag = 1; | |
| break; | |
| case 't': | |
| if ((tvalue = strtol(optarg, &ptr, 10)) < 0) | |
| die(EX_USAGE, "-t value may not be negative\n"); | |
| if (!strcmp(optarg, ptr) || errno == EINVAL) | |
| die(EX_USAGE, "-t value must be a number\n"); | |
| if (errno == ERANGE) | |
| die(EX_USAGE, "-t value out of range\n"); | |
| break; | |
| case 'V': | |
| die(EX_USAGE, "fenix 0.2\n"); | |
| case 'y': | |
| tvalue = 0; | |
| break; | |
| case '?': | |
| exit(EX_USAGE); | |
| } | |
| } | |
| if (argc <= optind) die(EX_USAGE, "No command provided\n"); | |
| cmd = argv[optind]; | |
| for (i = 0; i < optind; ++i) ++argv; | |
| while (mvalue) { | |
| switch (pid = fork()) { | |
| case -1: | |
| die(EX_OSERR, "failed to fork\n"); | |
| case 0: | |
| if (!qflag) { | |
| printf("Running \""); | |
| for (i = 0; i < argc - optind; ++i) | |
| printf("%s ", argv[i]); | |
| printf("\b\"\n"); | |
| } | |
| if (execvp(argv[0], argv) < 0) | |
| _exit(EX_UNAVAILABLE); | |
| else | |
| _exit(EX_OK); | |
| default: | |
| waitpid(pid, &returnStatus, 0); | |
| if (WEXITSTATUS(returnStatus) == EX_UNAVAILABLE) | |
| die(EX_UNAVAILABLE, | |
| "Cannot execute file \"%s\"\n", cmd); | |
| if (mvalue && mvalue != 1 && tvalue) | |
| if (respawn() || feof(stdin)) | |
| exit(EX_OK); | |
| if (mvalue > 0) --mvalue; | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment