Discussion:
idle (or inactivity) timeout in ash
rouble
2011-02-01 17:40:49 UTC
Permalink
Busybox Gurus,

I have a situation that I think should be fairly common. I use getty
to launch login, and then login launches an ash shell.

For security reasons, I need the shell to timeout if there is no
keyboard activity. Something like a telnet or ssh connection timeout.

I notice that getty has a timeout - does this take care of inactivity
in the shell?

I noticed that login has a default timeout that times out after some
time (60 seconds?)
<code>
# login
localhost login:
Login timed out after 60 seconds
<code>

And I also noticed that ash has no timeouts in the source at all.

I can code an idle timeout into ash, but I wanted to check to see how
others are handling this OR if I am missing something obvious. Any
comments on this are appreciated.

tia,
rouble
Cathey, Jim
2011-02-01 18:09:32 UTC
Permalink
Post by rouble
I notice that getty has a timeout - does this take care of inactivity
in the shell?
No.
Post by rouble
And I also noticed that ash has no timeouts in the source at all.
Completely normal.
Post by rouble
I can code an idle timeout into ash, but I wanted to check...
Please don't.

Idle timeouts are always implemented outside the shell.
Otherwise, consider how one can circumvent them by typing
something highly secret, like "ed". (Pick your favorite
interactive tool here.)

The idle timeout program (and I forget the name of the common
one) just watches the TTY accessed times, and if they stop moving
they kill the session.

-- Jim
rouble
2011-02-01 22:55:53 UTC
Permalink
Hi Jim et al,

Thanks for the comments. One question inline.

<SNIP>
Post by Cathey, Jim
Idle timeouts are always implemented outside the shell.
Otherwise, consider how one can circumvent them by typing
something highly secret, like "ed". ?(Pick your favorite
interactive tool here.)
The idle timeout program (and I forget the name of the common
one) just watches the TTY accessed times, and if they stop moving
they kill the session.
Using busybox utilities, is their a way to list idle TTY sessions?

tia,
rouble
Post by Cathey, Jim
-- Jim
Cathey, Jim
2011-02-01 23:14:45 UTC
Permalink
Post by rouble
Using busybox utilities, is their a way to list idle TTY sessions?
Is "w" part of BB? "who" also shows it. You have to infer
idleness yourself from the idle time field.

-- Jim
Denys Vlasenko
2011-02-01 23:14:46 UTC
Permalink
Post by Cathey, Jim
Post by rouble
I notice that getty has a timeout - does this take care of inactivity
in the shell?
No.
Post by rouble
And I also noticed that ash has no timeouts in the source at all.
Completely normal.
Post by rouble
I can code an idle timeout into ash, but I wanted to check...
Please don't.
Idle timeouts are always implemented outside the shell.
Otherwise, consider how one can circumvent them by typing
something highly secret, like "ed". (Pick your favorite
interactive tool here.)
The idle timeout program (and I forget the name of the common
one) just watches the TTY accessed times, and if they stop moving
they kill the session.
$ busybox timeout --help
BusyBox v1.19.0.git (2011-01-31 05:53:40 CET) multi-call binary.

Usage: timeout [-t SECS] [-s SIG] PROG ARGS

Runs PROG. Sends SIG to it if it is not gone in SECS seconds.
Defaults: SECS: 10, SIG: TERM.


But beware that all such tools can be easily fooled
by creating new program groups and/or sessions.
They are generally no good for security purposes.
You need to use "stronger" containers.
--
vda
Cathey, Jim
2011-02-01 23:17:38 UTC
Permalink
Post by Cathey, Jim
The idle timeout program (and I forget the name of the common
one) just watches the TTY accessed times, and if they stop moving
they kill the session.
Oh yeah, it's "idled", the Idle Daemon.

-- Jim
walter harms
2011-02-02 14:00:30 UTC
Permalink
Post by Cathey, Jim
Post by Cathey, Jim
The idle timeout program (and I forget the name of the common
one) just watches the TTY accessed times, and if they stop moving
they kill the session.
Oh yeah, it's "idled", the Idle Daemon.
so working solution is interessting. Several embedded device have a debug shell
running on serial port (or else) and if the technican unplug without exit the
shell remains open until the end.

re,
wh
Harald Becker
2011-02-01 18:38:58 UTC
Permalink
Hi!

In bash there exist a feature for auto-logout. Just set TMOUT variable like:

export TMOUT=60

But I don't know if this feature is in busybox ash ... don't know what
happen to the following (got just from Google) ...

http://www.mail-archive.com/busybox at busybox.net/msg02686.html

--
Harald
Thomas Geulig
2011-02-02 16:22:06 UTC
Permalink
Post by Harald Becker
export TMOUT=60
But I don't know if this feature is in busybox ash ... don't know what
happen to the following (got just from Google) ...
http://www.mail-archive.com/busybox at busybox.net/msg02686.html
Nothing happened to it, I'm still using it :-)

But I haven't got any feedback on it, and so it never went into the main
sources.

Maybe a newer version should also work for hush nowadays?

Thomas
rouble
2011-02-02 16:37:48 UTC
Permalink
I see an issue when running ash with this patch. When you run top,
with this patch installed, it does not run cleanly. It just dumps
data, and the screen does not stay in one place. I am testing with
1.17.3.

I can't explain why it does this, because I don't understand all the
flags in ash.c.

tia,
rouble
Post by Thomas Geulig
Post by Harald Becker
export TMOUT=60
But I don't know if this feature is in busybox ash ... don't know what
happen to the following (got just from Google) ...
http://www.mail-archive.com/busybox at busybox.net/msg02686.html
Nothing happened to it, I'm still using it :-)
But I haven't got any feedback on it, and so it never went into the main
sources.
Maybe a newer version should also work for hush nowadays?
Thomas
_______________________________________________
busybox mailing list
busybox at busybox.net
http://lists.busybox.net/mailman/listinfo/busybox
Thomas Geulig
2011-02-03 10:50:07 UTC
Permalink
Post by rouble
I see an issue when running ash with this patch. When you run top,
with this patch installed, it does not run cleanly. It just dumps
data, and the screen does not stay in one place. I am testing with
1.17.3.
I've never seen such issues. I used many versions between 1.0.0 and
1.18.2 on arm and 386 platforms.

But you could try the updated patch ...

Thomas
rouble
2011-02-03 17:01:03 UTC
Permalink
Hi Thomas et al,

I think I was mistaken about the problem I stated earlier. I can
recreate the top issue even without your patch - so it must be my
environment. I tried your latest patch, and it works fine.

One basic question I have about the code is, when the timer pops, how
does the code pop out of parsecmd() to test for timed_out?

Lastly, can we allow this patch into the official busybox release
train? It has been asked for numerous times on this alias, and it
makes ash, just a little bit more like bash.

tia,
rouble
Post by Thomas Geulig
Post by rouble
I see an issue when running ash with this patch. When you run top,
with this patch installed, it does not run cleanly. It just dumps
data, and the screen does not stay in one place. I am testing with
1.17.3.
I've never seen such issues. I used many versions between 1.0.0 and
1.18.2 on arm and 386 platforms.
But you could try the updated patch ...
Thomas
Harald Becker
2011-02-03 17:16:43 UTC
Permalink
Hi all,

just to state this out ...
Post by rouble
Lastly, can we allow this patch into the official busybox release
train? It has been asked for numerous times on this alias, and it
makes ash, just a little bit more like bash.
... I haven't tried that patch, but if it works correctly I will like to
see this feature in busybox ash too.

