apue 第19章 偽終端
阿新 • • 發佈:2017-12-29
fcntl 文件 分享 奇偶校驗 solaris file 訪問 tde for
偽終端是指對於一個應用程序而言,他看上去像一個終端,但事實上它並不是一個真正的終端。
- 進程打開偽終端設備,然後fork。子進程建立一個新的會話,打開一個相應的偽終端從設備。復制輸入、輸出和標準錯誤文件描述符,調用exec,子進程從設備編程偽終端。
- 偽終端能像終端一樣,但是無意義的函數調用如改變波特率、發送中斷符、設置奇偶校驗將被忽略。
- 偽終端可以做輸入和輸出。
posix_opent函數提供了一種可移植的方法來打開下一個可用偽終端主設備
#include <stdlib.h> #include <fcntl.h> int posix_openpt(int flags); 返回值:成功返回下一個可用的PTY主設備文件描述符,出錯-1 flags:設備操作標記,可以是0或者以下兩項的之一,O_RDWR允許對設備同時進行讀寫操作,此標記通常需要指定
O_NOCTTY不將設備作為進程的控制終端
在偽終端從設備可用之前,它的權限必須設置,以便應用程序可以訪問它。
改變指定master對應從設備的屬主與訪問權限
#define _XOPEN_SOURCE #include <stdlib.h> int grantpt(int fd);
int unlockpt(int fd);
返回值:成功0,出錯-1
fd:文件描述符
ptsname返回PTY從設備的名字
#define _XOPEN_SOURCE #include<stdlib.h> char *ptsname(int fd); #define _GNU_SOURCE #include <stdlib.h> int ptsname_r(int fd, char *buf, size_t buflen);
fd:文件描述符
apue寫的函數,打開下一個可用的PTY主設備。調用者必須分配一個數組來存放主設備或從設備名字。
#include "apue.h" int ptym_open(char *pts_name, int pts_namesz); 返回值:成功返回PTY主設備文件描述符,出錯-1 int ptys_open(char*pts_name);
返回值:成功返回PTY設備文件描述符,出錯-1
pts_name:打開設備的名字
pts_namesz:緩沖區字節長度
實現函數:
#include "apue.h" #include <errno.h> #include <fcntl.h> #if defined(SOLARIS) #include <stropts.h> #endif int ptym_open(char *pts_name, int pts_namesz) { char *ptr; int fdm, err; if((fdm = posix_openpt(O_RDWR)) < 0) return(-1); if(grantpt(fdm) < 0) goto errout; if(unlock(fdm) < 0) goto errout; if((ptr = ptsname(fmd)) == NULL) goto errout; strncpy(pts_name, ptr, pts_namesz); pts_name[pts_namesz - 1] = ‘\0‘; return(fdm); errout: err = errno; close(fdm); errno = err; return(-1); } int ptys_open(char *pts_name) { int fds; #if defined(SOLARIS) int err, setup; #endif if((fds = open(pts_name, O_RDWR)) < 0) goto errout; if(setup == 0) { if(ioctl(fds, I_PUSH, "ptem") < 0) goto errout; if(ioctl(fds, I_PUSH, "ldterm") < 0) goto errout; if(ioctl(fds, I_PUSH, "ttcompat") < 0) { errout: err = errno; close(fds); errno = err; return(-1); } } #endif return(fds); }pty_open
用fork調用打開主設備和從設備,創建作為會話首進程的子進程並使其具有控制終端。
#include "apue.h" #include <termios.h> pid_t pty_fork(int *ptrfdm, char *slave_name, int slave_namesz, const struct termios *slave_termios, const struct winsize *slave_winsize);
pty_fork函數
1 #include "apue.h" 2 #include <termios.h> 3 4 pid_t pty_fork(int *ptrfdm, char *slave_name, int slave_namesz, 5 const struct termios *slave_termios, 6 const struct winsize *slave_winsize) 7 { 8 int fdm, fds; 9 pid_t pid; 10 char pts_name[20]; 11 12 if((fdm = ptym_open(pts_name, sizeof(pts_name))) < 0) 13 err_sys("can‘t open master pty: %s, error %d", pts_name, fdm); 14 15 if(slave_name != NULL) { 16 strncpy(slave_name, pts_name, slave_namesz); 17 slave_name[slave_namesz - 1] = ‘\0‘; 18 } 19 20 if((pid = fork()) < 0) 21 return(-1); 22 else if(pid == 0) { /* childe */ 23 if(setsid() < 0) 24 err_sys("setsid error"); 25 26 if((fds = ptys_open(pts_name)) < 0) 27 err_sys("can‘t open slave pty"); 28 close(fdm); 29 #if defined(BSD) 30 if(ioctl(fds, TIOCSCTTY, (char *)0) < 0) 31 err_sys("TIOCSCTTY error"); 32 #endif 33 if(slave_termios != NULL) { 34 if(tcsetattr(fds, TCSANOW, slave_termios) < 0) 35 err_sys("tcsetattr error on slave pty"); 36 } 37 if(slave_winsize != NULL) { 38 if(ioctl(fds, TIOCSWINSZ, slave_winsize) < 0) 39 err_sys("TIOCSWINSZ error on slave pty"); 40 } 41 42 if(dup2(fds, STDIN_FILENO) != STDIN_FILENO) 43 err_sys("dup2 error to stdin"); 44 if(dup2(fds, STDOUT_FILENO) != STDOUT_FILENO) 45 err_sys("dup2 error to stdout"); 46 if(dup2(fds, STDERR_FILENO) != STDERR_FILENO) 47 err_sys("dup2 error to stderr"); 48 if(fds != STDIN_FILENO && fds != STDOUT_FILENO && 49 fds != STDERR_FILENO) 50 close(fds); 51 return(0); 52 } else { 53 *ptrfdm = fdm; 54 return(pid); 55 } 56 }pty_fork
apue 第19章 偽終端