X-Git-Url: https://git.xandkar.net/?p=khatus.git;a=blobdiff_plain;f=x5%2Fkhatus.c;h=5407acde0b145131f038515d773e0a8d17bf2526;hp=4626729e35c34c92b49287968f5ac05d400329c2;hb=HEAD;hpb=457f091d53ca576e5b04d6788fdefad8b7744812 diff --git a/x5/khatus.c b/x5/khatus.c index 4626729..5407acd 100644 --- a/x5/khatus.c +++ b/x5/khatus.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -28,7 +29,8 @@ static const char errmsg[] = ERRMSG; static const int errlen = sizeof(ERRMSG) - 1; -char *argv0; +char *argv0 = NULL; +int running = 1; /* TODO: Convert slot list to slot array. */ typedef struct Slot Slot; @@ -48,6 +50,7 @@ typedef struct Config Config; struct Config { double interval; char * separator; + char expiry_character; Slot * slots; int slot_count; int buf_width; @@ -139,7 +142,9 @@ slot_log(Slot *s) void slots_log(Slot *head) { - for (Slot *s = head; s; s = s->next) { + Slot *s = head; + + for (; s; s = s->next) { slot_log(s); } } @@ -173,14 +178,34 @@ slots_assert_fifos_exist(Slot *s) } void -slot_expire(Slot *s, struct timespec t, char *buf) +slot_close(Slot *s) +{ + close(s->in_fd); + s->in_fd = -1; + s->out_pos_cur = s->out_pos_lo; +} + +void +slots_close(Slot *s) +{ + for (; s; s = s->next) + if (s->in_fd > -1) + slot_close(s); +} + + +void +slot_expire(Slot *s, struct timespec t, char expiry_character, char *buf) { struct timespec td; timespecsub(&t, &(s->in_last_read), &td); if (timespeccmp(&td, &(s->out_ttl), >=)) { - /* TODO: Maybe configurable expiry character. */ - memset(buf + s->out_pos_lo, '_', s->out_width); + memset( + buf + s->out_pos_lo, + expiry_character, + s->out_width + ); khlib_warn("Slot expired: \"%s\"\n", s->in_fifo); } } @@ -313,7 +338,7 @@ slots_read(Config *cfg, struct timespec *ti, char *buf) switch (errno) { case EINTR: khlib_error( - "pselect temp failure: %d, errno: %d, msg: %s\n", + "pselect interrupted: %d, errno: %d, msg: %s\n", ready, errno, strerror(errno) @@ -367,10 +392,8 @@ slots_read(Config *cfg, struct timespec *ti, char *buf) case END_OF_MESSAGE: case END_OF_FILE: case FAILURE: - close(s->in_fd); - s->in_fd = -1; + slot_close(s); s->in_last_read = t; - s->out_pos_cur = s->out_pos_lo; ready--; break; case RETRY: @@ -379,7 +402,7 @@ slots_read(Config *cfg, struct timespec *ti, char *buf) assert(0); } } else { - slot_expire(s, t, buf); + slot_expire(s, t, cfg->expiry_character, buf); } } } while (ready); @@ -467,9 +490,12 @@ print_usage() " | -s SEPARATOR\n" " | -x (* Output to X root window *)\n" " | -l LOG_LEVEL\n" + " | -e EXPIRY_CHARACTER\n" " SEPARATOR = string\n" " INTERVAL = float (* (positive) number of seconds *)\n" " LOG_LEVEL = int (* %d through %d *)\n" + " EXPIRY_CHARACTER = string " + "(* Character with which to fill the slot upon expiration. *)\n" "\n", argv0, Nothing, @@ -532,6 +558,15 @@ parse_opts_opt_l(Config *cfg, int argc, char *argv[], int i) opts_parse_any(cfg, argc, argv, i); } +void +parse_opts_opt_e(Config *cfg, int argc, char *argv[], int i) +{ + if (i >= argc) + usage("Option -e parameter is missing.\n"); + cfg->expiry_character = argv[i++][0]; + opts_parse_any(cfg, argc, argv, i); +} + void parse_opts_opt(Config *cfg, int argc, char *argv[], int i) { @@ -552,6 +587,10 @@ parse_opts_opt(Config *cfg, int argc, char *argv[], int i) /* TODO: Generic set_int */ parse_opts_opt_l(cfg, argc, argv, ++i); break; + case 'e': + /* TODO: Generic set_str */ + parse_opts_opt_e(cfg, argc, argv, ++i); + break; default : usage("Option \"%s\" is invalid\n", argv[i]); } @@ -640,7 +679,7 @@ loop(Config *cfg, char *buf, Display *d) tc; /* time interval correction (ti - td) when td < ti */ ti = khlib_timespec_of_float(cfg->interval); - for (;;) { + while (running) { clock_gettime(CLOCK_MONOTONIC, &t0); // FIXME: check errors slots_read(cfg, &ti, buf); if (cfg->to_x_root) { @@ -669,12 +708,22 @@ loop(Config *cfg, char *buf, Display *d) } } +void +terminate(int s) +{ + khlib_debug("terminating due to signal %d\n", s); + running = 0; +} + int main(int argc, char *argv[]) { + argv0 = argv[0]; + Config cfg = { .interval = 1.0, .separator = "|", + .expiry_character = '_', .slots = NULL, .slot_count = 0, .buf_width = 0, @@ -682,10 +731,13 @@ main(int argc, char *argv[]) }; char *buf; Display *d = NULL; + struct sigaction sa; - /* TODO: Handle signals */ + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = terminate; + sigaction(SIGTERM, &sa, NULL); + sigaction(SIGINT , &sa, NULL); - argv0 = argv[0]; opts_parse(&cfg, argc, argv); slots_assert_fifos_exist(cfg.slots); config_stretch_for_separators(&cfg); @@ -693,5 +745,6 @@ main(int argc, char *argv[]) if (cfg.to_x_root && !(d = XOpenDisplay(NULL))) khlib_fatal("XOpenDisplay failed with: %p\n", d); loop(&cfg, buf, d); + slots_close(cfg.slots); return EXIT_SUCCESS; }