Руководство пользователя для GNU Awk
15. Библиотека функций awk
15.11 Чтение пользовательской базы данных
Специальный файл `/dev/user' (см. раздел 6.7 [Специальные имена файлов в gawk], стр. 72) обеспечивает доступ к текущему пользовательскому реальному и эффективному пользовательскому и групповому идентификационным номерам и, если есть, к дополнительному номеру пользовательского группового множества. Однако, поскольку это номера, они не содержат очень полезной для обычного пользователя информации. Хотелось бы найти некоторый путь к информации пользователя, связанной с пользователем и с номерами групп. Этот раздел предлагает комплект функций для поиска информации в пользовательских базах данных. См. раздел 15.12 [Чтение групповой базы данных], стр. 197, о подобном комплекте, который выдает информацию из групповых баз данных. Стандарт POSIX не определяет файл, где пользователь держит информацию. Вместо этого он обеспечивает заголовочный файл !pwd.h? и несколько подпрограмм на языке Си для получения пользовательской информации. Первичная функция есть getpwent ( сокращение от "get password entry", т.е. узнать пароль). Пароль получают из оригинального файла пользовательской базы данных, /etc/passwd', который содержит информацию пользователя вместе с зашифрованными паролями (отсюда и имя файла).
Поскольку awk-программы могут непосредственно читать `/etc/passwd' (формат хорошо известен),то из-за способа, которым файлы с паролями обрабатываются в сетевых системах, этот файл не может содержать полной информации о системном множестве пользователей.
Чтобы быть в состоянии произвести читаемую, полную версию пользовательской базы данных, необходимо написать маленькую Cи-программу, которая вызывает getpwent. getpwent определена для возвращения указателя к структуре passwd. При каждом вызове она возвращает следующий вход в базу данных. Если входов больше нет, она возвращает NULL, нулевой указатель. Когда это происходит, Cи-программа должна вызывать endpwent для закрытия базы данных. Приведем pwcat, Си-программу, которая "закошачивает" (cats) базу данных с паролем.
/*
* pwcat.c * * Генерирует печатную версию базы данных с паролем
* * Arnold Robbins * arnold@gnu.org * May 1993 * Public Domain */
#include !stdio.h? #include !pwd.h?
int main(argc, argv) int argc; char **argv; -
struct passwd *p;
while ((p = getpwent()) != NULL)
printf("%s:%s:%d:%d:%s:%s:%s"n",
p-?pw.name, p-?pw.passwd, p-?pw.uid, p-?pw.gid, p-?pw.gecos, p-?pw.dir,
p-?pw.shell);
endpwent(); exit(0); ""
Если вы не понимаете Си, не беспокойтесь. Выход от pwcat есть пользовательская база данных в традиционном формате `/etc/passwd' разделенных двоеточиями полей. Поля такие:
Login name
Пользовательское login name.
Зашифрованный пароль Пользовательский зашифрованный пароль . Он может быть недоступен на некоторых системах.
User-ID
Пользовательский идентификационный номер.
Group-ID
Числовой идентифкатор группы пользователей.
Full name
Полное имя пользователя ,возможно, и другая информация, связанная с ним.
начальный каталог
Начальный или входной каталог пользователя ($HOME по терминологии системных программистов).
Login shell
Программа, которая выполняется при входе пользователя в систему. Обычно это оболочка, такая как Bash (оболочка Gnu Bourne-Again).
Приведем несколько строк, представляющих выход pwcat.
$ pwcat
a root:3Ov02d5VaUPB6:0:1:Operator:/:/bin/sh
a nobody:*:65534:65534::/:
a daemon:*:1:1::/:
a sys:*:2:2::/:/bin/csh
a bin:*:3:3::/bin:
a arnold:xyzzy:2076:10:Arnold Robbins:/home/arnold:/bin/sh
a miriam:yxaay:112:10:Miriam Robbins:/home/miriam:/bin/sh
a andy:abcca2:113:10:Andy Jacobs:/home/andy:/bin/sh ...
После этого введения укажем группу функций для получения информации пользователя. Здесь имеются несколько функций, соответствующих функциям в Си с такими же именами.
# passwd.awk --- доступ к информации в файле password
# Arnold Robbins, arnold@gnu.org, Public Domain # May 1993
BEGIN -
# приспособьте это для своей системы
.pw.awklib = "/usr/local/libexec/awk/" ""
function .pw.init( oldfs, oldrs, olddol0, pwcat) -
if (.pw.inited)
return oldfs = FS oldrs = RS olddol0 = $0 FS = ":" RS = ""n"
pwcat = .pw.awklib "pwcat" while ((pwcat -- getline) ? 0) -
.pw.byname[$1] = $0 .pw.byuid[$3] = $0 .pw.bycount[++.pw.total] = $0 ""
close(pwcat) .pw.count = 0 .pw.inited = 1 FS = oldfs RS = oldrs
$0 = olddol0 ""
Правило BEGIN устанавливает частную переменную на каталог, где хранится pwcat. Поскольку она используется для помощи в извлечении библиотечной подпрограммы awk, мы решили положить ее в `/usr/local/libexec/awk'. Вы можете держать ее в другом каталоге в вашей системе.
Функция .pw.init хранит три копии информации о пользователях в трех ассоциативных массивах. Массивы индексируются по имени пользователей (.pw.byname), по идентификационному номеру пользователей (.pw.byuid), и по порядку расположения (.pw.bycount).
Переменная .pw.inited используется для эффективности; .pw.init нужно вызывать только один раз.
Так как эта функция использует getline для чтения информации из pwcat, она сначала запоминает значения FS, RS и $0. Это делать необходимо, поскольку эти функции могут вызываться из любого места программы пользователя, и пользователь может иметь свои собственные значения для FS и RS.
Главная часть функции использует цикл для чтения строк базы данных, разделения их на поля и затем при необходимости запоминает строки в каждом массиве. Когда цикл закончен, .pw.init завершает работу, закрывая конвейер, устанавливая .pw.inited в единицу и восстанавливая FS, RS и $0. Использование .pw.count будет пояснено ниже.
function getpwnam(name) -
.pw.init() if (name in .pw.byname)
return .pw.byname[name] return "" ""
Функция getpwnam получает имя пользователя в качестве строкового аргумента. Если этот пользователь находится в базе, она возвращает соответствующую строку. Иначе ответом служит пустая цепочка.
function getpwuid(uid) -
.pw.init() if (uid in .pw.byuid)
return .pw.byuid[uid] return "" ""
Аналогично, функция getpwuid имеет аргументом идентификационный номер пользователя. Если этот номер есть в базе, она возвращает соответствующую строку и пустую цепочку в противном случае.
function getpwent() -
.pw.init() if (.pw.count ! .pw.total)
return .pw.bycount[++.pw.count] return "" ""
Функция getpwent просто просматривает базу данных, по одному входу за раз. Она использует .pw.count для слежения за своей текущей позицией в массиве.
function endpwent() -
.pw.count = 0 ""
Функция endpwent сбрасывает .pw.count на ноль, так что последующие обращения к getpwent будут опять начинать с начала.
При проектировании этого комплекта функций предполагалось, что каждая подпрограмма вызывает .pw.init для инициализации массивов базы данных Служебный отдельный процесс для генерирования пользовательской базы данных и I/O для просмотра ее только и будут обязательны, если главная программа пользователя фактически вызывает одну из этих функций. Если этот библиотечный файл загружен вместе с пользовательской программой, но ни одна из подпрограмм ни разу не вызывается, не будет никакого дополнительного расхода машинного времени.
(Альтернативой может быть перенос тела .pw.init в правило BEGIN, которое будет всегда выполнять pwcat. Это упрощает код, но запускает дополнительный процесс, который может никогда не потребоваться.) В свою очередь, вызов pw.init не очень дорог, поскольку переменная .pw.inited предохраняет программу от чтения данных более одного раза. Если вы заинтересованы в удалении каждого лишнего цикла из вашей awk-программы, то проверка .pw.inited может быть выделена из .pw.init и дублирована во всех других функциях. Практически, это не необходимо, поскольку большинство awk-программ ориентированы на ввод и вывод и упомянутые действия только запутают ее код.
Программа id в разделе 16.1.3 [Печать информации о пользователях], стр.215, использует эти функции.
Назад | Вперед
Содержание (общее) | Содержание раздела
Если Вы не нашли что искали, то рекомендую воспользоваться поиском по сайту:
|