Терминалы и псевдотерминалы в Linux. Средства работы с терминалами

Определение понятия и назначения терминального интерфейса как специального символьного файла. Характеристика основных служебных программ и функций для управления терминалами. Возможности и порядок работы полнодуплексного режима утилита stty и tput.

Рубрика Программирование, компьютеры и кибернетика
Вид лабораторная работа
Язык русский
Дата добавления 27.11.2013
Размер файла 34,7 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

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

Размещено на http://www.allbest.ru/

2

Терминалы и псевдотерминалы в Linux. Средства работы с терминалами

Содержание занятия

1.Теоретическая часть. Терминальный интерфейс

1.1 Основные понятия и объекты

1.2 Служебные программы и функции для управления терминалами

1.1.11 Служебная программа tty

1.1.12 Утилита stty:

1.1.13 Утилита tput

терминал интерфейс символьный файл утилит

Цель работы: знакомство с терминальным интерфейсом и средствами для управления им.

1. Теоретическая часть. Терминальный интерфейс

1.1 Основные понятия и объекты

В стандарте POSIX-2001 терминал или терминальное устройство определяется как символьный специальный файл, удовлетворяющий спецификациям общего терминального интерфейса.

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

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

С каждым терминальным устройством ассоциирована очередь ввода, куда система помещает входные данные до того, как их прочитают прикладные процессы. На размер этой очереди (в байтах) может быть наложено ограничение {MAX_INPUT}. Поддерживается также очередь вывода, где хранятся записанные прикладными процессами, но еще не выведенные на терминал символы.

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

(Отметим, что в каноническом режиме приложение не обязано сразу прочитать всю буферизованную строку. Можно запросить любое количество байт (даже один), и данные не будут потеряны.)

В неканоническом режиме входные данные не подвергаются препроцессированию системой, а обработка запроса на чтение зависит от двух параметров - MIN и TIME. Запрос на чтение не будет удовлетворен, пока не поступит по крайней мере MIN байт или не истечет время задержки TIME (время задается в десятых долях секунды). Нулевое значение TIME трактуется как бесконечная задержка.

Более точно, если MIN > 0, TIME трактуется как задержка между поступлениями байт; следовательно, отсчет времени начинается после прихода очередного байта. Если MIN = 0, TIME означает общее время обслуживания запроса на чтение. Такой подход позволяет эффективно читать во время вспышек активности ввода и не препятствует побайтному вводу.

Помимо режима, канонического или нет, на передачу данных читающему процессу оказывает влияние флаг O_NONBLOCK, устанавливаемый функциями open() или fcntl(), а на обработку входных символов - режимы ввода и локальные режимы. Подобная обработка может включать, например, эхоотображение вводимых символов.

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

Ряд управляющих символов играет специальную роль при вводе и/или выводе. Кратко опишем эти функции, не уточняя их соответствия с нажатиями на клавиатуре, поскольку оно зависит от реализации. Отметим, что за некоторыми очевидными исключениями (например, перевод строки), специальные управляющие символы не передаются читающему процессу.

INTR

Генерирует сигнал прерывания (SIGINT), посылаемый всем процессам, для которых данный терминал является управляющим.

QUIT

Генерирует сигнал выхода.

ERASE

При каноническом режиме ввода устраняет предыдущий символ, но не далее начала строки.

KILL

При каноническом режиме ввода уничтожает всю строку.

EOF

При каноническом режиме ввода при получении этого символа все буферизованные байты передаются процессу, а сам символ EOF отбрасывается. Таким образом, если буферизованных байт нет, т. е. EOF встретился в начале строки, в процесс будет передано нуль байт, что и является стандартным обозначением конца файла.

NL

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

EOL

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

SUSP

Генерирует сигнал остановки.

STOP

Специальный символ как при вводе, так и при выводе, распознаваемый в случае наличия флагов IXON (управление выводом) или IXOFF (управление вводом). Обычно используется для временной приостановки вывода, когда нужно прочитать текст на экране терминала.

START

Употребляется для возобновления вывода, приостановленного с помощью символа STOP.

CR

При каноническом режиме ввода и выполнении некоторых дополнительных условий - эквивалент перевода строки.

Центральную роль в управлении терминалами играет структура termios, определенная во включаемом файле <termios.h>. Она должна содержать по крайней мере следующие поля.

tcflag_t c_iflag; /* Режимы ввода */

tcflag_t c_oflag; /* Режимы вывода */

tcflag_t c_cflag; /* Управляющие режимы */

tcflag_t c_lflag; /* Локальные режимы */

cc_t c_cc [NCCS]; /* Специальные управ-

ляющие символы */

Типы tcflag_t, cc_t и фигурирующий далее speed_t должны определяться реализацией посредством typedef как беззнаковые целые.

Обращение к элементам массива c_cc, хранящего специальные управляющие символы, которые могут быть изменены, выполняется с помощью индексов с именами, полученными вставкой буквы V перед названием символа: VEOF, VEOL, VERASE, VINTR, VKILL, VQUIT, VSTART, VSTOP, VSUSP. Кроме того, еще два индекса, VMIN и VTIME, используются для работы со значениями MIN и TIME и могут совпадать с VEOF и VEOL, соответственно (поскольку символы EOF и EOL нужны только в каноническом режиме, а значения MIN и TIME - только в неканоническом). Поле c_iflag структуры termios описывает основные параметры терминального ввода.

BRKINT

При разрыве соединения (когда в течение времени, превышающего длительность передачи байта, поступают нулевые биты) генерировать сигнал прерывания и сбрасывать очереди ввода/вывода.

ICRNL

Преобразовывать возврат каретки в перевод строки.

IGNBRK

Игнорировать разрыв соединения.

IGNCR

Игнорировать возврат каретки.

IGNPAR

Игнорировать символы с ошибками четности.

INLCR

Преобразовывать перевод строки в возврат каретки.

INPCK

Разрешить контроль четности.

ISTRIP

Отбрасывать старший бит, обрезая байты до семи бит.

IXOFF

Разрешить старт/стопное управление вводом.

IXON

Разрешить старт/стопное управление выводом.

PARMRK

Отмечать ошибки четности.

Поле c_oflag определяет системную обработку вывода. К числу обязательных для поддержки стандарт POSIX-2001 относит только один флаг - OPOST> (постпроцессировать вывод). В расширение XSI входят флаги, определяющие характер постпроцессирования: ONLCR (преобразовывать перевод строки в пару - перевод строки, возврат каретки), OCRNL (преобразовывать возврат каретки в перевод строки), NLDLY (выбрать задержку для перевода строки) и т.п.

Поле управляющих режимов c_cflag описывает аппаратные характеристики линии и терминала: размер символа в битах (CSIZE: от CS5 - 5 бит до CS8 - 8 бит), число стоп-бит (CSTOPB: два стоп-бита), освобождение линии при закрытии последнего файлового дескриптора, ассоциированного с терминалом (HUPCL), контроль четности (PARENB: контроль включен; PARODD: проверка на нечетность) и т.п.

Стандарт осторожен в части представления скорости передачи. Оговаривается только, что скорость хранится в структуре termios как значение типа speed_t, но не утверждается, что она представлена как часть поля c_cflag (хотя в исторически сложившихся реализациях это так). Допустимые значения скорости задаются именованными константами: от B0 - нулевой, означающей разрыв соединения, до B38400 - 38400 бит/сек.

Поле локальных режимов c_lflag структуры termios используется для управления различными характеристиками терминала. В их число входят:

ECHO

Включить эхоотображение.

ECHOE

Отображать символ забоя как тройку (возврат на шаг, пробел, возврат на шаг).

ECHOK

Отображать символ уничтожения строки (по крайней мере путем выдачи перевода строки).

ECHONL

Включить эхоотображение перевода строки.

ICANON

Канонический режим ввода.

ISIG

Разрешить сигналы. Если установлен флаг ISIG, то каждый вводимый символ сравнивается со специальными управляющими символами INTR, QUIT и SUSP. В случае совпадения выполняется ассоциированная функция.

1.2 Служебные программы и функции для управления терминалами

1.2.1 Служебная программа tty

позволяет узнать имя пользовательского терминала. Более точно, она выдает на стандартный вывод имя терминала, открытого в качестве стандартного ввода.

Если для примера перенаправить стандартный ввод (см. пример 9.1), можно получить результат, показанный в пример 9.2.

tty > /tmp/tty.res

tty < /tmp/tty.res > /tmp/tty.res

Листинг 9.1. Пример использования служебной программы tty.

/dev/ttyS4 not a tty

Листинг 9.2. Возможный результат использования служебной программы tty. Узнать, ассоциирован ли открытый файловый дескриптор с терминальным устройством, а также получить имя этого устройства можно с помощью функций isatty() и ttyname() (см. пример 9.3).

#include <unistd.h>

int isatty (int fildes);

char *ttyname (int fildes);

Листинг 9.3. Описание функций isatty() и ttyname().

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

1.2.2 Утилита stty

Каждый терминал обладает рядом характеристик, которые можно опросить и/или изменить. Для этого служит утилита stty:

stty [ -a | -g]

stty характеристика ...

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

-a

Выдать значение всех установленных характеристик.

-g

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

В частности, выдача команды

stty -a

может выглядеть так, как показано в пример 9.4. Здесь присутствуют как стандартные, так и специфичные для ОС Linux характеристики (минус перед именем характеристики означает, разумеется, что соответствующий флаг не установлен). Например, для опрашиваемого терминала задан канонический режим ввода и постпроцессирование вывода, но отсутствует контроль четности. Можно видеть также, какие символы назначены на роли специальных управляющих.

speed 19200 baud; rows 0; columns 0; line = 0;

intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;

eol2 = <undef>; start = ^Q; stop = ^S; susp = <undef>; rprnt = ^R; werase = ^W;

lnext = ^V; flush = ^O; min = 1; time = 0;

-parenb -parodd cs8 hupcl -cstopb cread clocal -crtscts

-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl ixon ixoff

-iuclc -ixany -imaxbel

opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0

ff0

isig icanon -iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt

-echoctl echoke

Листинг 9.4. Возможный результат команды stty -a.

Чтобы переустановить какую-либо характеристику, следует указать ее имя и, если нужно, новое значение. Например, после выполнения команды

stty kill '^k'

для отмены строки придется нажимать CTRL+K. Вслед за выполнением команды

stty -echo

на экране перестанут отображаться символы, вводимые пользователем, что, правда, не повлияет на выдачу результатов работы команд. Подобный режим применяется для обеспечения секретности, например, во время ввода пароля. Для восстановления эхоотображения советуем воспользоваться командой

stty echo

Сохранение и восстановление характеристик терминала можно реализовать так, как показано в пример 9.5.

saved="$(stty -g)"

stty новые_характеристики

. . .

stty $saved

Листинг 9.5. Пример сохранения и восстановления характеристик терминала.

1.2.3 Утилита tput

Некоторые, хотя и весьма ограниченные, возможности управления терминалами предоставляет служебная программа tput:

tput [-T тип_терминала] действие

Стандарт POSIX-2001 предусматривает всего три действия: clear (очистка экрана), init (инициализация терминала), reset (переустановка терминала). Действие осуществляется путем посылки на терминал соответствующей управляющей последовательности. Стандарт не специфицирует, как эта последовательность определяется, каковы все результаты ее посылки и чем инициализация отличается от переустановки.

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

ClearScreen=`tput clear`

может и не достичь цели (tput ничего не выдаст). В-третьих, стандартизованный перечень действий слишком ограничен, так что реально можно рекомендовать лишь включение строки вида

tput init

в разного рода инициализационные файлы. Тем не менее, показанный в пример 9.6 фрагмент командного файла, выполняющегося при загрузке ОС Linux, демонстрирует поучительные способы борьбы с немобильностью.

if [ -x /usr/bin/tput ]; then

if [ "x`tput kbs`" != "x" ]; then

stty erase `tput kbs`

elif [ -x /usr/bin/wc ]; then

if [ "`tput kbs | wc -c `" -gt 0 ]; then

stty erase `tput kbs`

fi

fi

fi

Листинг 9.6. Пример совместного использования утилит stty и tput.

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

На уровне функций опрос и изменение характеристик терминала разбиты на два семейства: tc*() (см. пример 9.7) и cf*() (см. пример 9.8), которые в стандарте POSIX введены в качестве замены исторически сложившейся, универсальной, но чрезмерно эклектичной, не вписывающейся ни в какие синтаксические рамки функции ioctl().

