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