Some examples demonstrating how to inject keystrokes into a terminal's input stream.
Created
July 10, 2015 10:34
-
-
Save johnlane/6bdeac9dd5a7b0c60820 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
bind '"\e[0n": "ls -l"'; printf '\e[5n' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdlib.h> | |
#include <argp.h> | |
#include <sys/ioctl.h> | |
#include <sys/fcntl.h> | |
const char *argp_program_version ="inject - see http://unix.stackexchange.com/q/213799"; | |
static char doc[] = "inject - write to terminal input stream"; | |
static struct argp_option options[] = { | |
{ "tty", 't', "TTY", 0, "target tty (defaults to current)"}, | |
{ "nonl", 'n', 0, 0, "do not output the trailing newline"}, | |
{ 0 } | |
}; | |
struct arguments | |
{ | |
int fd, nl, next; | |
}; | |
static error_t parse_opt(int key, char *arg, struct argp_state *state) { | |
struct arguments *arguments = state->input; | |
switch (key) | |
{ | |
case 't': arguments->fd = open(arg, O_WRONLY|O_NONBLOCK); | |
if (arguments->fd > 0) | |
break; | |
else | |
return EINVAL; | |
case 'n': arguments->nl = 0; break; | |
case ARGP_KEY_ARGS: arguments->next = state->next; return 0; | |
default: return ARGP_ERR_UNKNOWN; | |
} | |
return 0; | |
} | |
static struct argp argp = { options, parse_opt, 0, doc }; | |
static struct arguments arguments; | |
static void inject(char c) | |
{ | |
ioctl(arguments.fd, TIOCSTI, &c); | |
} | |
int main(int argc, char *argv[]) | |
{ | |
arguments.fd=0; | |
arguments.nl='\n'; | |
if (argp_parse (&argp, argc, argv, 0, 0, &arguments)) | |
{ | |
perror("Error"); | |
exit(errno); | |
} | |
int a,c; | |
for (a=arguments.next, c=0; a< argc; c=0 ) | |
{ | |
while (argv[a][c]) | |
inject (argv[a][c++]); | |
if (++a < argc) inject(' '); | |
} | |
if (arguments.nl) inject(arguments.nl); | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
require "sys/ioctl.ph"; | |
ioctl(STDIN, &TIOCSTI, $_) for split "", join " ", @ARGV |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
import fcntl, sys, termios | |
del sys.argv[0] | |
for c in ' '.join(sys.argv): | |
fcntl.ioctl(sys.stdin, termios.TIOCSTI, c) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/ruby | |
ARGV.join(' ').split('').each { |c| $stdin.ioctl(0x5412,c) } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Example wrapper around injected terminal input to | |
# prevent premature echo in front of the prompt. | |
# A more basic solution is to have the prompt pre-clear its line | |
# which can be done by prefixing it with "\r\e[M" | |
inject() { | |
if [[ $0 == "$BASH_SOURCE" ]] # executed or sourced ? | |
then | |
# ioctl TIOCSTI method works best (it works if sourced or executed) | |
echo using ioctl method | |
perl -e 'ioctl(STDIN, 0x5412, $_) for split "", join " ", @ARGV' "$@" "" | |
else | |
# escape method only works if script is sourced | |
echo using bind method | |
bind "\"\e[0n\": '$*'"; printf '\e[5n' | |
fi | |
} | |
saved_settings=$(stty -g) | |
stty -echo -icanon min 1 time 0 | |
inject echo $* | |
until read -t0; do | |
sleep 0.02 | |
done | |
stty "$saved_settings" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment