Давайте на некоторое время отвлечемся и поговорим о том, что эти
временные характеристики означают и как они могут быть модифицированы.
Одно интересное замечание: UNIX дает вам как обычному пользователю
возможность установить любое время доступа и время модификации файла
по вашему желанию. Это и хорошо, и плохо. Это обеспечивает гибкость,
когда дело касается информации индексного дескриптора файла, но также
позволяет скрывать следы при нарушении защищенной информации. Возьмем,
например, файл login. Кто-нибудь мог бы вставить новую строку регист-
рации перед старой и затем вернуть время доступа и время модификации в
исходные значения. Тогда бы никто, просматривая файл /bin/login коман-
дой ls, не смог бы сказать, что файл был изменен.

Однако в системе UNIX имеется третье время - время создания.
Система не позволяет вам изменить это время при помощи обычных команд.
Системный вызов utime(2) обеспечивает изменение только времени доступа
и модификации. Команда touch(1) также может изменить время доступа и
модификации, но не время создания. Команда touch строится только на
системном вызове. Она может делать не больше того, что обеспечивает
системный вызов. Команда fsdb(1) (отладчик файловой системы) является
единственным способом преодоления защиты от изменения времени созда-
ния. Но даже fsdb не может управлять временем создания. Вы должны вый-
ти за пределы поддерживаемых fsdb требований безопасности. Как это
сделать, показано в последующих главах.

В случае изменения регистрационной записи, рассмотренном выше, вы
могли бы посмотреть на время создания и увидеть, что оно очень близко
к текущему времени. Если же кто-либо использовал fsdb для подделки
времени создания, вы никогда не будете иметь уверенности в том, что
файл не был изменен.

Какое же все это имеет отношение к определению того, делал ли
пользователь что-либо недавно за своим терминалом? Время модификации
изменяется вызовом write(2). Поэтому представляется разумным, что за-
пись на терминал будет иметь место, когда драйвер читает символ, а за-
тем посылает его обратно на экран. По мере того, как кто-то нажимает
на клавиши, время модификации постоянно обновляется при эхо-отображе-
нии символов. Когда символы перестают поступать с клавиатуры, приоста-
навливается запись в файл терминала. Формула для определения последне-
го времени работы за терминалом (last_activity) такова:

last_activity = time(NULL) - mod_time,

где mod_time - время модификации. Эта формула закодирована внутри ко-
манды who(1). Отметим, что вызов команды time со значением NULL возв-
ращает истинное текущее время.

Команда activ не имеет опций. Если вы используете опции, напеча-
тается сообщение об ошибке.

    ПОЯСНЕНИЯ



В строках 4-8 выполняется проверка на наличие ошибок. Если число
аргументов командной строки больше нуля, на стандартное устройство ре-
гистрации ошибок выводится сообщение и программа завершается с неудач-
ным статусом.

Строка 10 - это команда, выполняющая вывод. Команда who вызвана с
опцией -u для получения основных данных. Затем ее выход по конвейеру
передается команде cut, которая отображает колонки 1-17 и 38-42. Тем
самым печатается только три поля, как показано в нашем предыдущем при-
мере.

------------------------------------------------------------
ИМЯ: info
------------------------------------------------------------

info Вывод на экран информации о пароле пользователя

    НАЗНАЧЕНИЕ



Печатает информацию поля комментария из файла /etc/ passwd для
указанного пользователя.

    ФОРМАТ ВЫЗОВА



info login_name [ login_name ... ]

    ПРИМЕР ВЫЗОВА



info russ Печатает информацию, которая хранится
о пользователе russ

    ТЕКСТ ПРОГРАММЫ



1 :
2 # @(#) info v1.0 Display password info on a user Author: Russ Sage
2а Отобразить парольную информацию пользователя

