2 * Writes the command line arguments (or standard input) to a tty using
3 * the TIOCSTI ioctl. This will typically require root access, the
4 * setuid bit set on this binary (danger!), or on Linux the appropriate
5 * capability granted. The bytes will be written as given, except on the
6 * command line a space will be written between each argument, and a
7 * final newline written if the -N option is set.
9 * Notable codes (via ttytest.c testing on Mac OS X) include:
11 * sudo ttywrite $(tty) $'\003' # SIGINT
12 * sudo ttywrite $(tty) $'\004' # EOF
13 * sudo ttywrite $(tty) $'\014' # clear (control+l)
14 * sudo ttywrite $(tty) $'\020' # SIGINFO
15 * sudo ttywrite $(tty) $'\020' # SIGTSTP
16 * sudo ttywrite $(tty) $'\020' # SIGQUIT
19 #include <sys/ioctl.h>
21 #if defined(__FreeBSD__) || defined(__OpenBSD__)
22 #include <sys/ttycom.h>
34 // https://github.com/thrig/goptfoo
38 void tty_write(int fd
, int argc
, char *argv
[], useconds_t delay
);
40 useconds_t Flag_Delay
= 0; // -d delay in milliseconds
41 bool Flag_Newline
= false; // -N
43 int main(int argc
, char *argv
[])
47 while ((ch
= getopt(argc
, argv
, "d:h?N")) != -1) {
50 /* KLUGE useconds_t is "unsigned int" on *BSD at time of
51 * writing so assume that as max for usleep(3) */
52 Flag_Delay
= (useconds_t
)
53 flagtoul(ch
, optarg
, 0UL,
54 (unsigned long) UINT_MAX
/ 1000) * 1000;
72 if ((fd
= open(*argv
, O_WRONLY
)) == -1)
73 err(EX_IOERR
, "could not open '%s'", *argv
);
74 tty_write(fd
, --argc
, ++argv
, Flag_Delay
);
82 fprintf(stderr
, "Usage: ttywrite [-d delayms] [-N] dev [command...|-]\n");
86 void tty_write(int fd
, int argc
, char *argv
[], useconds_t delay
)
90 if (argc
== 0 || ((*argv
)[0] == '-' && (*argv
)[1] == '\0')) {
91 while ((c
= getchar()) != EOF
) {
92 ioctl(fd
, TIOCSTI
, &c
);
97 err(EX_IOERR
, "error reading from standard input");
103 while (**argv
!= '\0') {
104 ioctl(fd
, TIOCSTI
, (*argv
)++);
108 ioctl(fd
, TIOCSTI
, " ");
113 ioctl(fd
, TIOCSTI
, "\n");