gpt4 book ai didi

克隆命令 `script` 和 PTY 后台作业问题 : terminal messed up

转载 作者:太空狗 更新时间:2023-10-29 15:07:12 26 4
gpt4 key购买 nike

我正在尝试重新编码 UNIX 命令 script(因为它在 OSX 上)。这是学校帮助学生学习 UNIX API 的练习的一部分。我们只能使用系统调用,更具体地说,只能使用 Mac OSX 上 MAN(2) 页面上可用的系统调用(因为这是我们学校的操作系统)。

我有一个这样的作品的“第一版”。运行诸如 ls 之类的程序会将正确的输出打印到屏幕和输出文件中。

问题场景

我从 script 克隆中运行 bash。第一个问题是我收到以下错误:
bash:此 shell 中没有作业控制

我已经尝试使用 setpgrpsetpgidbash 进程强制进入前台,但这并没有改变任何东西,所以我得出结论,这不是问题。

我也试图理解为什么真正的 script 命令使用 cfmakeraw(至少在 Linux 上),如 here 所示,但我不明白。 MAN 页面不是很有帮助。

真正的脚本也是dup2slave上的STDIN,如here所示,但是当我这样做时,似乎不再读取输入。

但是,bash 仍在运行,我可以在其中执行命令。

但是如果我在其中运行 vim,然后按 Ctrl-Z 将 vim 置于后台,终端就会困惑(当我'在我的常规终端中)。

所以我想我一定做错了什么。如果有任何建议/帮助,我将不胜感激。


这是源代码: https://github.com/conradkleinespel/unix-command-script/tree/2587b07e7a36dc74bf6dff0e82c9fdd33cb40411

您可以通过以下方式进行编译:make(它基于 OSX 10.9,希望也适用于 Linux)

然后运行:./ft_script

不知道将所有源代码放在 StackOverflow 中更有意义,因为它会挤满页面。如果需要,我可以用源代码替换 Git 链接。

最佳答案

我不使用 OS X,所以我不能直接测试你的代码,但我目前正在编写一个玩具终端模拟器并且遇到了类似的麻烦。

关于“bash:此 shell 中没有作业控制”

为了执行作业控制,shell 需要是其终端的 session 领导者控制进程。默认情况下,您的程序会继承您自己的 shell 的控制终端,该终端运行您的 script 程序,它也是 session 领导者。以下是如何在 fork 之后使您的新从属进程成为 session 领导者:

/* we don't need the inherited master fd */
close(master);
/* discard the previous controlling tty */
ioctl(0, TIOCNOTTY, 0);
/* replace existing stdin/out/err with the slave pts */
dup2(slave, 0);
dup2(slave, 1);
dup2(slave, 2);
/* discard the extra file descriptor for the slave pts */
close(slave);
/* make the pts our controlling terminal */
ioctl(0, TIOCSCTTY, 0);
/* make a new session */
setsid()

此时, fork 进程将stdin/out/err 绑定(bind)到新的pts,pts 成为它的控制终端,进程是 session 领导者。作业控制现在应该可以工作了。

关于原始 tty

当您在普通终端中运行程序时,它看起来像这样:

(term emulator, master side) <=> /dev/pts/42 <=> (program, slave side)

如果您按^Z,终端仿真器会将ascii 字符0x1A 写入pts。它是一个控制字符,因此不会发送给程序,而是内核会向程序发出SIGSTP 并暂停它。将字符转换成其他东西的过程称为“线 cooking ”,并且具有可以针对每个 tty 进行调整的各种设置。

现在让我们看看脚本的情况:

term emulator <=> /dev/pts/42 <=> script <=> /dev/pts/43 <=> program

在正常的线路设置下,当您按下 ^Z 时会发生什么?会被/dev/pts/42转化为SIGSTPscript会被挂起。但这不是我们想要的,相反,我们希望 ^Z 生成的 0x1A 字符按原样通过 /dev/pts/42,然后被script传递给/dev/pts/43,然后才被转化为SIGSTP来暂停程序。

这就是为什么你的终端和脚本之间的点必须配置为“原始”的原因,这样所有的控制字符都可以到达脚本和程序之间的点,就像你直接工作一样与它。

关于克隆命令 `script` 和 PTY 后台作业问题 : terminal messed up,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23443159/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com