主要函数

NAME

openpty, login_tty, forkpty - tty utility functions

SYNOPSIS

#include

int openpty(int *amaster, int *aslave, char *name,

struct termios *termp, struct winsize *winp);

pid_t forkpty(int *amaster, char *name, struct termios *termp,

struct winsize *winp);

#include

int login_tty(int fd);

Link with -lutil.

DESCRIPTION

The openpty() function finds an available pseudo-terminal and returns file descriptors for the master and slave in amaster and aslave. If name is not NULL, the filename of the slave is returned in name. If termp is not NULL, the terminal parameters of the slave will be set to the values in termp. If winp is not NULL, the window size of the slave will be set to the values in winp.

The login_tty() function prepares for a login on the tty fd (which may be a real tty device, or the slave of a pseudo-terminal as returned by openpty()) by creating a new session, making fd the controlling terminal for the calling process, setting fd to be the standard input, output, and error streams of the current process, and closing fd.

The forkpty() function combines openpty(), fork(2), and login_tty() to create a new process operating in a pseudo-terminal. The file descriptor of the master side of the pseudo-terminal is returned in amaster, and the filename of the slave in name if it is not NULL. The termp and winp arguments, if not NULL, will determine the terminal attributes and window size of the slave side of the pseudo-terminal.

RETURN VALUE

If a call to openpty(), login_tty(), or forkpty() is not successful, -1 is returned and errno is set to indicate the error. Otherwise, openpty(), login_tty(), and the child process of forkpty() return 0, and the parent process of forkpty() returns the process ID of the child process.

ERRORS

openpty() will fail if:

ENOENT There are no available ttys.

login_tty() will fail if ioctl(2) fails to set fd to the controlling terminal of the calling process.

forkpty() will fail if either openpty() or fork(2) fails.

CONFORMING TO

These are BSD functions, present in libc5 and glibc2.

用例

通常的例子像下面一样

用例一

交互式

//

// Created by : Harris Zhu

// Filename : main.c

// Author : Harris Zhu

// Created On : 2017-11-26 18:06:44

// Last Modified : 2017-11-26 18:06:44

// Update Count : 1

// Tags :

// Description :

// Conclusion :

//

//=======================================================================

#define _XOPEN_SOURCE 600

#include

#include

#include

#include

#include

#include

# include /* for openpty and forkpty */

#include

int main(void)

{

int fdm, fds, rc;

char input[150];

char sptyname[20]={'\0'};

int rtn;

int i=0;

rtn = openpty(&fdm, &fds, sptyname, NULL, NULL);

printf("slave name is %s\n", sptyname);

if (rtn != -1)

{

if (fork())

{

// parent

close(fds);

while (i<50)

{

write(1, "Input : ", sizeof("Input : "));

rc = read(0, input, sizeof(input));

if (rc > 0)

{

// Write the input to the child process through PTY

write(fdm, input, rc);

// Read the child's answer through PTY

rc = read(fdm, input, sizeof(input) - 1);

if (rc > 0)

{

input[rc] = '\0';

printf("%s", input);

}

else

{

break;

}

}

} // end while

}

else

{

// Child

close(fdm);

struct termios slave_orig_term_settings; // Saved terminal settings

struct termios new_term_settings; // Current terminal settings

// Save the default parameters of the slave side of the PTY

rc = tcgetattr(fds, &slave_orig_term_settings);

// Set raw mode on the slave side of the PTY

new_term_settings = slave_orig_term_settings;

cfmakeraw (&new_term_settings);

tcsetattr (fds, TCSANOW, &new_term_settings);

// The slave side of the PTY becomes the standard input and outputs of the child process

close(0); // Close standard input (current terminal)

close(1); // Close standard output (current terminal)

close(2); // Close standard error (current terminal)

dup(fds); // PTY becomes standard input (0)

dup(fds); // PTY becomes standard output (1)

dup(fds); // PTY becomes standard error (2)

while (i++<50)

{

rc = read(fds, input, sizeof(input) - 1);

if (rc > 0)

{

input[rc - 1] = '\0';

printf("Child received : '%s'\n", input);

}

else

{

break;

}

} // End while

}

}

return 0;

}

