Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
методичка ПО ОСРВ заочники.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
8.72 Mб
Скачать

2.5.5. Написание версии who2.С

В версии 2 нашей программы who внимание уделяется двум проблемам, о которых шла i речь в версии 1.

И вновь мы будем решать эти проблемы, обращаясь к необходимым документам спра­вочника и заголовочным файлам.

Подавление пустых записей

В реальной версии команды who выводится список пользовательских имен тех пользовате­лей, которые входили в систему. В нашей версии программы выводится список из того, что программа находит в файле utmp. Файл utmp содержит записи, касающиеся всех терми­налов, даже тех, которые не используются. Необходимо изменить нашу программу так, чтобы она не выводила записи о неиспользуемых терминальных линиях. Но как опреде­лить, какая из utmp - записей не представляет активную сессию?

Самое простое решение (которое не работает) - пропускать записи с пробелами в поле пользовательского имени. Это будет работать в большинстве случаев, но на экран не будет выводиться запись с полем LOGIN в строке, которая относится к консоли. Лучшим решением (которое работает) будет, если выбирать для вывода только те utmp - записи, которые соответствуют пользователем, вошедшим в систему.

Обратимся к файлу /usr/include/utmp.h и мы обнаружим там следующее:

Г Определения для ut type */

«define EMPTY

0

«define RUN LVL

1

«define BOOT TIME

2

«define OLD flME

3

«define NEW TIME

4

«define INIT PROCESS

5

/* Процесс был порожден процессом "init" */

«define LOGIN PROCESS

6

Г Процесс "getty" ждет login */

«define USER PROCESS

7

/* Пользовательский процесс */

«define DEAD PROCESS

8

Этот список весьма полезен. В каждой записи есть поле с именем utjype. Значения, ко­торые могут находиться в этом поле, и их символические имена представлены в приведен­ном выше списке. Тип 7 будет для нас счастливым номером. Если теперь мы сделаем ни­жеследующие небольшие изменения в нашей функции showjnfo, то пробельные записи должны исчезнуть:

,

show info(struct utmp *utbufp)

{

if (utbufp->ut_type != USER_PROCESS) j* только пользователи! */

return;

printf("%-8.8s", utbufp->ut_name); /* имя пользователя */

Отображение времени вхождения в систему в удобном для прочтения виде

Теперь решим проблемы представления времени в формате, который воспринимаем людьми. Начнем поиск в справочнике и поиск заголовочных файлов. Страниц по теме "time" во всех версиях Unix весьма много, и они разнообразны.

После набора

$ man-k time

получим много записей. На одной своей машине я получил 73 записи, а на другой машине получил 97. Вы можете просмотреть этот длинный список или можете отфильтровать по­лученный вывод. Следующие ниже конвейеры прекрасно проведут фильтрацию:

$ man -k time | grep transform

$ man -к time | grep -i convert

Через справочник выходим на необходимые заголовочные файлы. Файл /usr/include/time.h есть на ряде систем Unix. Проверьте вашу систему относительно информации, касающейся темы “time”. Нам же нужно обсудить вопрос

Как в Unix хранится значение времени: тип данных time_t

В Unix значение времени представляется целым числом, которое измеряет в секундах ин­тервал времени с полуночи первого января 1970 года по Гринвичу. Тип данных timej -это целочисленное представление времени в секундах. Этот формат в Unix используется во многих приложениях. Поле ut_time в utmp записях содержит время вхождения в сис­тему, которое представлено числом секунд с начала Эпохи.

Преобразование time_t в читаемый формат: ctime

Есть функция ctime, которая преобразует значение времени в секундах от начала работы системы Unix в значение времени в читабельном формате. Функция описана в разделе 3 электронного справочника.

$ man 3 ctime

CTIME(3)

Linux Programmer's Manual CTIME(3)

NAME

asctime, ctime, gmtime, localtime, mktime - transform

binary date and time to ASCII

SYNOPSIS

#include <time.h>

char "asctimefconst struct tm *timeptr);

char *ctime(const timej *timep);

struct tm "gmtime(const timej *timep);

struct tm *localtime( const timej *timep);

timej mktime(struct tm *timeptr);

extern char *tzname[2];

long int timezone;

extern int daylight;

DESCRIPTION

The ctime(), gmtimef) and localtime() functions all take

an argument of data type timej which represents calendar

time. When interpreted as an absolute time value, it rep-resents

the number of seconds elapsed since 00:00:00 on

January 1,1970, Coordinated Universal Time (UTC).

The ctime() function converts the calendar time timep into

a string of the form

"Wed Jun 30 21:49:08 1993\n"

The abbreviations for the days of the week are Sun,

Mon, Tue, Wed, Thu, Fri, and Sat. The abbre-viations

for the months are Jan, Feb, Mar, Apr,

May, Jun, Jul, Aug, Sep, Oct, Nov, and

Dec. The return value points to a statically allocated

string which might be overwritten by subsequent calls to

any of the date and time functions. The function also

Вот это то, что нам необходимо. Мы имеем значение time_t в записях utmp. А нам тре­буется строка в формате, подобном такому:

Jun 30 21:49

Функция ctime(3) выбирает указатель на time_t, а при окончании возвращает указатель на! строку, которая будет выглядеть примерно так:

Wed Jun 30 21:49:08 1993\n

ЛЛЛЛЛЛЛЛЛЛЛЛ

Заметим, что строка, которая нам нужна для работы who, вставляется в строку возврата функции ctime. Это позволяет достаточно просто производить кодировку даты для who. Мы обращаемся к функции ctime и получаем после ее работы строку из 12 символов со смещением, равным 4. Это выполняется при выполнении оператора printf("%12.12s", ctime(&t) +4).

