克隆命令`script`和PTY后台作业问题:终端搞砸了

时间:2014-05-03 10:23:39

标签: c macos unix

我试图重新编写UNIX命令script(就像它在OSX上一样)。这是学校帮助学生学习UNIX API的练习的一部分。我们只允许使用系统调用,更具体地说,只允许使用Mac OSX上的MAN(2)页面上的那些(因为那是我们在学校的操作系统)。

我有第一个版本'那种作品。运行ls等程序会将正确的输出打印到屏幕和输出文件中。

问题场景

我从bash克隆中运行script。第一个问题是我收到以下错误: bash: no job control in this shell

我尝试使用bashsetpgrp强制setpgid进程进入前台,但是没有改变任何内容,所以我认为这不是问题。

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

script上的真实dup2slave个STDIN,如here所示,但是当我这样做时,似乎输入无法读取了。

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

但是如果我在其中运行vim,然后点击Ctrl-Z将vim放到后台,终端就会搞砸(当我在我的时候不会发生这种情况常规终端)。

所以我想我一定做错了。我很感激任何建议/帮助。


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

您可以通过执行以下操作进行编译:{{1​​}}(它建立在OSX 10.9上,希望在Linux上也是如此)

执行:make

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

1 个答案:

答案 0 :(得分:2)

我不使用OS X,因此我无法直接测试您的代码,但我目前正在编写玩具终端模拟器并遇到类似问题。

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

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

/* 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()

此时,分叉进程已将stdin / out / err绑定到新pts,pts成为其控制终端,并且该进程是会话负责人。工作控制现在应该有效。

关于原始tty

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

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

如果按^Z,终端模拟器会将ascii字符0x1A写入pts。它是一个控制字符,因此它不会被发送到程序,而是内核会向程序发出SIGSTP并暂停它。将字符转换为其他字符的过程称为“行烹饪”,并具有可针对每个tty进行调整的各种设置。

现在让我们看一下script的情况:

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

使用普通线路设置,当您按^Z时会发生什么?它将被SIGSTP转换为/dev/pts/42script将被暂停。但这不是我们想要的,而是我们希望0x1A生成的^Z字符按原样/dev/pts/42生成,然后由script传递给{ {1}}然后才转换为/dev/pts/43以暂停程序。

这就是为什么你的终端和脚本之间的pts必须配置为“raw”的原因,这样所有控制字符都会到达SIGSTP和程序之间的pts,就像你直接使用它一样。