Linux 伪终端的基本原理 及其在远程登录(SSH,(4)

gcc -o ptmxtest ptmxtest.c mkfifo /tmp/p nc -l 2333 </tmp/p | ./ptmxtest >/tmp/p

至此,图中的②构建完毕,已经有一个nc在监听2333端口,它的输入输出通过管道送到ptmxtest程序中,ptmxtest又将这些信息搬运给master端。

在我的Ubuntu中运行命令后显示,创建的slave设备文件是/dev/pts/20。

服务端①:将login程序与终端关联起来

在图中①处的地方,需要将login与伪终端的输入输出关联起来。这一点通过输入输出重定向即可完成。不过,想要实现Ctrl+C等作业控制,还需要更多的设置。这涉及到一些Linux的进程管理的知识(感兴趣的可以去搜索“进程、进程组、会话、控制终端”等关键字)。

一个进程与终端的联系,不仅取决于它的输入输出,还有它的控制终端(Controlling terminal,可通过tty命令查询,通过/dev/tty打开)。简单地说,进程控制终端是谁,谁才能向进程发送控制信号。这里要将login的控制终端设为伪终端,具体说是slave设备文件才行。

设置控制终端需要使用终端设备的ioctl来实现。查看man tty_ioctl,可以找到相关信息:

Controlling terminal
TIOCSCTTY int arg
Make the given terminal the controlling terminal of the calling process. The calling process must be a session leader and not have a controlling terminal already. For this case, arg should be specified as zero.

...

TIOCNOTTY void
If the given terminal was the controlling terminal of the calling process, give up this controlling terminal. ...

比较重要的信息是,我们可以指定TIOCSCTTY参数来设置控制终端,但它要求调用者是没有控制终端的会话组长(Session leader)。所以要先指定TIOCNOTTY参数来放弃当前控制终端,并用setsid函数(man 2 setsid)创建新的会话并设置自己为组长。

我们将login包装一层,完成上面的操作,得到新的程序mylogin:

//mylogin.c #include<stdio.h> #define _XOPEN_SOURCE #include<stdlib.h> #include<unistd.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<termios.h> #include<sys/ioctl.h> int main(int argc, char *argv[]) { int old=open("/dev/tty",O_RDWR); //打开当前控制终端 ioctl(old, TIOCNOTTY); //放弃当前控制终端 //根据"man 2 setsid"的说明,调用setsid的进程不能是进程组组长(从bash中运行的命令是组长),故fork出一个子进程,让组长结束,子进程脱离进程组成为新的会话组长 int pid=fork(); if(pid==0){ setsid(); //子进程成为会话组长 perror("setsid"); //显示setsid是否成功 ioctl(0, TIOCSCTTY, 0); //这时可以设置新的控制终端了,设置控制终端为stdin execv("/bin/login", argv); //把当前进程刷成login } return 0; }

保存文件后,打开一个终端(称为终端B),编译运行:

gcc -o mylogin mylogin.c #假设这里的slave设备是/dev/pts/20 #因为login要读取密码文件,需要用root权限执行 sudo ./mylogin </dev/pts/20 >/dev/pts/20 2>&1

该命令将实验图中①处的slave设备,重定向至mylogin的stdin、stdout和stderr。在程序执行时,会将控制终端设置为伪终端,然后执行login。至此,服务端全部建立完毕。

客户端:连接远程机器,配置本地终端

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/13436.html