diff options
Diffstat (limited to '')
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | README | 15 | ||||
-rw-r--r-- | arg.h | 38 | ||||
-rw-r--r-- | slack.1 | 22 | ||||
-rw-r--r-- | slack.c | 184 |
5 files changed, 134 insertions, 127 deletions
@@ -8,7 +8,7 @@ all: slack slack: slack.o $(CC) -o $@ $^ $(LDFLAGS) -slack.o: slack.c +slack.o: slack.c arg.h $(CC) -c -o $@ $< $(CFLAGS) $(CPPFLAGS) install: slack @@ -2,8 +2,7 @@ NAME slack - Spawn processes with customised timer slack SYNOPSIS - slack (get | GET) - slack ((reset | INTERVAL) [--fatal] [--] COMMAND...) + slack [-f] ('get' | 'GET' | ('reset' | interval) command [argument] ... DESCRIPTION Get the current timer slack value or spawn a new process @@ -17,13 +16,13 @@ DESCRIPTION If the verb reset is used, the process shall set the timer slack value for the process to the default timer - slack value, and exec(3) to COMMAND. + slack value, and exec(3) to command. - If an INTERVAL is given, the process shall set the - timer slack value for the process to INTERVAL, and - exec(3) to COMMAND. + If an interval is given, the process shall set the + timer slack value for the process to interval, and + exec(3) to command. - INTERVAL must be a positive number, optionally with + interval must be a positive number, optionally with a prefix. Recognised prefixes (and units) are: ns, n nanoseconds (default) @@ -35,7 +34,7 @@ DESCRIPTION on PID 1. OPTIONS - --fatal + -f Fail if the timer slack value cannot be set. NOTES @@ -0,0 +1,38 @@ +/* + * Copy me if you can. + * by 20h + */ + +#ifndef ARG_H__ +#define ARG_H__ + +extern char *argv0; + +/* use main(int argc, char *argv[]) */ +#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\ + argv[0] && argv[0][0] && argv[0][1];\ + argc--, argv++) {\ + char argc_;\ + char **argv_;\ + int brk_;\ + if (argv[0][0] == '-') {\ + if (argv[0][1] == '-' && argv[0][2] == '\0') {\ + argv++;\ + argc--;\ + break;\ + }\ + for (brk_ = 0, argv[0]++, argv_ = argv;\ + argv[0][0] && !brk_;\ + argv[0]++) {\ + if (argv_ != argv)\ + break;\ + argc_ = argv[0][0];\ + switch (argc_) + +#define ARGEND }\ + } else {\ + break;\ + }\ + } + +#endif @@ -3,12 +3,10 @@ slack - Spawn processes with customised timer slack .SH SYNOPSIS .B slack -(get | GET) -.br -.B slack -.RI ((reset\ |\ INTERVAL ) -[\-\-fatal] [--] -.IR COMMAND ...) +[-f] ('get' | 'GET' | ('reset' | +.IR interval ) +.I command +.RI [ argument ]\ ...) .SH DESCRIPTION If the verb .B get @@ -24,19 +22,19 @@ If the verb reset is used, the process shall set the timer slack value for the process to the default timer slack value, and .BR exec (3) to -.IR COMMAND . +.IR command . .PP If an -.I INTERVAL +.I interval is given, the process shall set the timer slack value for the process to -.IR INTERVAL , +.IR interval , and .BR exec (3) to -.IR COMMAND . +.IR command . .PP -.I INTERVAL +.I interval must be a positive number, optionally with a prefix. Recognised prefixes (and units) are: .TP @@ -55,7 +53,7 @@ seconds The default timer slack value is the timer slack value on PID 1. .SH OPTIONS .TP -.B \-\-fatal +.B \-f Fail if the timer slack value cannot be set. .SH NOTES Real-time threads do not slack around. @@ -1,119 +1,91 @@ +/* See LICENSE file for copyright and license details. */ +#include <sys/prctl.h> +#include <errno.h> #include <stdio.h> -#include <string.h> #include <stdlib.h> +#include <string.h> #include <unistd.h> -#include <sys/prctl.h> +#include "arg.h" +#define NS (1L) +#define US (1000L) +#define MS (1000L * 1000L) +#define S (1000L * 1000L * 1000L) -#define NS (1L) -#define US (1000L) -#define MS (1000L * 1000L) -#define S (1000L * 1000L * 1000L) +char *argv0; - -static void usage(void) +static void +usage(void) { - printf("USAGE: slack (get | GET | ((reset | <interval>) [--fatal] [--] <command...>))\n"); - printf("\n"); - printf("The <interval> must be a positive number optionally with a suffix:\n"); - printf(" ns n nanoseconds (default)\n"); - printf(" µs µ us u microseconds\n"); - printf(" ms m milliseconds\n"); - printf(" s seconds\n"); - printf("\n"); - printf("If `GET' is used rather than `get', the timer slack value will be printed in\n"); - printf("nanoseconds without suffix. `GET' and `get' prints the current timer slack\n"); - printf("value and exits.\n"); - printf("\n"); - printf("`reset` reset the timer slack value to the default (the time slack value for\n"); - printf("the init process (PID 1) has.)\n"); - printf("\n"); - printf("Unless `--fatal` is used, the program will run <command> even if the timer\n"); - printf("slack could not be set.\n"); - printf("\n"); + fprintf(stderr, "usage: %s [-f] ('get' | 'GET' | (('reset' | interval) command [argument] ...))\n", argv0); + exit(1); } - -int main(int argc, char** argv) +int +main(int argc, char **argv) { - long slackvalue, r; - int i, j, fatal = 0; - char** exec_argv; - - if ((argc < 2) || !strcmp(argv[1], "--help") || !strcmp(argv[1], "help")) - return usage(), argc < 2 ? 1 : 0; - - if (!strcmp(argv[1], "get") || !strcmp(argv[1], "GET")) - { - const char* suffix; - if (r = prctl(PR_GET_TIMERSLACK), r < 0) - perror(*argv); - else - { - if (!strcmp(argv[1], "GET")) - suffix = ""; - else if (r % S == 0) suffix = "s", r /= S; - else if (r % MS == 0) suffix = "ms", r /= MS; - else if (r % US == 0) suffix = "µs", r /= US; - else suffix = "ns"; - printf("%li%s\n", r, suffix); + int fatal; + long int slackvalue; + const char *suffix; + char *end; + int r; + + ARGBEGIN { + case 'f': + fatal = 1; + break; + default: + usage(); + } ARGEND; + + if (!argc) + usage(); + + if (!strcmp(*argv, "get") || !strcmp(*argv, "GET")) { + if (argc > 1) + usage(); + r = prctl(PR_GET_TIMERSLACK); + if (r < 0) + return fprintf(stderr, "%s: prctl PR_GET_TIMERSLACK: %s\n", argv0, strerror(errno)), 1; + if (!strcmp(*argv, "GET")) suffix = ""; + else if (r % S == 0) suffix = "s", r /= S; + else if (r % MS == 0) suffix = "ms", r /= MS; + else if (r % US == 0) suffix = "µs", r /= US; + else suffix = "ns"; + printf("%i%s\n", r, suffix); + return 0; + } + + if (argc < 2) + usage(); + + if (!strcmp(*argv, "reset")) { + slackvalue = 0; + } else { + slackvalue = strtol(*argv, &end, 10); + if (end == *argv) + return fprintf(stderr, "%s: no slack value specified\n", argv0), 1; + if (!strcmp(end, "n") || !strcmp(end, "ns") || !strcmp(end, "")) slackvalue *= NS; + else if (!strcmp(end, "µ") || !strcmp(end, "µs")) slackvalue *= US; + else if (!strcmp(end, "u") || !strcmp(end, "us")) slackvalue *= US; + else if (!strcmp(end, "m") || !strcmp(end, "ms")) slackvalue *= MS; + else if (!strcmp(end, "s")) slackvalue *= S; + else + return fprintf(stderr, "%s: unrecognised suffix for slack value\n", argv0), 1; + if (slackvalue <= 0) + return fprintf(stderr, "%s: invalid slack value: %lins\n", argv0, slackvalue), 1; + } + + r = prctl(PR_SET_TIMERSLACK, slackvalue); + if (r < 0) { + fprintf(stderr, "%s: prctl PR_SET_TIMERSLACK %li: %s\n", argv0, slackvalue, strerror(errno)); + if (fatal) + return 1; } - return r > 0 ? 0 : 1; - } - - for (i = 2; i < argc; i++) - if (!strcmp(argv[i], "--fatal")) - fatal = 1; - else if (!strcmp(argv[i], "--")) - { - i++; - break; - } - else if (strstr(argv[i], "-") == argv[i]) - return usage(), 1; - else - break; - - if (i == argc) - return usage(), 1; - - exec_argv = malloc((argc - i + 1) * sizeof(char*)); - if (exec_argv == NULL) - return perror(*argv), 2; - exec_argv[argc - i] = NULL; - for (j = 0; i < argc; j++, i++) - exec_argv[j] = argv[i]; - - if (!strcmp(argv[1], "reset")) - slackvalue = 0; - else - { - char* end; - - slackvalue = strtol(argv[1], &end, 10); - if (end == argv[1]) - return fprintf(stderr, "No slack value specified."), free(exec_argv), 1; - - if (!strcmp(end, "n") || !strcmp(end, "ns") || !strcmp(end, "")) slackvalue *= NS; - else if (!strcmp(end, "µ") || !strcmp(end, "µs")) slackvalue *= US; - else if (!strcmp(end, "u") || !strcmp(end, "us")) slackvalue *= US; - else if (!strcmp(end, "m") || !strcmp(end, "ms")) slackvalue *= MS; - else if (!strcmp(end, "s")) slackvalue *= S; - else - return fprintf(stderr, "Unrecognised suffix for slack value."), free(exec_argv), 1; - - if (slackvalue <= 0) - return fprintf(stderr, "Invalid slack value: %lins", slackvalue), free(exec_argv), 1; - } - - if (r = prctl(PR_SET_TIMERSLACK, slackvalue), r < 0) - if (perror(*argv), fatal) - return free(exec_argv), 2; - - execvp(*exec_argv, exec_argv); - perror(*argv); - free(exec_argv); - return 2; -} + argv++; + execvp(*argv, argv); + fprintf(stderr, "%s: execvp %s: %s\n", argv0, *argv, strerror(errno)); + return 1; +} |