Программирование в стандарте POSIX

       

res tty


tty > /tmp/tty. res tty < /tmp/tty.res > /tmp/tty.res
Листинг 9.1. Пример использования служебной программы tty.
Закрыть окно




/dev/ttyS4 not a tty
Листинг 9.2. Возможный результат использования служебной программы tty.
Закрыть окно




#include <unistd.h> int isatty (int fildes); char *ttyname (int fildes);
Листинг 9.3. Описание функций isatty() и ttyname().
Закрыть окно






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.
Закрыть окно




saved="$(stty -g)" stty новые_характеристики . . . stty $saved
Листинг 9.5. Пример сохранения и восстановления характеристик терминала.
Закрыть окно




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.
Закрыть окно




#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*().
Закрыть окно




#include <poll.h> int poll ( struct pollfd fds [], nfds_t nfds, int timeout);
Листинг 9.9. Описание функции poll().
Закрыть окно




/* * * * * * * * * * * * * * * * * * * * * * * * */ /* Программа запускает 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. Пример программы, использующей псевдотерминалы.
Закрыть окно




#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*() для работы с управляющими терминалами.
Закрыть окно




#include <stdio.h> char *ctermid (char *s);
Листинг 9.12. Описание функции ctermid().
Закрыть окно



Содержание раздела