Читаем Linux API. Исчерпывающее руководство полностью

struct winsize ws;

fd_set inFds;

char buf[BUF_SIZE];

ssize_t numRead;

pid_t childPid;

if (tcgetattr(STDIN_FILENO, &ttyOrig) == -1)

errExit("tcgetattr");

if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) < 0)

errExit("ioctl-TIOCGWINSZ");

childPid = ptyFork(&masterFd, slaveName, MAX_SNAME, &ttyOrig, &ws);

if (childPid == -1)

errExit("ptyFork");

if (childPid == 0) { /* Потомок запускает командную оболочку во вторичном pty */

 shell = getenv("SHELL");

if (shell == NULL || *shell == '\0')

shell = "/bin/sh";

 execlp(shell, shell, (char *) NULL);

errExit("execlp");

/* Если мы добрались до этой строчки, значит что-то пошло не так */

}

/* Родитель передает данные между терминалом и первичным pty */

scriptFd = open((argc > 1)? argv[1]: "typescript",

O_WRONLY | O_CREAT | O_TRUNC,

S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);

if (scriptFd == -1)

errExit("open typescript");

ttySetRaw(STDIN_FILENO, &ttyOrig);

if (atexit(ttyReset)!= 0)

errExit("atexit");

for (;;) {

FD_ZERO(&inFds);

FD_SET(STDIN_FILENO, &inFds);

FD_SET(masterFd, &inFds);

 if (select(masterFd + 1, &inFds, NULL, NULL, NULL) == -1)

errExit("select");

 if (FD_ISSET(STDIN_FILENO, &inFds)) { /* stdin — > pty */

numRead = read(STDIN_FILENO, buf, BUF_SIZE);

if (numRead <= 0)

exit(EXIT_SUCCESS);

if (write(masterFd, buf, numRead)!= numRead)

fatal("partial/failed write (masterFd)");

}

 if (FD_ISSET(masterFd, &inFds)) { /* pty — > stdout+файл */

numRead = read(masterFd, buf, BUF_SIZE);

if (numRead <= 0)

exit(EXIT_SUCCESS);

if (write(STDOUT_FILENO, buf, numRead)!= numRead)

fatal("partial/failed write (STDOUT_FILENO)");

if (write(scriptFd, buf, numRead)!= numRead)

fatal("partial/failed write (scriptFd)");

}

}

}

pty/script.c

Применение программы из листинга 60.3 демонстрируется в следующей сессии командной строки. Сначала мы выводим имя псевдотерминала, которое используется в терминале xterm, выполняющем нашу сессию, а также идентификатор процесса командной оболочки. Эта информация пригодится в дальнейшем.

$ tty

/dev/pts/1

$ echo $$

7979

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

$ ./script

$ tty

/dev/pts/24 Вторичное устройство, открытое программой script

$ echo $$

29825 PID оболочки, запущенной программой script

Теперь воспользуемся утилитой ps(1), чтобы вывести сведения о двух командных оболочках и процессе, выполняющем программу script, после чего завершим оболочку, запущенную этой программой:

$ ps — p 7979 — p 29825 — C script — o "pid ppid sid tty cmd"

PID PPID SID TT CMD

7979 7972 7979 pts/1 /bin/bash

29824 7979 7979 pts/1./script

29825 29824 29825 pts/24 /bin/bash

$ exit

Вывод утилиты ps(1) показывает, что исходная командная строка, процесс, выполняющий программу script, и вторая командная оболочка, запущенная этой программой, имеют родственные связи.

На данном этапе мы вернулись в исходную командную строку. Если вывести содержимое файла typescript, то можно увидеть запись всех входящих и исходящих данных, которые были сгенерированы во время работы программы script:

$ cat typescript

$ tty

/dev/pts/24

$ echo $$

29825

$ ps — p 7979 — p 29825 — C script — o "pid ppid sid tty cmd"

PID PPID SID TT CMD

7979 7972 7979 pts/1 /bin/bash

29824 7979 7979 pts/1./script

29825 29824 29825 pts/24 /bin/bash

$ exit

60.7. Атрибуты терминала и размер окна

Первичное и вторичное устройства используют одни и те же структуры с атрибутами терминала (termios) и размером окна (winsize), которые были описаны в главе 58. Это значит, что программа, работающая в первичном устройстве псевдотерминала, может изменять указанные атрибуты для своего вторичного конца, применяя к первичному файловому дескриптору операции tcsetattr() и ioctl().

Одним из примеров того, как можно применять подобные изменения, является программа script. Представьте, что мы запускаем данную программу в окне эмулятора терминала и изменяем размер данного окна. В таком случае эмулятор оповестит ядро об изменении размера соответствующего терминального устройства, однако это не затронет отдельную запись, выделенную ядром для вторичного конца псевдотерминала (см. рис. 60.4). Следовательно, программы, которые манипулируют экраном (такие как vi) и выполняются во вторичном устройстве псевдотерминала, начнут генерировать некорректный вывод, поскольку их представление о размере окна терминала будет отличаться от его реального размера. Эту проблему можно решить следующим образом.

1. Устанавливаем в родительском процессе программы script обработчик сигнала SIGWINCH с целью получать уведомления об изменениях размера окна терминала.

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных