Троан Эрик В.
Шрифт:
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++;