4 for NAME in $@
5 do
6 USER=`grep "^${NAME}:" /etc/passwd`
7 echo "$NAME:\t`echo ${USER}|cut -d: -f6`\t`
echo ${USER}|cut -d: -f5`"
8 done

    ПЕРЕМЕННЫЕ СРЕДЫ ВЫПОЛНЕНИЯ



NAME Каждое имя, указанное в командной строке
USER Полная запись в файле /etc/passwd для данного имени

ОПИСАНИЕ

ЗАЧЕМ НАМ НУЖЕН КОМАНДНЫЙ ФАЙЛ info?

Система UNIX использует конфигурационные файлы для хранения
основной информации о пользователях и другой системной информации. Од-
ними из наиболее популярных конфигурационных файлов являются
/etc/group, /etc/passwd и /etc/inittab. Для получения информации о
пользователях нам необходимо заглянуть в эти файлы.

В системе Berkeley имеется команда finger, которая получает ин-
формацию о пользователях из их регистрационных каталогов и из файла
паролей. В System V не так много программ, выполняющих такого рода ра-
боту, поэтому нам необходимо разработать их.

ЧТО ДЕЛАЕТ info?

Info - это командный файл, который получает информацию из регист-
рационного каталога и комментарий о пользователе из файла /etc/passwd.
Результат выглядит так:

-------------------
|
| name: home dir comments
| имя: регистрационный каталог комментарии
|

Если в вашей системе используется это поле комментариев, то эта
информация может быть полезной. "Вручную" выполнить просмотр пользова-
телей в файле паролей можно следующим образом:

grep login_name /etc/passwd

При этом распечатывается вся строка со всеми полями данных. Info
берет эти необработанные данные и выделяет из них каталог регистрации
пользователя и поле комментария.

В командной строке можно указать несколько регистрационных имен.
Каждое имя берется по порядку из командной строки.


    ПРИМЕР



$ for NAME in `cat /etc/passwd | cut -d: -f1`
> do
> NAMELIST="$NAMELIST $NAME"
> done; info $NAMELIST

Имя каждого пользователя в файле паролей добавляется к списку
имен. Затем этот список передается в командную строку info, которая
печатает все данные. Смысл команды: "Дай мне информацию обо всех поль-
зователях системы".

    ПОЯСНЕНИЯ



Строки 4-8 - это цикл for, который обрабатывает все имена, пере-
данные в командной строке. Для каждого переданного имени выполняются
строки 6 и 7.

В строке 6 в переменную USER заносится результат команды grep,
заключенной между символами ударения (`). Начиная с начала строки
(обозначено символом ^), grep ищет имя, за которым следует символ дво-
еточия (:). Такое указание заставляет выполнять поиск образца только в
первом поле файла паролей.

В строке 7 мы отображаем нашу выходную строку командой echo,
внутри которой вложены другие команды echo. Мы могли бы получать эле-
менты информации отдельно, присваивая их значения отдельным перемен-
ным, и затем создавать необходимый формат вывода, используя значения
этих переменных. Однако помещение всей информации в командную строку
работает быстрее, и текст программы более компактный, хотя и не очень
читабельный. Мы можем также использовать символы форматирования в ко-
манде echo для форматирования нашей распечатки.

Сначала отображается имя в том же виде, как оно получено из ко-
мандной строки. Затем выводится табуляция (\t). За первой табуляцией
следует поле номер шесть из файла паролей. Поскольку мы еще не имеем
этих данных, мы должны выделить их из значения переменной USER, кото-
рую мы уже имеем из предыдущей строки. Чтобы сделать это, мы командой
echo выводим всю строку и выделяем шестое поле, используя разделяющие
двоеточия. После этого поля мы выводим еще одну табуляцию и затем пя-
тое поле файла паролей. Мы получили это поле таким же образом, как и
шестое поле - эхо-отображением и выделением.

Такая техника получения данных медленная, поскольку вовлечены все
процессы, но это самый быстрый путь сделать это на языке shell. Коман-
да awk была бы понятнее и, возможно, быстрее, но наша реализация де-
монстрирует гибкость языка shell. Язык shell может выполнять почти
все, но не всегда лучшим образом. Вот почему в некоторых случаях мы
используем язык Си, в чем вы убедитесь по мере продвижения по нашей
книге.

-----------------------------------------------------------
ИМЯ: uchk
-----------------------------------------------------------

uchk Проверка процессов, запущенных другим пользователем

    НАЗНАЧЕНИЕ



Отобразить все процессы каждого пользователя, указанного в ко-
мандной строке

    ФОРМАТ ВЫЗОВА



uchk [-a] login_name [...]

    ПРИМЕР ВЫЗОВА



uchk -a Вывод всех процессов, запущенных администраторами

    ТЕКСТ ПРОГРАММЫ



1 :
2 # @(#) uchk v1.0 Check processes of another user Author: Russ Sage
2а Проверка процессов другого пользователя

4 trap "rm /tmp/ps$$ 2> /dev/null" 0 1 2 3 15

