Листинг 40.4. Вывод содержимого файла lastlog
loginacct/view_lastlog.c
#include
#include
#include
#include
#include "ugid_functions.h" /* Объявление userIdFromName() */
#include "tlpi_hdr.h"
int
main(int argc, char *argv[])
{
struct lastlog llog;
int fd, j;
uid_t uid;
if (argc > 1 && strcmp(argv[1], "-help") == 0)
usageErr("%s [username…]\n", argv[0]);
fd = open(_PATH_LASTLOG, O_RDONLY);
if (fd == -1)
errExit("open");
for (j = 1; j < argc; j++) {
uid = userIdFromName(argv[j]);
if (uid == -1) {
printf("No such user: %s\n", argv[j]);
continue;
}
if (lseek(fd, uid * sizeof(struct lastlog), SEEK_SET) == -1)
errExit("lseek");
if (read(fd, &llog, sizeof(struct lastlog)) <= 0) {
printf("read failed for %s\n", argv[j]);
/* Конец файла или ошибка */
continue;
}
printf("%-8.8s %-6.6s %-20.20s %s", argv[j], llog.ll_line,
llog.ll_host, ctime((time_t *) &llog.ll_time));
}
close(fd);
exit(EXIT_SUCCESS);
}
loginacct/view_lastlog.c
Механизм учета входа в систему записывает данные о пользователях, которые находятся в системе, а также сведения обо всех их предыдущих входах. Эта информация хранится в трех файлах: utmp (записи обо всех пользователях, находящихся в системе), wtmp (записи обо всех входах и выходах из системы) и lastlog (записи о времени последнего входа в систему каждого пользователя). Эти данные используются разными командами, такими как who и last.
Библиотека языка C предоставляет функции для извлечения и изменения информации, содержащейся в файлах учета входа в систему. Приложения, позволяющие входить в систему, должны задействовать настоящие функции для обновления соответствующих учетных данных, чтобы команды, работа которых зависит от этих данных, вели себя корректно.
Если не считать справочную страницу utmp(5), наиболее полезным источником информации о функциях учета входа в систему является исходный код различных приложений, которые их используют. Просмотрите, к примеру, исходные тексты программ mingetty (или agetty), login, init, telnet, ssh и ftp.
40.1. Реализуйте функцию getlogin(). Как отмечалось в разделе 40.5, в процессах, выполняющихся в рамках некоторых эмуляторов терминала, она может вести себя некорректно, поэтому ее работу лучше проверять в виртуальной консоли.
40.2. Измените программу из листинга 40.3 (utmpx_login.c) таким образом, чтобы она обновляла не только файлы utmp и wtmp, но и lastlog.
40.3. Прочитайте справочные страницы login(3), logout(3) и logwtmp(3). Реализуйте соответствующие функции.
40.4. Реализуйте упрощенную версию команды who(1).
41. Основы разделяемых библиотек
Разделяемые библиотеки — это механизм размещения библиотечных функций в едином файле, доступном сразу нескольким выполняющимся процессам. Такой подход может сэкономить как дисковое пространство, так и оперативную память. В данной главе мы обсудим основы разделяемых библиотек, а в следующей рассмотрим ряд продвинутых возможностей, которыми они обладают.
Один из способов сборки приложения заключается в компиляции его исходных файлов в объектные с последующей их компоновкой в итоговую исполняемую программу. Например:
$ cc — g — c prog.c mod1.c mod2.c mod3.c
$ cc — g — o prog_nolib prog.o mod1.o mod2.o mod3.o
На самом деле сборка выполняется отдельной программой-компоновщиком, ld. Когда мы компилируем программу с помощью команды cc (или gcc), утилита ld вызывается автоматически, незаметно для нас. В Linux компоновщик всегда следует вызывать через компилятор, так как это позволяет запустить его с корректными параметрами и скомпоновать программу с подходящими библиотечными файлами.
Однако часто бывает так, что некоторые из исходных файлов можно было бы использовать в нескольких программах. Первым делом, чтобы не заниматься лишней работой, эти файлы можно скомпилировать только один раз и затем уже по необходимости компоновать их с разными исполняемыми файлами. И хотя такой подход уменьшает время компиляции, он все равно не избавляет от необходимости каждый раз указывать все объектные файлы на этапе компоновки. Более того, с увеличением количества таких файлов можно создать неразбериху в каталоге проекта.
Чтобы обойти эти проблемы, можно сгруппировать набор объектных файлов в единую сущность —