У каждой программы на языке C должна быть функция по имени main(), с которой и начинается выполнение программы. Когда программа выполняется, к аргументам командной строки (отдельным словам, анализируемым оболочкой) открывается доступ через два аргумента функции main(). Первый аргумент, int argc, показывает, сколько есть аргументов командной строки. Второй аргумент, char *argv[], является массивом указателей на аргументы командной строки, каждый из которых представляет символьную строку, завершающуюся нулевым байтом. Первая из этих строк, argv[0], является (по традиции) именем самой программы. Список указателей в argv завершается указателем со значением NULL (то есть argv[argc] имеет значение NULL).
Поскольку в argv[0] содержится имя, под которым программа была вызвана, это можно использовать для выполнения полезного приема. На одну и ту же программу можно создать несколько ссылок (то есть имен для нее), а затем заставить программу заглянуть в argv[0] и выполнить различные действия в зависимости от имени, используемого для ее вызова. Пример такой технологии предоставляется командами gzip(1), gunzip(1) и zcat(1): в некоторых дистрибутивах это ссылки на один и тот же исполняемый файл. (Применяя эту технологию, нужно быть готовым обработать вызов пользователя программы по ссылке с именем, не входящим в перечень ожидаемых имен.)
На рис. 6.4 продемонстрирован пример структур данных, связанных с argc и argv, при выполнении программы, приведенной в листинге 6.2. На этой схеме завершающие нулевые байты в конце каждой строки показаны с использованием принятой в языке C записи \0.
Рис. 6.4.
Программа в листинге 6.2 повторяет на экране аргументы своей командной строки, выводя каждый из них с новой строки и ставя перед ними строку, показывающую, какой именно по счету элемент argv выводится на экран.
Листинг 6.2. Повторение на экране аргументов командной строки
proc/necho.c
#include "tlpi_hdr.h"
int
main(int argc, char *argv[])
{
int j;
for (j = 0; j < argc; j++)
printf("argv[%d] = %s\n", j, argv[j]);
exit(EXIT_SUCCESS);
}
proc/necho.c
Поскольку список argv завершается значением NULL, для построчного вывода только аргументов командной строки тело программы в листинге 6.2 можно записать по-другому:
char **p;
for (p = argv; *p!= NULL; p++)
puts(*p);
Одно из ограничений механизма, использующего argc и argv, заключается в том, что эти переменные доступны только как аргументы функции main(). Чтобы сделать аргументы командной строки переносимыми и доступными в других функциях, нужно либо передать argv таким функциям в качестве аргумента, либо определить глобальную переменную, указывающую на argv.
Существует два непереносимых способа получения доступа ко всей этой информации или к ее части из любого места программы.
• Аргументы командной строки любого процесса могут быть считаны через характерный для Linux файл /proc/PID/cmdline, в котором каждый аргумент завершается нулевым байтом. (Программа может получить доступ к аргументам своей собственной командной строки через файл /proc/self/cmdline.)
• GNU-библиотека C предоставляет две глобальные переменные, который могут применяться в любом месте программы с целью получения имени, использовавшегося для ее запуска (то есть первого аргумента командной строки). Первая из этих переменных, program_invocation_name, предоставляет полное путевое имя, использованное для запуска программы. Вторая переменная, program_invocation_short_name, обеспечивает версию этого имени без указания каких-либо каталогов (то есть базовую часть путевого имени). Объявления этих двух переменных могут быть получены из