How to send ^D / EOT character to stdin of a shell process?
Suppose I have two shells open, one with PID 1234 and the other - 5678.
I can clear the screen and reset of the other shell via echo $'33c' > /proc/1234/fd/0
as if reset
was typed on the prompt of the terminal itself. However, when I do echo $'4' > /proc/1234/fd/0
to send EOT character, this doesn't seem to work. How can I achieve the desired effect ?
command-line escape-characters
|
show 1 more comment
Suppose I have two shells open, one with PID 1234 and the other - 5678.
I can clear the screen and reset of the other shell via echo $'33c' > /proc/1234/fd/0
as if reset
was typed on the prompt of the terminal itself. However, when I do echo $'4' > /proc/1234/fd/0
to send EOT character, this doesn't seem to work. How can I achieve the desired effect ?
command-line escape-characters
2
Perhaps send SIGHUP, since you cannot send EOF.
– Thomas Dickey
Jan 10 at 0:48
@ThomasDickey EOF is not a character, EOT however is actually on the list of ASCII characters, hex 04 value. That's what I'm trying to send. Heemayls answer there isn't accurate, I think.
– Sergiy Kolodyazhnyy
Jan 10 at 0:56
Maybe because you're in canonical mode so such bytes would be consumed by tty driver before it get send.
– 炸鱼薯条德里克
Jan 10 at 0:56
@炸鱼 OK, how do I check if I'm canonical mode ?
– Sergiy Kolodyazhnyy
Jan 10 at 1:00
stty -a
will dump the terminal settings for the current terminal. In the flags portion you will seeicanon
, the canonical flag. If this flag is preceded by an-
then it is off, no dash then its on.
– datUser
Jan 10 at 1:27
|
show 1 more comment
Suppose I have two shells open, one with PID 1234 and the other - 5678.
I can clear the screen and reset of the other shell via echo $'33c' > /proc/1234/fd/0
as if reset
was typed on the prompt of the terminal itself. However, when I do echo $'4' > /proc/1234/fd/0
to send EOT character, this doesn't seem to work. How can I achieve the desired effect ?
command-line escape-characters
Suppose I have two shells open, one with PID 1234 and the other - 5678.
I can clear the screen and reset of the other shell via echo $'33c' > /proc/1234/fd/0
as if reset
was typed on the prompt of the terminal itself. However, when I do echo $'4' > /proc/1234/fd/0
to send EOT character, this doesn't seem to work. How can I achieve the desired effect ?
command-line escape-characters
command-line escape-characters
asked Jan 9 at 23:58
Sergiy KolodyazhnyySergiy Kolodyazhnyy
8,53412254
8,53412254
2
Perhaps send SIGHUP, since you cannot send EOF.
– Thomas Dickey
Jan 10 at 0:48
@ThomasDickey EOF is not a character, EOT however is actually on the list of ASCII characters, hex 04 value. That's what I'm trying to send. Heemayls answer there isn't accurate, I think.
– Sergiy Kolodyazhnyy
Jan 10 at 0:56
Maybe because you're in canonical mode so such bytes would be consumed by tty driver before it get send.
– 炸鱼薯条德里克
Jan 10 at 0:56
@炸鱼 OK, how do I check if I'm canonical mode ?
– Sergiy Kolodyazhnyy
Jan 10 at 1:00
stty -a
will dump the terminal settings for the current terminal. In the flags portion you will seeicanon
, the canonical flag. If this flag is preceded by an-
then it is off, no dash then its on.
– datUser
Jan 10 at 1:27
|
show 1 more comment
2
Perhaps send SIGHUP, since you cannot send EOF.
– Thomas Dickey
Jan 10 at 0:48
@ThomasDickey EOF is not a character, EOT however is actually on the list of ASCII characters, hex 04 value. That's what I'm trying to send. Heemayls answer there isn't accurate, I think.
– Sergiy Kolodyazhnyy
Jan 10 at 0:56
Maybe because you're in canonical mode so such bytes would be consumed by tty driver before it get send.
– 炸鱼薯条德里克
Jan 10 at 0:56
@炸鱼 OK, how do I check if I'm canonical mode ?
– Sergiy Kolodyazhnyy
Jan 10 at 1:00
stty -a
will dump the terminal settings for the current terminal. In the flags portion you will seeicanon
, the canonical flag. If this flag is preceded by an-
then it is off, no dash then its on.
– datUser
Jan 10 at 1:27
2
2
Perhaps send SIGHUP, since you cannot send EOF.
– Thomas Dickey
Jan 10 at 0:48
Perhaps send SIGHUP, since you cannot send EOF.
– Thomas Dickey
Jan 10 at 0:48
@ThomasDickey EOF is not a character, EOT however is actually on the list of ASCII characters, hex 04 value. That's what I'm trying to send. Heemayls answer there isn't accurate, I think.
– Sergiy Kolodyazhnyy
Jan 10 at 0:56
@ThomasDickey EOF is not a character, EOT however is actually on the list of ASCII characters, hex 04 value. That's what I'm trying to send. Heemayls answer there isn't accurate, I think.
– Sergiy Kolodyazhnyy
Jan 10 at 0:56
Maybe because you're in canonical mode so such bytes would be consumed by tty driver before it get send.
– 炸鱼薯条德里克
Jan 10 at 0:56
Maybe because you're in canonical mode so such bytes would be consumed by tty driver before it get send.
– 炸鱼薯条德里克
Jan 10 at 0:56
@炸鱼 OK, how do I check if I'm canonical mode ?
– Sergiy Kolodyazhnyy
Jan 10 at 1:00
@炸鱼 OK, how do I check if I'm canonical mode ?
– Sergiy Kolodyazhnyy
Jan 10 at 1:00
stty -a
will dump the terminal settings for the current terminal. In the flags portion you will see icanon
, the canonical flag. If this flag is preceded by an -
then it is off, no dash then its on.– datUser
Jan 10 at 1:27
stty -a
will dump the terminal settings for the current terminal. In the flags portion you will see icanon
, the canonical flag. If this flag is preceded by an -
then it is off, no dash then its on.– datUser
Jan 10 at 1:27
|
show 1 more comment
1 Answer
1
active
oldest
votes
First of all, a tty, even if it appears a single file object, is actually a pair of pipes/queues -- one for the output and one for the input, the other ends of each being connected either to the TX/RX of some hardware device, or made available to another program in the case of a pseudo-tty. When you're writing anything to the fd linked to a tty, you're writing into the output queue, even if that's the fd 0 (stdin) of your process, and will not be looped back into the input queue.
There's a special ioctl (TIOCSTI
) which allows you to insert a byte into the input queue of a tty, as if it were received from the other end. TIOCSTI
will only work as root when not used on the controlling tty of the process calling it.
$ cc -Wall tiocsti.c -o tiocsti
-- as root --
# printf '4' | ./tiocsti >/proc/5460/fd/0
If your process is running in a pseudo-tty, another way to "fake" input is to connect with a debugger to the process holding the master side of the pseudo-tty, and write(2)
your stuff into it from there.
$ gdb -p pid_of_xterm
(gdb) p write(4, "x04", 1) # 4 is the fd of the master pty
(gdb) c
Both methods are just overkill. If you want to control a running process, you better attach with a debugger to that very process instead of faking it some input; if you want to instrumentalize an interactive program, you better run it in expect
; both will work on any Unix system and don't require extra privileges for that.
Also notice that ^D
/ 04
will only work as EOF if a) the tty is in canonical mode b) the c_cc[VEOF]
special character wasn't changed to something else c) the output queue is empty (otherwise c_cc[VEOF]
will have to be sent twice). And of course, it will be the process which is just reading from tty which will get the EOF or those bytes, not necessarily the shell.
Note:
As to why anyone would ever want to change VEOF
to something else than ^D
here is a case: if you want to input a password from the user, you turn echo off, keep canonical mode on (so the user be able to backspace, etc), set VEOL2
to ^D
(a ^D
will end the password, just like a newline), and VEOF
to ^C
(a ^C
will abort the password, and you will get that as 0 return from read
). That way, you can implement getpass(3)
without having to mess with any signals.
tiocsti.c
#include <sys/ioctl.h>
#include <unistd.h>
#include <err.h>
int main(void){
char c; ssize_t r;
for(;;){
if((r = read(0, &c, 1)) <= 0){
if(r < 0) err(1, "read");
return 0;
}
if(ioctl(1, TIOCSTI, &c)) err(1, "ioctl(TIOCSTI)");
}
}
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "106"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f493578%2fhow-to-send-d-eot-character-to-stdin-of-a-shell-process%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
First of all, a tty, even if it appears a single file object, is actually a pair of pipes/queues -- one for the output and one for the input, the other ends of each being connected either to the TX/RX of some hardware device, or made available to another program in the case of a pseudo-tty. When you're writing anything to the fd linked to a tty, you're writing into the output queue, even if that's the fd 0 (stdin) of your process, and will not be looped back into the input queue.
There's a special ioctl (TIOCSTI
) which allows you to insert a byte into the input queue of a tty, as if it were received from the other end. TIOCSTI
will only work as root when not used on the controlling tty of the process calling it.
$ cc -Wall tiocsti.c -o tiocsti
-- as root --
# printf '4' | ./tiocsti >/proc/5460/fd/0
If your process is running in a pseudo-tty, another way to "fake" input is to connect with a debugger to the process holding the master side of the pseudo-tty, and write(2)
your stuff into it from there.
$ gdb -p pid_of_xterm
(gdb) p write(4, "x04", 1) # 4 is the fd of the master pty
(gdb) c
Both methods are just overkill. If you want to control a running process, you better attach with a debugger to that very process instead of faking it some input; if you want to instrumentalize an interactive program, you better run it in expect
; both will work on any Unix system and don't require extra privileges for that.
Also notice that ^D
/ 04
will only work as EOF if a) the tty is in canonical mode b) the c_cc[VEOF]
special character wasn't changed to something else c) the output queue is empty (otherwise c_cc[VEOF]
will have to be sent twice). And of course, it will be the process which is just reading from tty which will get the EOF or those bytes, not necessarily the shell.
Note:
As to why anyone would ever want to change VEOF
to something else than ^D
here is a case: if you want to input a password from the user, you turn echo off, keep canonical mode on (so the user be able to backspace, etc), set VEOL2
to ^D
(a ^D
will end the password, just like a newline), and VEOF
to ^C
(a ^C
will abort the password, and you will get that as 0 return from read
). That way, you can implement getpass(3)
without having to mess with any signals.
tiocsti.c
#include <sys/ioctl.h>
#include <unistd.h>
#include <err.h>
int main(void){
char c; ssize_t r;
for(;;){
if((r = read(0, &c, 1)) <= 0){
if(r < 0) err(1, "read");
return 0;
}
if(ioctl(1, TIOCSTI, &c)) err(1, "ioctl(TIOCSTI)");
}
}
add a comment |
First of all, a tty, even if it appears a single file object, is actually a pair of pipes/queues -- one for the output and one for the input, the other ends of each being connected either to the TX/RX of some hardware device, or made available to another program in the case of a pseudo-tty. When you're writing anything to the fd linked to a tty, you're writing into the output queue, even if that's the fd 0 (stdin) of your process, and will not be looped back into the input queue.
There's a special ioctl (TIOCSTI
) which allows you to insert a byte into the input queue of a tty, as if it were received from the other end. TIOCSTI
will only work as root when not used on the controlling tty of the process calling it.
$ cc -Wall tiocsti.c -o tiocsti
-- as root --
# printf '4' | ./tiocsti >/proc/5460/fd/0
If your process is running in a pseudo-tty, another way to "fake" input is to connect with a debugger to the process holding the master side of the pseudo-tty, and write(2)
your stuff into it from there.
$ gdb -p pid_of_xterm
(gdb) p write(4, "x04", 1) # 4 is the fd of the master pty
(gdb) c
Both methods are just overkill. If you want to control a running process, you better attach with a debugger to that very process instead of faking it some input; if you want to instrumentalize an interactive program, you better run it in expect
; both will work on any Unix system and don't require extra privileges for that.
Also notice that ^D
/ 04
will only work as EOF if a) the tty is in canonical mode b) the c_cc[VEOF]
special character wasn't changed to something else c) the output queue is empty (otherwise c_cc[VEOF]
will have to be sent twice). And of course, it will be the process which is just reading from tty which will get the EOF or those bytes, not necessarily the shell.
Note:
As to why anyone would ever want to change VEOF
to something else than ^D
here is a case: if you want to input a password from the user, you turn echo off, keep canonical mode on (so the user be able to backspace, etc), set VEOL2
to ^D
(a ^D
will end the password, just like a newline), and VEOF
to ^C
(a ^C
will abort the password, and you will get that as 0 return from read
). That way, you can implement getpass(3)
without having to mess with any signals.
tiocsti.c
#include <sys/ioctl.h>
#include <unistd.h>
#include <err.h>
int main(void){
char c; ssize_t r;
for(;;){
if((r = read(0, &c, 1)) <= 0){
if(r < 0) err(1, "read");
return 0;
}
if(ioctl(1, TIOCSTI, &c)) err(1, "ioctl(TIOCSTI)");
}
}
add a comment |
First of all, a tty, even if it appears a single file object, is actually a pair of pipes/queues -- one for the output and one for the input, the other ends of each being connected either to the TX/RX of some hardware device, or made available to another program in the case of a pseudo-tty. When you're writing anything to the fd linked to a tty, you're writing into the output queue, even if that's the fd 0 (stdin) of your process, and will not be looped back into the input queue.
There's a special ioctl (TIOCSTI
) which allows you to insert a byte into the input queue of a tty, as if it were received from the other end. TIOCSTI
will only work as root when not used on the controlling tty of the process calling it.
$ cc -Wall tiocsti.c -o tiocsti
-- as root --
# printf '4' | ./tiocsti >/proc/5460/fd/0
If your process is running in a pseudo-tty, another way to "fake" input is to connect with a debugger to the process holding the master side of the pseudo-tty, and write(2)
your stuff into it from there.
$ gdb -p pid_of_xterm
(gdb) p write(4, "x04", 1) # 4 is the fd of the master pty
(gdb) c
Both methods are just overkill. If you want to control a running process, you better attach with a debugger to that very process instead of faking it some input; if you want to instrumentalize an interactive program, you better run it in expect
; both will work on any Unix system and don't require extra privileges for that.
Also notice that ^D
/ 04
will only work as EOF if a) the tty is in canonical mode b) the c_cc[VEOF]
special character wasn't changed to something else c) the output queue is empty (otherwise c_cc[VEOF]
will have to be sent twice). And of course, it will be the process which is just reading from tty which will get the EOF or those bytes, not necessarily the shell.
Note:
As to why anyone would ever want to change VEOF
to something else than ^D
here is a case: if you want to input a password from the user, you turn echo off, keep canonical mode on (so the user be able to backspace, etc), set VEOL2
to ^D
(a ^D
will end the password, just like a newline), and VEOF
to ^C
(a ^C
will abort the password, and you will get that as 0 return from read
). That way, you can implement getpass(3)
without having to mess with any signals.
tiocsti.c
#include <sys/ioctl.h>
#include <unistd.h>
#include <err.h>
int main(void){
char c; ssize_t r;
for(;;){
if((r = read(0, &c, 1)) <= 0){
if(r < 0) err(1, "read");
return 0;
}
if(ioctl(1, TIOCSTI, &c)) err(1, "ioctl(TIOCSTI)");
}
}
First of all, a tty, even if it appears a single file object, is actually a pair of pipes/queues -- one for the output and one for the input, the other ends of each being connected either to the TX/RX of some hardware device, or made available to another program in the case of a pseudo-tty. When you're writing anything to the fd linked to a tty, you're writing into the output queue, even if that's the fd 0 (stdin) of your process, and will not be looped back into the input queue.
There's a special ioctl (TIOCSTI
) which allows you to insert a byte into the input queue of a tty, as if it were received from the other end. TIOCSTI
will only work as root when not used on the controlling tty of the process calling it.
$ cc -Wall tiocsti.c -o tiocsti
-- as root --
# printf '4' | ./tiocsti >/proc/5460/fd/0
If your process is running in a pseudo-tty, another way to "fake" input is to connect with a debugger to the process holding the master side of the pseudo-tty, and write(2)
your stuff into it from there.
$ gdb -p pid_of_xterm
(gdb) p write(4, "x04", 1) # 4 is the fd of the master pty
(gdb) c
Both methods are just overkill. If you want to control a running process, you better attach with a debugger to that very process instead of faking it some input; if you want to instrumentalize an interactive program, you better run it in expect
; both will work on any Unix system and don't require extra privileges for that.
Also notice that ^D
/ 04
will only work as EOF if a) the tty is in canonical mode b) the c_cc[VEOF]
special character wasn't changed to something else c) the output queue is empty (otherwise c_cc[VEOF]
will have to be sent twice). And of course, it will be the process which is just reading from tty which will get the EOF or those bytes, not necessarily the shell.
Note:
As to why anyone would ever want to change VEOF
to something else than ^D
here is a case: if you want to input a password from the user, you turn echo off, keep canonical mode on (so the user be able to backspace, etc), set VEOL2
to ^D
(a ^D
will end the password, just like a newline), and VEOF
to ^C
(a ^C
will abort the password, and you will get that as 0 return from read
). That way, you can implement getpass(3)
without having to mess with any signals.
tiocsti.c
#include <sys/ioctl.h>
#include <unistd.h>
#include <err.h>
int main(void){
char c; ssize_t r;
for(;;){
if((r = read(0, &c, 1)) <= 0){
if(r < 0) err(1, "read");
return 0;
}
if(ioctl(1, TIOCSTI, &c)) err(1, "ioctl(TIOCSTI)");
}
}
edited Jan 10 at 15:25
answered Jan 10 at 11:28
mosvymosvy
6,2461425
6,2461425
add a comment |
add a comment |
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f493578%2fhow-to-send-d-eot-character-to-stdin-of-a-shell-process%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
2
Perhaps send SIGHUP, since you cannot send EOF.
– Thomas Dickey
Jan 10 at 0:48
@ThomasDickey EOF is not a character, EOT however is actually on the list of ASCII characters, hex 04 value. That's what I'm trying to send. Heemayls answer there isn't accurate, I think.
– Sergiy Kolodyazhnyy
Jan 10 at 0:56
Maybe because you're in canonical mode so such bytes would be consumed by tty driver before it get send.
– 炸鱼薯条德里克
Jan 10 at 0:56
@炸鱼 OK, how do I check if I'm canonical mode ?
– Sergiy Kolodyazhnyy
Jan 10 at 1:00
stty -a
will dump the terminal settings for the current terminal. In the flags portion you will seeicanon
, the canonical flag. If this flag is preceded by an-
then it is off, no dash then its on.– datUser
Jan 10 at 1:27