作为linux的菜鸟,最近在看《Linux/Uinx系统编程手册》,不得不说这是本很好很好的书。今天整理了一下在本书上册开始部分给出的错误处理函数如下,希望对大家有所帮助:
//tlpi_hdr.h
#ifndef TPLI_HDR_H
#define TPLI_HDR_H /*Prevent accidental double inclusion*/
#include <sys/types.h> /*Type definitionos used by many programs*/
#include <stdio.h> /*Standard I/O function*/
#include <stdlib.h> /**Prototypes of commonly used library functions, plus EXIT_SUCCESS and EXIT_FAILURE constants*/
#include <unistd.h> /*Prototypes for many system calls*/
#include <errno.h> /*Declares errno and defines error constants*/
#include <string.h> /*Commonly used string-handing functions*/
#include "get_num.h" /*Declares our functions for handing numeric arguments (getInt(), getLong())*/
#include "error_functions.h" /*Declars our error-handing functions*/
typedef enum {
FALSE,
TRUE
}Boolean;
#define min(m, n) ((m) < (n) ? (m) : (n))
#define max(m, n) ((m) > (n) ? (m) : (n))
#endif
//error_functions.h
#ifndef ERROR_FUNCTIONS
#define ERROR_FUNCTIONS
void errMsg(const char *format, ...);
#ifdef _GNUC_
#define NORETURN _attribute_ ((_noreturn))
#else
#define NORETURN
#endif
void errExit(const char *format, ...) NORETURN;
void err_exit(const char *format, ...) NORETURN;
void errExitEN(int errnum, const char *format, ...) NORETURN;
void fatal(const char *format, ...) NORETURN;
void usageErr(const char *format, ...) NORETURN;
void cmdLineErr(const char *format, ...) NORETURN;
#endif
//error_functions.c
#include
#include "error_functions.h"
#include "tlpi_hdr.h"
#include "ename.c.inc"
#ifdef _GNUC_
_attribute_((_noreturn_))
#endif
static void
terminate(Boolean useExit3) {
char *s;
s = getenv("EF_DUMPCORE");
if (s != NULL && *s != '\0') {
abort();
}
else if (useExit3) {
exit(EXIT_FAILURE);
}
else {
_exit(EXIT_FAILURE);
}
}
static void
outputError(Boolean useErr, int err, Boolean flushStdout,
const char *format, va_list ap) {
#define BUF_SIZE 500
char buf[BUF_SIZE], userMsg[BUF_SIZE], errText[BUF_SIZE];
vsnprintf(userMsg, BUF_SIZE, format, ap);
if (useErr) {
snprintf(errText, BUF_SIZE, " [%s %s]",
(err > 0 && err <= MAX_ENAME) ?
ename[err] : "?UNKNOWN?", strerror(err));
}
else {
snprintf(errText, BUF_SIZE, ":");
}
snprintf(buf, BUF_SIZE, "ERROR%s %s\n", errText, userMsg);
if (flushStdout) {
fflush(stdout);
}
fputs(buf, stderr);
fflush(stderr);
}
void errMsg(const char*format, ...) {
va_list argList;
int saveErrno;
saveErrno = errno;
va_start(argList, format);
outputError(TRUE, errno, TRUE, format, argList);
va_end(argList);
errno = saveErrno;
}
void
errExit(const char *format, ...) {
va_list argList;
va_start(argList, format);
outputError(TRUE, errno, TRUE, format, argList);
va_end(argList);
terminate(TRUE);
}
void
err_exit(const char *format, ...) {
va_list argList;
va_start(argList, format);
outputError(TRUE, errno, FALSE, format, argList);
va_end(argList);
terminate(FALSE);
}
void
errExitEN(int errnum, const char *format, ...) {
va_list argList;
va_start(argList, format);
outputError(TRUE, errnum, TRUE, format, argList);
va_end(argList);
terminate(TRUE);
}
void
fatal(const char *format, ...) {
va_list argList;
va_start(argList, format);
outputError(FALSE, 0, TRUE, format, argList);
va_end(argList);
terminate(TRUE);
}
void
usageErr(const char *format, ...) {
va_list argList;
fflush(stdout);
fprintf(stderr, "Usage:");
va_start(argList, format);
vfprintf(stderr, format, argList);
va_end(argList);
exit(EXIT_FAILURE);
}
void
cmdLineErr(const char *format, ...) {
va_list argList;
fflush(stdout);
fprintf(stderr, "Command-line usage error:");
va_start(argList, format);
vfprintf(stderr, format, argList);
va_end(argList);
fflush(stderr);
exit(EXIT_FAILURE);
}
//get_num.h
#ifndef GET_NUM_H
#define GET_NUM_H
#define GN_NONNEG 01 /*Value mustmust be > 0*/
#define GN_GT_0 02 /*Value*/
#define GN_ANY_BASE 0100 /*By default, integers are decimal*/
#define GN_BASE_8 0200 /*Can use any base - like strtol(3)*/
#define GN_BASE_16 0400 /*Value is expressed in octal*/
long getLong(const char *arg, int flags, const char *name);
int getInt(const char *arg, int flags, const char *name);
#endif
//get_num.c
#include
#include
#include
#include
#include
#include "get_num.h"
static void
gnFail(const char *fname, const char *msg, const char *arg, const char *name) {
fprintf(stderr, "%s error", fname);
if (name != NULL) {
fprintf(stderr, "(in %s)", name);
}
fprintf(stderr, ": %s\n", msg);
if (arg != NULL && *arg != '\0') {
fprintf(stderr, " offending text :%s\n", arg);
}
exit(EXIT_FAILURE);
}
static long
getNum(const char *fname, const char *arg, int flags, const char *name) {
long res;
char *endptr;
int base;
if (arg == NULL || *arg == '\0') {
gnFail(fname, "null or empty string", arg, name);
}
base = (flags & GN_ANY_BASE) ? 0 : (flags & GN_BASE_8) ? 8:
(flags & GN_BASE_16) ? 16 : 10;
errno = 0;
res = strtol(arg, &endptr, base);
if (errno != 0) {
gnFail(fname, "strtol() failed", arg, name);
}
if (*endptr != '\0') {
gnFail(fname, "nonnumeric characters", arg, name);
}
if (flags & GN_NONNEG && res < 0) {
gnFail(fname, "negative value not allowed", arg, name);
}
if ((flags & GN_GT_0) && res <= 0) {
gnFail(fname, "value must be > 0", arg, name);
}
return res;
}
long
getLong(const char *arg, int flags, const char *name) {
return getNum("getLong", arg, flags, name);
}
int
getInt(const char *arg, int flags, const char *name) {
long res;
res = getNum("getInt", arg, flags, name);
if (res > INT_MAX || res < INT_MIN) {
gnFail("getInt", "integer out of range", arg, name);
}
return (int)res;
}
//ename.c.inc
static char *ename[] = {
/* 0*/ "",
/* 1*/ "EPERM", "ENOENT", "ESRCH", "EINTR", "EIO", "ENXIO", "E2BIG",
/* 8*/ "ENOEXEC", "EBADF", "ECHILD", "EAGAIN/EWOULDBLOCK", "ENOMEM",
/* 13*/ "EACCES", "EFAULT", "ENOTBLK", "EBUSY", "EEXIT", "EXDEV",
/* 19*/ "ENODEV", "ENOTDIR", "EISDIR", "EINVAL", "ENFILE", "EMFILE",
/* 25*/ "ENOTTY", "ERXTBSY", "EFBIG", "ENOSPC", "ESPIPE", "EROFS",
/* 31*/ "EMLINK", "EPIPE", "EDOM", "ERANG", "EDEADLK/EDEADLOCK",
/* 36*/ "ENAMETOOLONG", "ENOLCK", "ENOSYS", "ENOTEMPTY", "ELOOP",
/* 42*/ "ENOMSG", "EIDRM", "ECHRNG", "EL2NSYNC", "EL3HLT", "EL3RST",
/* 48*/ "ELNTNG", "EUNATCH", "ENOCSI", "EL2HLT", "EBADE", "EBADR",
/* 54*/ "EXFULL", "ENOANO", "EBASRQC", "EBADSLT", "", "EBFONT", "ENOSTR",
/* 61*/ "ENODATA", "ETIME", "ENOSR", "ENONET", "ENOPKG", "EREMOTE",
/* 67*/ "ENOLINK", "EADV", "ESRMNT", "ECOMM", "EPROTO", "EMULTIHOP",
/* 73*/ "EDOTDOT", "EBADMSG", "EOVERFLOW", "ENOTUNIO", "EBADFD",
/* 78*/ "EREMCHG", "ELIBACC", "ELIBBAD", "ELIBSCN", "ELIBMAX",
/* 83*/ "ELIBEXEC", "EILSEQ", "ERESTART", "ESTRPIPE", "EUSERS",
/* 88*/ "ENOTSOCK", "EDESTADDRREQ", "EMSGSIZE", "EPROTOTYPE",
/* 92*/ "ENOPROTOOPT", "EPROTONOSUPPORT", "ESOCKTNOSUPPORT",
/* 95*/ "EOPNOTSUPP/ENOTSUP", "EPFNSUPPORT", "EAFNOSUPPORT",
/* 98*/ "EADDRINUSE", "EADDRNOTAVAIL", "ENETDOWN", "ENETUNREACH",
/*102*/ "ENETRESET", "ECONNABORTED", "ECONNREACH", "ENOBUFS", "EISCONN",
/*107*/ "ENOTCONN", "ESHUTDOWN", "ETOOMANYREFS", "ETIMEOUT",
/*111*/ "ECONNREFUSED", "EHOSTDOWN", "EHOSTUNREACH", "EALREADY",
/*115*/ "EINPROGRESS", "ESTALE", "EUCLEAN", "ENOTNAM", "ENAVAIL",
/*120*/ "EISNAM", "EREMOTEIO", "EDQUOT", "ENOMEDIUM", "EMEDIUMTYPE",
/*125*/ "ECANCELED", "ENOKEY", "EKEYEXPIRED", "EKEYREVOKED",
/*129*/ "EKEYREJECTED", "EOWNERDEAD", "ENOTRCOVERABLE", "ERFKILL"
};
#define MAX_ENAME 132