aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomasz Kramkowski <tk@the-tk.com>2015-12-12 23:05:59 +0000
committerTomasz Kramkowski <tk@the-tk.com>2015-12-12 23:05:59 +0000
commit4d99702f60f96279511ab5ab5d360bf0c2577e47 (patch)
tree9522a333c7111798501f176e3011b9630f2d46d9
parentd94dcc7b2d449ffd50a153c59d858fb35c156c32 (diff)
downloadc-stuff-4d99702f60f96279511ab5ab5d360bf0c2577e47.tar.gz
c-stuff-4d99702f60f96279511ab5ab5d360bf0c2577e47.tar.xz
c-stuff-4d99702f60f96279511ab5ab5d360bf0c2577e47.zip
timer.c: cleanup
-rw-r--r--timer.c169
1 files changed, 68 insertions, 101 deletions
diff --git a/timer.c b/timer.c
index 3d43a7c..f2490d1 100644
--- a/timer.c
+++ b/timer.c
@@ -22,62 +22,25 @@
#include <unistd.h>
#include <limits.h>
-#define SEC_SECOND 1
-#define SEC_MINUTE 60
-#define SEC_HOUR 3600
-#define SEC_DAY 86400
-#define SEC_MONTH 2629746
-#define SEC_YEAR 31556940
-
+static const unsigned long long SEC_SECOND = 1, SEC_MINUTE = 60,
+ SEC_HOUR = 3600, SEC_DAY = 86400, SEC_MONTH = 2629746,
+ SEC_YEAR = 31556940;
static const unsigned long interval_nsec = 1000000000 / 4;
-unsigned short term_width = 0; /* Maybe volatile? */
+
+volatile unsigned short term_width = 0;
void sigwinch(int sig) {
+ struct winsize ws;
+
if (sig != SIGWINCH)
return;
- struct winsize ws;
-
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1)
error(1, errno, "Failed to get terminal width");
term_width = ws.ws_col;
}
-unsigned long int get_seconds(char *code)
-{
- int length = strlen(code), multiplier = 0;
- char suffix = code[length - 1], value[length + 1];
- unsigned long retval;
-
- if (length < 2) {
- return 0;
- }
-
- switch (suffix) {
- case 's': multiplier = SEC_SECOND; break; // 1 second
- case 'm': multiplier = SEC_MINUTE; break; // 1 minute
- case 'h': multiplier = SEC_HOUR; break; // 1 hour
- case 'D': multiplier = SEC_DAY; break; // 1 day
- case 'M': multiplier = SEC_MONTH; break; // 30.4368 days
- case 'Y': multiplier = SEC_YEAR; break; // 365.242 days
- default : return 0;
- }
-
- strncpy(value, code, length + 1);
-
- value[length - 1] = '\0';
-
- errno = 0;
-
- retval = strtoul(value, NULL, 10) * multiplier;
-
- if (retval == ULONG_MAX && errno != 0)
- error(1, errno, "Error converting time specifier %s", code);
-
- return retval;
-}
-
void clear_line(void)
{
if (term_width <= 1)
@@ -85,49 +48,39 @@ void clear_line(void)
for (unsigned short i = 0; i < term_width - 1; i++)
putchar(' ');
-
putchar('\r');
if (fflush(stdout) != 0)
error(1, errno, "Failed to flush stdout");
}
+void format_dmy(char *dest, size_t size, const char *name,
+ unsigned long long count)
+{
+ if (count == 1)
+ snprintf(dest, size, "%llu %s, ", count, name);
+ else if (count > 1)
+ snprintf(dest, size, "%llu %ss, ", count, name);
+ else
+ dest[0] = '\0';
+}
-void print_time(unsigned long total_sec, bool show_colon)
+void print_time(unsigned long long total_sec, bool show_colon)
{
- unsigned long years, months, days, hours, minutes, seconds;
- char colon = show_colon ? ':' : ' ', syears[128], smonths[16],
- sdays[16];
+ unsigned long long count, hours, minutes, seconds;
+ char colon = show_colon ? ':' : ' ', syears[128], smonths[16], sdays[16];
- years = total_sec / SEC_YEAR;
+ count = total_sec / SEC_YEAR;
total_sec %= SEC_YEAR;
+ format_dmy(syears, sizeof syears, "year", count);
- if (years == 1)
- snprintf(syears, sizeof syears, "%lu year, ", years);
- else if (years > 1)
- snprintf(syears, sizeof syears, "%lu years, ", years);
- else
- syears[0] = '\0';
-
- months = total_sec / SEC_MONTH;
+ count = total_sec / SEC_MONTH;
total_sec %= SEC_MONTH;
+ format_dmy(smonths, sizeof smonths, "month", count);
- if (months == 1)
- snprintf(smonths, sizeof smonths, "%lu month, ", months);
- else if (months > 1)
- snprintf(smonths, sizeof smonths, "%lu months, ", months);
- else
- smonths[0] = '\0';
-
- days = total_sec / SEC_DAY;
+ count = total_sec / SEC_DAY;
total_sec %= SEC_DAY;
-
- if (days == 1)
- snprintf(sdays, sizeof sdays, "%lu day, ", days);
- else if (days > 1)
- snprintf(sdays, sizeof sdays, "%lu days, ", days);
- else
- sdays[0] = '\0';
+ format_dmy(sdays, sizeof sdays, "day", count);
hours = total_sec / SEC_HOUR;
total_sec %= SEC_HOUR;
@@ -139,18 +92,45 @@ void print_time(unsigned long total_sec, bool show_colon)
total_sec %= SEC_SECOND;
if (total_sec != 0)
- error(1, 0, "An error occured during time formatting");
+ error(1, 0, "A bug occured during time formatting");
- printf(" %s%s%s%.2lu%c%.2lu%c%.2lu\r", syears, smonths, sdays, hours,
+ printf(" %s%s%s%.2llu%c%.2llu%c%.2llu\r", syears, smonths, sdays, hours,
colon, minutes, colon, seconds);
if (fflush(stdout) != 0)
error(1, errno, "Failed to flush stdout");
}
-void usage(char *cmd)
+unsigned long long get_seconds(char *code)
{
- printf("Usage:\n\t%s <n>{s,m,h,D,M,Y} ...\n", cmd);
+ size_t length = strlen(code);
+ unsigned long long multiplier, retval;
+ char suffix, value[length];
+
+ if (length < 2)
+ return 0;
+
+ suffix = code[length - 1];
+ switch (suffix) {
+ case 's': multiplier = SEC_SECOND; break; /* 1 second */
+ case 'm': multiplier = SEC_MINUTE; break; /* 1 minute */
+ case 'h': multiplier = SEC_HOUR; break; /* 1 hour */
+ case 'D': multiplier = SEC_DAY; break; /* 1 day */
+ case 'M': multiplier = SEC_MONTH; break; /* 30.4368 days */
+ case 'Y': multiplier = SEC_YEAR; break; /* 365.242 days */
+ default: return 0;
+ }
+
+ strncpy(value, code, sizeof value);
+
+ value[sizeof value - 1] = '\0';
+
+ errno = 0;
+ retval = strtoul(value, NULL, 10) * multiplier; /* Possibly might overflow */
+ if (retval == ULONG_MAX && errno != 0)
+ error(1, errno, "Error converting time specifier %s", code);
+
+ return retval;
}
int main(int argc, char **argv)
@@ -158,42 +138,29 @@ int main(int argc, char **argv)
bool blink = false;
int sig;
sigset_t sigset;
- struct itimerspec its;
- struct sigevent sev;
- struct sigaction sigact;
+ struct itimerspec its = {{0, interval_nsec}, {0, interval_nsec}};
+ struct sigaction sigact = {.sa_handler = sigwinch};
timer_t timerid;
-
- unsigned long total_seconds = 0;
+ struct sigevent sev = {.sigev_notify = SIGEV_SIGNAL,
+ .sigev_signo = SIGRTMIN, .sigev_value.sival_ptr = &timerid};
+ unsigned long long total_seconds = 0;
if (!isatty(STDOUT_FILENO))
error(1, 0, "Error: stdout is not a tty");
- if (argc < 2) {
- fprintf(stderr, "Not enough arguments.\n");
- usage(argv[0]);
- exit(1);
- }
+ if (argc < 2)
+ error(1, 0, "Not enough arguments.\nUsage:\n"
+ "\t%s <n>{s,m,h,D,M,Y} ...", argv[0]);
for (int i = 1; i < argc; i++)
total_seconds += get_seconds(argv[i]);
- sigact.sa_handler = sigwinch;
-
if (sigaction(SIGWINCH, &sigact, NULL) != 0)
error(1, errno, "Unable to set SIGWINCH signal action");
- sev.sigev_notify = SIGEV_SIGNAL;
- sev.sigev_signo = SIGRTMIN;
- sev.sigev_value.sival_ptr = &timerid;
-
if (timer_create(CLOCK_MONOTONIC, &sev, &timerid) != 0)
error(1, errno, "Could not create timer");
- its = (struct itimerspec){
- {0, interval_nsec},
- {0, interval_nsec}
- };
-
if (sigemptyset(&sigset) != 0)
error(1, errno, "Could not empty signal set");
@@ -208,12 +175,12 @@ int main(int argc, char **argv)
sigwinch(SIGWINCH);
- for (unsigned long i = 0; i < total_seconds; i++)
+ for (unsigned long long i = 0; i < total_seconds; i++)
for (int ii = 0; ii < 4; ii++) {
if (sigwait(&sigset, &sig), sig != SIGRTMIN)
error(1, 0, "sigwait returned unexpected signal %d", sig);
if (sigaddset(&sigset, SIGRTMIN) != 0)
- error(1, errno, "Could not add signal to set");
+ error(1, errno, "Could not add SIGRTMIN to signal set");
clear_line();
print_time(total_seconds - i, ii < 2);
@@ -229,7 +196,7 @@ int main(int argc, char **argv)
break;
if (sigaddset(&sigset, SIGRTMIN) != 0)
- error(1, errno, "Could not add signal to set");
+ error(1, errno, "Could not add SIGRTMIN to signal set");
clear_line();