That ^C handling is done by the terminal device driver, not the shell.
It's when that character is received on the wire that connects to a tty device (or written on the master side of the master side of a pseudo-terminal pair (like xterm
does when you press Ctrl+C)) that the tty line discipline (a driver in the kernel) sends the SIGINT signal to the foreground process group of the terminal.
So you'd need to send that character on the fd that xterm has open on the master side.
$ eval "$(xprop -notype -id $WINDOWID 32i '=$0\n' _NET_WM_PID)"; lsof -ap "$_NET_WM_PID" /dev/ptmx
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
xterm 21123 stephane 4u CHR 5,2 0t0 1460 /dev/ptmx
Writing it to /proc/21123/fd/4
on Linux would not work as that would just reopen /dev/ptmx
so not refer to the same pseudo-terminal. You'd need to convince that xterm
to write that ^C to its fd 4.
So not really an option.
You could start your own pseudo-terminal pair and run sh and ping` in it. Then you could write ^C on the master side for that SIGINT to be sent to the foreground process group, but easier here would be to send a signal directly (SIGTERM would be prefered).
Also note that trying to write a character on /proc/$pid/fd/0
, doesn't really make sense. The file descriptor is usually open for reading. On Linux, doing an open() on that /proc/$pid/fd/0
actually reopens the resource that that fd points to.
So for instance if sh
was started with sh < /some/file
, doing echo something > "/proc/$shpid/fd/0"
would replace the content of /some/file
with something\n
. If it was a tty, then that would just display something
on that terminal. The only case where writing something
would have that something read by sh
would be when that sh stding is a pipe. On Linux (and Linux only), if you do an open()
in write mode to /proc/$shpid/fd/0
(where that is a pipe), then that opens the writing end of that pipe (while that fd 0 actually points to the reading end).