void cmdLineErr(const char *
Функция fatal() применяется для определения типа ошибок общего характера, включая ошибки библиотечных функций, не устанавливающих значения для errno. У нее точно такой же список аргументов, что и у функции printf(), за исключением того, что к строке вывода автоматически добавляется символ конца строки. Она выдает отформатированный вывод на стандартное устройство вывода ошибки, а затем завершает выполнение программы с помощью errExit().
Функция usageErr() предназначена для определения типов ошибок при использовании аргументов командной строки. Она принимает список аргументов в стиле printf() и выводит строку Usage:, за которой следует отформатированный вывод на стандартное устройство вывода ошибки, после чего она завершает выполнение программы путем вызова exit(). (Некоторые примеры программ в этой книге предоставляют свою собственную расширенную версию функции usageErr() под именем usageError().)
Функция cmdLineErr() похожа на usageErr(), но предназначена для определения типов ошибок в переданных программе аргументах командной строки.
Реализации функций определения типов ошибок показаны в листинге 3.3.
Листинг 3.3. Функции обработки ошибок, используемые всеми программами
lib/error_functions.c
#include
#include "error_functions.h"
#include "tlpi_hdr.h"
#include "ename.c.inc" /* Определяет ename и MAX_ENAME */
#ifdef __GNUC__
__attribute__ ((__noreturn__))
#endif
static void
terminate(Boolean useExit3)
{
char *s;
/* Сохраняет дамп ядра, если переменная среды EF_DUMPCORE определена
и содержит непустую строку; в противном случае вызывает exit(3)
или _exit(2), в зависимости от значения 'useExit3'. */
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); /* При отсутствии построчной буферизации в stderr */
}
void
errMsg(const char *format…)
{
va_list argList;
int savedErrno;
savedErrno = errno; /* В случае ее изменения на следующем участке */
va_start(argList, format);
outputError(TRUE, errno, TRUE, format, argList);
va_end(argList);
errno = savedErrno;
}
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);
fflush(stderr); /* При отсутствии построчной буферизации в stderr */
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); /* При отсутствии построчной буферизации в stderr */
exit(EXIT_FAILURE);
}
lib/error_functions.c
Файл ename.c.inc, подключенный в листинге 3.3, показан в листинге 3.4. В этом файле определен массив строк ename, содержащий символьные имена, соответствующие каждому возможному значению errno. Наши функции обработки ошибок используют этот массив для вывода символьного имени, соответствующего конкретному номеру ошибки. Это выход из ситуации, при которой, с одной стороны, строка, возвращенная strerror(), не идентифицирует символьную константу, соответствующую ее сообщению об ошибке, в то время как, с другой стороны, на страницах руководства дается описание ошибок с использованием их символьных имен. По символьному имени на страницах руководства можно легко найти причину возникновения ошибки.