How does "suspend-emacs" get my shell to run a command?

7 views
Skip to first unread message

Benjamin Esham

unread,
Sep 9, 2019, 2:58:36 PM9/9/19
to
GNU Emacs has a function called "suspend-emacs" which will suspend the Emacs
process. It takes an optional argument called "string", about which the
manual [1] says,

| If "string" is non-nil, its characters are sent to Emacs's superior shell,
| to be read as terminal input. The characters in "string" are not echoed by
| the superior shell; only the results appear.

And it does work as advertised: I tried running [2]

(suspend-emacs "date")

which had the effect of putting Emacs into the background and running the
"date" command in my shell. It appeared in every way like I had run "date"
myself: below the message saying "zsh: suspended emacs" was my shell prompt
with "date" after it, followed by the "date" output and then another prompt
line.

I found this very surprising! My mental model of running programs from a
shell did not include the possibility of a program reaching up into the
shell and forcing it to run a command. Can anyone explain the mechanism by
which Emacs is communicating with my shell in this situation? Does it rely
on the process still being running (albeit in the background)?

Thanks,

Benjamin


[1]: https://www.gnu.org/software/emacs/manual/html_node/elisp/Suspending-Emacs.html

[2]: If like me you're an Emacs neophyte, you can try this out by launching
Emacs, typing M-: (i.e. Meta-Colon), typing that line above, and
pressing Return.

--
Benjamin Esham
https://esham.io

Richard Kettlewell

unread,
Sep 9, 2019, 3:41:41 PM9/9/19
to
Benjamin Esham <use...@esham.io> writes:
> I found this very surprising! My mental model of running programs from a
> shell did not include the possibility of a program reaching up into the
> shell and forcing it to run a command. Can anyone explain the mechanism by
> which Emacs is communicating with my shell in this situation? Does it rely
> on the process still being running (albeit in the background)?

On Linux, have a look for TIOCSTI in ‘man ioctl-tty’.

In general, if you want to know how a program achieved some kind of OS
interaction like this, strace is good for shedding light on the question.

--
https://www.greenend.org.uk/rjk/

Keith Thompson

unread,
Sep 9, 2019, 4:35:36 PM9/9/19
to
Richard Kettlewell <inv...@invalid.invalid> writes:
> Benjamin Esham <use...@esham.io> writes:
>> I found this very surprising! My mental model of running programs from a
>> shell did not include the possibility of a program reaching up into the
>> shell and forcing it to run a command. Can anyone explain the mechanism by
>> which Emacs is communicating with my shell in this situation? Does it rely
>> on the process still being running (albeit in the background)?
>
> On Linux, have a look for TIOCSTI in ‘man ioctl-tty’.

It's 'man ioctl_tty' (underscore, not hyphen).

> In general, if you want to know how a program achieved some kind of OS
> interaction like this, strace is good for shedding light on the question.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */

Richard Kettlewell

unread,
Sep 9, 2019, 5:16:08 PM9/9/19
to
Keith Thompson <ks...@mib.org> writes:
> Richard Kettlewell <inv...@invalid.invalid> writes:
>> Benjamin Esham <use...@esham.io> writes:
>>> I found this very surprising! My mental model of running programs from a
>>> shell did not include the possibility of a program reaching up into the
>>> shell and forcing it to run a command. Can anyone explain the mechanism by
>>> which Emacs is communicating with my shell in this situation? Does it rely
>>> on the process still being running (albeit in the background)?
>>
>> On Linux, have a look for TIOCSTI in ‘man ioctl-tty’.
>
> It's 'man ioctl_tty' (underscore, not hyphen).

Sorry, yes,

--
https://www.greenend.org.uk/rjk/

Benjamin Esham

unread,
Sep 10, 2019, 1:04:46 PM9/10/19
to
Keith Thompson wrote:

> Richard Kettlewell <inv...@invalid.invalid> writes:
>> Benjamin Esham <use...@esham.io> writes:
>>> I found this very surprising! My mental model of running programs from a
>>> shell did not include the possibility of a program reaching up into the
>>> shell and forcing it to run a command. Can anyone explain the mechanism by
>>> which Emacs is communicating with my shell in this situation? Does it rely
>>> on the process still being running (albeit in the background)?
>>
>> On Linux, have a look for TIOCSTI in ‘man ioctl-tty’.
>
> It's 'man ioctl_tty' (underscore, not hyphen).

Interesting--I don't have that man page on my system (Ubuntu 16.04), and
typing "man ioct<TAB>" suggests that the relevant pages I have are "ioctl",
"ioctl_fat", and "ioctl_list", the latter of which describes itself as "a
list of ioctl calls in Linux/i386 kernel 1.3.27". (That kernel was released
on September 14, 1995, if you were curious.)

I wonder if Ubuntu relegates the ioctl_tty page to some "extra docs" package
that isn't installed by default. Which distribution are you using?

Benjamin Esham

unread,
Sep 10, 2019, 2:56:06 PM9/10/19
to
Richard Kettlewell wrote:

> Benjamin Esham <use...@esham.io> writes:
>
>> I found this very surprising! My mental model of running programs from a
>> shell did not include the possibility of a program reaching up into the
>> shell and forcing it to run a command. Can anyone explain the mechanism
>> by which Emacs is communicating with my shell in this situation? Does it
>> rely on the process still being running (albeit in the background)?
>
> On Linux, have a look for TIOCSTI in ‘man ioctl-tty’.

