Прототип этой функции показан ниже.
int globerr(const char * pathname, int globerrno);
Функции передается путевое имя, вызвавшее ошибку, и значение errno
, возвращенное одним из системных вызовов opendir()
, readdir()
или stat()
. Если функция ошибки возвращает величину больше нуля, glob()
возвращается с ошибкой. В противном случае операция универсализации продолжается.
Результаты универсализации хранятся в структуре glob_t
, на которую ссылается pglob
. Она включает описанные ниже элементы, позволяющие абоненту найти согласованные имена файлов.
gl_pathc |
Количество путевых имен, соответствующих шаблону. |
gl_pathv |
Массив путевых имен, соответствующих шаблону. |
После использования возвращенного результата glob_t
занимаемую им память следует освободить, передав его в globfree()
.
void globfree(glob_t * pglob);
Системный вызов glob()
возвращает GLOB_NOSPACE
в случае нехватки памяти, GLOB_ABEND
, если ошибка чтения привела к неудачному выполнению функции, GLOB_NOMATCH
, если соответствия не были найдены, или 0
, если функция выполнилась удачно и нашла соответствия.
Для иллюстрации работы glob()
ниже приведена программа globit
, которая принимает множество шаблонов в качестве аргументов, универсализирует их и отображает результат. В случае ошибки отображается сообщение, описывающее ошибку, а операция универсализации продолжается.
1: /* globit.с */
2:
3: #include
4: #include
5: #include
6: #include
7: #include
8:
9: /* Это функция ошибки, которая передается в glob(). Она просто отображает
10: сообщение об ошибке и возвращает состояние успеха, что позволяет glob()
11: продолжить работу. */
12: int errfn(const char * pathname, int theerr) {
13: fprintf(stderr, "ошибка при доступе к %s: %s\n", pathname,
14: strerror(theerr));
15:
16: /* Операция универсализации должна продолжаться, поэтому вернуть 0 */
17: return 0;
18: }
19:
20: int main(int argc, const char ** argv) {
21: glob_t result;
22: int i, rc, flags;
23:
24: if (argc < 2) {
25: printf("необходимо передать хотя бы один аргумент\n") ;
26: return 1;
27: }
28:
29: /* установить flags в 0; позже он будет изменен на GLOB_APPEND */
30: flags = 0;
31:
32: /* совершить проход по всем аргументам командной строки */
33: for (i = 1; i < argc; i++) {
34: rc = glob(argv[i], flags, errfn, &result);
35:
36: /* благодаря errfn, GLOB_ABEND не происходит */
37: if (rc == GLOB_NOSPACE) {
38: fprintf(stderr, "не хватает памяти для выполнения универсализации\n");
39: return 1;
40: }
41:
42: flags |= GLOB_APPEND;
43: }
44:
45: if (!result.gl_pathc) {
46: fprintf(stderr, "соответствий нет\n");
47: rc = 1;
48: } else {
49: for (i = 0; i < result.gl_pathc; i++)
50: puts(result.gl_pathv[i]);
51: rc = 0;
52: }
53:
54: /* структура glob_t занимает память из пула malloc(),
55: которая должна быть освобождена */
56: globfree(&result);
57:
58: return rc;
59: }
14.6. Добавление к ladsh
возможностей работы с каталогами и универсализацией
Продолжим эволюцию ladsh
, добавив к ladsh3.с
четыре новых возможности.
1. Встроенная команда cd
для смены каталогов.
2. Встроенная команда pwd
для отображения текущего каталога.
3. Универсализация файловых имен.
4. Отображение ряда новых сообщений, позволяющее воспользоваться преимуществами strsignal()
. Эти изменения обсуждались в главе 12.
14.6.1. Добавление встроенных команд cd
и pwd
Добавление встроенных команд является прямым применением вызовов chdir()
и getcwd()
. Код соответствует runProgram()
как раз там, где обрабатываются другие встроенные команды. Ниже показан раздел обработки встроенных команд в ladsh3.с
.
422: if (!strcmp(newJob.progs[0].argv[0], "exit")) {
423: /* здесь должен возвращаться реальный код завершения */
424: exit(0);
425: } else if (!strcmp(newJob.progs[0].argv[0], "pwd")) {
426: len = 50;
427: buf = malloc(len);
428: while (!getcwd(buf, len) && errno == ERANGE) {
429: len += 50;
430: buf = realloc(buf, len);
431: }
432: printf("%s\n", buf);
433: free(buf);
434: return 0;
435: } else if (!strcmp(newJob.progs[0].argv[0], "cd")) {
436: if (!new Job.progs[0].argv[1] == 1)
437: newdir = getenv("HOME");
Читать дальше