#include <termios.h>

int tcgetattr (int fildes, struct termios *termios_p);

int tcsetattr (int fildes, int optional_actions, const struct termios *termios_p);

int tcflow (int fildes, int action);

int tcflush (int fildes, int queue_selector);

int tcdrain (int fildes);

int tcsendbreak (int fildes, int duration);

Листинг 9.7. Описание функций семейства tc*().

#include <termios.h>

speed_t cfgetispeed (const struct termios *termios_p);

speed_t cfgetospeed (const struct termios *termios_p);

int cfsetispeed (struct termios *termios_p, speed_t speed);

int cfsetospeed (struct termios *termios_p, speed_t speed);

Листинг 9.8. Описание функций семейства cf*().

Пара функций tcgetattr()/tcsetattr() позволяет стандартным образом опросить/изменить характеристики терминала, ассоциированного с открытым файловым дескриптором fildes. Значения характеристик помещаются в структуру, на которую указывает аргумент termios_p. Нюансами изменения ведает аргумент optional_actions. Если его значение равно TCSANOW, изменение выполняется немедленно. Значение TCSADRAIN предписывает сначала дождаться передачи на терминальное устройство всех записанных по дескриптору fildes данных; это полезно, если изменения затрагивают режимы вывода. Значение TCSAFLUSH дополнительно означает предварительный сброс введенных устройством, но не прочитанных прикладными процессами символов.

Отметим, что вызов tcsetattr() завершается успешно (и возвращает нулевое значение), если удалось осуществить хотя бы одно из запрошенных изменений характеристик терминала. Это сделано по соображениям мобильности, поскольку разные реализации могут поддерживать разные подмножества характеристик. После tcsetattr() целесообразно снова вызвать tcgetattr() и узнать реальное состояние терминального устройства.

Приложение, изменяющее характеристики терминала, обязано позаботиться об их последующем восстановлении (например, при завершении процесса). Завершение должно выполняться аккуратно, с обработкой сигналов.

Функция tcflow() позволяет приостановить или возобновить терминальный ввод/вывод. Если значение аргумента action равно TCOOFF, приостанавливается вывод; по значению TCOON он возобновляется. Значение TCIOFF вызывает передачу на терминал символа STOP, значение TCION - символа START, что оказывает соответствующее воздействие на ввод.

С помощью функции tcflush() можно сбросить очередь ввода (значение TCIFLUSH аргумента queue_selector), вывода (TCOFLUSH) или совместить их (значение TCIOFLUSH).

Функция tcdrain() действует мягче. Она блокирует вызывающий процесс, пока все данные, записанные по дескриптору fildes, не будут переданы на терминальное устройство, дожидаясь тем самым физического окончания вывода.

Функция tcsendbreak() носит технический характер, позволяя организовать разрыв соединения путем посылки на терминал нулевых бит в течение заданного интервала времени. Если значение аргумента duration равно нулю, посылка продолжается от четверти до половины секунды.

Поскольку стандарт POSIX-2001 не специфицирует способ представления в структуре termios данных о скорости передачи, для выборки/записи данной характеристики из/в termios потребовалось ввести семейство функций cf*(), что, конечно, хорошо, ибо это проявление (возможно, невольное) объектно-ориентированного подхода. Кроме того, в общем случае терминальное устройство может поддерживать для ввода и вывода разные скорости, поэтому определено четыре функции, названия которых говорят сами за себя. Разумеется, для реального опроса/изменения скорости обмена с терминалом нужно воспользоваться функциями tcgetattr()/tcsetattr(). Отметим также, что скорость должна задаваться не в виде целого числа, а с помощью определенных в заголовочном файле <termios.h> констант B0, ..., B38400.

При работе с (псевдо)терминалами (а также с каналами и сокетами) полезна функция poll() (см. пример 9.9), входящая в расширение XSI и позволяющая мультиплексировать ввод/вывод в пределах набора файловых дескрипторов.

#include <poll.h>

int poll (struct pollfd fds [],

nfds_t nfds, int timeout);

Листинг 9.9. Описание функции poll().

