../../03-memory.texi
...
Обратите внимание, что нам пришлось взять аргументы в кавычки, чтобы предотвратить их разворачивание оболочкой!
Универсализация имен? Что это?
В былые времена, около V6 Unix, для осуществления разворачивания символов подстановки оболочка использовала за кулисами отдельную программу. Эта программа называлась
/etc/glob
, и согласно исходному коду V6
[130], имя «glob» было сокращением от «global».
Таким образом глагол «to glob» проник в лексикон Unix со значением «осуществлять разворачивание символов подстановки». Это, в свою очередь, дает нам имена функций
glob()
и
globfree()
. Так что обычно недооцениваемое чувство юмора, время от времени проглядывающее из руководства Unix, все еще живо, официально сохраненное в стандарте POSIX. (Можете ли вы представить кого-нибудь в IBM в 70-х или 80-х годах XX века, называющего системную процедуру
glob()
?)
12.7.3. Разворачивание слов оболочкой:
wordexp()
и wordfree()
Многие члены комитета POSIX чувствовали, что
glob()
делает недостаточно: им нужна была библиотечная процедура, способная делать все, что может делать оболочка разворачивание тильды ('
echo ~arnold
'), разворачивание переменных оболочки ('
echo $HOME
') и подстановку команд ('
echo $(cd ; pwd)
'). Многие другие чувствовали, что
glob()
не подходила для этой цели. Чтобы «удовлетворить» каждого, POSIX предоставляет две дополнительные функции, которые делают все:
#include <wordexp.h> /* POSIX */
int wordexp(const char *words, wordexp_t *pwordexp, int flags);
void wordfree(wordexp_t *wordexp);
Эти функции работают сходным с
glob()
и
globfree()
образом, но со структурой
wordexp_t
:
typedef struct {
size_t we_wordc; /* Число подходящих слов */
char **we_wordv; /* Список развернутых слов */
size_t we_offs; /* Резервируемые в we_wordv слоты */
} wordexp_t;
Члены структуры полностью аналогичны описанным ранее для
glob_t
; мы не будем здесь повторять все описание.
Как и для
glob()
, поведение
wordexp()
управляется несколькими флагами. Флаги перечислены в табл. 12.5.
Таблица 12.5. Флаги для
wordexp()
Константа | Значение |
WRDE_APPEND
| Добавить результаты текущего вызова к предыдущим |
WRDE_DOOFFS
| Зарезервировать we_offs мест в начале we_wordv
|
WRDE_NOCMD
| Запретить подстановку команд |
WRDE_REUSE
| Повторно использовать память, на которую указывает we_wordv
|
WRDE_SHOWERR
| Не молчать при возникновении во время разворачивания ошибок |
WRDE_UNDEF
| Неопределенные переменные оболочки должны вызывать ошибку |
Возвращаемое значение равно 0, если все прошло хорошо, или одно из значений из табл. 12.6, если нет.
Таблица 12.6. Возвращаемые значения ошибок для
wordexp()
Константа | Значение |
WRDE_BADCHAR
| Метасимвол (конец строки, '|', &, ;, <, >, (, ), {, или }) в недопустимом месте |
WRDE_BADVAL
| Переменная не определена при установленном WRDE_UNDEF
|
WRDE_CMDSUB
| Попытка подстановки команды при установленном WRDE_NOCMD
|
WRDE_NOSPACE
| Была проблема с выделением динамической памяти |
WRDE_SYNTAX
| Синтаксическая ошибка оболочки. |
Мы оставляем вам в качестве упражнения (см. далее) модификацию
ch12-glob.c
для использования
wordexp()
и
wordfree()
. Вот наша версия в действии:
$ <b>ch12-wordexp</b> 'echo $HOME' /* Развертывание переменных оболочки */
echo
/home/arnold
$ <b>ch12-wordexp 'echo $HOME/*.gz'</b> /* Переменные и символы подстановки */
echo
/home/arnold/48000.wav.gz
/home/arnold/ipmasq-HOWTO.tar.gz
/home/arnold/rc.firewall-examples.tar.gz
$ <b>ch12-wordexp 'echo ~arnold'</b> /* Развертывание тильды */
echo
/home/arnold
$ <b>ch12-wordexp 'echo ~arnold/.p*'</b> /* Тильда и символы подстановки */
echo
/home/arnold/.postitnotes
/home/arnold/.procmailrc
/home/arnold/.profile
$ <b>ch12-wordexp "echo '~arnold/.p*'"</b> /* Кавычки работают */