#define _POSIX_C_SOURCE 199309L #include #include #include #include #include #include #include static volatile sig_atomic_t keepRunning = 1; void restoreCursor(int sig) { (void)sig; printf("\033[?25h\n"); fflush(stdout); exit(0); } // Prints help/usage void printHelp(const char *progName) { printf("Neralie %s\n", VERSION); printf("Usage: %s [OPTION]... [TIME]\n", progName); printf("Convert standard time to Neralie, or run a continuous clock.\n\n"); printf("Options:\n"); printf(" -c, --count run in continuous count mode\n"); printf(" -h, --help display this help and exit\n"); printf(" -v, --version display version information and exit\n\n"); printf("Arguments:\n"); printf(" TIME convert a specific time (formats: HH:MM:SS, HHMMSS, HH:MM, HHMM, HH)\n"); printf(" If omitted, prints the current local time.\n\n"); printf("Examples:\n"); printf(" %s # Print current Neralie time\n", progName); printf(" %s -c # Run live Neralie clock\n", progName); printf(" %s 14:30 # Convert 14:30:00 to Neralie\n", progName); printf(" %s 143000 # Convert 14:30:00 to Neralie\n", progName); } // Converts standard time to Neralie and prints it void printNeralie(int h, int m, int s, long ns) { long ms = (h * 3600 + m * 60 + s) * 1000 + (ns / 1000000); long nera = (ms * 5) / 432; printf("%03ld:%03ld", nera / 1000, nera % 1000); } void prNera(void) { struct timespec ts; struct tm *tm; time_t t; clock_gettime(CLOCK_REALTIME, &ts); t = ts.tv_sec; tm = localtime(&t); printNeralie(tm->tm_hour, tm->tm_min, tm->tm_sec, ts.tv_nsec); } void countMode(void) { struct timespec req = {0, 86400000}; printf("\033[?25l"); signal(SIGINT, restoreCursor); signal(SIGTERM, restoreCursor); while (keepRunning) { printf("\r"); prNera(); fflush(stdout); nanosleep(&req, NULL); } restoreCursor(0); } void parseAndConvert(const char *input) { int h = 0, m = 0, s = 0; char clean[32]; int j = 0; for (int i = 0; input[i] != '\0'; i++) { if (!isspace((unsigned char)input[i])) { if (j < (int)sizeof(clean) - 1) { clean[j++] = input[i]; } } } clean[j] = '\0'; if (strchr(clean, ':') != NULL) { int count = sscanf(clean, "%d:%d:%d", &h, &m, &s); if (count == 2) { s = 0; } } else { int len = strlen(clean); switch (len) { case 6: sscanf(clean, "%2d%2d%2d", &h, &m, &s); break; case 5: sscanf(clean, "%1d%2d%2d", &h, &m, &s); break; case 4: sscanf(clean, "%2d%2d", &h, &m); break; case 3: sscanf(clean, "%1d%2d", &h, &m); break; case 2: sscanf(clean, "%2d", &h); break; case 1: sscanf(clean, "%1d", &h); break; default: fprintf(stderr, "Error: Invalid time format. Use HH:MM[:SS] or HHMM[SS].\n"); exit(EX_USAGE); } } if (h < 0 || h > 23 || m < 0 || m > 59 || s < 0 || s > 59) { fprintf(stderr, "Error: Invalid time values (Expected 00-23 for hours, 00-59 for min/sec).\n"); exit(EX_DATAERR); } printNeralie(h, m, s, 0); printf("\n"); } int main(int argc, char *argv[]) { if (argc > 1) { for (int i = 1; i < argc; i++) { if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) { printHelp(argv[0]); return 0; } if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--version") == 0) { printf("Neralie %s\n", VERSION); return 0; } } int countRequested = 0; if (argv[1][0] == '-' && argv[1][1] != '-') { for (int j = 1; argv[1][j] != '\0'; j++) { if (argv[1][j] == 'c') countRequested = 1; } } else if (strcmp(argv[1], "--count") == 0) { countRequested = 1; } if (countRequested) { countMode(); } else if (argv[1][0] != '-') { parseAndConvert(argv[1]); } else { fprintf(stderr, "Error: Unknown argument '%s'\n", argv[1]); exit(EX_USAGE); } } else { prNera(); printf("\n"); } return 0; }