crocboy crocboy - 16 days ago 5
C Question

Sending SIGINT through stdin

I'm currently writing an application that allows users to access the bash shell of a remote machine through telnet. The application is a telnet server that runs on the remote machine. I am piping the output from the telnet stream into a bash process that I spawned like so:

char *execArgs[] = {"/bin/bash", "-i", 0};
execv(execArgs[0], execArgs);


I am able to do almost everything you can do in a normal shell; typing commands, backspacing, etc. However, I am having problems killing tasks with CTRL+C. When I receive a CTRL+C sequence from the telnet end, it comes in as [0xFF][0xF8]. The FF puts the telnet into IAC mode (allowing it to interpret commands), and the F8 tells my program to send an ETX (0x03):

char tmpchar = 3;
retval = write(outfd[1], &tmpchar, 1);
fflush(fstdin);


Where outfd is the stream into the bash process. However, I don't think the
0x03
is being interpreted as a SIGINT signal, or at least it isn't killing the currently running task. Why would this be?

Answer

Since you have no terminal, you cannot expect any terminal functions. So if you send a ^C down the pipe, a ^C will come out of the pipe. You can use kill to send a SIGINT to the process.

But you'd be much better off using a terminal to talk to bash! Shells expect to interact with terminals, not pipes. Punch man pty into your system to start learning how to do it right.

From the pty(7) man page:

A pseudoterminal (sometimes abbreviated "pty") is a pair of virtual character devices that provide a bidirectional communication channel. One end of the channel is called the master; the other end is called the slave. The slave end of the pseudoterminal provides an interface that behaves exactly like a classical terminal. A process that expects to be connected to a terminal, can open the slave end of a pseudoterminal and then be driven by a program that has opened the master end.

Anything that is written on the master end is provided to the process on the slave end as though it was input typed on a terminal. For example, writing the interrupt character (usually control-C) to the master device would cause an interrupt signal (SIGINT) to be generated for the foreground process group that is connected to the slave. Conversely, anything that is written to the slave end of the pseudoterminal can be read by the process that is connected to the master end. Pseudoterminals are used by applications such as network login services (ssh(1), rlogin(1), telnet(1)), terminal emulators, script(1), screen(1), and expect(1).

This is what you want.