Thank you! The first Google result for this was a Hacker News thread from
2018 [1] which confirmed my suspicion: TIOCSTI is a vector for security
problems, partly because it's not very well known. OpenBSD removed support
for it in 2017 "due to risks known for decades" [2]. On the other hand, I'm
using this capability to make Emacs launch Vim and then resume itself after
Vim exits [3], and it seems to be the smoothest way to do that kind of
juggling. Classic security-convenience tradeoff.

> In general, if you want to know how a program achieved some kind of OS
> interaction like this, strace is good for shedding light on the question.

Thanks for the tip. I don't know how to use strace, though, so I'm afraid
that would lead me to more questions than answers ;-)

Benjamin

[1]: https://news.ycombinator.com/item?id=17311808
[2]: https://marc.info/?l=openbsd-cvs&m=149870941319610
[3]: https://emacs.stackexchange.com/a/52551/24262

Keith Thompson

unread,
Sep 10, 2019, 4:03:02 PM9/10/19
to
Benjamin Esham <use...@esham.io> writes:
> Keith Thompson wrote:
>> Richard Kettlewell <inv...@invalid.invalid> writes:
[...]
>>> On Linux, have a look for TIOCSTI in ‘man ioctl-tty’.
>>
>> It's 'man ioctl_tty' (underscore, not hyphen).
>
> Interesting--I don't have that man page on my system (Ubuntu 16.04), and
> typing "man ioct<TAB>" suggests that the relevant pages I have are "ioctl",
> "ioctl_fat", and "ioctl_list", the latter of which describes itself as "a
> list of ioctl calls in Linux/i386 kernel 1.3.27". (That kernel was released
> on September 14, 1995, if you were curious.)
>
> I wonder if Ubuntu relegates the ioctl_tty page to some "extra docs" package
> that isn't installed by default. Which distribution are you using?

On my Ubuntu 18.04.3 system, that man page is part of the "manpages-dev"
package -- but so are the ioctl and ioctl_* man pages, including the
ones you listed.

Benjamin Esham

unread,
Sep 10, 2019, 5:40:00 PM9/10/19
to
Keith Thompson wrote:

> Benjamin Esham <use...@esham.io> writes:
>
>> Keith Thompson wrote:
>>
>>> It's 'man ioctl_tty' (underscore, not hyphen).
>>
>> Interesting--I don't have that man page on my system (Ubuntu 16.04), and
>> typing "man ioct<TAB>" suggests that the relevant pages I have are
>> "ioctl", "ioctl_fat", and "ioctl_list", the latter of which describes
>> itself as "a list of ioctl calls in Linux/i386 kernel 1.3.27". (That
>> kernel was released on September 14, 1995, if you were curious.)
>>
>> I wonder if Ubuntu relegates the ioctl_tty page to some "extra docs"
>> package that isn't installed by default. Which distribution are you
>> using?
>
> On my Ubuntu 18.04.3 system, that man page is part of the "manpages-dev"
> package -- but so are the ioctl and ioctl_* man pages, including the
> ones you listed.

I do indeed have manpages-dev installed... some digging on the Ubuntu
Packages Search site reveals that this man page was not part of that package
in Xenial (16.04, the version I'm using) but was added in the next release
(Bionic, 18.04) and has been there since. I wonder what the reason was for
the omission.

Benjamin

Keith Thompson

unread,
Sep 10, 2019, 6:03:21 PM9/10/19
to
The source for "manpages-dev" is in a git repo at

https://salsa.debian.org/debian/manpages.git

The "Changes.old" file in that repo includes this:

ioctl_tty.2
Michael Kerrisk
Renamed from tty_ioctl(4)
All other ioctl(2) pages are in section 2. Make this
page consistent.
Michael Kerrisk
Packet mode state change events give POLLPRI events for poll(2)

Try "man tty_ioctl" or "man 4 tty_ioctl". (On Ubuntu 18.04, "tty_ioctl"
redirects to "ioctl_tty".)

Benjamin Esham

unread,
Sep 11, 2019, 1:00:46 PM9/11/19
to
Keith Thompson wrote:

> Benjamin Esham <use...@esham.io> writes:
>> Keith Thompson wrote:
>>> Benjamin Esham <use...@esham.io> writes:
>>>> I wonder if Ubuntu relegates the ioctl_tty page to some "extra docs"
>>>> package that isn't installed by default. Which distribution are you
>>>> using?
>>>
>>> On my Ubuntu 18.04.3 system, that man page is part of the "manpages-dev"
>>> package -- but so are the ioctl and ioctl_* man pages, including the
>>> ones you listed.
>>
>> I do indeed have manpages-dev installed... some digging on the Ubuntu
>> Packages Search site reveals that this man page was not part of that
>> package in Xenial (16.04, the version I'm using) but was added in the
>> next release (Bionic, 18.04) and has been there since. I wonder what the
>> reason was for the omission.
>
> [snip]
>
> Try "man tty_ioctl" or "man 4 tty_ioctl". (On Ubuntu 18.04, "tty_ioctl"
> redirects to "ioctl_tty".)

Thanks for doing this digging. I /do/ have that man page, finally.
Reply all
Reply to author
Forward
0 new messages