/** * @file errno.c * * Time-stamp: "2011-08-02 14:04:06 bkorb" * * Print out error numbers and meanings * * Copyright (c) 2002-2011 Bruce Korb - all rights reserved * * errno 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. * * errno 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 this program. If not, see . */ #include #include #include #include #include #include #include "err-names.h" static char const usage_text[] = "USAGE: errno [...]\n" "For each argument, the program will find the error(s) that match\n" "the name, error number or description pattern and print a line:\n" " nnn (ENAME. . . . . ) == Description\n" "where 'nnn' is the numerical number, 'ENAME' is the #defined name,\n" "and 'Description' may be plain text or a regular expression.\n"; #ifndef NUL #define NUL '\0' #endif /** * Print usage and exit. This is always a success procedure because * all command line arguments are presumed to be an error number * search expression. This is only called when no arguments are provided. */ static void usage(void) { fwrite(usage_text, sizeof(usage_text) - 1, 1, stdout); exit(EXIT_SUCCESS); } /** * parse a number. If there is any problem with the number, return -1. * The entire input string must be consumed. If it looks like a number, * but is not a valid errno number, "print_errno()" will catch it and * return "false" to its caller. * * @param arg input string * @returns -1 or the number indicated by the string */ static int parse_errno(char const * arg) { errno = 0; char * end; unsigned long val = strtoul(arg, &end, 0); if ((errno != 0) || (*end != NUL)) return -1; return (int)val; } /** * print the error number, name and description. * The error number must be in the error name table. * * @param err the error number * @param desc the error description * @returns false if the error number is invalid, otherwise true. */ static bool print_errno(int err, char const * desc) { if ((unsigned)err >= ERRNO_LIMIT) return false; char const * name = errno_names[err]; if (name == NULL) return false; char buf[1024]; int len = snprintf(buf, sizeof(buf), show_fmt, err, name, desc); char * ps = strchr(buf, '('); char * pe = strchr(ps, ')'); if ((ps != NULL) && (pe != NULL)) { for (;;) { ps += 2; if (ps >= pe) break; if (*ps == ' ') *ps = '.'; } } fwrite(buf, len, 1, stdout); return true; } static int re_find_err(regex_t * re) { int find_ct = 0; for (int err = 1; err < 255; err++) { char const * errstr = strerror(err); if (regexec(re, errstr, 0, NULL, 0) == 0) { find_ct++; print_errno(err, errstr); } } return find_ct; } static int print_by_name(char const * ename) { for (int idx = 1; idx < ERRNO_LIMIT; idx++) { char const * name = errno_names[idx]; if ((name != NULL) && (strcmp(ename, name) == 0)) { char const * txt = strerror(idx); print_errno(idx, txt); return EXIT_SUCCESS; } } fprintf(stderr, "no error is named '%s'\n", ename); return EXIT_FAILURE; } static int find_errno(char const * arg) { static char const not_name_chars[] = " \t.,;/abcdefghijklmnopqrstuvwxyz"; if ((*arg == 'E') && (strpbrk(arg, not_name_chars) == NULL)) return print_by_name(arg); regex_t re; int err = regcomp(&re, arg, 0); int match_ct = 0; printf("looking for matches to: '%s'\n", arg); if (err == 0) { match_ct = re_find_err(&re); regfree(&re); } else { for (err = 1; err < 255; err++) { char const * errstr = strerror(err); if (strstr(errstr, arg) != NULL) { match_ct++; print_errno(err, errstr); } } } if (match_ct == 0) { fprintf(stderr, "no error descriptions match '%s'\n\n", arg); return EXIT_FAILURE; } putc('\n', stdout); return EXIT_SUCCESS; } int main(int argc, char ** argv) { int res = EXIT_SUCCESS; if (argc <= 1) usage(); while (--argc > 0) { char * arg = *++argv; int err = parse_errno(arg); if (err < 0) res |= find_errno(arg); else if (! print_errno(err, strerror(err))) { res |= EXIT_FAILURE; fprintf(stderr, "error number %d is invalid\n", err); } } return res; } /* * Local Variables: * mode: C * c-file-style: "stroustrup" * indent-tabs-mode: nil * End: * end of agen5/autogen.c */