tMany improvements and style changes - watch - minimalist watch program | |
git clone git://src.adamsgaard.dk/watch | |
Log | |
Files | |
Refs | |
LICENSE | |
--- | |
commit aaaa2f8bc15b34aa1d66fe30fd4f86bc6ed4ee79 | |
parent 56fe3ac4a98f0f5a3c401ecbb5f281b9d82d04c8 | |
Author: Anders Damsgaard <[email protected]> | |
Date: Sat, 23 May 2020 22:21:39 +0200 | |
Many improvements and style changes | |
Diffstat: | |
M Makefile | 16 ++-------------- | |
M watch.c | 152 ++++++++++++++---------------… | |
2 files changed, 69 insertions(+), 99 deletions(-) | |
--- | |
diff --git a/Makefile b/Makefile | |
t@@ -1,33 +1,21 @@ | |
-CFLAGS = -g -std=c99 -pedantic -Wall | |
LDFLAGS = -lm | |
OBJ = watch.o | |
BIN = watch | |
-PREFIX ?= ~/.local | |
-INSTALL ?= install | |
-STRIP ?= strip | |
- | |
-default: $(BIN) | |
+PREFIX = /usr/local | |
$(BIN): $(OBJ) $(HDR) | |
$(CC) $(LDFLAGS) $(OBJ) -o $@ | |
install: $(BIN) | |
- $(STRIP) $(BIN) | |
$(INSTALL) -m 0755 -d $(DESTDIR)$(PREFIX)/bin | |
$(INSTALL) -m 0755 $(BIN) $(DESTDIR)$(PREFIX)/bin | |
uninstall: | |
rm -f $(DESTDIR)$(PREFIX)/bin/$(BIN) | |
-memtest: $(BIN) | |
- valgrind --error-exitcode=1 --leak-check=full $(BIN) -h | |
- valgrind --error-exitcode=1 --leak-check=full $(BIN) -v | |
- valgrind --error-exitcode=1 --leak-check=full $(BIN) -q -r 2 date | |
- valgrind --error-exitcode=1 --leak-check=full $(BIN) -q -n 2 -r 2 ls | |
- | |
clean: | |
rm -f $(OBJ) | |
rm -f $(BIN) | |
-.PHONY: default install uninstall memtest clean | |
+.PHONY: install uninstall clean | |
diff --git a/watch.c b/watch.c | |
t@@ -3,49 +3,46 @@ | |
#include <getopt.h> | |
#include <string.h> | |
#include <unistd.h> | |
+#include <stdarg.h> | |
-#define VERSION "0.1.0" | |
-#define PROGNAME "watch" | |
+#define VERSION "0.2.0" | |
+#define CMD_MAX_LEN 45 | |
-void | |
-usage(int interval) | |
+static int interval = 5; | |
+ | |
+static void | |
+usage() | |
{ | |
printf("%s: %s [OPTIONS] COMMAND\n" | |
"will repeatedly run COMMAND every %d seconds.\n" | |
"Following OPTIONS are valid:\n" | |
- " -h, --help show this message\n" | |
- " -v, --version show version and license information… | |
- " -n, --interval SECONDS set interval between command invocat… | |
- " -r, --repeat N repeat for N times and then quit\n" | |
- " -q, --quiet suppress output (stdout) from COMMAN… | |
- " -c, --no-clear do not clear screen between COMMAND … | |
- " -- do not consider any following args a… | |
+ " -v show version\n" | |
+ " -n SECONDS set interval between command invocations\n" | |
+ " -r N repeat for N times and then quit\n" | |
+ " -q suppress output (stdout) from COMMAND\n" | |
+ " -c do not clear screen between COMMAND calls\n" | |
+ " -- do not consider any following args as options\n" | |
, | |
- __func__, PROGNAME, interval); | |
+ __func__, getprogname(), interval); | |
} | |
-void | |
-version() | |
+static void | |
+die(const char *errstr,...) | |
{ | |
- printf("%s version %s\n" | |
- "Licensed under the GNU Public License, v3+\n" | |
- "Written by Anders Damsgaard, [email protected]\n", | |
- PROGNAME, VERSION); | |
-} | |
+ va_list ap; | |
-void | |
-die(char* error_message) | |
-{ | |
- fprintf(stderr, "%s", error_message); | |
+ va_start(ap, errstr); | |
+ vfprintf(stderr, errstr, ap); | |
+ va_end(ap); | |
exit(1); | |
} | |
-void | |
-run_cmd(int sleeptime, char* command, int quiet, int clearscreen) | |
+static void | |
+run_cmd(int sleeptime, char *command, int quiet, int clearscreen) | |
{ | |
if (!quiet) { | |
if (clearscreen) | |
- printf("\e[1;1H\e[2J"); /* clear screen (POSIX) */ | |
+ printf("\e[1;1H\e[2J"); /* clear screen (POSIX)… | |
else | |
puts(""); | |
printf("Every %ds: %s\n\n", sleeptime, command); | |
t@@ -57,81 +54,66 @@ run_cmd(int sleeptime, char* command, int quiet, int clear… | |
} | |
int | |
-main(int argc, char* argv[]) | |
+main(int argc, char *argv[]) | |
{ | |
int i, opt; | |
- int interval, repeat, quiet, clearscreen; | |
- const char* optstring; | |
- char* command; | |
- | |
- interval = 5; | |
- quiet = 0; | |
- optstring = "hvn:r:qc"; | |
- const struct option longopts[] = { | |
- {"help", no_argument, NULL, 'h'}, | |
- {"version", no_argument, NULL, 'v'}, | |
- {"interval", required_argument, NULL, 'n'}, | |
- {"repeat", required_argument, NULL, 'r'}, | |
- {"quiet", no_argument, NULL, 'q'}, | |
- {"no-clear", no_argument, NULL, 'c'}, | |
- {NULL, 0, NULL, 0} | |
- }; | |
+ int repeat = 0, quiet = 0, clearscreen = 1; | |
+ char command[CMD_MAX_LEN] = ""; | |
- repeat = 0; | |
- clearscreen = 1; | |
- while ((opt = getopt_long(argc, argv, optstring, longopts, NULL)) != -… | |
+ while ((opt = getopt(argc, argv, "hvn:r:qc")) != -1) { | |
switch (opt) { | |
- case -1: /* no more arguments */ | |
- case 0: /* long options toggles*/ | |
- break; | |
- case 'h': | |
- usage(interval); | |
- return 0; | |
- case 'v': | |
- version(); | |
- return 0; | |
- case 'n': | |
- interval = atoi(optarg); | |
- break; | |
- case 'r': | |
- repeat = atoi(optarg); | |
- break; | |
- case 'q': | |
- quiet = 1; | |
- break; | |
- case 'c': | |
- clearscreen = 0; | |
- break; | |
- default: | |
- fprintf(stderr, "%s: invalid option -- %c\n", … | |
- fprintf(stderr, "try `%s --help` for more info… | |
- argv[0]); | |
- return -2; | |
+ case -1: /* no more arguments */ | |
+ case 0: /* long options toggles */ | |
+ break; | |
+ case 'h': | |
+ usage(); | |
+ return 0; | |
+ break; | |
+ case 'v': | |
+ die("%s " VERSION "\n", argv[0]); | |
+ break; | |
+ case 'n': | |
+ interval = atoi(optarg); | |
+ break; | |
+ case 'r': | |
+ repeat = atoi(optarg); | |
+ break; | |
+ case 'q': | |
+ quiet = 1; | |
+ break; | |
+ case 'c': | |
+ clearscreen = 0; | |
+ break; | |
+ default: | |
+ fprintf(stderr, "%s: invalid option -- %c\n", argv[0],… | |
+ fprintf(stderr, "try `%s --help` for more information\… | |
+ argv[0]); | |
+ return -2; | |
} | |
} | |
+ argc -= optind; | |
+ argv += optind; | |
- if (optind == argc) | |
+ if (argc < 1) | |
die("error: no COMMAND specified\n"); | |
- if ((command = malloc(512)) != NULL) { | |
- command[0] = '\0'; | |
- strcat(command, "[ -f ~/.profile ] && . ~/.profile "); | |
- for (i=optind; i<argc; ++i) { | |
- strcat(command, argv[i]); | |
- if (i < argc-1) | |
- strcat(command, " "); | |
- } | |
- } else { | |
- die("command malloc failed"); | |
+ strcat(command, "[ -f ~/.profile ] && . ~/.profile; "); | |
+ for (i = 0; i < argc; ++i) { | |
+ if (strlen(command) + strlen(argv[i]) + | |
+ (i > 0 && i < argc - 1 ? 1 : 0) >= CMD_MAX_LEN) | |
+ die("error: command length exceeded\n"); | |
+ | |
+ strcat(command, argv[i]); | |
+ if (i > 0 && i < argc - 1) | |
+ strcat(command, " "); | |
} | |
if (repeat > 0) { | |
- for (i=0; i<repeat; ++i) | |
+ for (i = 0; i < repeat; ++i) | |
run_cmd(interval, command, quiet, clearscreen); | |
} else { | |
for (;;) | |
run_cmd(interval, command, quiet, clearscreen); | |
} | |
- free(command); | |
return 0; | |
} |