--
Harald
Denys Vlasenko
2011-02-02 19:24:28 UTC
Permalink
Post by Thomas Geulig
Post by Harald Becker
export TMOUT=60
But I don't know if this feature is in busybox ash ... don't know what
happen to the following (got just from Google) ...
http://www.mail-archive.com/busybox at busybox.net/msg02686.html
Nothing happened to it, I'm still using it :-)
But I haven't got any feedback on it, and so it never went into the main
sources.
+static volatile int timed_out;
+
+static void alrm_catcher(int i)
+{
+ printf ("\007timed out waiting for input: auto-logout\n");
+ timed_out = 1;
+ return;
+}

(1) printf in signal handler is a bad idea.
(2) you need to save/restore errno around printf.


+#if ENABLE_ASH_IDLE_TIMEOUT
+ timed_out = 0;
+ tmout_var = NULL;
+ tmout_len = 0;
+ old_alrm = (void *)SIG_IGN;
+ if (iflag) {
+ if ((tmout_var = lookupvar("TMOUT")) != NULL
+ && (tmout_len = atoi(tmout_var)) > 0) {
+ signal(SIGALRM, alrm_catcher);
+ alarm(tmout_len);
+ }
+ }
+#endif
+
setstackmark(&smark);
#if JOBS
if (jobctl)
@@ -10885,6 +10915,15 @@
#endif
}
n = parsecmd(inter);
+#if ENABLE_ASH_IDLE_TIMEOUT
+ if (iflag && timed_out)
+ break;
+ if (iflag && tmout_var && (tmout_len > 0))

Can be made simpler:
if (timed_out)
break;
if (tmout_len > 0) ...



+ {
+ alarm(0);
+ signal(SIGALRM, old_alrm);

(1) old_alrm is SIG_IGN, always. Can be eliminated.
(2) why SIG_IGN? I bet child processes aren't happy
having their SIGALRM ignored.

+ }
+#endif
Rich Felker
2011-02-03 06:04:41 UTC
Permalink
Post by Denys Vlasenko
+static volatile int timed_out;
+
+static void alrm_catcher(int i)
+{
+ printf ("\007timed out waiting for input: auto-logout\n");
+ timed_out = 1;
+ return;
+}
(1) printf in signal handler is a bad idea.
It's not just a bad idea; it *will* lead to memory corruption and/or
deadlock when it happens while stdout is in use. Using dprintf instead
should be safe even though POSIX doesn't require it to be safe.
Post by Denys Vlasenko
(2) you need to save/restore errno around printf.
This is a much smaller issue, but yes...

Rich
Thomas Geulig
2011-02-03 10:24:51 UTC
Permalink
Thanks for the hints and explanations.

Here is an updated patch.

Thomas

-------------- next part --------------
A non-text attachment was scrubbed...
Name: idle_timeout.patch2
Type: text/x-patch
Size: 1850 bytes
Desc: not available
URL: <http://lists.busybox.net/pipermail/busybox/attachments/20110203/c53ae470/attachment-0001.bin>
Denys Vlasenko
2011-02-04 13:45:12 UTC
Permalink
Post by Thomas Geulig
Thanks for the hints and explanations.
Here is an updated patch.
Doesn't work as intended: needs additional <Enter> from the user after timeout.

# TMOUT=3 strace -tt -s99 -oLOG ./busybox ash
~/srcdevel/bbox/fix/busybox.t1 # <waiting ~10 seconds, nothing
happens> <pressing enter key>
timed out waiting for input: auto-logout
# _

LOG:
....
14:28:58.627959 rt_sigaction(SIGALRM, {0x8082d30, [ALRM],
SA_RESTORER|SA_RESTART, 0x80487fb}, {SIG_DFL, [], 0}, 8) = 0
14:28:58.628117 alarm(3) = 0
...
14:28:58.651596 write(1, "~/srcdevel/bbox/fix/busybox.t1 # ", 33) = 33
14:28:58.673380 poll([{fd=0, events=POLLIN}], 1, 4294967295) = ?
ERESTART_RESTARTBLOCK (To be restarted)
14:29:01.628353 --- SIGALRM (Alarm clock) @ 0 (0) ---
^^^^^^^^^^^^^ 3 seconds passed
14:29:01.628462 sigreturn() = -1 EINTR (Interrupted system call)
14:29:01.628632 poll([{fd=0, events=POLLIN}], 1, 4294967295) = 1
([{fd=0, revents=POLLIN}])
^^^^^^^^^^^^^ returns to poll which waits for input
14:29:08.852947 read(0, "\n", 1) = 1
^^^^^^^^^^^^^ user pressed <Enter> (note timestamps!)
14:29:08.853149 write(1, "\n", 1) = 1
14:29:08.853328 ioctl(0, SNDCTL_TMR_START or TCSETS, {B38400 opost
isig icanon echo ...}) = 0
14:29:08.853489 ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost
isig icanon echo ...}) = 0
14:29:08.853642 rt_sigaction(SIGWINCH, {SIG_DFL, [WINCH],
SA_RESTORER|SA_RESTART, 0x80487fb}, {0x80d62ad, [WINCH],
SA_RESTORER|SA_RESTART, 0x80487fb}, 8) = 0
14:29:08.853889 write(1, "\7timed out waiting for input:
auto-logout\n", 42) = 42
14:29:08.854075 ioctl(10, TIOCSPGRP, [3401]) = 0
14:29:08.854237 setpgid(0, 3401) = 0
14:29:08.854386 close(10) = 0
14:29:08.854528 _exit(0) = ?

bash exits without waiting for line input to finish.

(I simplified patch a bit, see it in attachment)
--
vda
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 1.patch
Type: application/octet-stream
Size: 1729 bytes
Desc: not available
URL: <http://lists.busybox.net/pipermail/busybox/attachments/20110204/1da01e92/attachment.obj>
Thomas Geulig
2011-02-04 14:18:16 UTC
Permalink
Post by Denys Vlasenko
Post by Thomas Geulig
Thanks for the hints and explanations.
Here is an updated patch.
Doesn't work as intended: needs additional <Enter> from the user after timeout.
[...]
Post by Denys Vlasenko
bash exits without waiting for line input to finish.
I know, but it was "good enough" for me at the time.

I suppose, I could take another look.
Post by Denys Vlasenko
(I simplified patch a bit, see it in attachment)
Beware, moving the printf prevents it from getting seen if logged in
via telnet/ssh.

Thomas
Denys Vlasenko
2011-02-04 14:40:21 UTC
Permalink
Post by Thomas Geulig
Post by Denys Vlasenko
(I simplified patch a bit, see it in attachment)
Beware, moving the printf prevents it from getting seen if logged in
via telnet/ssh.
Why?
--
vda
Thomas Geulig
2011-02-04 14:55:14 UTC
Permalink
Post by Thomas Geulig
Post by Denys Vlasenko
(I simplified patch a bit, see it in attachment)
Beware, moving the printf prevents it from getting seen if logged in
via telnet/ssh.
Why?
Correction: it happens only with my telnetd, so this is a different
problem.

So the patch is basically ok now (aside from the addional input needed).

Thomas
Harald Becker
2011-02-04 15:08:20 UTC
Permalink
Hallo Thomas!
Post by Thomas Geulig
Correction: it happens only with my telnetd, so this is a different
problem.
Could it be, you need to flush after printf to forward the message? Some
telnetd's have this problem.

In addition a small sleep of 1 or 2 seconds after message but before
exit due to auto logout could be a good decision (allows human notice of
message if screen gets cleared, e.g. due to respawning of getty on tty).

--
Harald
Thomas Geulig
2011-02-04 15:31:41 UTC
Permalink
Post by Harald Becker
Could it be, you need to flush after printf to forward the message? Some
telnetd's have this problem.
In addition a small sleep of 1 or 2 seconds after message but before
exit due to auto logout could be a good decision (allows human notice of
message if screen gets cleared, e.g. due to respawning of getty on tty).
Danke Harald!

These lines (added after the printf)

fflush_all();
sleep(2);

did the trick.

The flush itself is not enough. A flush happens anyway later in
exitshell(), but the telnet daemon seems to need more time.

Thomas
Harald Becker
2011-02-04 15:58:42 UTC
Permalink
Hallo Thomas!
Post by Thomas Geulig
The flush itself is not enough. A flush happens anyway later in
exitshell(), but the telnet daemon seems to need more time.
flush probably needs an extra tcflush to empty the tty kernel buffers.
As telnetd uses pseudo tty's there is such an kernel buffer too. If
slave side of pty is closed before telnetd received all data from master
pty some telnetd's (and other applications) close the upstream
connection before transmitting the last output lines :-( ... but doing a
2 second sleep is simpler and works in about 99 percent :-)

--
Harald
Denys Vlasenko
2011-02-04 15:44:26 UTC
Permalink
Post by Thomas Geulig
Post by Thomas Geulig
Post by Denys Vlasenko
(I simplified patch a bit, see it in attachment)
Beware, moving the printf prevents it from getting seen if logged in
via telnet/ssh.
Why?
Correction: it happens only with my telnetd, so this is a different
problem.
What version of telnetd do you have?
--
vda
Thomas Geulig
2011-02-04 16:01:06 UTC
Permalink
Post by Denys Vlasenko
Post by Thomas Geulig
Post by Thomas Geulig
Post by Denys Vlasenko
(I simplified patch a bit, see it in attachment)
Beware, moving the printf prevents it from getting seen if logged in
via telnet/ssh.
Why?
Correction: it happens only with my telnetd, so this is a different
problem.
What version of telnetd do you have?
Old stuff ;-) telnetd v1.9 (BSD?; part of uClinux)