gcc -o main main0.c -lutil

例子二

下面是非交互的例子

//

// Created by : Harris Zhu

// Filename : main.c

// Author : Harris Zhu

// Created On : 2017-11-26 18:06:44

// Last Modified : 2017-11-26 18:06:44

// Update Count : 1

// Tags :

// Description :

// Conclusion :

//

//=======================================================================

#define _XOPEN_SOURCE 600

#include

#include

#include

#include

#include

#include

# include

# include

# include /* for openpty and forkpty */

#include /* for login_tty */

#include

int main(void)

{

int fdm, fds, rc;

char sptyname[20]={'\0'};

char input[150];

int rtn;

int i=0;

rtn = openpty(&fdm, &fds, sptyname, NULL,NULL);

if(rtn != -1)

{

printf("slave name is %s\n", sptyname);

if (fork())

{

// Parents

close(fds);

while (i<50)

{

sprintf(input, "the time is %d\n", i++);

write(fdm, input, strlen(input));

rc = read(fdm, input, sizeof(input) - 1);

if (rc > 0)

{

input[rc] = '\0';

printf("%s", input);

}

else

{

break;

}

} // End while

}

else

{

// Child

close(fdm);

struct termios slave_orig_term_settings; // Saved terminal settings

struct termios new_term_settings; // Current terminal settings

// Save the default parameters of the slave side of the PTY

rc = tcgetattr(fds, &slave_orig_term_settings);

// Set raw mode on the slave side of the PTY

new_term_settings = slave_orig_term_settings;

cfmakeraw (&new_term_settings);

tcsetattr (fds, TCSANOW, &new_term_settings);

// The slave side of the PTY becomes the standard input and outputs of the child process

close(0); // Close standard input (current terminal)

close(1); // Close standard output (current terminal)

close(2); // Close standard error (current terminal)

dup(fds); // PTY becomes standard input (0)

dup(fds); // PTY becomes standard output (1)

dup(fds); // PTY becomes standard error (2)

int i=0;

while (i++<50)

{

rc = read(fds, input, sizeof(input) - 1);

if (rc > 0)

{

input[rc - 1] = '\0';

printf("Child received : '%s'\n", input);

}

else

{

break;

}

} // End while

}

}

return 0;

}

上面如果在child里不创建新的term属性,那么在parent进程里,每次write到mpty里的字符会被下一行的read读到,然后输出就会是重复的字符

On the slave side we can note the calls to cfmakeraw() and tcsetattr() to reconfigure the slave side of the pty. This sets the raw mode to disable the echoing among other things.

$ ./main

slave name is /dev/pts/1

the time is 0

Child received : 'the time is 0'

the time is 1

Child received : 'the time is 1'

the time is 2

Child received : 'the time is 2'

the time is 3

Child received : 'the time is 3'

the time is 4

Child received : 'the time is 4'

the time is 5

Child received : 'the time is 5'

the time is 6

Child received : 'the time is 6'

the time is 7

Child received : 'the time is 7'

the time is 8

奇怪的是把上面的cfmakeraw()和tcsetattr()改成login_tty(fds), 还是有回显问题。

用例三

读取另一个程序的输入输出

//

// Created by : Harris Zhu

// Filename : main0.c

// Author : Harris Zhu

// Created On : 2017-11-29 18:02:08

// Last Modified : 2017-11-29 18:02:08

// Update Count : 1

// Tags :

// Description :

// Conclusion :

//

//=======================================================================

#define _XOPEN_SOURCE 600

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

int main(int ac, char *av[])