Одновременный вывод всего сразу

Теперь мы знаем, как подавить пустые записи, и знаем, как отобразить значение utjime в читабельном виде. Далее представлена окончательная версия программы who2.c:

/* who2.c

- читает файл /etc/utmp и выводит список информации из него

*

- подавляет пустые записи

*/

- правильно форматирует время

#include <stdio.h>

#include <unistd.h>

#include <utmp.h>

#include <fcntl.h>

#include <time.h>

/* «define SHOWHOST*/

void showtime(long);

void showjnfofstruct utmp *);

int main()

{

struct utmp utbuf; Г сюда читается информация */

int utmpfd; /* чтение происходит из этого дескриптора */

if((utmpfd = open(UTMP FILE, О RDONLY)) == -1){

perror(UTMP.FILE);

exit(1);

}

while(read(utmpfd, &utbuf, sizeof(utbuf)) == sizeof(utbuf))

show_info(&utbuf);

close( utmpfd);

return 0;

}

/*

* show info()

* отображает содежимое структуры utmp

* в удобном для восприятия виде

* * ничего не отображает, если в записи нет имени пользователя*/ void show_info(struct utmp *utbufp)

{ \

if (utbufp->ut_type != USER_PROCESS)

return;

printf("%-8.8s", utbufp->ut_name); /* входное имя */

printf(""); I* пробел */

printf("%-8.8s", utbufp->ut_line); /* терминал */

printf(""); /* пробел */

showtime(utbufp->ut_time); /* отображение времени 7

#ifdefSHOWHOST

if(utbufp->ut_host[0] !='\0')

printff' (%s)", utbufp->ut_host); /* хост */

#endif

printf("\n"); /* перевод на новую строку */

}

void showtimeflong timeval)

/*

* отображает времяз^формате, удобном для восприятия

* использует функцию ctime для формирования строки с изображением времени

* Замечание: посредством формата %12.12s выводится строка из 12 символов,

* при значении LIMITS, равно 12 символов.

*/

{

char *ср; /* адрес со значением времени */

ср = ctime(&timeval); /* преобразование значения времени в строку */

/* строка должна иметь приблизительно такой вид */

/* Моn Feb 4 00:46:40 EST 1991 */

/* 0123456789012345. */

printf("%12.12s", cp+4); /* вывести 12 символов с позиции 4 */

}

Тестирование программы who2.c

Откомпилируем и запустим на исполнение программу who2.c. Для разнообразия вы­ключим настройку SHOWHOST. Далее запустим на исполнение системную версию команды who и сравним полученные результаты:

$ccwho2.c –о iwho2

$who2

rlscott

ttyp2

Jul 23 01:07

acotton

ttyp3

Jul 22 22:24

spradlin

ttyp5

Jul 17 20:51

spradlin

ttyp7

Jul 19 22:04

king

ttyp8

Jul 22 11:32

berschba

ttyp9

Jul 21 10:05

rserved

ttypa

Jul 1321:29

Rserved

ttypd

Jul 13 21:31

molay

ttyqO

Jul 22 20:03

cweiner

ttyq8

Jul 21 16:40

mnabavi

ttyx2

Apr 10 23:11

$who

rlscott

ttyp2

Jul 23 01:07

acotton

ttyp3

Jul 22 22:24

spradlin

ttyp5

Jul 17 20:51

spradiin

ttyp7

Jul 19 22:04

king

ttyp8

Jul 22 11:32

berschba

ttyp9

Jul 21 10:05

rserved

ttypa

Jul 13 21:29

rserved

ttypd

Jul 13 21:31

molay

ttyqO

Jul 22 20:03

Cweiner

ttyq8

Jul 21 16:40

mnabavi

ttyx2

Apr 10 23:11

$

Есть некоторое отличие в форматировании результатов. В различных версиях команды who используются различные по ширине колонки при выводе результатов. При изменении размеров колонок протокола вывода мы можем в точности добиться совпадения формата вывода по отношению к стандартному варианту. Можете заняться этим на своей системе.

В некоторых версиях команды who производится вывод имени хоста для удаленной систе­мы, если такая система была зафиксирована. В других же версиях такое имя не выводится. Программа выдает точный список пользователей, имена их терминальных линий и време­на вхождения пользователей в систему.

2.5.6. Взгляд назад и взгляд вперед

Мы начали эту главу с постановки простого вопроса: ''Как работает в Unix команда who?" Мы следовали в тексте трем сформулированным шагам. Во-первых, мы изучили, что де­лает команда. Затем мы разобрались^гюсредством детального изучения технической доку­ментации, как работает команда. Далее написали собственную версию программы, чтобы убедиться в том, что мы действительно понимаем, как работает команда.

По мере нахождения решений на каждом из трех шагов мы научились использовать элект­ронный справочник Unix и заголовочные файлы. Написание собственной версии програм­мы привело к закреплению рассмотренного материала. Стала ясной структура файла utmp. Мы убедились в том, что каждое вхождение в систему приводит к появлению записи в журнале. Мы изучили, каким образом в Unix представляются временные величины. Это будет полезно при работе с другими частями Unix.

Наконец, мы почитали документацию по надлежащим темам. На страницах справочника для файла utmp были найдены ссылки на файл wtmp. А со страниц справочника для функ­ции ctime есть ссылки на другие функции, которые связаны со временем. Эти ссылки дают дополнительное представление о структуре системы.