Для каждого элемента массива fds (с числом элементов nfds) функция проверяет, наступили ли заданные события; в частности, возможны ли чтение или запись без блокирования процесса.

Согласно стандарту, структура pollfd содержит по крайней мере следующие поля.

int fd;

/* Опрашиваемый файловый дескриптор */

short events;

/* Флаги опрашиваемых событий */

short revents;

/* Флаги произошедших событий */

Среди событий, обрабатываемых функцией poll(), выделим POLLIN (информирует о том, что можно без блокирования прочитать данные, не являющиеся высокоприоритетными), POLLRDNORM (можно прочитать обычные данные), POLLOUT (без блокирования можно записать обычные данные), POLLERR (выходной флаг - зафиксирована ошибка устройства или потока).

Разделение данных на обычные, приоритетные и высокоприоритетные зависит от реализации.

Если запрашиваемые события не наступают, poll() ждет по крайней мере timeout миллисекунд. Значение -1 задает бесконечную задержку.

В качестве примера описанных функций приведем упрощенную версию программы, запускающей командный интерпретатор на псевдотерминале (см. пример 9.10). Программа использует библиотеку curses для высокоуровневой работы с терминалами, которую мы не описываем, однако понять смысл фигурирующих в ней функций довольно просто. Отметим лишь, что функция endwin() восстанавливает характеристики терминала.

/* * * * * * * * * * * * * * * * * * * * * * * * */

/* Программа запускает shell на псевдотерминале */

/* * * * * * * * * * * * * * * * * * * * * * * * */

#include <unistd.h>

#include <stdlib.h>

#include <stdio.h>

#include <fcntl.h>

#include <termios.h>

#include <signal.h>

#include <poll.h>

#include <sys/resource.h>

#include <curses.h>

/* Действия при завершении процесса */

static void termination (int errcode) {

endwin ();

exit (errcode);

}

/* Функция обработки сигнала SIGCHLD */

static void chldied (int dummy) {

/* Просто завершимся*/

termination (34);

}

