/* See LICENSE file for copyright and license details. */ #include #include #include #include #include #include NUSAGE(2, "number ..."); #if defined(__GNUC__) __attribute__((__pure__)) #endif static int check_luhn(const char *s) { unsigned sum = 0; switch (strlen(s) & 1U) { for (;;) { case 0: if ('0' <= *s && *s <= '4') sum += 2U * (unsigned)(*s - '0'); else if ('5' <= *s && *s <= '9') sum += 2U * (unsigned)(*s - '0') - 9U; else if (*s) return 0; else break; s++; /* fall through */ case 1: if ('0' <= *s && *s <= '9') sum += (unsigned)(*s - '0'); else if (*s) return 0; else break; s++; sum %= 10U; } } return (sum % 10U) == 0U; } int main(int argc, char *argv[]) { int use_colour; int ret = 0; int r, ok; ARGBEGIN { default: usage(); } ARGEND; if (!argc) usage(); use_colour = isatty(STDOUT_FILENO); for (; *argv; argv++) { ok = check_luhn(*argv); ret |= !ok; r = printf("%s%s %s%s\n", use_colour ? ok ? "\033[1;32m" : "\033[1;31m" : "", *argv, ok ? "is OK" : "is invalid", use_colour ? "\033[m" : ""); if (r < 0) { fprintf(stderr, "%s: printf: %s\n", argv0, strerror(errno)); exit(2); } } if (fflush(stdout) || fclose(stdout)) { fprintf(stderr, "%s: printf: %s\n", argv0, strerror(errno)); exit(2); } return ret; }