/**
* @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 */