int main (void) {

WINDOW *win1, *win2;

/* win1 - окно только для рамки */

/* win2 - окно для shell */

int pty, tty; /* Дескрипторы обеих сторон псевдотерминала */

int fr; /* Результат fork'а */

unsigned char ch; /* Прочитанный символ */

struct termios pt; /* Структура для смены характеристик псевдотерминала */

struct pollfd fds [2]; /* Массив параметров для вызова poll */

char ptybuf [L_ctermid]; /* Массив для хранения имени псевдотерминала */

char *s, *t; /* Указатели для перебора компонентов имени псевдотерминала */

int w2lines, w2cols; /* Размер создаваемого окна */

int x, y; /* Координаты в окне */

struct sigaction sact;

int i;

initscr ();

cbreak ();

noecho ();

win1 = newwin (LINES, COLS, 0, 0);

box (win1, 0, 0);

wrefresh (win1);

w2lines = LINES - 2;

w2cols = COLS - 4;

win2 = newwin (w2lines, w2cols, 1, 2);

scrollok (win2, TRUE);

/* Откроем первый свободный псевдотерминал */

for (s = "pqrs"; *s; s++) {

for (t = "0123456789abcdef"; *t; t++) {

sprintf (ptybuf, "/dev/pty%c%c", *s, *t);

if ((pty = open (ptybuf, O_RDWR)) >= 0) {

goto findpty;

}

}

}

fprintf (stderr, "Не удалось найти свободный псевдотерминал\n");

termination (-1);

findpty:

ptybuf [5] = 't';

if ((tty = open (ptybuf, O_RDWR)) < 0) {

perror ("TTY OPEN ERROR");

termination (-1);

}

/* Установим подходящие характеристики псевдотерминала */

if (tcgetattr (pty, &pt) < 0) {

perror ("PTY TERMIOS GET ERROR");

return (1);

}

pt.c_iflag = 0;

pt.c_oflag = ONLCR;

pt.c_cflag = CS8 | HUPCL;

pt.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK;

pt.c_cc [VINTR] = 3; /* CTRL+C */

pt.c_cc [VEOF] = 4; /* CTRL+D */

if (tcsetattr (pty, TCSADRAIN, &pt) < 0) {

perror ("PTY TERMIOS SET ERROR");

return (2);

}

/* То же - для стандартного ввода */

(void) tcgetattr (0, &pt);

pt.c_lflag &= ~ISIG;

(void) tcsetattr (0, TCSADRAIN, &pt);

/* Установим обработку сигнала о завершении потомка */

sact.sa_handler = chldied;

(void) sigemptyset (&sact.sa_mask);

sact.sa_flags = 0;

(void) sigaction (SIGCHLD, &sact, (struct sigaction *) NULL);

/* Раздвоимся на процесс чтения с клавиатуры и вывода на экран */

/* и на процесс, в рамках которого запустим shell */

if ((fr = fork ()) < 0) {

perror ("FORK1 ERROR");

termination (-1);

} else if (fr) {

/* Это процесс, читающий с клавиатуры */

/* и выводящий на экран */

close (tty);

/* Будем ждать ввода с клавиатуры или псевдотерминала */

fds [0].fd = 0;

fds [0].events = POLLIN;

fds [1].fd = pty;

fds [1].events = POLLIN;

while (1) {

if (poll (fds, 2, -1) < 0) {

perror ("POLL ERROR");

termination (0);

}

if (fds [0].revents & POLLIN) {

/* Пришел символ со стандартного ввода */

read (0, &ch, 1);

write (pty, &ch, 1);

}

if (fds [1].revents & POLLIN) {

/* Пришел символ с псевдотерминала */

read (pty, &ch, 1);

switch (ch) {

case '\n': {

/* Проинтерпретируем перевод строки */

getyx (win2, y, x);

if (y == (w2lines - 1)) {

wmove (win2, y, w2cols - 1);

waddch (win2, (chtype) ch);

} else {

wmove (win2, y + 1, 0);

}

break;

}

default: {

/* Символ не интерпретируется */

waddch (win2, (chtype) ch);

break;

}

}

wrefresh (win2);

}

}

/* Просто завершимся */

termination (0);

} else { /* Порожденный процесс - запустим в нем shell */

/* Закроем все файлы, кроме псевдотерминала */

for (i = 0; i < RLIMIT_NOFILE; i++) {

if (i != tty) {

(void) close (i);

}

}

/* Сделаем процесс лидером сеанса */

(void) setsid ();

/* Свяжем стандартные ввод, вывод и протокол с псевдотерминалом */

(void) fcntl (tty, F_DUPFD, 0);

(void) fcntl (tty, F_DUPFD, 0);

(void) fcntl (tty, F_DUPFD, 0);

close (tty);

/* Сделаем псевдотерминал управляющим */

if ((tty = open (ptybuf, O_RDWR)) < 0) {

perror ("TTY OPEN ERROR");

exit (-1);

}

close (tty);

/* Поместим в окружение параметры псевдотерминала */

{

char lnbuf [20];

char clbuf [20];

sprintf (lnbuf, "LINES=%2d", w2lines);

sprintf (clbuf, "COLUMNS=%2d", w2cols);

putenv (lnbuf);

putenv (clbuf);

}

if (execl ("/bin/sh", "sh", (char *) NULL) < 0) {

perror ("EXECL ERROR");

exit (-1);

}

}

return 0;

}

Листинг 9.10. Пример программы, использующей псевдотерминалы.

В соответствии с определением, выводимые на псевдотерминал символы являются входными для порожденного процесса. Они читаются по дескриптору pty, а затем интерпретируются и выводятся на физический терминал. Обратим также внимание на манипуляции с флагом ISIG: сигналы разрешены только для псевдотерминала (но не для стандартного ввода).

В целях полноты изложения укажем, что в (частично) описанное выше семейство tc*() входят еще три функции, предназначенные для работы с управляющими терминалами (см. пример 9.11).

#include <unistd.h>

pid_t tcgetpgrp (int fildes);

#include <unistd.h>

int tcsetpgrp (int fildes, pid_t pgid_id);

#include <termios.h>

pid_t tcgetsid (int fildes);

Листинг 9.11. Описание функций семейства tc*() для работы с управляющими терминалами.

