Существуют две общих причины, по которым производится доступ к системным идентификационным базам данных: если ядро получает номер, а вам необходимо имя, или если какой-то пользователь или какая-то программа предоставляют вам имя, а вы должны сообщить ядру номер. Предусмотрены две функции поиска числовых идентификаторов, getpwuid()
и getgrgid()
, которые принимают целочисленный идентификатор и возвращают указатель на структуру, содержащую информацию из соответствующей системной базы данных. Точно так же имеются две функции, которые производят поиск имен, getpwnam()
и getgrnam()
, и они возвращают те же две структуры.
База данных пользователей | База данных групп | |
---|---|---|
Номер | getpwuid() | getgrgid() |
Имя | getpwnam() | getgrnam() |
Каждая из этих функций возвращает указатели на структуры. Структуры являются статическими и перезаписываются при последующем вызове функции, поэтому если вам по какой-либо причине нужно отслуживать структуру, потребуется сделать ее копию.
Четыре вышеупомянутых функции являются, по сути, сокращениями, предлагающими наиболее часто используемые функции для доступа к системным базам данных. Функции низкого уровня, getpwent()
и getgrent()
, производят итерации по строкам в базе данных вместо поиска конкретной записи. Каждый раз при вызове одной из этих функций она будет считывать другой элемент из соответствующей системной базы данных, и возвращать его. После того как вы завершите чтение элементов, вызовите функцию endpwent()
или endgrent()
, чтобы закрыть файл.
В качестве примера далее приводится функция getpwuid()
, записанная в отношении функции getpwent()
.
struct passwd * getpwuid(uid_t uid) {
struct passwd * pw;
while (pw = getpwent()) {
if (!pw)
/* обнаружена ошибка; * сквозной проход для обработки ошибки */
break;
if (pw->pw_uid == uid) {
endpwent();
return(pw);
}
}
endpwent();
return NULL;
}
28.1.1. Пример: команда id
Команда id
использует многие из этих функций и предлагает несколько хороших примеров работы с ними. Она также использует некоторые функциональные возможности ядра, описанные в главе 10.
1: /* id.с */
2:
3: #include
4: #include
5: #include
6: #include
7: #include
8: #include
9: #include
10:
11: void usage (int die, char *error) {
12: fprintf(stderr, "Использование: id [<имя_пользователя>]\n") ;
13: if (error) fprintf(stderr, "%s\n", error);
14: if (die) exit(die);
15: }
16:
17: void die(char *error) {
18: if (error) fprintf(stderr, "%s\n", error);
19: exit(3);
20: }
21:
22: int main(int argc, const char *argv[]) {
23: struct passwd *pw;
24: struct group *gp;
25: int current_user = 0;
26: uid_t id;
27: int i;
28:
29: if (argc > 2)
30: usage(1, NULL);
31:
32: if (argc == 1) {
33: id = getuid();
34: current_user = 1;
35: if (!(pw = getpwuid(id)))
36: usage(1, "Имя пользователя не существует");
37: } else {
38: if (!(pw = getpwnam(argv[1])))
39: usage(1, "Имя пользователя не существует");
40: id = pw->pw_uid;
41: }
42:
43: printf("uid=%d(%s)", id, pw->pw_name);
44: if ((gp = getgrgid(pw->pw_gid)))
45: printf(" gid=%d(%s)", pw->pw_gid, gp->gr_name);
46:
47: if (current_user) {
48: gid_t *gid_list;
49: int gid_size;
50:
51: if (getuid() != geteuid()) {
52: id = geteuid();
53: if (!(pw = getpwuid(id)))
54: usage(1, "Имя пользователя не существует");
55: printf(" euid=%d(%s)", id, pw->pw_name);
56: }
57:
58: if (getgid() != getegid()) {