But I just tried the telnet daemon from busybox.
This works as expected.

Thomas
rouble
2011-02-04 21:02:28 UTC
Permalink
It works for me though. I get this:
# TMOUT=3 strace -tt -s99 -oLOG ash
/system/etc # <Wait 4 seconds >timed out waiting for input: auto-logout

Without pressing the enter key.

tia,
rouble
Post by Denys Vlasenko
Post by Thomas Geulig
Thanks for the hints and explanations.
Here is an updated patch.
Doesn't work as intended: needs additional <Enter> from the user after timeout.
# TMOUT=3 strace -tt -s99 -oLOG ./busybox ash
~/srcdevel/bbox/fix/busybox.t1 # <waiting ~10 seconds, nothing
happens> <pressing enter key>
timed out waiting for input: auto-logout
# _
....
14:28:58.627959 rt_sigaction(SIGALRM, {0x8082d30, [ALRM],
SA_RESTORER|SA_RESTART, 0x80487fb}, {SIG_DFL, [], 0}, 8) = 0
14:28:58.628117 alarm(3) ? ? ? ? ? ? ? ?= 0
...
14:28:58.651596 write(1, "~/srcdevel/bbox/fix/busybox.t1 # ", 33) = 33
14:28:58.673380 poll([{fd=0, events=POLLIN}], 1, 4294967295) = ?
ERESTART_RESTARTBLOCK (To be restarted)
^^^^^^^^^^^^^ 3 seconds passed
14:29:01.628462 sigreturn() ? ? ? ? ? ? = -1 EINTR (Interrupted system call)
14:29:01.628632 poll([{fd=0, events=POLLIN}], 1, 4294967295) = 1
([{fd=0, revents=POLLIN}])
^^^^^^^^^^^^^ returns to poll which waits for input
14:29:08.852947 read(0, "\n", 1) ? ? ? ?= 1
^^^^^^^^^^^^^ user pressed <Enter> (note timestamps!)
14:29:08.853149 write(1, "\n", 1) ? ? ? = 1
14:29:08.853328 ioctl(0, SNDCTL_TMR_START or TCSETS, {B38400 opost
isig icanon echo ...}) = 0
14:29:08.853489 ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost
isig icanon echo ...}) = 0
14:29:08.853642 rt_sigaction(SIGWINCH, {SIG_DFL, [WINCH],
SA_RESTORER|SA_RESTART, 0x80487fb}, {0x80d62ad, [WINCH],
SA_RESTORER|SA_RESTART, 0x80487fb}, 8) = 0
auto-logout\n", 42) = 42
14:29:08.854075 ioctl(10, TIOCSPGRP, [3401]) = 0
14:29:08.854237 setpgid(0, 3401) ? ? ? ?= 0
14:29:08.854386 close(10) ? ? ? ? ? ? ? = 0
14:29:08.854528 _exit(0) ? ? ? ? ? ? ? ?= ?
bash exits without waiting for line input to finish.
(I simplified patch a bit, see it in attachment)
--
vda
_______________________________________________
busybox mailing list
busybox at busybox.net
http://lists.busybox.net/mailman/listinfo/busybox
Denys Vlasenko
2011-02-04 21:28:55 UTC
Permalink
Post by rouble
# TMOUT=3 strace -tt -s99 -oLOG ash
/system/etc # <Wait 4 seconds >timed out waiting for input: auto-logout
Without pressing the enter key.
Can you send your .config and LOG?
--
vda
rouble
2011-02-04 21:41:40 UTC
Permalink
Here is my LOG:
<SNIP>
21:40:12.997206 --- SIGALRM (Alarm clock) @ 0 (0) ---
21:40:12.997447 fstat64(2, {st_mode=S_IFCHR|0600, st_rdev=makedev(136,
0), ...}) = 0
21:40:12.998248 mmap2(NULL, 4096, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb779f000
21:40:12.998680 _llseek(2, 0, 0xbf9acf58, SEEK_CUR) = -1 ESPIPE (Illegal seek)
21:40:12.999121 write(2, "\7timed out waiting for input:
auto-logout\n", 42) = 42
21:40:12.999678 munmap(0xb779f000, 4096) = 0
21:40:13.000131 sigreturn() = ? (mask now [])
21:40:13.000627 poll(

And this is what the screen output looks like, note I have not pressed
enter here:
# TMOUT=3 strace -tt -s99 -oLOG ash
/system/etc # timed out waiting for input: auto-logout

tia,
rouble
Post by Denys Vlasenko
Post by rouble
# TMOUT=3 strace -tt -s99 -oLOG ash
/system/etc # <Wait 4 seconds >timed out waiting for input: auto-logout
Without pressing the enter key.
Can you send your .config and LOG?
--
vda
Denys Vlasenko
2011-02-04 22:06:50 UTC
Permalink
Post by rouble
<SNIP>
21:40:12.997447 fstat64(2, {st_mode=S_IFCHR|0600, st_rdev=makedev(136,
0), ...}) = 0
21:40:12.998248 mmap2(NULL, 4096, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb779f000
21:40:12.998680 _llseek(2, 0, 0xbf9acf58, SEEK_CUR) = -1 ESPIPE (Illegal seek)
auto-logout\n", 42) = 42
21:40:12.999678 munmap(0xb779f000, 4096) = 0
21:40:13.000131 sigreturn() = ? (mask now [])
21:40:13.000627 poll(
And this is what the screen output looks like, note I have not pressed
# TMOUT=3 strace -tt -s99 -oLOG ash
/system/etc # timed out waiting for input: auto-logout
You see the message because you still emit message from signal handler.

This is just a fragment of LOG. It does not show what happened after poll.
Did hell exit? If so, why?
Post by rouble
Post by Denys Vlasenko
Post by rouble
Without pressing the enter key.
Can you send your .config and LOG?
Please send .config too.
--
vda
rouble
2011-02-05 00:17:05 UTC
Permalink
Hi Denys,

You are right. In my case the shell does not exit. I see the message,
which triggers me to press Enter, and that exits the shell.

Thinking out loud here, is it not possible to write "\n" to the input
stream of readtoken from the alarm handler (after setting timed_out to
true)?

Cheers
Rouble
Post by Denys Vlasenko
Post by rouble
<SNIP>
21:40:12.997447 fstat64(2, {st_mode=S_IFCHR|0600, st_rdev=makedev(136,
0), ...}) = 0
21:40:12.998248 mmap2(NULL, 4096, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb779f000
21:40:12.998680 _llseek(2, 0, 0xbf9acf58, SEEK_CUR) = -1 ESPIPE (Illegal seek)
auto-logout\n", 42) = 42
21:40:12.999678 munmap(0xb779f000, 4096) = 0
21:40:13.000131 sigreturn() ? ? ? ? ? ? = ? (mask now [])
21:40:13.000627 poll(
And this is what the screen output looks like, note I have not pressed
# TMOUT=3 strace -tt -s99 -oLOG ash
/system/etc # timed out waiting for input: auto-logout
You see the message because you still emit message from signal handler.
This is just a fragment of LOG. It does not show what happened after poll.
Did hell exit? If so, why?
Post by rouble
Post by Denys Vlasenko
Post by rouble
Without pressing the enter key.
Can you send your .config and LOG?
Please send .config too.
--
vda
Denys Vlasenko
2011-02-05 00:21:51 UTC
Permalink
Post by rouble
Hi Denys,
You are right. In my case the shell does not exit. I see the message,
which triggers me to press Enter, and that exits the shell.
Thinking out loud here, is it not possible to write "\n" to the input
stream of readtoken from the alarm handler (after setting timed_out to
true)?
I committed a patch which closes stdio on timeout. It seems to work.
--
vda
rouble
2011-02-05 14:42:45 UTC
Permalink
Hi Denys,

Can you share the patch here.

tia
Rouble
Post by Denys Vlasenko
Post by rouble
Hi Denys,
You are right. In my case the shell does not exit. I see the message,
which triggers me to press Enter, and that exits the shell.
Thinking out loud here, is it not possible to write "\n" to the input
stream of readtoken from the alarm handler (after setting timed_out to
true)?
I committed a patch which closes stdio on timeout. It seems to work.
--
vda
Denys Vlasenko
2011-02-06 16:16:30 UTC
Permalink
Post by rouble
Hi Denys,
Can you share the patch here.
Sure.

http://git.busybox.net/busybox/commit/?id=046341e8bd91a2a2c0d44b40217fa1c5ce1dd949
--
vda
rouble
2011-02-07 16:44:30 UTC
Permalink
Hi Denys,

There is an issue with this patch. In my testing, when the timeout
occurs, the shell exits perfectly, but the terminal that I am in
becomes unusable.

# ash
/ # export TMOUT=30
/ # /tmp/busybox ash
/ # timed out waiting for input: auto-logout
/ # / # / # / # / # / #

Notice pressing return, does not give me a new line. Instead, just
keeps printing the command prompt on the same line. Also, nothing I
type comes out on the screen. I can type 'ls' followed by return, and
it prints the contents of the directory, but I never see 'ls' on the
screen.

Cheers
Rouble

On Sun, Feb 6, 2011 at 11:16 AM, Denys Vlasenko
Post by Denys Vlasenko
Post by rouble
Hi Denys,
Can you share the patch here.
Sure.
http://git.busybox.net/busybox/commit/?id=046341e8bd91a2a2c0d44b40217fa1c5ce1dd949
--
vda
Harald Becker
2011-02-07 22:29:05 UTC
Permalink
Post by rouble
Notice pressing return, does not give me a new line. Instead, just
keeps printing the command prompt on the same line. Also, nothing I
type comes out on the screen. I can type 'ls' followed by return, and
it prints the contents of the directory, but I never see 'ls' on the
screen.
It looks like the terminal settings got screwed up ... do a "reset"
command ... does this return to a fully functioning command prompt?

--
Harald
rouble
2011-02-07 22:49:45 UTC
Permalink
Yes, 'reset' fixes the terminal.

In Denys' fix, he closes STDIN when the inactivity timer pops. I
wonder why that messes up the terminal?

cheers
rouble
Post by Harald Becker
Post by rouble
Notice pressing return, does not give me a new line. Instead, just
keeps printing the command prompt on the same line. Also, nothing I
type comes out on the screen. I can type 'ls' followed by return, and
it prints the contents of the directory, but I never see 'ls' on the
screen.
It looks like the terminal settings got screwed up ... do a "reset"
command ... does this return to a fully functioning command prompt?
--
Harald
_______________________________________________
busybox mailing list
busybox at busybox.net
http://lists.busybox.net/mailman/listinfo/busybox
Cathey, Jim
2011-02-07 23:18:32 UTC
Permalink
Post by rouble
In Denys' fix, he closes STDIN when the inactivity timer pops. I
wonder why that messes up the terminal?
Perhaps because shells routinely mess up the terminal
in normal operation, and this interfered with its trying
to put it back? (Also routine.)

-- Jim
Harald Becker
2011-02-07 23:23:21 UTC
Permalink
Post by rouble
Yes, 'reset' fixes the terminal.
In Denys' fix, he closes STDIN when the inactivity timer pops. I
wonder why that messes up the terminal?
Oh thats nothing to wonder about: The shell has to fiddle with the
terminal settings (raw/cooked) to allow line (advanced) editing.
Normally the terminal settings get saved and restored on shell exit ...
but if Denys closes stdio on alarm, that restore of the settings get
lost ...

... hey Denys, could you try to close only stdin on alarm and do the
terminal restore on stdout/stderr instead? ... just as a hint for a
possible solution.

--
Harald
Cathey, Jim
2011-02-07 23:25:43 UTC
Permalink
Post by Harald Becker
... hey Denys, could you try to close only stdin on alarm and do the
terminal restore on stdout/stderr instead? ... just as a hint for a
possible solution.
Shells have historically always used STDIN for the
tty settings, due to the extremely common cases where
stdout/stderr are redirected.

Y'all are starting to swim in some pretty shark-infested waters...

-- Jim
Harald Becker
2011-02-08 00:22:15 UTC
Permalink
Shells have historically always used STDIN for the tty settings, due
to the extremely common cases where stdout/stderr are redirected.
True ... but have you ever used an interactive shell where
stdin/stdout/stderr are redirected to different sources/destinations?
... and restoring terminal settings on none tty's doesn't harm in any way.

It would be better to restore terminal settings on stdin just before
closing, if this is possible ... but if not, it could be a possible
solution to consider using stdout/stderr for this.
Y'all are starting to swim in some pretty shark-infested waters...
Programming in environments used/controlled by others is probably
(always?) like swimming in shark-infested waters ... and modifying big
programs of others is like calling that big white shark ... have I nice
time! :-)

--
Harald
Denys Vlasenko
2011-02-08 03:13:10 UTC
Permalink
Post by Harald Becker
Post by rouble
Yes, 'reset' fixes the terminal.
In Denys' fix, he closes STDIN when the inactivity timer pops. I
wonder why that messes up the terminal?
Oh thats nothing to wonder about: The shell has to fiddle with the
terminal settings (raw/cooked) to allow line (advanced) editing.
Normally the terminal settings get saved and restored on shell exit ...
but if Denys closes stdio on alarm, that restore of the settings get
lost ...
... hey Denys, could you try to close only stdin on alarm and do the
terminal restore on stdout/stderr instead? ... just as a hint for a
possible solution.
I plan to remove the hack of closing stdin and implement it properly
in lineedit.
--
vda
Harald Becker
2011-02-08 03:27:25 UTC
Permalink
Post by Denys Vlasenko
I plan to remove the hack of closing stdin and implement it properly
in lineedit.
That will surely be a better solution.

--
Harald
Denys Vlasenko
2011-02-08 04:08:44 UTC
Permalink
Post by Denys Vlasenko
Post by Harald Becker
Post by rouble
Yes, 'reset' fixes the terminal.
In Denys' fix, he closes STDIN when the inactivity timer pops. I
wonder why that messes up the terminal?
Oh thats nothing to wonder about: The shell has to fiddle with the
terminal settings (raw/cooked) to allow line (advanced) editing.
Normally the terminal settings get saved and restored on shell exit ...
but if Denys closes stdio on alarm, that restore of the settings get
lost ...
... hey Denys, could you try to close only stdin on alarm and do the
terminal restore on stdout/stderr instead? ... just as a hint for a
possible solution.
I plan to remove the hack of closing stdin and implement it properly
in lineedit.
Like this:

diff -ad -urpN busybox.3/editors/ed.c busybox.4/editors/ed.c
--- busybox.3/editors/ed.c 2011-02-06 19:52:35.000000000 +0100
+++ busybox.4/editors/ed.c 2011-02-08 04:41:44.000000000 +0100
@@ -129,7 +129,7 @@ static void doCommands(void)
* 0 on ctrl-C,
* >0 length of input string, including terminating '\n'
*/
- len = read_line_input(": ", buf, sizeof(buf), NULL);
+ len = read_line_input(NULL, ": ", buf, sizeof(buf), /*timeout*/ -1);
if (len <= 0)
return;
endbuf = &buf[len - 1];
@@ -227,7 +227,7 @@ static void doCommands(void)
}
if (!dirty)
return;
- len = read_line_input("Really quit? ", buf, 16, NULL);
+ len = read_line_input(NULL, "Really quit? ", buf, 16, /*timeout*/ -1);
/* read error/EOF - no way to continue */
if (len < 0)
return;
@@ -541,7 +541,7 @@ static void addLines(int num)
* 0 on ctrl-C,
* >0 length of input string, including terminating '\n'
*/
- len = read_line_input("", buf, sizeof(buf), NULL);
+ len = read_line_input(NULL, "", buf, sizeof(buf), /*timeout*/ -1);
if (len <= 0) {
/* Previously, ctrl-C was exiting to shell.
* Now we exit to ed prompt. Is in important? */
diff -ad -urpN busybox.3/include/libbb.h busybox.4/include/libbb.h
--- busybox.3/include/libbb.h 2011-02-08 04:16:08.000000000 +0100
+++ busybox.4/include/libbb.h 2011-02-08 04:40:55.000000000 +0100
@@ -1403,12 +1403,11 @@ line_input_t *new_line_input_t(int flags
* 0 on ctrl-C (the line entered is still returned in 'command'),
* >0 length of input string, including terminating '\n'
*/
-/* NB: ash has timeout code which can be moved into read_line_input, if needed */
-int read_line_input(const char* prompt, char* command, int maxsize, line_input_t *state) FAST_FUNC;
+int read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize, int timeout) FAST_FUNC;
#else
#define MAX_HISTORY 0
int read_line_input(const char* prompt, char* command, int maxsize) FAST_FUNC;
-#define read_line_input(prompt, command, maxsize, state) \
+#define read_line_input(state, prompt, command, maxsize, timeout) \
read_line_input(prompt, command, maxsize)
#endif

diff -ad -urpN busybox.3/libbb/lineedit.c busybox.4/libbb/lineedit.c
--- busybox.3/libbb/lineedit.c 2011-02-06 19:52:35.000000000 +0100
+++ busybox.4/libbb/lineedit.c 2011-02-08 04:53:05.000000000 +0100
@@ -1809,10 +1809,9 @@ static void win_changed(int nsig)
errno = sv_errno;
}

-static int lineedit_read_key(char *read_key_buffer)
+static int lineedit_read_key(char *read_key_buffer, int timeout)
{
int64_t ic;
- int timeout = -1;
#if ENABLE_UNICODE_SUPPORT
char unicode_buf[MB_CUR_MAX + 1];
int unicode_idx = 0;
@@ -1917,7 +1916,7 @@ static int isrtl_str(void)
* 0 on ctrl-C (the line entered is still returned in 'command'),
* >0 length of input string, including terminating '\n'
*/
-int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, line_input_t *st)
+int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize, int timeout)
{
int len;
#if ENABLE_FEATURE_TAB_COMPLETION
@@ -1991,7 +1990,6 @@ int FAST_FUNC read_line_input(const char
new_settings.c_cc[VINTR] = _POSIX_VDISABLE;
tcsetattr_stdin_TCSANOW(&new_settings);

- /* Now initialize things */
previous_SIGWINCH_handler = signal(SIGWINCH, win_changed);
win_changed(0); /* do initial resizing */
#if ENABLE_USERNAME_OR_HOMEDIR
@@ -2033,7 +2031,7 @@ int FAST_FUNC read_line_input(const char
int32_t ic, ic_raw;

fflush_all();
- ic = ic_raw = lineedit_read_key(read_key_buffer);
+ ic = ic_raw = lineedit_read_key(read_key_buffer, timeout);

#if ENABLE_FEATURE_EDITING_VI
newdelflag = 1;
@@ -2194,7 +2192,7 @@ int FAST_FUNC read_line_input(const char
case 'd'|VI_CMDMODE_BIT: {
int nc, sc;

- ic = lineedit_read_key(read_key_buffer);
+ ic = lineedit_read_key(read_key_buffer, timeout);
if (errno) /* error */
goto return_error_indicator;
if (ic == ic_raw) { /* "cc", "dd" */
@@ -2258,7 +2256,7 @@ int FAST_FUNC read_line_input(const char
break;
case 'r'|VI_CMDMODE_BIT:
//FIXME: unicode case?
- ic = lineedit_read_key(read_key_buffer);
+ ic = lineedit_read_key(read_key_buffer, timeout);
if (errno) /* error */
goto return_error_indicator;
if (ic < ' ' || ic > 255) {
diff -ad -urpN busybox.3/shell/ash.c busybox.4/shell/ash.c
--- busybox.3/shell/ash.c 2011-02-06 19:52:35.000000000 +0100
+++ busybox.4/shell/ash.c 2011-02-08 05:01:28.000000000 +0100
@@ -102,8 +102,7 @@
//config: default n
//config: depends on ASH
//config: help
-//config: Enables bash-like auto-logout after "$TMOUT" seconds
-//config: of idle time.
+//config: Enables bash-like auto-logout after $TMOUT seconds of idle time.
//config:
//config:config ASH_JOB_CONTROL
//config: bool "Job control"
@@ -408,6 +407,9 @@ static const char *var_end(const char *v


/* ============ Interrupts / exceptions */
+
+static void exitshell(void) NORETURN;
+
/*
* These macros allow the user to suspend the handling of interrupt signals
* over a period of time. This is similar to SIGHOLD or to sigblock, but
@@ -9573,10 +9575,21 @@ preadfd(void)
if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
nr = nonblock_safe_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
else {
+ int timeout = -1;
+# if ENABLE_ASH_IDLE_TIMEOUT
+ if (iflag) {
+ const char *tmout_var = lookupvar("TMOUT");
+ if (tmout_var) {
+ timeout = atoi(tmout_var) * 1000;
+ if (timeout <= 0)
+ timeout = -1;
+ }
+ }
+# endif
# if ENABLE_FEATURE_TAB_COMPLETION
line_input_state->path_lookup = pathval();
# endif
- nr = read_line_input(cmdedit_prompt, buf, IBUFSIZ, line_input_state);
+ nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout);
if (nr == 0) {
/* Ctrl+C pressed */
if (trap[SIGINT]) {
@@ -9587,9 +9600,17 @@ preadfd(void)
}
goto retry;
}
- if (nr < 0 && errno == 0) {
- /* Ctrl+D pressed */
- nr = 0;
+ if (nr < 0) {
+ if (errno == 0) {
+ /* Ctrl+D pressed */
+ nr = 0;
+ }
+# if ENABLE_ASH_IDLE_TIMEOUT
+ else if (errno == EAGAIN && timeout > 0) {
+ printf("\007timed out waiting for input: auto-logout\n");
+ exitshell();
+ }
+# endif
}
}
#else
@@ -12056,23 +12077,6 @@ evalcmd(int argc UNUSED_PARAM, char **ar
return exitstatus;
}

-#if ENABLE_ASH_IDLE_TIMEOUT
-static smallint timed_out;
-
-static void alrm_sighandler(int sig UNUSED_PARAM)
-{
- /* Close stdin, making interactive command reading stop.
- * Otherwise, timeout doesn't trigger until <Enter> is pressed.
- */
- int sv = errno;
- close(0);
- open("/dev/null", O_RDONLY);
- errno = sv;
-
- timed_out = 1;
-}
-#endif
-
/*
* Read and execute commands.
* "Top" is nonzero for the top level command loop;
@@ -12089,20 +12093,6 @@ cmdloop(int top)
TRACE(("cmdloop(%d) called\n", top));
for (;;) {
int skip;
-#if ENABLE_ASH_IDLE_TIMEOUT
- int tmout_seconds = 0;
-
- if (top && iflag) {
- const char *tmout_var = lookupvar("TMOUT");
- if (tmout_var) {
- tmout_seconds = atoi(tmout_var);
- if (tmout_seconds > 0) {
- signal(SIGALRM, alrm_sighandler);
- alarm(tmout_seconds);
- }
- }
- }
-#endif

setstackmark(&smark);
#if JOBS
@@ -12115,14 +12105,6 @@ cmdloop(int top)
chkmail();
}
n = parsecmd(inter);
-#if ENABLE_ASH_IDLE_TIMEOUT
- if (timed_out) {
- printf("\007timed out waiting for input: auto-logout\n");
- break;
- }
- if (tmout_seconds > 0)
- alarm(0);
-#endif
#if DEBUG
if (DEBUG > 2 && debug && (n != NODE_EOF))
showtree(n);
@@ -12850,7 +12832,6 @@ ulimitcmd(int argc UNUSED_PARAM, char **
/*
* Called to exit the shell.
*/
-static void exitshell(void) NORETURN;
static void
exitshell(void)
{
diff -ad -urpN busybox.3/shell/hush.c busybox.4/shell/hush.c
--- busybox.3/shell/hush.c 2011-02-07 02:02:44.000000000 +0100
+++ busybox.4/shell/hush.c 2011-02-08 04:41:59.000000000 +0100
@@ -1902,7 +1902,7 @@ static void get_user_input(struct in_str
G.flag_SIGINT = 0;
/* buglet: SIGINT will not make new prompt to appear _at once_,
* only after <Enter>. (^C will work) */
- r = read_line_input(prompt_str, G.user_input_buf, CONFIG_FEATURE_EDITING_MAX_LEN-1, G.line_input_state);
+ r = read_line_input(G.line_input_state, prompt_str, G.user_input_buf, CONFIG_FEATURE_EDITING_MAX_LEN-1, /*timeout*/ -1);
/* catch *SIGINT* etc (^C is handled by read_line_input) */
check_and_run_traps(0);
} while (r == 0 || G.flag_SIGINT); /* repeat if ^C or SIGINT */
diff -ad -urpN busybox.3/util-linux/fdisk.c busybox.4/util-linux/fdisk.c
--- busybox.3/util-linux/fdisk.c 2011-02-06 19:52:35.000000000 +0100
+++ busybox.4/util-linux/fdisk.c 2011-02-08 04:41:18.000000000 +0100
@@ -548,7 +548,7 @@ read_line(const char *prompt)
{
int sz;

- sz = read_line_input(prompt, line_buffer, sizeof(line_buffer), NULL);
+ sz = read_line_input(NULL, prompt, line_buffer, sizeof(line_buffer), /*timeout*/ -1);
if (sz <= 0)
exit(EXIT_SUCCESS); /* Ctrl-D or Ctrl-C */
Thomas Geulig
2011-02-08 09:32:37 UTC
Permalink
Post by Denys Vlasenko
Post by Harald Becker
Post by rouble
Yes, 'reset' fixes the terminal.
In Denys' fix, he closes STDIN when the inactivity timer pops. I
wonder why that messes up the terminal?
Oh thats nothing to wonder about: The shell has to fiddle with the
terminal settings (raw/cooked) to allow line (advanced) editing.
Normally the terminal settings get saved and restored on shell exit ...
but if Denys closes stdio on alarm, that restore of the settings get
lost ...
... hey Denys, could you try to close only stdin on alarm and do the
terminal restore on stdout/stderr instead? ... just as a hint for a
possible solution.
I plan to remove the hack of closing stdin and implement it properly
in lineedit.
[...]

This seems to work fine. Nice work.

Thomas
rouble
2011-02-08 16:32:15 UTC
Permalink
Works like a champ. Good work Denys.

Will this be part of the next busybox stable release (1.18.3) ?

Cheers
rouble

On Mon, Feb 7, 2011 at 11:08 PM, Denys Vlasenko
Post by Denys Vlasenko
Post by Denys Vlasenko
Post by Harald Becker
Post by rouble
Yes, 'reset' fixes the terminal.
In Denys' fix, he closes STDIN when the inactivity timer pops. I
wonder why that messes up the terminal?
Oh thats nothing to wonder about: The shell has to fiddle with the
terminal settings (raw/cooked) to allow line (advanced) editing.
Normally the terminal settings get saved and restored on shell exit ...
but if Denys closes stdio on alarm, that restore of the settings get
lost ...
... hey Denys, could you try to close only stdin on alarm and do the
terminal restore on stdout/stderr instead? ... just as a hint for a
possible solution.
I plan to remove the hack of closing stdin and implement it properly
in lineedit.
diff -ad -urpN busybox.3/editors/ed.c busybox.4/editors/ed.c
--- busybox.3/editors/ed.c ? ? ?2011-02-06 19:52:35.000000000 +0100
+++ busybox.4/editors/ed.c ? ? ?2011-02-08 04:41:44.000000000 +0100
@@ -129,7 +129,7 @@ static void doCommands(void)
? ? ? ? ? ? ? ? * 0 ?on ctrl-C,
? ? ? ? ? ? ? ? * >0 length of input string, including terminating '\n'
? ? ? ? ? ? ? ? */
- ? ? ? ? ? ? ? len = read_line_input(": ", buf, sizeof(buf), NULL);
+ ? ? ? ? ? ? ? len = read_line_input(NULL, ": ", buf, sizeof(buf), /*timeout*/ -1);
? ? ? ? ? ? ? ?if (len <= 0)
? ? ? ? ? ? ? ? ? ? ? ?return;
? ? ? ? ? ? ? ?endbuf = &buf[len - 1];
@@ -227,7 +227,7 @@ static void doCommands(void)
? ? ? ? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ? ? ? ?if (!dirty)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?return;
- ? ? ? ? ? ? ? ? ? ? ? len = read_line_input("Really quit? ", buf, 16, NULL);
+ ? ? ? ? ? ? ? ? ? ? ? len = read_line_input(NULL, "Really quit? ", buf, 16, /*timeout*/ -1);
? ? ? ? ? ? ? ? ? ? ? ?/* read error/EOF - no way to continue */
? ? ? ? ? ? ? ? ? ? ? ?if (len < 0)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?return;
@@ -541,7 +541,7 @@ static void addLines(int num)
? ? ? ? ? ? ? ? * 0 ?on ctrl-C,
? ? ? ? ? ? ? ? * >0 length of input string, including terminating '\n'
? ? ? ? ? ? ? ? */
- ? ? ? ? ? ? ? len = read_line_input("", buf, sizeof(buf), NULL);
+ ? ? ? ? ? ? ? len = read_line_input(NULL, "", buf, sizeof(buf), /*timeout*/ -1);
? ? ? ? ? ? ? ?if (len <= 0) {
? ? ? ? ? ? ? ? ? ? ? ?/* Previously, ctrl-C was exiting to shell.
? ? ? ? ? ? ? ? ? ? ? ? * Now we exit to ed prompt. Is in important? */
diff -ad -urpN busybox.3/include/libbb.h busybox.4/include/libbb.h
--- busybox.3/include/libbb.h ? 2011-02-08 04:16:08.000000000 +0100
+++ busybox.4/include/libbb.h ? 2011-02-08 04:40:55.000000000 +0100
@@ -1403,12 +1403,11 @@ line_input_t *new_line_input_t(int flags
?* 0 ?on ctrl-C (the line entered is still returned in 'command'),
?* >0 length of input string, including terminating '\n'
?*/
-/* NB: ash has timeout code which can be moved into read_line_input, if needed */
-int read_line_input(const char* prompt, char* command, int maxsize, line_input_t *state) FAST_FUNC;
+int read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize, int timeout) FAST_FUNC;
?#else
?#define MAX_HISTORY 0
?int read_line_input(const char* prompt, char* command, int maxsize) FAST_FUNC;
-#define read_line_input(prompt, command, maxsize, state) \
+#define read_line_input(state, prompt, command, maxsize, timeout) \
? ? ? ?read_line_input(prompt, command, maxsize)
?#endif
diff -ad -urpN busybox.3/libbb/lineedit.c busybox.4/libbb/lineedit.c
--- busybox.3/libbb/lineedit.c ?2011-02-06 19:52:35.000000000 +0100
+++ busybox.4/libbb/lineedit.c ?2011-02-08 04:53:05.000000000 +0100
@@ -1809,10 +1809,9 @@ static void win_changed(int nsig)
? ? ? ?errno = sv_errno;
?}
-static int lineedit_read_key(char *read_key_buffer)
+static int lineedit_read_key(char *read_key_buffer, int timeout)
?{
? ? ? ?int64_t ic;
- ? ? ? int timeout = -1;
?#if ENABLE_UNICODE_SUPPORT
? ? ? ?char unicode_buf[MB_CUR_MAX + 1];
? ? ? ?int unicode_idx = 0;
@@ -1917,7 +1916,7 @@ static int isrtl_str(void)
?* 0 ?on ctrl-C (the line entered is still returned in 'command'),
?* >0 length of input string, including terminating '\n'
?*/
-int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, line_input_t *st)
+int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize, int timeout)
?{
? ? ? ?int len;
?#if ENABLE_FEATURE_TAB_COMPLETION
@@ -1991,7 +1990,6 @@ int FAST_FUNC read_line_input(const char
? ? ? ?new_settings.c_cc[VINTR] = _POSIX_VDISABLE;
? ? ? ?tcsetattr_stdin_TCSANOW(&new_settings);
- ? ? ? /* Now initialize things */
? ? ? ?previous_SIGWINCH_handler = signal(SIGWINCH, win_changed);
? ? ? ?win_changed(0); /* do initial resizing */
?#if ENABLE_USERNAME_OR_HOMEDIR
@@ -2033,7 +2031,7 @@ int FAST_FUNC read_line_input(const char
? ? ? ? ? ? ? ?int32_t ic, ic_raw;
? ? ? ? ? ? ? ?fflush_all();
- ? ? ? ? ? ? ? ic = ic_raw = lineedit_read_key(read_key_buffer);
+ ? ? ? ? ? ? ? ic = ic_raw = lineedit_read_key(read_key_buffer, timeout);
?#if ENABLE_FEATURE_EDITING_VI
? ? ? ? ? ? ? ?newdelflag = 1;
@@ -2194,7 +2192,7 @@ int FAST_FUNC read_line_input(const char
? ? ? ? ? ? ? ?case 'd'|VI_CMDMODE_BIT: {
? ? ? ? ? ? ? ? ? ? ? ?int nc, sc;
- ? ? ? ? ? ? ? ? ? ? ? ic = lineedit_read_key(read_key_buffer);
+ ? ? ? ? ? ? ? ? ? ? ? ic = lineedit_read_key(read_key_buffer, timeout);
? ? ? ? ? ? ? ? ? ? ? ?if (errno) /* error */
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?goto return_error_indicator;
? ? ? ? ? ? ? ? ? ? ? ?if (ic == ic_raw) { /* "cc", "dd" */
@@ -2258,7 +2256,7 @@ int FAST_FUNC read_line_input(const char
? ? ? ? ? ? ? ? ? ? ? ?break;
?//FIXME: unicode case?
- ? ? ? ? ? ? ? ? ? ? ? ic = lineedit_read_key(read_key_buffer);
+ ? ? ? ? ? ? ? ? ? ? ? ic = lineedit_read_key(read_key_buffer, timeout);
? ? ? ? ? ? ? ? ? ? ? ?if (errno) /* error */
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?goto return_error_indicator;
? ? ? ? ? ? ? ? ? ? ? ?if (ic < ' ' || ic > 255) {
diff -ad -urpN busybox.3/shell/ash.c busybox.4/shell/ash.c
--- busybox.3/shell/ash.c ? ? ? 2011-02-06 19:52:35.000000000 +0100
+++ busybox.4/shell/ash.c ? ? ? 2011-02-08 05:01:28.000000000 +0100
@@ -102,8 +102,7 @@
?//config: ? ? ?default n
?//config: ? ? ?depends on ASH
?//config: ? ? ?help
-//config: ? ? ? ?Enables bash-like auto-logout after "$TMOUT" seconds
-//config: ? ? ? ?of idle time.
+//config: ? ? ? ?Enables bash-like auto-logout after $TMOUT seconds of idle time.
?//config:config ASH_JOB_CONTROL
?//config: ? ? ?bool "Job control"
@@ -408,6 +407,9 @@ static const char *var_end(const char *v
?/* ============ Interrupts / exceptions */
+
+static void exitshell(void) NORETURN;
+
?/*
?* These macros allow the user to suspend the handling of interrupt signals
?* over a period of time. ?This is similar to SIGHOLD or to sigblock, but
@@ -9573,10 +9575,21 @@ preadfd(void)
? ? ? ?if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
? ? ? ? ? ? ? ?nr = nonblock_safe_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
? ? ? ?else {
+ ? ? ? ? ? ? ? int timeout = -1;
+# if ENABLE_ASH_IDLE_TIMEOUT
+ ? ? ? ? ? ? ? if (iflag) {
+ ? ? ? ? ? ? ? ? ? ? ? const char *tmout_var = lookupvar("TMOUT");
+ ? ? ? ? ? ? ? ? ? ? ? if (tmout_var) {
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? timeout = atoi(tmout_var) * 1000;
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (timeout <= 0)
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? timeout = -1;
+ ? ? ? ? ? ? ? ? ? ? ? }
+ ? ? ? ? ? ? ? }
+# endif
?# if ENABLE_FEATURE_TAB_COMPLETION
? ? ? ? ? ? ? ?line_input_state->path_lookup = pathval();
?# endif
- ? ? ? ? ? ? ? nr = read_line_input(cmdedit_prompt, buf, IBUFSIZ, line_input_state);
+ ? ? ? ? ? ? ? nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout);
? ? ? ? ? ? ? ?if (nr == 0) {
? ? ? ? ? ? ? ? ? ? ? ?/* Ctrl+C pressed */
? ? ? ? ? ? ? ? ? ? ? ?if (trap[SIGINT]) {
@@ -9587,9 +9600,17 @@ preadfd(void)
? ? ? ? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ? ? ? ?goto retry;
? ? ? ? ? ? ? ?}
- ? ? ? ? ? ? ? if (nr < 0 && errno == 0) {
- ? ? ? ? ? ? ? ? ? ? ? /* Ctrl+D pressed */
- ? ? ? ? ? ? ? ? ? ? ? nr = 0;
+ ? ? ? ? ? ? ? if (nr < 0) {
+ ? ? ? ? ? ? ? ? ? ? ? if (errno == 0) {
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* Ctrl+D pressed */
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? nr = 0;
+ ? ? ? ? ? ? ? ? ? ? ? }
+# if ENABLE_ASH_IDLE_TIMEOUT
+ ? ? ? ? ? ? ? ? ? ? ? else if (errno == EAGAIN && timeout > 0) {
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? printf("\007timed out waiting for input: auto-logout\n");
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? exitshell();
+ ? ? ? ? ? ? ? ? ? ? ? }
+# endif
? ? ? ? ? ? ? ?}
? ? ? ?}
?#else
@@ -12056,23 +12077,6 @@ evalcmd(int argc UNUSED_PARAM, char **ar
? ? ? ?return exitstatus;
?}
-#if ENABLE_ASH_IDLE_TIMEOUT
-static smallint timed_out;
-
-static void alrm_sighandler(int sig UNUSED_PARAM)
-{
- ? ? ? /* Close stdin, making interactive command reading stop.
- ? ? ? ?* Otherwise, timeout doesn't trigger until <Enter> is pressed.
- ? ? ? ?*/
- ? ? ? int sv = errno;
- ? ? ? close(0);
- ? ? ? open("/dev/null", O_RDONLY);
- ? ? ? errno = sv;
-
- ? ? ? timed_out = 1;
-}
-#endif
-
?/*
?* Read and execute commands.
?* "Top" is nonzero for the top level command loop;
@@ -12089,20 +12093,6 @@ cmdloop(int top)
? ? ? ?TRACE(("cmdloop(%d) called\n", top));
? ? ? ?for (;;) {
? ? ? ? ? ? ? ?int skip;
-#if ENABLE_ASH_IDLE_TIMEOUT
- ? ? ? ? ? ? ? int tmout_seconds = 0;
-
- ? ? ? ? ? ? ? if (top && iflag) {
- ? ? ? ? ? ? ? ? ? ? ? const char *tmout_var = lookupvar("TMOUT");
- ? ? ? ? ? ? ? ? ? ? ? if (tmout_var) {
- ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? tmout_seconds = atoi(tmout_var);
- ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (tmout_seconds > 0) {
- ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? signal(SIGALRM, alrm_sighandler);
- ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? alarm(tmout_seconds);
- ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
- ? ? ? ? ? ? ? ? ? ? ? }
- ? ? ? ? ? ? ? }
-#endif
? ? ? ? ? ? ? ?setstackmark(&smark);
?#if JOBS
@@ -12115,14 +12105,6 @@ cmdloop(int top)
? ? ? ? ? ? ? ? ? ? ? ?chkmail();
? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ?n = parsecmd(inter);
-#if ENABLE_ASH_IDLE_TIMEOUT
- ? ? ? ? ? ? ? if (timed_out) {
- ? ? ? ? ? ? ? ? ? ? ? printf("\007timed out waiting for input: auto-logout\n");
- ? ? ? ? ? ? ? ? ? ? ? break;
- ? ? ? ? ? ? ? }
- ? ? ? ? ? ? ? if (tmout_seconds > 0)
- ? ? ? ? ? ? ? ? ? ? ? alarm(0);
-#endif
?#if DEBUG
? ? ? ? ? ? ? ?if (DEBUG > 2 && debug && (n != NODE_EOF))
? ? ? ? ? ? ? ? ? ? ? ?showtree(n);
@@ -12850,7 +12832,6 @@ ulimitcmd(int argc UNUSED_PARAM, char **
?/*
?* Called to exit the shell.
?*/
-static void exitshell(void) NORETURN;
?static void
?exitshell(void)
?{
diff -ad -urpN busybox.3/shell/hush.c busybox.4/shell/hush.c
--- busybox.3/shell/hush.c ? ? ?2011-02-07 02:02:44.000000000 +0100
+++ busybox.4/shell/hush.c ? ? ?2011-02-08 04:41:59.000000000 +0100
@@ -1902,7 +1902,7 @@ static void get_user_input(struct in_str
? ? ? ? ? ? ? ?G.flag_SIGINT = 0;
? ? ? ? ? ? ? ?/* buglet: SIGINT will not make new prompt to appear _at once_,
? ? ? ? ? ? ? ? * only after <Enter>. (^C will work) */
- ? ? ? ? ? ? ? r = read_line_input(prompt_str, G.user_input_buf, CONFIG_FEATURE_EDITING_MAX_LEN-1, G.line_input_state);
+ ? ? ? ? ? ? ? r = read_line_input(G.line_input_state, prompt_str, G.user_input_buf, CONFIG_FEATURE_EDITING_MAX_LEN-1, /*timeout*/ -1);
? ? ? ? ? ? ? ?/* catch *SIGINT* etc (^C is handled by read_line_input) */
? ? ? ? ? ? ? ?check_and_run_traps(0);
? ? ? ?} while (r == 0 || G.flag_SIGINT); /* repeat if ^C or SIGINT */
diff -ad -urpN busybox.3/util-linux/fdisk.c busybox.4/util-linux/fdisk.c
--- busybox.3/util-linux/fdisk.c ? ? ? ?2011-02-06 19:52:35.000000000 +0100
+++ busybox.4/util-linux/fdisk.c ? ? ? ?2011-02-08 04:41:18.000000000 +0100
@@ -548,7 +548,7 @@ read_line(const char *prompt)
?{
? ? ? ?int sz;
- ? ? ? sz = read_line_input(prompt, line_buffer, sizeof(line_buffer), NULL);
+ ? ? ? sz = read_line_input(NULL, prompt, line_buffer, sizeof(line_buffer), /*timeout*/ -1);
? ? ? ?if (sz <= 0)
? ? ? ? ? ? ? ?exit(EXIT_SUCCESS); /* Ctrl-D or Ctrl-C */
Denys Vlasenko
2011-02-08 20:24:42 UTC
Permalink
Post by rouble
Works like a champ. Good work Denys.
Will this be part of the next busybox stable release (1.18.3)?
1.18.x is in bugfix mode. This change will go into 1.19.0
--
vda
Loading...