Функция tcgetpgrp() позволяет узнать идентификатор группы процессов переднего плана, ассоциированной с терминалом, заданным открытым файловым дескриптором fildes. Для установки идентификатора группы служит функция tcsetpgrp(). Требуется, чтобы аргумент fildes соответствовал управляющему терминалу вызывающего процесса. Функция tcgetsid(), входящая в расширение XSI, по сути аналогична tcgetpgrp(). Она позволяет узнать идентификатор группы процессов лидера сеанса, для которого терминал, ассоциированный с файловым дескриптором fildes, является управляющим.

Для выполнения в известном смысле обратной операции - получения маршрутного имени управляющего терминала для вызывающего процесса - служит функция ctermid() (см. пример 9.12).

#include <stdio.h>

char *ctermid (char *s);

Листинг 9.12. Описание функции ctermid().

Если значение аргумента s отлично от NULL, маршрутное имя управляющего терминала записывается по этому адресу; предполагается, что массив s имеет длину не менее L_ctermid байт. В противном случае имя помещается в область статической памяти, которая перезаписывается каждым вызовом.

Размещено на Allbest.ru


Подобные документы

  • Linux – одна из наиболее популярных распространяемых бесплатно операционных систем. Работа с базовым ограниченным набором программ по умолчанию. Характеристика основных программ, которые расширяют возможности операционной системы Linux для пользователя.

    презентация [486,5 K], добавлен 09.10.2013

  • Разложение функции в ряд Тейлора, алгоритм работы программного интерфейса сокетов, исходный текст программ с комментариями. Возможности языка программирования Си и среда разработки приложений в ОС Linux. Виртуальная среда VMWare Player и VirtualBox.

    лабораторная работа [1,8 M], добавлен 02.09.2014

  • Характеристика и принцип работы подсистемы-инсталлятора Windows Installer, ее структура и назначение. Порядок и варианты установки программ в ОС Linux, их преимущества и недостатки. Методика и основные этапы составления базы данных программ-аналогов.

    курсовая работа [369,2 K], добавлен 24.08.2009

  • Назначение команды "diskcomp". Текст и запуск командного файла. Сравнение команды в Windows 7 и Windows XP. Разработка файла-сценария в ОС Linux. Создание файла в подкаталоге. Создание файла "oglavlenie.txt" с отсортированным по времени списком файлов.

    курсовая работа [1,6 M], добавлен 22.08.2012

  • Базовые инструменты Linux Shell и Make. Скриптовый язык Shell. Make как утилита, автоматизирующая процесс преобразования файлов из одной формы в другую. Встраиваемые системы Buildroot и OpenWrt на базе Linux. Переменные и блоки define BuildPackage.

    курсовая работа [27,4 K], добавлен 19.01.2016

  • Состав операционных систем. Наиболее частое применение утилит Linux: GNU Screen, IPTraf, ELinks, Iotop, Cmus. Сворачивание в фон программ, которые сами этого не умеют. Различные типы сетевых интерфейсов. Использование swap-раздела, консольный медиаплеер.

    презентация [532,1 K], добавлен 09.10.2013

  • Компоновка и конфигурирование Linux сервера. Общая информация об ALT Linux Server 5, его подвиды и основные функциональные возможности. Установка дистрибутива ALT Linux 5.0 "Ковчег" и Apache2+php+MySQL. Пример настройки работы сайта на web-сервере.

    курсовая работа [6,0 M], добавлен 24.10.2012

  • Особенности графической среды разработки и Visual C++. Разработка проекта с использованием функций библиотеки MFC для удаления комментариев из текстов программ, автоматического выбора языка, на котором написана утилита и сохранения результата в файл.

    курсовая работа [22,7 K], добавлен 07.11.2010

  • Разработка подключаемых модулей аутентификации как средства аутентификации пользователей. Модуль Linux-PAM в составе дистрибутивов Linux. Принцип работы, администрирование, ограничение по времени и ресурсам. Обзор подключаемых модулей аутентификации.

    курсовая работа [192,0 K], добавлен 29.01.2011

  • Особенности операционных систем Linux. Аппаратно-программные требования для работы с лабораторным практикумом. Настройка виртуальной машины. Аналоги программ WINDOWS в Mandriva. Разграничение прав доступа. Настройка безопасности и политика паролей.

    курсовая работа [1,8 M], добавлен 06.11.2014

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.