Руководство пользователя для GNU Awk
15. Библиотека функций awk
15.12 Чтение групповых баз данных
Большинство рассуждений, представленных в разделе 15.11 [Чтение пользовательской базы данных], стр. 192, в такой же мере приложимы и к групповым базам данных. Хотя традиционно использовался известный файл, `/etc/group', в хорошо известном формате, стандарт POSIX имеет только группу подпрограмм из библиотеки Си (!grp.h? и getgrent) для доступа к информации. Даже если такой файл существует, он вероятно не содержит полной информации. Поэтому, как и с пользовательской базой данных, необходимо иметь небольшую Си-программу, которая генерирует групповую базу как свой выход.
Приведем grcat, программу языка Си, которая "окошачивает" ("cats") групповую базу данных.
/*
* grcat.c * * Generate a printable version of the group database
* * Arnold Robbins, arnold@gnu.org * May 1993 * Public Domain */
#include !stdio.h? #include !grp.h?
int main(argc, argv) int argc; char **argv; -
struct group *g; int i;
while ((g = getgrent()) != NULL) -
printf("%s:%s:%d:", g-?gr.name, g-?gr.passwd,
g-?gr.gid); for (i = 0; g-?gr.mem[i] != NULL; i++) -
printf("%s", g-?gr.mem[i]); if (g-?gr.mem[i+1] != NULL)
putchar(','); "" putchar('"n'); "" endgrent(); exit(0); ""
Каждая строка в групповой базе данных представляет одну группу. Поля разделены двоеточиями и содержат следующую информацию.
Group Name
Имя группы.
Group Password
Зашифрованный групповой пароль. Это поле практически никогда не используется. Оно обычно пусто или содержит `*'.
Group ID Number
Числовой идентификатор группы. Номер должен быть уникальны в файле.
Group Member List
Разделенный запятыми список имен пользователей. Эти пользователи являются членами группы. Большинство систем Unix разрешают пользователям быть членами нескольких групп одновременно. Если это возможно и в вашей системе, то чтение `/dev/user' возвратит эти групповые номера в $5 через $NF. (Заметим что `/dev/user' есть расширение gawk; см. раздел 6.7 [Специальные имена файлов в gawk], стр. 72.)
Ниже показано, что может привести выполнение grcat:
$ grcat
a wheel:*:0:arnold
a nogroup:*:65534:
a daemon:*:1:
a kmem:*:2:
a staff:*:10:arnold,miriam,andy
a other:*:20:...
Вот функции для получения информации из групповой базы. Имеется несколько функций, моделирующих функции с теми же именами из библиотеки Си.
# group.awk --- функции для действий с групповым файлом
# Arnold Robbins, arnold@gnu.org, Public Domain # May 1993
BEGIN " -
# измените в соответствии с вашей системой
.gr.awklib = "/usr/local/libexec/awk/" ""
function .gr.init( oldfs, oldrs, olddol0, grcat, n, a, i) -
if (.gr.inited)
return
oldfs = FS oldrs = RS olddol0 = $0 FS = ":" RS = ""n"
grcat = .gr.awklib "grcat" while ((grcat -- getline) ? 0) -
if ($1 in .gr.byname)
.gr.byname[$1] = .gr.byname[$1] "," $4 else
.gr.byname[$1] = $0 if ($3 in .gr.bygid)
.gr.bygid[$3] = .gr.bygid[$3] "," $4 else
.gr.bygid[$3] = $0
n = split($4, a, "[ "t]*,[ "t]*") for (i = 1; i != n; i++)
if (a[i] in .gr.groupsbyuser)
.gr.groupsbyuser[a[i]] = "
.gr.groupsbyuser[a[i]] " " $1 else
.gr.groupsbyuser[a[i]] = $1
.gr.bycount[++.gr.count] = $0 ""
close(grcat) .gr.count = 0 .gr.inited++ FS = oldfs RS = oldrs $0 = olddol0 ""
Правило BEGIN устанавливает частную переменную на каталог, где хранится grcat. Поскольку она используется для помощи в извлечении подпрограммы из awk-библиотеки, мы решили положить ее в`/usr/local/libexec/awk'. Вы можете разместить ее в другом каталоге в вашей системе.
Эти подпрограммы следуют той же самой общей форме, что и подпрограммы пользовательской базы данных (см. раздел 15.11 [Чтение пользовательской базы данных], стр. 192). Переменная .gr.inited используется для обеспечения сканирования базы не более одного раза. Функция .gr.init сначала запоминает FS, RS и $0, затем устанавливает в FS и RS правильные значения для сканирования групповой информации. Эта информация записывается в несколько ассоциативных массивов. Массивы индексируются групповыми именами (.gr.byname), групповыми идентификационными номерами (.gr.bygid) и позициями в базе данных (.gr.bycount). Имеется дополнительный массив, индексированный именами пользователей (.gr.groupsbyuser), представляющий список разделенных пробелами групп, к которым принадлежит каждый пользователь. В отличие от пользовательской базы данных, можно иметь кратные записи в базе данных для той же самой группы. Это обычно, когда группа имеет большое количество членов. Подобная пара входов может выглядеть так:
tvpeople:*:101:johny,jay,arsenio tvpeople:*:101:david,conan,tom,joan
По этой причине .gr.init смотрит, не встречалось ли раньше некоторое групповое имя или групповой идентификатор. Если да, пользовательские имена просто присоединяются к прежнему списку пользователей. (Фактически имеется небольшая проблема с представленным выше кодом. Предположим, что в первое время никаких имен не было. Этот код добавляет имена с ведущей запятой. Он также не проверяет, что имеется $4.) В конце .gr.init закрывает конвейер к grcat, восстанавливает FS, RS и $0, инициализирует .gr.count нулем (это нужно позднее) и делает .gr.inited не нулем.
function getgrnam(group) -
.gr.init() if (group in .gr.byname)
return .gr.byname[group] return "" ""
Функция getgrnam получает в качестве аргумента групповое имя, и если эта группа имеется, то она и возвращается. В противном случае getgrnam возвращает пустую цепочку.
function getgrgid(gid) -
.gr.init() if (gid in .gr.bygid)
return .gr.bygid[gid] return "" ""
Функция getgrgid подобна функции getgrнам, она получает числовой идентификатор группы и ищет информацию, связанную с этим групповым идентификатором.
function getgruser(user) -
.gr.init() if (user in .gr.groupsbyuser)
return .gr.groupsbyuser[user] return "" ""
Функция getgruser не имеет двойника в Си. Она получает имя пользователя и возвращает список групп, членом которых является названный пользователь.
function getgrent() -
.gr.init() if (++.gr.count in .gr.bycount)
return .gr.bycount[.gr.count] return "" ""
Функция getgrent просматривает базу последовательно шаг за шагом. Она использует .gr.count для слежения за своей позицией в списке.
function endgrent() -
.gr.count = 0 ""
endgrent устанавливает .gr.count на ноль так что getgrent может стартовать опять с начала. Так же как с подпрограммами пользовательской базы данных, каждая функция вызывает .gr.init для инициализации массивов. Делая так, она тратит лишний прогон grcat, если эти функции используются (в противоположность варианту с переносом тела .gr.init в правило BEGIN). Большинство работы состоит в сканировании базы данных и построении различных связанных массивов. Функции, которые вызывает пользователь, сами по себе очень просты, они используют в своей работе ассоциативные массивы awk.
Программа id в разделе 16.1.3 [Печать выходной пользовательской информации], стр.215, использует эти функции.
Назад | Вперед
Содержание (общее) | Содержание раздела
Если Вы не нашли что искали, то рекомендую воспользоваться поиском по сайту:
|