{

int fdm, fds;

int rc;

char input[150];

char fdsname[150];

// Check arguments

if (ac <= 1)

{

fprintf(stderr, "Usage: %s program_name [parameters]\n", av[0]);

exit(1);

}

if (openpty(&fdm, &fds, fdsname, NULL, NULL) == -1)

{

fprintf(stderr, "error open pty pairs\n");

exit(1);

} else {

printf("the slave is %s\n", fdsname);

}

// Create the child process

if (fork())

{

// FATHER

// Close the slave side of the PTY

close(fds);

fd_set fd_in;

while (1)

{

// Wait for data from standard input and master side of PTY

FD_ZERO(&fd_in);

FD_SET(0, &fd_in);

FD_SET(fdm, &fd_in);

rc = select(fdm + 1, &fd_in, NULL, NULL, NULL);

switch(rc)

{

case -1 :

{

fprintf(stderr, "Error %d on select()\n", errno);

exit(1);

}

default :

{

// If data on standard input

if (FD_ISSET(0, &fd_in))

{

rc = read(0, input, sizeof(input));

if (rc > 0)

{

// Send data on the master side of PTY

write(fdm, input, rc);

}

else

{

if (rc < 0)

{

fprintf(stderr, "Error %d on read standard input\n", errno);

exit(1);

}

}

}

// If data on master side of PTY

if (FD_ISSET(fdm, &fd_in))

{

rc = read(fdm, input, sizeof(input));

if (rc > 0)

{

// Send data on standard output

write(1, input, rc);

}

else

{

if (rc < 0)

{

fprintf(stderr, "Error %d on read master PTY\n", errno);

exit(1);

}

}

}

}

} // End switch

} // End while

}

else

{

// CHILD

// Close the master side of the PTY

close(fdm);

struct termios slave_orig_term_settings; // Saved terminal settings

struct termios new_term_settings; // Current terminal settings

// Save the defaults parameters of the slave side of the PTY

rc = tcgetattr(fds, &slave_orig_term_settings);

// Set RAW mode on slave side of PTY

new_term_settings = slave_orig_term_settings;

cfmakeraw (&new_term_settings);

tcsetattr (fds, TCSANOW, &new_term_settings);

// The slave side of the PTY becomes the standard input and outputs of the child process

close(0); // Close standard input (current terminal)

close(1); // Close standard output (current terminal)

close(2); // Close standard error (current terminal)

dup(fds); // PTY becomes standard input (0)

dup(fds); // PTY becomes standard output (1)

dup(fds); // PTY becomes standard error (2)

// Now the original file descriptor is useless

close(fds);

// Make the current process a new session leader

setsid();

// As the child is a session leader, set the controlling terminal to be the slave side of the PTY

// (Mandatory for programs like the shell to make them manage correctly their outputs)

// ioctl(0, TIOCSCTTY, 1);

ioctl(0, TIOCSCTTY, 1);

// Execution of the program

{

char **child_av;

int i;

// Build the command line

child_av = (char **)malloc(ac * sizeof(char *));

for (i = 1; i < ac; i ++)

{

child_av[i - 1] = strdup(av[i]);

}

child_av[i - 1] = NULL;

rc = execvp(child_av[0], child_av);

}

// if Error...

return 1;

}

return 0;

}

运行结果如下:

$ ./main bc

the slave is /dev/pts/1

bc 1.06.95

Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.

This is free software with ABSOLUTELY NO WARRANTY.

