Выбрать главу

/* 19 */ "ENODEV", "ENOTDIR", "EISDIR", "EINVAL", "ENFILE", "EMFILE",

/* 25 */ "ENOTTY", "ETXTBSY", "EFBIG", "ENOSPC", "ESPIPE", "EROFS",

/* 31 */ "EMLINK", "EPIPE", "EDOM", "ERANGE", "EDEADLK/EDEADLOCK",

/* 36 */ "ENAMETOOLONG", "ENOLCK", "ENOSYS", "ENOTEMPTY", "ELOOP", "",

/* 42 */ "ENOMSG", "EIDRM", "ECHRNG", "EL2NSYNC", "EL3HLT", "EL3RST",

/* 48 */ "ELNRNG", "EUNATCH", "ENOCSI", "EL2HLT", "EBADE", "EBADR",

/* 54 */ "EXFULL", "ENOANO", "EBADRQC", "EBADSLT", "", "EBFONT",

"ENOSTR",

/* 61 */ "ENODATA", "ETIME", "ENOSR", "ENONET", "ENOPKG", "EREMOTE",

/* 67 */ "ENOLINK", "EADV", "ESRMNT", "ECOMM", "EPROTO", "EMULTIHOP",

/* 73 */ "EDOTDOT", "EBADMSG", "EOVERFLOW", "ENOTUNIQ", "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", "EPFNOSUPPORT", "EAFNOSUPPORT",

/* 98 */ "EADDRINUSE", "EADDRNOTAVAIL", "ENETDOWN", "ENETUNREACH",

/* 102 */ "ENETRESET", "ECONNABORTED", "ECONNRESET", "ENOBUFS", "EISCONN",

/* 107 */ "ENOTCONN", "ESHUTDOWN", "ETOOMANYREFS", "ETIMEDOUT",

/* 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", "ENOTRECOVERABLE", "ERFKILL"

};

#define MAX_ENAME 132

lib/ename.c.inc

Функции для анализа числовых аргументов командной строки

Заголовочный файл в листинге 3.5 содержит объявление двух функций, часто используемых для анализа целочисленных аргументов командной строки: getInt() и getLong(). Главное преимущество использования этих функций вместо atoi(), atol() и strtol() заключается в том, что они предоставляют основные средства проверки на допустимость числовых аргументов.

#include "tlpi_hdr.h"

int getInt(const char *arg, int flags, const char *name);

long getLong(const char *arg, int flags, const char *name);

Обе возвращают значение arg, преобразованное в число

Функции getInt() и getLong() преобразуют строку, на которую указывает параметр arg, в значение типа int или long соответственно. Если arg не содержит допустимый строковый образ целого числа (то есть не состоит только лишь из цифр и символов + и —), эта функция выводит сообщение об ошибке и завершает выполнение программы.

Если аргумент name не содержит значение NULL, в нем должна находиться строка, идентифицирующая аргумент в параметре arg. Эта строка становится частью любого выводимого этими функциями сообщения об ошибке.

Аргумент flags предоставляет возможность управления работой функций getInt() и getLong(). Изначально они ожидают получения строк, содержащих десятичные целые числа со знаком. Путем логического сложения (|) в аргументе flags нескольких констант вида GN_*, определенных в листинге 3.5, можно выбрать иную основу для преобразования и ограничить диапазон чисел неотрицательными значениями или значениями больше нуля.

Листинг 3.5. Заголовочный файл для get_num.c

lib/get_num.h

#ifndef GET_NUM_H

#define GET_NUM_H

#define GN_NONNEG 01 /* Значение должно быть >= 0 */

#define GN_GT_0 02 /* Значение должно быть > 0 */

/* По умолчанию целые числа являются десятичными */

#define GN_ANY_BASE 0100 /* Можно использовать любое основание –

наподобие strtol(3) */

#define GN_BASE_8 0200 /* Значение выражено в виде восьмеричного числа */

#define GN_BASE_16 0400 /* Значение выражено в виде шестнадцатеричного числа */

long getLong(const char *arg, int flags, const char *name);

int getInt(const char *arg, int flags, const char *name);

#endif

lib/get_num.h

Реализации функций getInt() и getLong() показаны в листинге 3.6.

Хотя аргумент flags позволяет принудительно проверять диапазон допустимых значений, рассмотренный в основном тексте, в некоторых случаях в примерах программ такие проверки не запрашиваются, даже если этот запрос кажется вполне логичным. Отказ от проверки диапазона в подобных случаях позволяет не только проводить эксперименты с правильным использованием системных вызовов и вызовов библиотечных функций, но и наблюдать, что произойдет, если будут предоставлены недопустимые аргументы. В приложениях, созданных для реальной работы, обычно вводятся более строгие проверки аргументов командной строки.

Листинг 3.6. Функции для анализа числовых аргументов командной строки

lib/get_num.c

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <limits.h>

#include <errno.h>

#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;