6 if [ $# -eq 0 ]
7 then echo "uchk: argument error" >&2
8 echo "usage: uchk [-a] login_name [ ... ]" >&2
9 exit 1
10 fi

12 if [ "`echo $1 | cut -c1`" = "-" -a "$1" != "-a" ]
13 then echo "uchk: invalid argument $1" >&2
14 echo "usage: uchk [-a] login_name [ ... ]" >&2
15 exit 1
16 fi

18 ADMIN="administrators names go here"
19 if [ "$1" = "-a" ]
20 then shift
21 set $ADMIN $@
22 fi

24 ps -ef > /tmp/ps$$
25 for NAME
26 do
27 echo
28 fgrep "$NAME" /tmp/ps$$
29 done

    ПЕРЕМЕННЫЕ СРЕДЫ ВЫПОЛНЕНИЯ



ADMIN Строка с именами пользователей, являющихся
администраторами в вашей системе
NAME Содержит каждое имя, считываемое из командной строки

ОПИСАНИЕ

ЗАЧЕМ НАМ НУЖЕН КОМАНДНЫЙ ФАЙЛ uchk?

Поскольку UNIX является многопользовательской системой, множество
задач выполняются одновременно. Единственный способ следить за такими
задачами - с помощью команды ps. Ps - это довольно специфичная команда
в том смысле, что она должна обращаться к памяти (/dev/mem) и прохо-
дить по связанному списку структур процесса. Это тяжелая вещь, поэтому
нелегко сделать свою собственную команду для вывода такого рода инфор-
мации. Вдобавок память защищена, и доступ к ней имеет только пользова-
тель root.

Так что мы должны или удовлетвориться опциями, которые дает ко-
манда ps, или модифицировать вывод этой команды. Uchk скорее относится
к последней категории. Мне хотелось получить список состояний про-
цессов по имени пользователя, а не смесь информации, относящейся к
разным пользователям. Хотя то, что я хотел, не соответствует ни одной
из стандартных опций команды ps, я смог модифицировать ее выход для
получения того, что мне надо.

ЧТО ДЕЛАЕТ uchk?

Uchk - это средство, которое генерирует, анализирует и сообщает о
процессах, запущенных каждым указанным пользователем. За один раз вы
можете проверить столько пользователей, сколько вам нужно. Все про-
цессы для каждого пользователя печатаются вместе.

Чтобы делать это, uchk должен работать с временными файлами.
Система UNIX весьма элегантно управляет временными файлами. Shell поз-
воляет использовать идентификатор процесса для создания уникальных
имен файлов для каждого запуска. После того как утилита запущена, вре-
менные файлы очищаются путем использования команды trap в shell'е. Ко-
манда trap удаляет файл, если что-либо прервало выполнение командного
файла или когда программа завершается. Это прекрасная особенность, ко-
торая исключает накопление случайных файлов в системе.

Если uchk была вызвана без аргументов или была использована недо-
пустимая опция, то печатается сообщение об ошибке и выполнение завер-
шается.

Uchk имеет переменную ADMIN, которая определяет всех администра-
торов вашей системы. Отредактируйте символьную строку, присваиваемую
переменной ADMIN, указав имена администраторов, которых вы хотите про-
верить. Имена должны быть разделены пробелами. Это позволит вам прове-
рять процессы ваших администраторов, указывая опцию -a в командной
строке. Все остальные имена должны быть указаны в командной строке.
Естественно, вы таким же образом могли бы установить другие группы
пользователей. Слежение за администраторами поможет вам оценить, как
они управляют сохранностью информации, а также распознать администра-
тивные задачи, которые имеют склонность загружать процессор.

    ПРИМЕР



$ uchk -a russ uucp

Показывает процессы всех администраторов, мои собственные, и про-
цессы uucp по порядку. Все сообщения об ошибках выводятся на стандарт-
ное устройство регистрации ошибок, а списки процессов выводятся на
стандартное устройство вывода.

    ПОЯСНЕНИЯ



Строка 4 - это оператор trap. Символьная строка между двойными
кавычками содержит команды, которые должны быть выполнены, когда про-
исходит прерывание. В этом случае мы удаляем временный файл и переад-
ресовываем все выходные данные на нулевое устройство. Когда команда rm
пытается удалить несуществующий файл, выводятся сообщения об ошибках.
Поскольку мы не знаем, какие файлы могут быть в наличии в тот момент,
когда возникнет прерывание, то мы хотим избавиться от сообщений об
ошибках. Оператор trap активизируется по выходу из программы (program
exit, сигнал 0), разрыву линии (hangup, сигнал 1), прерыванию
(interrupt, сигнал 2), выходу (quit, сигнал 3) или программному завер-
шению (software termination, сигнал 15).

В строках 6-10 проверяется, переданы ли какие-либо аргументы.
Если вы вызвали uchk без аргументов, выводится сообщение об ошибке и
uchk завершается.

В строках 12-16 проверяется, указана ли какая-то опция со знаком
минус и является ли она опцией -a - единственно допустимой опцией. Ко-
мандный файл делает это, применяя команды проверки для сравнения двух
различных случаев. Первая проверка вырезает первый символ первого по-
зиционного параметра и смотрит, является ли он символом "-". Следующая
проверка делается для того, чтобы увидеть, что первый позиционный па-
раметр не является опцией -a. Поскольку обе проверки соединены опера-
цией AND, то для получения значения "истина" они обе должны быть
истинными. Если они обе истинны, выводится сообщение об ошибке и uchk
завершается.

Почему мы должны выполнять такую сложную проверку? Проблема в
том, что у нас нет иного способа определить, является первый позицион-
ный параметр опцией или нет. Он может быть опцией, а может быть име-
нем, которое нужно искать. Таким образом, мы должны задать вопрос:
"Является ли это опцией, и если да, то допустима ли эта опция?"

В строке 18 переменная ADMIN инициализируется символьной строкой,
следующей за ней. Это строка, которую вы должны модифицировать в соот-
ветствии с вашей системой. Все, что вы должны сделать - это использо-
вать редактор vi и вставить в эту строку имена администраторов, разде-
ленные пробелами. Ниже мы используем переменную ADMIN для обработки
аргументов командной строки.

В строках 19-22 проверяется, была ли указана в командной строке
опция -a. Если да, эта опция удаляется из командной строки с целью из-
бавления от нее. Строка 21 использует команду set для того, чтобы по-
местить символьную строку ADMIN в позиционные параметры. Команда set
вставляет значение переменной ADMIN, начиная с первого позиционного
параметра, и сдвигает все настоящие параметры вправо. Тем самым в цикл
for передается множество имен, которые должны быть обработаны.

В строке 24 выполняется команда ps для всех пользователей. Эта
команда использует опцию f для вывода большого количества данных. Ре-
зультат помещается во временный файл, в имени которого применяется
идентификационный номер процесса. Этот один большой файл представляет
собой источник для остальных распечаток. Возможно, все это немного
отстает от реального времени, но программа выполняется гораздо быст-
рее, чем при многократном вызове команды ps.

Строки 25-29 представляют собой цикл for, который выполняется от
$1 до $x, где x - последний позиционный параметр. Для каждого имени
выполняется следующее: печатается пустая строка для разделения листин-
га (строка 27), затем командой fgreps (для ускорения) выбираются из
временного файла все процессы, принадлежащие данному пользователю.
Благодаря применению команды fgrep для каждого имени пользователя, все
процессы данного пользователя печатаются за один раз. Когда закончится
проверка всех имен, указанных в командной строке, цикл завершится, за-
вершится командный файл и сработает оператор trap, который удаляет вре-
менный файл.

-------------------------------------------------------------
ИМЯ: watch
-------------------------------------------------------------

watch Наблюдение за регистрацией указанных пользователей

    НАЗНАЧЕНИЕ



Следит за тем, кто работает в системе, и сообщает
о регистрации указанных пользователей.

    ФОРМАТ ВЫЗОВА



watch [-k] [login_name ...]

    ПРИМЕР ВЫЗОВА



watch Наблюдение за регистрацией всех пользователей,
указанных во внутренней переменной LIST

    ТЕКСТ ПРОГРАММЫ



1 :
2 # @(#) watch v1.0 Watch for specific logins Author: Russ Sage
2а Наблюдение за регистрацией пользователей

4 if [ "`echo $1 | cut -c1`" = "=" -a "$1" != "-k" ]
5 then echo "watch: invalid argument $1" >&2
6 echo "usage: watch [-k] [login_name ...]" >&2
7 echo " -k kill background process"
8 exit 1
9 fi

11 if [ "$1" = "-k" ]
12 then if [ -s $HOME/.watch ]
13 then echo "killed `cat $HOME/.watch`"
14 kill `cat $HOME/.watch`
15 rm $HOME/.watch
16 exit 0
17 fi
18 fi

20 echo $$ > $HOME/.watch

22 LIST="root sys bin administrator1 administrator2 $*"

24 while :
25 do
26 for NAME in `who | cut -d" " -f1`
27 do
28 for PERSON in $LIST
29 do
30 if [ "$NAME" = $PERSON" ]
31 then echo ONLINE: $NAME
32 fi
33 done
34 done
35 sleep 10
36 done &

    ПЕРЕМЕННЫЕ СРЕДЫ ВЫПОЛНЕНИЯ



HOME Полный маршрут к вашему регистрационному каталогу
LIST Список имен пользователей системы, разделенных
пробелами
NAME Содержит имена зарегистрированных в настоящий
момент пользователей
PERSON Отдельное имя из списка имен в переменной LIST


ОПИСАНИЕ

ЗАЧЕМ НАМ НУЖЕН КОМАНДНЫЙ ФАЙЛ watch?

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

ЧТО ДЕЛАЕТ watch?

Подразумевается, что watch является фоновой задачей, которая
постоянно следит за тем, кто зарегистрировался. Когда лицо или лица,
предварительно вами отмеченные, регистрируются в системе, на ваш экран
выводится сообщение о том, что они на связи.

Количество имен, за которыми вы можете следить, не ограничено.
Общий перечень имен - это объединение имен, указанных в командной
строке, и списка системных пользователей, т.е. пользователя root и
всех сопровождающих его администраторов. В командном файле watch
список системных имен ВСЕГДА включен. Это вызвано тем, что это важные
пользователи и вы хотите всегда знать об их входе в систему и выходе
из нее. Это отличает watch от uchk, поскольку последний требует указа-
ния опции -a для включения списка с системными именами.

Хотя мы устанавливаем watch с точки зрения пользователя, который
желает следить за администраторами и другими пользователями, админист-
раторы тоже могут иметь список "критических пользователей" или предпо-
лагаемых нарушителей защиты информации и использовать watch для полу-
чения сигнала о регистрации таких пользователей.

За кем бы мы ни следили, мы сталкиваемся с одной проблемой. После
регистрации в системе указанного лица сообщение об этом поступает на
ваш экран, не обращая внимания на то, чем вы в данное время занима-
лись, что не очень приятно. Единственный способ остановить вывод сооб-
щения - аварийно завершить watch командой kill. Это легко сделать пу-
тем помещения идентификатора этого процесса в файл $HOME/.watch. Затем
этот номер может быть использован в операторе kill для остановки вы-
полнения командного файла. Для того чтобы попроще избавиться от watch,
возможность аварийного завершения оформлена в виде опции -k данного
командного файла.

    ПРИМЕРЫ



1. $ LIST="root bin" watch daemon

Если переменная LIST не была инициализирована внутри самого ко-
мандного файла watch, то мы можем инициализировать ее на командном
уровне shell'а, а затем вызвать watch. Список пользователей для watch
будет такой: root, bin и daemon по порядку, поскольку watch добавляет
имена, указанные в ее командной строке к именам, имеющимся в перемен-
ной LIST. Такой способ указания имен более гибок, чем жесткое програм-
мирование части списка в тексте командного файла watch, но он требует
помнить больше информации и больше нужно набирать на клавиатуре.

2. echo "Watch (y/n): \c"
read ANS
if [ "$ANS" = "y" ]
then watch
fi

Это фрагмент, который вы можете вставить в ваш .profile. Когда вы
регистрируетесь, вам автоматически предлагается запустить watch. Если
вы ответите "y", watch станет фоновой задачей и запустится по умолча-
нию (просматривая пользователей согласно списку в переменной LIST).
Если будет введен любой символ, отличный от y, watch не запустится.


    ПОЯСНЕНИЯ



Строки 4-9 выполняют проверку на наличие ошибок в опциях команд-
ной строки. Для первого позиционного параметра проверяется, что он
имеет тире и не является единственной допустимой опцией "-k". Если ре-
зультатом проверки является истина, печатается сообщение об ошибке и
командный файл завершается.

Строки 11-16 проверяют, что первый позиционный параметр - это -k.
Если это так, значит пользователь хочет уничтожить уже запущенный про-
цесс watch. В этом случае выводится сообщение, указывающее идентифика-
тор процесса, который будет уничтожен, и выполнение продолжается. В
строке 12 мы смотрим, существует ли в нашем регистрационном каталоге
файл с именем .watch. Если нет, то это означает, что предыдущий эк-
земпляр watch предположительно уже уничтожен и нет необходимости пы-
таться сделать это снова, поэтому происходит переход к оставшейся
части программы и выполнение watch происходит так, как будто опция
"-k" не была указана.

Если же файл .watch имеется, то в строке 14 используется команда
kill для уничтожения фонового процесса watch. Напомним, что при
использовании опции -k мы подразумеваем, что watch был вызван ранее,
поэтому файл $HOME/.watch имеет идентификационный номер самого про-
цесса watch. В строке 15 удаляется временный файл watch и в строке 16
происходит выход из программы. Теперь командный файл watch более не
выполняется как фоновый.

Строка 20 выполняется, если опция -k не была указана или если нет
файла .watch. (Последнее может произойти, если пользователь пытается
уничтожить процесс, забыв, что он уже был уничтожен.) Если опция -k не
была указана, мы можем считать, что watch был вызван, чтобы стать фо-
новым процессом и выполнять свою работу. Для того чтобы сделать это,
текущий процесс отображает свой идентификатор процесса в файл .watch.
Этот файл остается в вашем регистрационном каталоге до тех пор, пока
он не будет удален вручную или же изменен путем повторного запуска
watch.

В строке 22 инициализируется переменная LIST. Ее значением явля-
ется символьная строка с именами, разделенными пробелами. Вам нужно
вручную отредактировать переменную LIST перед запуском в вашей систе-
ме. Просто уберите ее нынешнее содержимое и вставьте туда имена адми-
нистраторов вашей системы. Если в командной строке будут указаны до-
полнительные имена пользователей, они будут добавлены в переменную
LIST посредством символов расширения параметров $*. Тем самым перемен-
ная LIST станет основным списком всех имен пользователей, за которыми
будет вестись наблюдение.

Строки 24-36 выполняют цикл постоянного наблюдения. В начале каж-
дой итерации с помощью команды who создается список имен пользовате-
лей, который передается циклу for в строке 26. Цикл for использует ко-
мандную подстановку для получения списка слов, образованного из перво-
го поля команды who. Каждое зарегистрированное имя сравнивается со
списком предварительно определенных имен, за которыми мы наблюдаем.
Обратите внимание, что внешний цикл while сам себя помещает на выпол-
нение в фоновом режиме. Это означает, что вам нет необходимости вво-
дить это с клавиатуры.

Строки 29-33 управляют внутренним циклом, который проходит по
именам, содержащимся в нашем основном списке, и сравнивает их с имена-
ми, полученными от команды who. Когда имя, полученное от команды who
(имя зарегистрированного пользователя) совпадает с именем в нашем
списке, на экран выводится сообщение о том, что данное лицо зарегист-
рировалось.

После того как все имена проверены, командный файл watch приоста-
навливается на 10 секунд (строка 35). Когда он снова пробуждается, вы-
полняется следующая итерация вечного цикла while. Все зарегистрирован-
ные имена вновь сравниваются со списком. Это будет продолжаться до тех
пор, пока вы не прекратите выполнение watch. Как отмечалось ранее,
watch можно легко уничтожить с помощью опции -k или же вручную путем
ввода команды "kill `cat $HOME/.watch`".


    МОДИФИКАЦИИ



Watch выполняет довольно мало работы и использует какую-то часть
времени центрального процессора. Вы можете поэкспериментировать с уве-
личением интервала паузы (sleep), чтобы watch запускался не так часто.
Большинство пользователей находятся в системе по крайней мере минуту,
поэтому вы можете попробовать значение sleep(60). Вы по-прежнему може-
те обнаружить регистрацию всех интересующих вас пользователей?

---------------------------------------------------------------
ИМЯ: whox
---------------------------------------------------------------

whox Команда who с дополнительными возможностями

    НАЗНАЧЕНИЕ



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

    ФОРМАТ ВЫЗОВА



whox [-f] [-n] [-m] [-p] [-t] [-w] [-x]

где
-f указывает каждого зарегистрированного пользователя

-n сортирует выход команды who по именам

-m передает почту каждому пользователю

-p выводит информацию о паролях пользователей

-t сортирует выход команды who по времени (умолчание)

-w показывает возможность записи на зарегистрированные
терминальные устройства

-x дополнительная информация о регистрационном
каталоге и паролях

    ПРИМЕР ВЫЗОВА



whox -w

Показывает права доступа к файлу (возможность чтения и записи)
для каждого зарегистрированного терминального устройства

    ТЕКСТ ПРОГРАММЫ



1 :
2 # @(#) whox v1.0 Who with expanded options Author: Russ Sage
2а Команда who с дополнительными опциями

4 XTRA="no"
5 SORT="sort -b +2"