Чтение онлайн

ЖАНРЫ

Разработка приложений в среде Linux. Второе издание

Троан Эрик В.

Шрифт:

330: src++;

331: if (!*src) {

332: freeJob(job);

333: fprintf(stderr, "после \\ ожидался символ\n");

334: return 1;

335: }

336: if (* src == '*' || *srс == '[' | | *src == ']'

337: || *srс == '?')

338: *buf++ = '\\';

339: /* сквозная обработка */

340: default:

341: *buf++ = *src;

Для

заключения знаков универсализации в кавычки здесь был добавлен тот же самый код.

Эти две кодовые последовательности обеспечивают передачу каждого аргумента в

glob
без поиска неожиданных совпадений.

Теперь добавим функцию

globLastArgument
, которая универсализирует самый последний аргумент для дочерней программы и замещает его любым найденным совпадением.

Для облегчения управления памяти к

struct childProgram
добавляется элемент
globResult
типа
glob_t
, используемый для хранения результатов всех операций универсализации. Кроме того, добавляется целочисленный элемент
freeGlob
, не равный нулю, если
freeJob
должна освободить
globResult
. Ниже показано полное описание
struct childProgram
в
ladsh3.c
.

35: struct childProgram {

36: pid; /* 0, если завершена */

37: char ** argv; /* имя и аргументы программы */

38: int numRedirections; /* элементы в массиве перенаправлений */

39: struct redirection Specifier * redirections; /* перенаправления ввода-вывода */

40: glob_t globResult; /* результат универсализации параметров */

41: int freeGlob; /* нужно ли освобождать globResult? */

42: };

Во время первого запуска для командной строки функция

globLastArgument
(когда
argc
для текущей дочерней оболочки равно 1) инициализирует
globResult
. Для остальных аргументов она пользуется преимуществом
GLOB_APPEND
для добавления новых совпадений к существующим. Это избавляет от необходимости распределения собственной памяти для целей универсализации, поскольку одиночный
glob_t
при необходимости автоматически расширяется.

Если

globLastArgument
не находит совпадений, символы
\
с кавычками удаляются из аргумента. В противном случае все новые совпадения копируются в список аргументов, создаваемый для дочерней программы.

Ниже приведена полная реализация

globLastArgument
. Все сложные ее части относятся к управлению памятью; фактическая универсализация похожа на реализованную в программе
globit.с
, которая представлена ранее в главе.

 87: void globLastArgument(struct childProgram * prog, int * argcPtr,

 88: int * argcAllocedPtr) {

 89: int argc = *argcPtr;

 90: int argcAlloced = *argcAllocedPtr;

 91: int rc;

 92: int flags;

 93: int i;

 94: char * src, * dst;

 95:

 96: if (argc >1) {/* cmd->globResult
уже инициализирован */

 97: flags = GLOB_APPEND;

 98: i = prog->globResult.gl_pathc;

 99: } else {

100: prog->freeGlob = 1;

101: flags = 0;

102: i = 0;

103: }

104:

105: rc = glob(prog->argv[argc - 1], flags, NULL, &prog->globResult);

106: if (rc == GLOB_NOSPACE) {

107: fprintf (stderr, "не хватает памяти для выполнения универсализации\n");

108: return;

109: } else if (rc == GLOB_NOMATCH ||

110: (!rc && (prog->globResult.gl_path - i) == 1 &&

111: !strcmp(prog->argv[argc - 1],

112: prog->globResult.gl_pathv[i]))) {

113: /* необходимо удалить кавычки в \, если они все еще присутствуют */

114: src = dst = prog->argv[argc - 1];

115: while (*src) {

116: if (*src ! = '\\') *dst++ = *src;

117: src++;

118: }

119: *dst = '\0';

120: } else if (!rc) {

121: argcAlloced += (prog->globResult.gl_pathc - i);

122: prog->argv = realloc(prog->argv,

123: argcAlloced * sizeof(*prog->argv));

124: memcpy(prog->argv + (argc - 1),

125: prog->globResult.gl_pathv + i,

126: sizeof(*(prog->argv)) *

127: (prog->globResult.gl_pathc - i));

128: argc += (prog->globResult.gl_pathc - i - 1);

129: }

130:

131: *argcAllocedPtr = argcAlloced;

132: *argcPtr = argc;

133: }

Последними изменениями касаются вызовов

globLastArgument
, которые должны совершаться после синтаксического разбора нового аргумента. Вызовы добавляются в двух местах: когда за пределами строки в кавычках найдены пробелы и когда вся командная строка разобрана. Оба вызова выглядят следующим образом:

globLastArgument(prog, &argc, &argvAlloced);

Полный код

ladsh3.с
доступен на Web-сайте издательства, а также на сайте, посвященном книге.

14.7. Обход деревьев файловых систем

Существуют две функции, которые облегчают приложениям просмотр всех файлов каталога, включая файлы в подкаталогах. Рекурсивный просмотр всех элементов древовидной структуры (например, файловой системы) часто называется обходом (walk) дерева и он реализуется функциями

ftw
и
nftw
.
nftw
представляет собой усовершенствованную версию
ftw
.

Поделиться с друзьями: