Cloning command `script` and PTY background job problems: terminal messed up Cloning command `script` and PTY background job problems: terminal messed up unix unix

Cloning command `script` and PTY background job problems: terminal messed up


I don't use OS X, so I can't directly test your code, but I'm currently writing a toy terminal emulator and had similar troubles.

about "bash: no job control in this shell"

In order to perform job control, a shell needs to be a session leader and the controlling process of its terminal. By default, your program inherits the controlling terminal of your own shell which runs your script program and which is also a session leader. Here is how to make your new slave process a session leader after 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()

At this point, the forked process has stdin/out/err bound to the new pts, the pts became its controlling terminal, and the process is a session leader. The job control should now work.

about raw tty

When you run a program inside a normal terminal, it looks like this:

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

If you press ^Z, the terminal emulator will write the ascii character 0x1A to the pts. It is a control character, so it won't be sent to the program, but instead the kernel will issue SIGSTP to the program and suspend it. The process of transforming characters into something else is called "line cooking" and has various settings that can be adjusted for each tty.

Now let's look at the situation with script:

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

With normal line settings, what happens when you press ^Z? It will be transformed into SIGSTP by /dev/pts/42 and script will be suspended. But that's not what we want, instead we'd like the 0x1A character produced by our ^Z to go as-is through /dev/pts/42, then be passed by script to /dev/pts/43 and only then be transformed into SIGSTP to suspend the program.

This is the reason why the pts between your terminal and script must be configured as "raw", so that all control characters reach the pts between script and the program, as if you were directly working with it.