Получение информации о паролях и группах
Информация о вашем пользовательском имени и идентификаторе, кото-рая имеется в системе UNIX, практически открыта. По сути дела, любая программа, которая не сочтет за труд заглянуть в файл /etc/passwd,
поможет вам увидеть почти все, кроме незашифрованного пароля. Зтот файл имеет особый формат, определяемый в passwd(5),
и выглядит приблизительно так:
name:pa3swd:uid:gid:gcos:dir:shell
Поля определены следующим образом:
name
Регистрационное имя пользователя
passwd
Зашифрованими пароль или что-нибудь простое, если используется теневой файл паролей
uid
Идентификатор пользователя (для пользователя root — 0, для обычных пользователей — ненулевое число)
gid
Регистрационная группа по умолчанию (группа 0 может быть привиле-гированной, но не обязательно)
gcos
Как правило, содержит полное имя пользователя, за которым через запятую следует и другая информация
dir
Начальний каталог (каталог, в который вы переходите, когда даєте команду cd без аргументов, и в котором хранится большинство ваших файлов, имена которых начинаются с точки)
shell
Ваш регистрационный shell, как правило, /bin/sh
или /Ып/csh (а, может быть, даже /usr/bin/perl,
если вы большой оригинал)
Типичные злементы файла паролей выглядят так:
fred:*:123:15:Fred Flintstone,,,:/home/fred:/bin/csh barney:*:125:15:Barney Rubble,,,:/home/barney:/bin/csh
Сейчас в Perl достаточно инструментов для того, чтобы можно было легко выполнить разбор такой строки (например, с помощью функции split), не прибегая к специальным программам. Тем не менее в библиотеке UNIX все же єсть набор специальных программ: getpwent(3), getpwuid(3), gelpwnam(3) и т.д. Зти программы доступны в Perl под теми же именами, с похожими аргументами и возвращаемыми значеннями.
Например, программа getpwnam в Perl становится функцией getpwnam. Ее единственный аргумент — пользовательское имя (например, fred или barney), а возвращаемое значение — строка файла /etc/passwd, преобра-зованная в массив со следующими значеннями:
($name, $passwd, $uid, $gid, $quota, $cominent, $gcos, $dir, $shell)
Обратите внимание: здесь несколько больше значений, чем в файле паролей. Обычно в UNIX-системах, по крайней мере в тех, которые мы видели, поле $quota всегда пусто, а поля $comment и $gcos часто оба содержат персональную информацию о пользователе (поле GCOS). Так, для старины Фреда мы получаем
("fred", "*", 123, 15, "", "Fred Flintstone,,,", "Fred Flintstone,,,", "/home/gred"," /bin/csh")
посредством любого из следующих вызовов:
getpwuid(123) getpwnam("fred")
Отметим, что в качестве аргумента функция getpwuid принимает иден-тификатор пользователя, a getpwnam — регистрационное имя.
При вьгзове в скалярном контексте функции getpwnam и getpwuid таюке имеют возвращаемое значение — данные, которые вы запросили с их помощью. Например:
$idnum = getpwuid("daemon");
$login °= getpwnam (25);
Возможно, вам захочется получить зти результаты по отдельности, ис-пользуя некоторые из уже знакомых вам операций, проводимых над списками. Один способ — получить часть списка, используя для зтого срез списка, например получить для Фреда только начальний каталог:
($fred home) = (getpwnam ("fred"))[7]; # начальний каталог Фреда
Как просмотреть весь файл паролей? Для зтого можно бьгло бн поступить, к примеру, так:
for($id = 0; $id <= 10_000; $id++) f @stuff = getpwuid $id;
} ### не рекомендуется!
Зто, однако, неверный путь. Наличие нескольких способов само по себе еще не означает, что все они в равной степени зффективны.
Функции getpwuid и getpwnam можно считать функциями произволь-ного доступа; они извлекают конкретний злемент по его ключу, позтому для начала у вас должен быть ключ. Другой метод доступа к файлу паролей — последовательный, т.е. поочередное получение его записей.
Программами последовательного доступа к файлу паролей являются функции setpwent, getpwent и endpwent. В совокупности зти три функции выполняют последовательный проход по всем записям файла паролей. Функция setpwent инициализирует просмотр. После инициализации каж-дый вызов getpwent возвращает следующую запись файла паролей. Если данных для обработки больше нет, getpwent возвращает пустой список. Наконец, вызов endpwent освобождает ресурсы, используемне программой просмотра; зто делается автоматически и при выходе из программы.
Приведенное описание может сказаться не совсем понятным без приме-ра, позтому дадим его:
setpwent (); # инициализировать просмотр while (@list " getpwent ()) ( # выбрать следующий злемент
($login,$home) = @list[0,7]; # получить регистрационное имя # и начальний каталог
print "Home directory for $login is $home\n"; # сообщить зто } endpwent(); # все сделано
Зта программа сообщает имена начальних каталогов всех пользователей, перечисленные в файле паролей. А если вы хотите расставить начальные каталоги в алфавитном порядке? В предыдущей главе мы изучили функцию sort, давайте воспользуемся ею:
setpwentf); # инициализировать просмотр while (@list = getpwentO) ( # вибрать следующий злемент
($login,$home) = @list[0,7]; # долучить регистрационное имя # и начальний каталог
$home($login} = $home; # сохранить их )
endpwent(); # все сделано Skeys = sort ( $home($a( cmp $home($b) } keys %home;
foreach $login (Skeys) ( # пройти по рассортированньпл именам
print "home of $login is $home($login)\n";
}
Зтот несколько более длинный фрагмент иллюстрирует важную особен-ность последовательного просмотра файла паролей: вы можете сохранять соответствующие фрагменты данных в структурах данных, выбираемых по своєму усмотрению. Первая часть примера — зто код просмотра всего файла паролей с созданием хеша, в котором ключ — регистрационное имя, а значение — начальний каталог, соответствующий зтому регистрационному имени. Строка sort получает ключи хеша и сортирует их в соответствии со строковим значением. Завершающий цикл — зто проход по рассортирован-ным ключам и поочередный вывод всех значений.
В общем случае для просмотра небольшого количества значений реко-мендуется использовать программы произвольного доступа (getpwuid и getpwnam). Если значений много или необходим просмотр всех значений, проще выполнить проход с последовательним доступом (с помощью функ-ций setpwent, getpwent и endpwent) и помостить конкретные значення, которые вы будете искать, в хеш*.
Доступ к файлу /etc/group
осуществляется аналогичным образом. После-довательный доступ обеспечивается вызовами функций setgrent, getgrent и endgrent. Вызов getgrent возвращает значення в следующем формате:
<$name, $passwd, $gid, $members)
Зти четыре значення примерно соответствуют четырем полям файла /etc/group,
позтому за подробной информацией обращайтесь к описанням, приведенным на man-страницах, относящихся к формату зтого файла. Соответствующие функций произвольного доступа — getgrgid (по иден-тификатору группы) и getgrnam (по имени группы).
* Если у вас узел с большой NIS-картой, то по соображениям производительности такой способ предобработки файла паролей лучше не использовать.