/* * Copyright (C) 2021 P. J. McDermott * * This file is part of @ * * @ is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * @ is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with @. If not, see . */ #include #include #include #include #include #include #include #include "config.h" #include "datetime.h" #if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG #include #endif extern const char *PACKAGE_VERSION_GIT; #if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG struct option LONGOPTS_[] = { { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h', }, { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V', }, }; #endif static void _print_usage(FILE *stream, const char *program_name) { fprintf(stream, "Usage: %s [date]time\n", program_name); } static void _print_help(const char *program_name) { _print_usage(stdout, program_name); puts("Options:"); #if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG puts("\t-h, --help Show this help information"); puts("\t-V, --version Show version information"); #else puts("\t-h Show this help information"); puts("\t-V Show version information"); #endif } static void _print_version(void) { printf("@ (atsign) %s%s\n", PACKAGE_VERSION, PACKAGE_VERSION_GIT); puts("Copyright (C) 2021 P. J. McDermott"); puts("License GPLv3+: GNU GPL version 3 or later " "."); puts("This is free software: you are free to change and redistribute " "it."); puts("There is NO WARRANTY, to the extent permitted by law.\n"); printf("Please report bugs to <%s>.\n", PACKAGE_BUGREPORT); } static char * _concat_args(int argc, char * const argv[]) { int buf_l; int i; char *buf; int buf_i; int j; buf_l = 0; for (i = 0; i < argc; ++i) { buf_l += strlen(argv[i]) + 1; } buf = calloc(buf_l, sizeof(*buf)); if (buf == NULL) { fprintf(stderr, "Failed to allocate buffer: %s\n", strerror(errno)); return NULL; } buf_i = 0; for (i = 0; i < argc; ++i) { for (j = 0; argv[i][j] != '\0'; ++j) { buf[buf_i++] = argv[i][j]; } buf[buf_i++] = ' '; } buf[--buf_i] = '\0'; return buf; } int main(int argc, char * const argv[]) { int opt; char *buf; time_t arg; time_t now; time_t dif; optind = 1; opterr = 0; #if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG while ((opt = getopt_long(argc, argv, "hV", LONGOPTS_, NULL)) > 0) { #else while ((opt = getopt(argc, argv, "hV")) > 0) { #endif switch (opt) { case 'h': _print_help(argv[0]); return EXIT_SUCCESS; case 'V': _print_version(); return EXIT_SUCCESS; default: _print_usage(stderr, argv[0]); #if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG fprintf(stderr, "Try '%s --help' for more " "information.\n", argv[0]); #else fprintf(stderr, "Try '%s -h' for more " "information.\n", argv[0]); #endif return EXIT_FAILURE; } } argc -= optind; argv += optind; buf = _concat_args(argc, argv); if (buf == NULL) { return EXIT_FAILURE; } if (datetime_parse(buf, &arg) < 0) { free(buf); return EXIT_FAILURE; } free(buf); time(&now); dif = arg - now; if (dif >= 1000 * 24 * 60 * 60) { fputs("Date too far in the future\n", stderr); return EXIT_FAILURE; } setvbuf(stdout, NULL, _IONBF, 0); while (arg > now) { printf("\r%03d:%02d:%02d:%02d", (int) dif / 60 / 60 / 24, (int) dif / 60 / 60 % 24, (int) dif / 60 % 60, (int) dif % 60); sleep(1); time(&now); dif = arg - now; } printf("\r000:00:00:00\n"); return EXIT_SUCCESS; }