For details type `warranty'.

1+2

3

4*5

20

quit

Error 5 on read master PTY

telnet结构

expect的结构

linux openpty函数,pseudo-terminal 基础一相关推荐

  1. Linux 鸟叔的私房菜 基础学习篇(第四版) 课后习题答案

    答案仅供参考,来源于本人和网上,并非绝对正确,请酌情参考! 文章目录 第零章 计算机概论 第一章 Linux是什么与如何学习 第二章 主机划分与磁盘分区 第三章 安装CentOs 7.x 第四章 首次 ...

  2. Linux下Mysql数据库的基础操作

    Linux下Mysql数据库的基础操作 一.Mysql数据介绍 二.数据库相关术语介绍 1.数据库相关名词 2.相关术语介绍 三.Mysql数据库的管理 1.创建数据库用户 2.查询用户状态 3.修改 ...

  3. console、tty、pts、pty、Terminal、Physical console、Virtual console、Pseudo Terminal关系解析...

    前言: 为什么想到写这个话题,其实源于客户在排查用户登录,问到与用户登录相关的tty格式?有哪些,有什么区别?原以为10多年小机系统管理经验,回答应该so easy,突然发现解释起来有点乱,所以梳理了 ...

  4. linux fork函数的精辟解说

    此文原文来源于一个blog,文章的名称为:linux fork函数的精辟解说原文地址:http://blog.chinaunix.net/space.php?uid=12461657&do=b ...

  5. Linux 系统应用编程——线程基础

    传送门:Linux多线程编程实例解析 . linux多线程编程--同步与互斥 . 传统多任务操作系统中一个可以独立调度的任务(或称之为顺序执行流)是一个进程.每个程序加载到内存后只可以唯一地对应创建一 ...

  6. Linux系统编程25:基础IO之亲自实现一个动静态库

    本文接:Linux系统编程24:基础IO之在Linux下深刻理解C语言中的动静态库以及头文件和库的关系 文章目录 A:说明 B:实现静态库 C:实现动态库 A:说明 前面说过,库其实就是头文件和和.a ...

  7. 【分享】4412开发板-嵌入式Linux开发须要掌握的基础知识和技能

    本文转自迅为电子论坛:http://www.topeetboard.com 1.Linux 基础 安装Linux操作系统 Linux文件系统 Linux经常使用命令 Linux启动过程具体解释 熟悉L ...

  8. linux第一阶段学习笔记基础

    linux学习 day01 1.计算机基础 运维人员的职责: 7*24是服务器稳定运行 数据不能丢失损坏 提升用户体验 常见的服务器种类 DELL DELL 1U 2U 2010 1850/1950 ...

  9. 关于Linux下C语言开发基础的实验内容。

    Linux下C语言开发基础实验内容 目录 1.Linux下C语言开发流程 2.vi,vim编辑器的使用 3.Gcc编译器的使用 总体选项: 警告选项: 4.GDB 基本命令的使用 5.Make 工程管 ...

  10. linux下wait函数,Linux wait函数详解

    wait和waitpid出现的原因 SIGCHLD --当子进程退出的时候,内核会向父进程SIGCHLD信号,子进程的退出是个异步事件(子进程可以在父进程运行的任何时刻终止) --子进程退出时,内核将 ...

最新文章

  1. python装饰器教学_Python装饰器学习(九步入门)
  2. 使用JackJSON 流式API 创建JSON串【学习记录】
  3. (1)java虚拟机概念和结构图
  4. 2016 - 1 - 19NSOpertation的依赖关系和监听
  5. php-fpm中启用慢日志配置
  6. mysql binlog2sql闪回数据
  7. SAP信用控制配置事物码
  8. android 清除矩形
  9. Leetcode | Pow(x, n)
  10. 配置centos防火墙(iptables)开放80端口
  11. mysql创建数据库指定utf 8_MySQL创建数据库时指定编码utf8mb4和添加用户
  12. iOS 使用CocoaPods
  13. 全国草地资源类型分布数据/植被类型分布数据/土地利用类型分布数据
  14. RHEL 7.0安装配置LAMP服务器(Apache+PHP+MariaDB)
  15. ubuntu上常用的软件安装
  16. java源码社团管理系统_基于jsp的社团管理系统-JavaEE实现社团管理系统 - java项目源码...
  17. hdu 5053 水
  18. activiti 获取审批人员_Activiti审批汇总流程
  19. 【2.skynet c gate服务中databuffer解析(解包)】
  20. 固定资产管理系统能给行政和IT人员带来什么?

热门文章

  1. 刍议当代大学生恋爱观
  2. 浪潮存储通过ISCSI映射至Linux服务器、多路径配置方法
  3. 使用 SSH config 文件
  4. Wifi文件传输项目总结
  5. 剑指 Offer 46. 把数字翻译成字符串 【 c++/java详细题解 】
  6. ajax向后台传递参数为对象实例
  7. 离散数学——coq学习笔记(一)
  8. ios 故事板跳转
  9. MySQL variables、procedure、function、trigger [vaynexiao]
  10. Next.js 中的路由初学者指南,附有示例