Майкл Джонсон - Разработка приложений в среде Linux. Второе издание
- Название:Разработка приложений в среде Linux. Второе издание
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:2007
- Город:Москва
- ISBN:978-5-8459-1143-8
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Майкл Джонсон - Разработка приложений в среде Linux. Второе издание краткое содержание
Книга известных профессионалов в области разработки коммерческих приложений в Linux представляет собой отличный справочник для широкого круга программистов в Linux, а также тех разработчиков на языке С, которые перешли в среду Linux из других операционных систем. Подробно рассматриваются концепции, лежащие в основе процесса создания системных приложений, а также разнообразные доступные инструменты и библиотеки. Среди рассматриваемых в книге вопросов можно выделить анализ особенностей применения лицензий GNU, использование свободно распространяемых компиляторов и библиотек, системное программирование для Linux, а также написание и отладка собственных переносимых библиотек. Изобилие хорошо документированных примеров кода помогает лучше усвоить особенности программирования в Linux.
Книга рассчитана на разработчиков разной квалификации, а также может быть полезна для студентов и преподавателей соответствующих специальностей.
Разработка приложений в среде Linux. Второе издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
55: (*name)[8] = "pqrstuvwxyzPQRST"[i];
56: (*name)[9] = "0123456789abcdef"[j];
57: /* открыть ведущее устройство pty */
58: if ((master = open(*name, O_RDWR)) < 0) {
59: if (errno == ENOENT) {
60: /* устройства pty исчерпаны */
61: free(*name);
62: return(master);
63: }
64: }
65: }
66: }
67:
68: if ((master < 0) && (i == 16) && (j == 16)) {
69: /* необходимо для каждого неудачного pty */
70: free(*name);
71: return(master);
72: }
73:
74: /* Подставляя букву, изменить имя ведущего устройства pty
75: * в имени подчиненного компонента pty.
76: */
77: (*name)[5] = 't';
78:
79: return(master);
80: }
81:
82: /* get_slave_pty() возвращает целочисленный файловый дескриптор.
83: * Если возвращается значение < 0, значит, возникла ошибка.
84: * В противном случае возвращается файловый дескриптор подчиненного
85: * компонента. */
86:
87: int get_slave_pty(char * name) {
88: struct group *gptr;
89: gid_t gid;
90: int slave = -1;
91:
92: if (strcmp(name, "/dev/pts/")) {
93: /* Интерфейс Unix98 не использовался, необходима
94: * специальная обработка полномочий или прав владения.
95: *
96: * Выполнить chown/chmod для соответствующего pty, если возможно.
97: * Это будет работать, только если имеет полномочия root.
98: * В качестве альтернативы можно написать и запустить небольшую
99: * setuid-программу, которая сделает все это.
100: *
101: * В противном случае все проигнорировать и пользоваться
102: * только интерфейсом Unix98.
103: */
104: if ((gptr = getgrnam("tty")) != 0) {
105: gid = gptr->gr_gid;
106: } else {
107: /* если группа tty не существует, не изменять группу
108: * на подчиненном компоненте pty, а только владельца
109: */
110: gid = -1;
111: }
112:
113: /* Обратите внимание, что здесь не осуществляется проверка на ошибки.
114: * Однако если выполняемые действия являются критически важными,
115: * проверка ошибок должна быть. */
116: chown(name, getuid(), gid);
117:
118: /* Этот код делает подчиненный компонент доступным для чтения/записи
119: * только конкретному пользователю. Если код предназначен для
120: * интерактивной оболочки, которая должна получать сообщения
121: * "write" и "wall", добавьте ниже "ИЛИ" с S_IWGRP во второй аргумент.
122: * В таком случае потребуется перенести эту строку за пределы
123: * оператора if(), чтобы код мог выполняться для интерфейсов как
124: * BSD-стиля, так и Unix98-стиля.
125: */
126: chmod(name, S_IRUSR|S_IWUSR);
127: }
128:
129: /* открыть соответствующий подчиненный компонент pty */
130: slave = open(name, O_RDWR);
131:
132: return(slave);
133: }
Функция get_slave_pty()
не делает ничего нового. Все функции описываются в других местах этой книги, поэтому здесь они не объясняются.
16.6.4. Примеры псевдотерминалов
Возможно, одной из самых простых программ, которая может быть написана для использования pty, является программа, открывающая пару pty и запускающая оболочку на подчиненном компоненте pty, соединяя его с управляющим устройством pty. Написав эту программу, вы можете расширять ее любым подходящим способом, forkptytest.с
является примером использования функции forkpty()
, a ptytest.с
— это пример, который использует функции, определенные в ptypair.с
, и является несколько более сложным.
1: /* forkptytest.с */
2:
3: #include
4: #include
5: #include
6: #include
7: #include
8: #include
9: #include
10: #include
11: #include
12:
13:
14: volatile int propagate_sigwinch = 0;
15:
16: /* sigwinch_handler
17: * распространяет изменения размеров окна из входного файлового
18: * дескриптора на ведущую сторону pty.
19: */
20: void sigwinch_handler(int signal) {
21: propagate_sigwinch = 1;
22: }
23:
24:
25: /* forkptytest пытается открыть пару pty с запуском оболочки
26: * на подчиненной стороне pty.
27: */
28: int main(void) {
29: int master;
30: int pid;
31: struct pollfd ufds[2];
32: int i;
33: #define BUFSIZE 1024
34: char buf[1024];
35: struct termios ot, t;
36: struct winsize ws;
37: int done = 0;
38: struct sigaction act;
39:
40: if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) < 0) {
41: perror("ptypair: не удается получить размеры окна");
42: exit(1);
43: }
44:
45: if ((pid = forkpty(&master, NULL, NULL, &ws)) < 0) {
46: perror("ptypair");
47: exit(1);
48: }
49:
50: if (pid == 0) {
51: /* запустить оболочку */
52: execl("/bin/sh", "/bin/sh", 0);
53:
54: /* сюда управление никогда не попадет */
55: exit(1);
56: }
57:
58: /* родительский процесс */
59: /* установить обработчик SIGWINCH */
60: act.sa_handler = sigwinch_handler;
61: sigemptyset(&(act.sa_mask));
62: act.sa_flags = 0;
63: if (sigaction(SIGWINCH, &act, NULL) < 0) {
64: perror("ptypair: невозможно обработать SIGWINCH");
65: exit(1);
66: }
67:
68: /* Обратите внимание, что настройки termios устанавливаются только
69: * для стандартного ввода; ведущая сторона pty НЕ является tty.
70: */
71: tcgetattr(STDIN_FILENO, &ot);
72: t = ot;
73: t.c_lflag &= ~(ICANON | ISIG | ECHO | ECHOCTL | ECHOE |
74: ECHOK | ECHOKE | ECHONL | ECHOPRT);
75: t.c_iflag |= IGNBRK;
76: t.c_cc[VMIN] = 1;
77: t.c_cc[VTIME] = 0;
78: tcsetattr(STDIN_FILENO, TCSANOW, &t);
79:
80: /* Этот код взят без изменений из robin.с
81: * Если дочерний процесс завершается, читающая ведущая сторона
82: * дoлжнa вернуть -1 и завершиться.
83: */
84: ufds[0].fd = STDIN_FILENO;
85: ufds[0].events = POLLIN;
86: ufds[1].fd = master;
87: ufds[1].events = POLLIN;
88:
89: do {
90: int r;
91:
92: r = poll(ufds, 2, -1);
93: if ((rs < 0) && (errno != EINTR)) {
94: done = 1;
95: break;
96: }
97:
98: /* сначала проверить возможность завершения */
99: if ((ufds[0].revents | ufds[1].revents) &
100: (POLLERR | POLLHUP | POLLNVAL)) {
101: done = 1;
102: break;
103: }
104:
105: if (propagate_sigwinch) {
106: /* обработчик сигналов запросил распространение SIGWINCH */
107: if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) < 0) {
108: perror("ptypair: не удается получить размеры окна");
109: }
110: if (ioctl(master, TIOCSWINSZ, &ws) < 0) {
111: perror("не удается восстановить размеры окна");
112: }
113:
114: /* не делать этого снова до поступления следующего SIGWINCH */
Интервал:
Закладка: