<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Made of Bugs &#187; termios</title>
	<atom:link href="http://blog.nelhage.com/tag/termios/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.nelhage.com</link>
	<description>It's software. It's made of bugs.</description>
	<lastBuildDate>Thu, 18 Aug 2011 21:57:23 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>reptyr: Changing a process&#8217;s controlling terminal</title>
		<link>http://blog.nelhage.com/2011/02/changing-ctty/</link>
		<comments>http://blog.nelhage.com/2011/02/changing-ctty/#comments</comments>
		<pubDate>Wed, 09 Feb 2011 03:06:50 +0000</pubDate>
		<dc:creator>nelhage</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[reptyr]]></category>
		<category><![CDATA[termios]]></category>
		<category><![CDATA[tty]]></category>
		<category><![CDATA[unix]]></category>

		<guid isPermaLink="false">http://blog.nelhage.com/?p=461</guid>
		<description><![CDATA[reptyr (announced recently on this blog) takes a process that is currently running in one terminal, and transplants it to a new terminal. reptyr comes from a proud family of similar hacks, and works in the same basic way: We use ptrace(2) to attach to a target process and force it to execute code of [...]]]></description>
			<content:encoded><![CDATA[<p><a href="https://github.com/nelhage/reptyr">reptyr</a> (<a href="http://blog.nelhage.com/2011/01/reptyr-attach-a-running-process-to-a-new-terminal/">announced</a> recently on this blog) takes a
process that is currently running in one terminal, and transplants it
to a new terminal. <code>reptyr</code> comes from a proud family of similar
hacks, and works in the same basic way: We use <a href="http://linux.die.net/man/2/ptrace"><code>ptrace(2)</code></a>
to attach to a target process and force it to execute code of our own
choosing, in order to open the new terminal, and <code>dup2(2)</code> it over
stdout and stderr.</p>

<p>The main special feature of <code>reptyr</code> is that it actually changes the
controlling terminal of the target process. The &#8220;controlling terminal&#8221;
is a concept maintained by UNIX operating systems that is independent
of a process&#8217;s file descriptors. The controlling terminal governs
details like where <code>^C</code> gets delivered, and how applications are
notified of changes in window size.</p>

<p>Processes are grouped into two levels of hierarchical groups:
sessions, and process groups. Each group is named by an ID, which is
the PID of the initial <strong>leader</strong> (either &#8220;session leader&#8221; or &#8220;process
group leader&#8221;). Even if the leader exits, that number is still the ID
for the group. Sessions are used for terminal management &#8212; Every
process in a session has the same controlling terminal, and each
terminal belongs to at most one session. Process groups are a
sub-division within sessions, and are used primarily for job control
within the shell. For a more in-depth explanation, see <a href="http://blog.nelhage.com/2010/01/a-brief-introduction-to-termios-signaling-and-job-control/">part
3</a> of my earlier series on termios.</p>

<p>If you check out <code>tty_ioctl(4)</code>, you&#8217;ll find that Linux has an
<code>ioctl</code>, <code>TIOCSCTTY</code>, that can be used to set the controlling terminal
of a process, and you could be forgiven for thinking that all we need
is to make the target call that ioctl, and we&#8217;re done.</p>

<p>However, if we read closer, we find that it has several
restrictions. In particular:</p>

<blockquote>
  <p>The calling process must be a session leader and not have a
  controlling terminal already.  If this terminal is already the
  controlling terminal of a different session group then the ioctl fails
  with EPERM […]</p>
</blockquote>

<p>In the typical case, where I&#8217;m trying to attach a (say) <code>mutt</code> that
you spawned from your shell, <code>mutt</code> won&#8217;t be a session leader &#8212; your
shell will be the session leader, and <code>mutt</code> will be the process group
leader for a process group containing only itself.</p>

<p>So, we need to make the target a session leader. Conveniently, there&#8217;s
a system call for that: <code>setsid(2)</code>.</p>

<p>However, reading that man page, we find a new caveat: <code>setsid(2)</code>
fails with <code>EPERM</code> if</p>

<blockquote>
  <p>The process group ID of any process equals the PID of the calling
  process.  Thus, in particular, setsid() fails if the calling process
  is already a process group leader.</p>
</blockquote>

<p>The shell creates a new process group for every job you launch, and so
our target <code>mutt</code> will be a process group leader, and unable to
<code>setsid()</code>. The usual solution for programs that want to setsid is to
<code>fork()</code>, so that the child is still in the parent&#8217;s session and
process group, and then <code>setsid()</code> in the child. However, <code>fork()</code>ing
our <code>mutt</code> and killing off the parent seems potentially disruptive, so
let&#8217;s see if we can avoid that.</p>

<p>So, we&#8217;re going to need to change <code>mutt</code>&#8216;s process group ID, so that
there are no processes with process group IDs equal to its
PID. Following some trusty <em><code>SEE ALSO</code></em> links, we get to
<code>setpgid(2)</code>. There&#8217;s a bunch of text in that man page, but the key
bit is:</p>

<blockquote>
  <p>If setpgid() is used to move a process from one process group to
  another, both process groups must be part of the same session (see
  setsid(2) and credentials(7)).  In this case, the pgid specifies an
  existing process group to be joined and the session ID of that group
  must match the session ID of the joining process.</p>
</blockquote>

<p>We need to find a process group in the same session as <code>mutt</code> to move
our <code>mutt</code> into, and then we&#8217;ll be able to <code>setsid</code>. We could try to
find one &#8212; the shell is a plausible candidate, for instance &#8212; but
there&#8217;s an alternate, more direct route: Create one.</p>

<p>While we have <code>mutt</code> captured with <code>ptrace</code>, we can make it <code>fork(2)</code>
a dummy child, and start tracing that child, too. We&#8217;ll make the child
<code>setpgid</code> to make it into its own process group, and then get <code>mutt</code>
to <code>setpgid</code> itself into the child&#8217;s process group. <code>mutt</code> can then
<code>setsid</code>, moving into a new session, and now, as a session leader, we
can finally <code>ioctl(TIOCSCTTY)</code> on the new terminal, and we win.</p>

<p>It turns out I didn&#8217;t invent this technique &#8212; <a href="http://blog.habets.pp.se/2009/03/Moving-a-process-to-another-terminal">injcode</a> and
<a href="http://caca.zoy.org/wiki/neercs">neercs</a> work the same way. But I did discover it
independently of them, and it was a fun little hunt through unix
arcana.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nelhage.com/2011/02/changing-ctty/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>reptyr: Attach a running process to a new terminal</title>
		<link>http://blog.nelhage.com/2011/01/reptyr-attach-a-running-process-to-a-new-terminal/</link>
		<comments>http://blog.nelhage.com/2011/01/reptyr-attach-a-running-process-to-a-new-terminal/#comments</comments>
		<pubDate>Sat, 22 Jan 2011 01:56:01 +0000</pubDate>
		<dc:creator>nelhage</dc:creator>
				<category><![CDATA[Low-level hacking]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[ptrace]]></category>
		<category><![CDATA[reptyr]]></category>
		<category><![CDATA[screenify]]></category>
		<category><![CDATA[termios]]></category>

		<guid isPermaLink="false">http://blog.nelhage.com/?p=450</guid>
		<description><![CDATA[Over the last week, I&#8217;ve written a nifty tool that I call reptyr. reptyr is a utility for taking an existing running program and attaching it to a new terminal. Started a long-running process over ssh, but have to leave and don&#8217;t want to interrupt it? Just start a screen, use reptyr to grab it, [...]]]></description>
			<content:encoded><![CDATA[<p>Over the last week, I&#8217;ve written a nifty tool that I call
<a href="http://github.com/nelhage/reptyr">reptyr</a>. reptyr is a utility for taking an existing running
program and attaching it to a new terminal. Started a long-running
process over ssh, but have to leave and don&#8217;t want to interrupt it?
Just start a screen, use reptyr to grab it, and then kill the ssh
session and head on home.</p>

<p>You can <a href="http://github.com/nelhage/reptyr">grab the source</a>, or read on for some more details.</p>

<p>There&#8217;s a shell script called <a href="http://tomaw.net/tmp/screenify">screenify</a> that&#8217;s been going
around the internet for nigh on 10 years now that is supposed to use
gdb to accomplish the same thing. There&#8217;s also a project called
<a href="http://pasky.or.cz/~pasky/dev/retty/">retty</a> that tries to do the same thing, in C using <code>ptrace()</code>
directly.</p>

<p>The difference between those programs and reptyr is that reptyr works
much, much, better.</p>

<p>If you attach a <code>less</code> using screenify or retty, it will still take
input from the old terminal. If you attach an ncurses program, and
resize the window, the program probably won&#8217;t resize correctly. <code>^C</code>
and <code>^Z</code> will still be processed on the old terminal &#8212; typing them in
the new terminal won&#8217;t do anything useful.</p>

<p>reptyr fixes all of these problems and more, and is the only such tool
I know of that does so. I&#8217;ve never seen a program that doesn&#8217;t behave
noticeably incorrectly after attaching with retty or screenify,
whereas with reptyr most programs I have tried work flawlessly.</p>

<h2>How does it work?</h2>

<p><code>reptyr</code> works in the same basic way as <code>screenify</code> and <code>retty</code> &#8212; it
attaches to the target process using the <code>ptrace</code> API, opens the new
terminal, and <code>dup2</code>s it over the old file descriptors. It also copies
the termios settings from the old terminal to the new terminal.</p>

<p>The main thing that reptyr does that no one else does is that it
actually changes the controlling terminal of the process you are
attaching. This is the detail that makes many things Just Work,
including <code>^C</code> and <code>^Z</code> and window resizing.</p>

<p>Switching the target&#8217;s controlling terminal is not easy and involves a
fair bit of trickery with <code>ptrace</code> and Linux&#8217;s terminal APIs. I will
probably do another blog post some time about the dirty details of how
I make this work, but for now you can check out
<a href="https://github.com/nelhage/reptyr/blob/master/attach.c">attach.c</a> if
you really want to know.</p>

<p>reptyr still has a number of limitations &#8212; it doesn&#8217;t generally work,
for example, if the target process has any children. I know how to fix
most of these problems, though, so expect it to get better with
time. Please let me know if you find it useful!</p>

<h2>Appendix</h2>

<p>(Edited to add:) Nothing is really new. A commenter on reddit pointed out that <a href="http://blog.habets.pp.se/2009/03/Moving-a-process-to-another-terminal">injcode</a>
and <a href="http://caca.zoy.org/wiki/neercs">neercs</a> both accomplish the same thing, even using the same trick
to change the CTTY. Ah well, I had run writing it anyways, and apparently I
wasn&#8217;t the only one who didn&#8217;t know about the existing alternatives. <code>neercs</code> is a full screen replacement, though, and I think that reptyr should be more robust than <code>injcode</code> &#8212; I use a different techique for <code>ptrace</code>-hijacking, for example &#8212; and so hopefully this tool still has a niche as a more robust standalone utility. Certainly, judging from the amount of enthusiasm I&#8217;ve seen for this tool, this still isn&#8217;t a problem that is solved to the average user&#8217;s satisfaction.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nelhage.com/2011/01/reptyr-attach-a-running-process-to-a-new-terminal/feed/</wfw:commentRss>
		<slash:comments>42</slash:comments>
		</item>
		<item>
		<title>A Brief Introduction to termios: Signaling and Job Control</title>
		<link>http://blog.nelhage.com/2010/01/a-brief-introduction-to-termios-signaling-and-job-control/</link>
		<comments>http://blog.nelhage.com/2010/01/a-brief-introduction-to-termios-signaling-and-job-control/#comments</comments>
		<pubDate>Mon, 11 Jan 2010 05:42:52 +0000</pubDate>
		<dc:creator>nelhage</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[signals]]></category>
		<category><![CDATA[termios]]></category>
		<category><![CDATA[tty]]></category>
		<category><![CDATA[unix]]></category>

		<guid isPermaLink="false">http://blog.nelhage.com/?p=60</guid>
		<description><![CDATA[(This is part three of a multi-part introduction to termios and terminal emulation on UNIX. Read part 1 or part 2 if you&#8217;re new here) For my final entry on termios, I will be looking at job control in the shell (i.e. backgrounding and foreground jobs) and the very closely related topic of signal generation [...]]]></description>
			<content:encoded><![CDATA[<p>(This is part three of a multi-part introduction to termios and
terminal emulation on UNIX. Read <a href="http://blog.nelhage.com/archives/14">part 1</a> or <a href="http://blog.nelhage.com/archives/27">part 2</a>
if you&#8217;re new here)</p>

<p>For my final entry on termios, I will be looking at job control in the
shell (i.e. backgrounding and foreground jobs) and the very closely
related topic of signal generation by termios, in response to <code>INTR</code>
and friends.</p>

<h2>Sessions and Process Groups</h2>

<p>For the purposes of termios, processes are organized into two
hierarchical groups, <strong>process groups</strong> and <strong>sessions</strong>. Every
process belongs to exactly one process group and one session, and each
process group is contained entirely within a session.</p>

<p>Process groups and sessions are both named by the process ID of the
process to create the group. This process is known as the <strong>process
group leader</strong> or <strong>session leader</strong>. A process creates a new session
using <code>setsid(2)</code>, or a new process group using <code>setpgid(2)</code>.</p>

<p>On Linux, you can inspect the process group and session of a process
using the <code>stat</code> field in <code>/proc/$PID</code>. The first several fields in
that file are:</p>

<pre><code>    pid (name) state ppid pgid sid …
</code></pre>

<p>or, in more words:</p>

<pre><code>    [process id] ([name]) [state] [parent process id] [process group id] [session id] …
</code></pre>

<h3>Sessions</h3>

<p>Sessions are the fundamental group of terminal management. Every
session may have an associated <strong>controlling terminal</strong>, which is
treated specially. A process may open and talk to any number of
terminals, but the special behaviors related to access control and job
control only apply to a process&#8217;s controlling terminal. Each terminal
may be the controlling terminal of at most one session. It follows
that calling <code>setsid(2)</code> to create a new session causes a process to
lose its previous controlling terminal. Acquiring a controlling
terminal is OS-specific, but can usually be accomplished by opening a
terminal device without the <code>O_NOCTTY</code> flag, while not already having
a controlling terminal.</p>

<p>Generally, all your processes within a single login session, or within
a single instance of your terminal emulator, are within the same
session, with the <code>pty</code> allocated by your terminal emulator or <code>ssh</code>
or whatever as their controlling terminal.</p>

<h3>Process Groups</h3>

<p>Process groups are the unit of control for signal generation by a
terminal. A terminal never sends a signal to a specific process, but
always to all processes within a process group.</p>

<p>Access to a terminal is also mediated in terms of process groups. In
addition to having an associated session, every terminal has exactly
one <strong>foreground process group</strong>. Every other process in that
terminal&#8217;s session is a <strong>background process group</strong>.</p>

<p>The foreground process group is awarded special access to its
controlling terminal. It is allowed unrestricted access to read from
and write to the terminal, as well as to call various control
functions, such as <code>tcsetattr</code> on it.</p>

<p>In addition, if any signal-generating character is read by a terminal,
it generates the appropriate signal to the foreground process group.</p>

<p>Background process groups are restricted in their access to their
controlling terminal. If any process in a background process group
attempts to read from its controlling terminal, it will result in
<code>SIGTTIN</code> being sent to its process group. Background processes may
write to their controlling terminal, unless <code>TOSTOP</code> is set in
<code>c_lflag</code>, in which case doing so will generate <code>SIGTTOU</code> to its
process group. Calling terminal control functions such as <code>tcsetattr</code>
is treated like a write operation with <code>TOSTOP</code> set (i.e. <code>SIGTTOU</code> is
sent unless the process is blocking or ignoring it).</p>

<p>The foreground process group for a terminal may be set by the
<code>tcsetpgrp(3)</code> function, which may be called by any process in the
terminal&#8217;s session, but is treated in the same way as <code>tcsetattr</code> in
the previous paragraph.</p>

<h2>Job control</h2>

<p>We&#8217;ve now got most of what we need to understand job control in your
shell.</p>

<p>When processing each command line, the shell uses <code>setpgid</code> to place
all of the programs executed by the line into the same process group,
and then calls <code>tcsetpgrp</code> to make that job the foreground job, and
does a <code>waitpid</code> to wait on that process.</p>

<p>Thus, when you run a shell pipeline (<code>foo | bar | grep baz</code>), all the
programs in the pipeline are in the same process group, and in the
foreground, which is why a <code>^C</code> kills all of them.</p>

<p>When you <code>^Z</code> a jobs, all the processes in the process group are
stopped, and the shell&#8217;s <code>waitpid</code> returns, informing it of the status
change. The shell restores itself to the foreground process group, and
marks the job as backgrounded.</p>

<p>When you use <code>bg</code> to background a stopped job, the shell just uses
<code>killpg(2)</code> to <code>SIGCONT</code> the group. If a job in the background tries
to read from the terminal, the <code>SIGTTIN</code> stops it and the shell&#8217;s
<code>wait</code> detects the state change and adjusts the job&#8217;s state
appropriately.</p>

<p>If you launch a job in the background, the shell simply doesn&#8217;t
<code>tcsetpgrp</code> it into the foreground, nor <code>wait</code> on it.</p>

<h1>In conclusion</h1>

<p>That&#8217;s probably all I want to say about termios. I could talk more about terminal emulation, ncurses, <code>$TERM</code> and friends, but it&#8217;s less interesting to me &#8212; I think I&#8217;m a kernel hacker at heart, and that stuff is just userspace programs talking to each other at this point. I hope you found this series interesting and/or informative, and I&#8217;m always happy to answer questions.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nelhage.com/2010/01/a-brief-introduction-to-termios-signaling-and-job-control/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Brief Introduction to termios: termios(3) and stty</title>
		<link>http://blog.nelhage.com/2009/12/a-brief-introduction-to-termios-termios3-and-stty/</link>
		<comments>http://blog.nelhage.com/2009/12/a-brief-introduction-to-termios-termios3-and-stty/#comments</comments>
		<pubDate>Wed, 30 Dec 2009 05:47:17 +0000</pubDate>
		<dc:creator>nelhage</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[apis]]></category>
		<category><![CDATA[termios]]></category>
		<category><![CDATA[tty]]></category>
		<category><![CDATA[unix]]></category>

		<guid isPermaLink="false">http://blog.nelhage.com/?p=27</guid>
		<description><![CDATA[(This is part two of a multi-part introduction to termios and terminal emulation on UNIX. Read part 1 if you&#8217;re new here) In this entry, we&#8217;ll look at the interfaces that are used to control the behavior of the &#8220;termios&#8221; box sitting between the master and slave pty. The behaviors I described last time are [...]]]></description>
			<content:encoded><![CDATA[<p>(This is part two of a multi-part introduction to termios and terminal
emulation on UNIX. Read <a href="http://blog.nelhage.com/archives/14">part 1</a> if you&#8217;re new here)</p>

<p>In this entry, we&#8217;ll look at the interfaces that are used to control
the behavior of the &#8220;termios&#8221; box sitting between the master and
slave pty. The behaviors I described last time are fine if you have a
completely dumb program talking to the terminal, but if the program
over on the right is using curses (like emacs or vim), or even just
readline (like bash), it will want to disable or customize some of the
behaviors.</p>

<p>The primary programmatic interface to termios is the <code>struct termios</code>
and two functions:</p>

<pre><code>   int tcgetattr(int fd, struct termios *termios_p);
   int tcsetattr(int fd, int optional_actions,
                 const struct termios *termios_p);
</code></pre>

<p>which retrieve and set the <code>struct termios</code> associated with a given terminal device.
They are all documented in <code>termios(3)</code> (If you&#8217;re
unfamiliar with the convention, that means document <code>termios</code> in section
<code>3</code> of the unix <code>man</code> pages &#8212; <code>man 3 termios</code> on a command-line will
get it for you).</p>

<p>So what&#8217;s inside <code>struct termios</code>? POSIX
specifies that this structure contains at least the following fields:</p>

<pre><code>       tcflag_t c_iflag;      /* input modes */
       tcflag_t c_oflag;      /* output modes */
       tcflag_t c_cflag;      /* control modes */
       tcflag_t c_lflag;      /* local modes */
       cc_t     c_cc[NCCS];   /* control chars */
</code></pre>

<p>Each &#8220;flag&#8221; field contains a number of flags (implemented as a bitmask) that can be individually enabled or disabled.
<code>c_iflag</code> and <code>c_oflag</code> contain flags that affect the processing
of input and output, respectively. <code>c_cflag</code> we will mostly ignore, as
it contains settings that relate to the control of modems and serial
lines that are mostly irrelevant these days. <code>c_lflag</code> is perhaps the most interesting of the flag values. It
contains flags that control the broad-scale behavior of the
<code>tty</code>. I&#8217;ll look at just a few of the interesting bits in each:</p>

<h3>local modes</h3>

<ul>
<li><p><code>ICANON</code> &#8211; Perhaps the most important bit in <code>c_lflag</code> is the <code>ICANON</code>
bit. Enabling it enables &#8220;canonical&#8221; mode &#8212; also known as
&#8220;line editing&#8221; mode. When <code>ICANON</code> is set, the terminal buffers a line
at a time, and enables line editing. Without <code>ICANON</code>, input is made
available to programs immediately (this is also known as &#8220;cbreak&#8221;
mode). </p></li>
<li><p><code>ECHO</code> in <code>c_lflag</code> controls whether input is immediately re-echoed as
output. It is independent of <code>ICANON</code>, although they are often turned on and off together. When <code>passwd</code> prompts for your password, your terminal is in canonical mode, but <code>ECHO</code> is disabled.</p></li>
<li><p><code>ISIG</code> in <code>c_lflag</code> controls whether <code>^C</code> and <code>^Z</code> (and friends) generate signals or
not. When unset, they are passed directly through as characters,
without generating signals to the application.</p></li>
</ul>

<h3>input and output modes</h3>

<p>There are also a few flags in <code>c_iflag</code> and <code>c_oflag</code> worth mentioning.</p>

<ul>
<li><p><code>IXON</code> in <code>c_iflag</code> enables the &#8220;flow control&#8221; mediated by
<code>^S</code> and <code>^Q</code> (by default). With <code>IXON</code>, once <code>^S</code> has been received
by the master pty, the slave will not accept any output (<code>write</code>s to it will hang) until <code>^Q</code> is received by the master pty.</p></li>
<li><p><code>IUTF8</code> in <code>c_iflag</code> is an interesting hack. In canonical mode, backspace needs to
delete the previous character in the input buffer. In non-ASCII encodings, a single character may be several bytes long, but the terminal still only sees a byte stream, and has no explicit information about the encoding or character boundaries on either end.
<code>IUTF8</code> tells termios that the input stream is utf-8 encoded, which permits the
correct handling of backspace. If <code>IUTF8</code> is unset, and you enter a
multibyte character and then press backspace, only the final byte will
be deleted, leaving you with a corrupt utf-8 stream.</p></li>
<li><p><code>OLCUC</code> in <code>c_oflag</code> &#8220;Map[s] lowercase characters to uppercase on
output.&#8221; Just in CASE YOU NEED YOUR TERMINAL TO LOOK MORE LIKE
SHOUTING.</p></li>
</ul>

<p>There are many more flags, controlling such details as newline translation and how character erase works. The full list is documented in <code>termios(3)</code>.</p>

<h3>c_cc</h3>

<p>Next up is <code>c_cc</code>. This field sets the various control characters used to interact with the
terminal. Characters like <code>^C</code> and <code>^Z</code> and delete that have special meanings to termios are not hard coded anywhere, but rather defined via the <code>c_cc</code> array.</p>

<p><code>c_cc</code> is indexed by various constants for the various control characters, and
the value at any index is the character that should have that effect. Some of the notable ones are:</p>

<ul>
<li><p><code>VINTR</code> &#8212; Generate a <code>SIGINT</code> (<code>^C</code> by default).</p></li>
<li><p><code>VSUSP</code> &#8212; Generate a <code>SIGTSTP</code> (stop the program) (<code>^Z</code> by default).</p></li>
<li><p><code>VERASE</code> &#8212; Erase the previous character. This tends to be one of
<code>^H</code> and <code>^?</code> (ASCII <code>0x7f</code>) by default &#8212; if you&#8217;ve ever pressed
&#8220;backspace&#8221; and been greeted by a <code>^H</code>, your terminal and your
<code>struct termios</code> disagree on the value of <code>VERASE</code>.</p></li>
<li><p><code>VEOF</code> &#8212; End of file. Sends the current line to the program
without waiting for end-of-line, or, as the first character on the line, causes the next <code>read</code> call by the slave to return return end-of-file. (<code>^D</code> by default)</p></li>
<li><p><code>VSTOP</code> and <code>VSTART</code> &#8212; <code>^S</code> and <code>^Q</code> by default, stop and start
output.</p></li>
</ul>

<p>Setting any of these to NULL (0) disables that special control character. Many of the <code>c_cc</code> elements are only relevant when certain modes are active &#8212; <code>VINTR</code> and <code>VSUSP</code>, for instance, only matter if <code>ISIG</code> is enabled in <code>c_lflag</code>, and <code>VSTOP</code> and <code>VSTART</code> are ignored unless <code>IXON</code> is set.</p>

<p>(A brief note on the representation of control characters &#8212; The characters <code>^A</code> through <code>^Z</code>, pronounced &#8220;Ctrl-FOO&#8221;, are represented by the bytes with values 1 through 26. So when I say that <code>c_cc[VINTR]</code> is equal to <code>^C</code> by default,
that&#8217;s actually just the number <code>3</code> &#8212; your terminal took the keypresses and just translated them into the byte <code>3</code> on the wire.)</p>

<h2>stty</h2>

<p>While <code>termios(3)</code> is the standard programmatic interface to control
termios, a much more convenient interface for experimentation is the
<code>stty</code> program, which is just a thin wrapper around <code>tcgetattr</code> and
<code>tcsetattr</code> designed to be usable from shell scripts or directly from the shell.</p>

<p><code>stty</code> gets or sets options on a terminal device. By default, it operates on the one connected to its standard out, but you can pass it an arbitrary device using the <code>-F</code> option.</p>

<p>Without aguments, <code>stty</code> prints in what way its terminal&#8217;s settings differ from an internal set of &#8220;sane&#8221;
defaults. <code>stty -a</code> causes it to print the value of every flag in the
<code>struct termios</code> in a human-readable format.</p>

<p>You can toggle flags using <tt>stty <i>flag</i></tt> to enable a flag, and <tt>stty
-<i>flag</i></tt> to disable it. So for instance, <code>stty -isig</code> will disable
signal generation &#8212; run a program after doing this, and you&#8217;ll find
yourself unable to <code>^C</code> it. In general it uses the same names as the C constants, except in lowercase, but check the man page if in doubt.</p>

<p><code>stty</code> can also change the value of the control characters in
<code>c_cc</code>, using <tt>stty <i>symbolic-name</i> <i>character</i></tt>. If you wanted <code>^G</code> to be the interrupt character, instead of <code>^C</code>, a simple <code>stty intr ^G</code> would suffice. You can spell <code>0</code> as <code>undef</code> to disable a given control character. So, if you hate flow
control and want to totally disable it, you could try <code>stty -ixon stop
undef</code> &#8212; disable <code>IXON</code>, and then also disable the <code>VSTOP</code>
character for good measure. (You might still be foiled by screen or some other layer doing its own flow control, unfortunately).</p>

<p><code>stty</code>&#8216;s <code>-F</code> option can be great for peeking at what some other program is
doing to its terminal. If you run <code>tty</code> in a shell, it will print the
path to that shell&#8217;s terminal device (usually of the form
<tt>/dev/pts/<i>N</i></tt>, at least under Linux). Now,
from a different shell, you can run <tt>stty -a -F /dev/pts/<i>N</i></tt> to see how
the first shell&#8217;s terminal is configured.  You can then run programs
in the first shell, and repeat the <code>stty</code> incant in shell two to see
what settings are getting set. For example, if I run <code>stty -F /dev/pts/10</code> right now (while I have a <code>bash</code> talking to a <code>gnome-terminal</code> via that pty), I see:</p>

<pre><code>$ stty -F /dev/pts/10
speed 38400 baud; line = 0;
eol = M-^?; eol2 = M-^?; swtch = M-^?; lnext = &lt;undef&gt;; min = 1; time = 0;
-icrnl iutf8
-icanon -echo
</code></pre>

<p>So we can see that bash/readline has disabled CR→LF translation on input (<code>icrnl</code>), disabled canonical mode and echo, but turned on UTF-8 mode (because bash detected a utf-8 locale). Note that if I run <code>stty</code> directly in that shell, I see something slightly different:</p>

<pre><code>$ stty
speed 38400 baud; line = 0;
eol = M-^?; eol2 = M-^?; swtch = M-^?;
iutf8
</code></pre>

<p>This is because bash maintains its own set of termios settings (for readline), and saves and restores settings around running programs, so that settings in place while running a program are different from those in place while you&#8217;re typing at the bash prompt. </p>

<p>In the next post, we&#8217;ll look at signal generation from <code>ISIG</code> and how it interacts with job control in your shell.</p>

<h2>Addendum: <code>ioctl(2)</code></h2>

<p>This last section is a brief aside, which has very little to do with termios specifically, so you should feel free to skip it. But read on if you&#8217;re curious about some of the low-level details of how the APIs work.</p>

<p>If you&#8217;re familiar with man page conventions, you may have noticed
that the <code>termios</code> functions are in man page section 3, which means
that they&#8217;re provided by system libraries, and are not system
calls. But at the same time, I told you last time that termios is
implemented inside the kernel &#8212; so how are the libraries talking to
the kernel, if not through syscalls?</p>

<p>The answer is a single odd little catch-all system call, known as
<code>ioctl</code>. Historically, one of the &#8220;big ideas&#8221; of UNIX was that
&#8220;everything is a file&#8221; &#8212; you could communicate with devices just like
you could files, by opening files in <code>/dev/</code>. But a file on UNIX is also just a stream of bytes, without any
OS-imposed structure. And for a device, you may often need to send
out-of-band control data &#8212; e.g. to set the baud and parity bit settings on a
serial port. And adding new system calls for every new device type would
be untenable for a number of reasons.</p>

<p>So the answer was one new new system call, <code>ioctl</code> (pronounced as any
of &#8220;I-O-cuddle&#8221;, &#8220;I-octal&#8221; or &#8220;I-O-C-T-L&#8221;). <code>ioctl</code> is prototyped as:</p>

<pre><code>int ioctl(int fd, int request, ...);
</code></pre>

<p>It takes a file descriptor, a numeric &#8220;request&#8221; code, and an unspecified number of
other arguments. <code>ioctl</code> looks up whatever device (or file
system, network protcol, or whatever) is backing that file descriptor, and hands it the &#8220;request&#8221; and the arguments
to do with as they will. </p>

<p>So any device that needs extra control channels can define some <code>ioctl</code> numbers and parameters and document them somewhere, and they become the interface to control that device. So, for instance (at least on Linux), an <code>ioctl</code> on a tty device with  a &#8220;request&#8221; of <code>TCGETS</code> (defined in <code>termios.h</code>) takes a parameter that is a pointer to a <code>struct termios</code>, and copies the in-kernel settings for that tty to the provided struct. So somewhere in libc, <code>tcgetattr(fd, p)</code> is just defined to do an <code>ioctl(fd, TCGETS, p)</code>. Similar ioctls are defined for <code>tcsetattr</code> and all the functions in <code>termios(3)</code>. On Linux, at least, the morbidly curious can find out all the gory details in <code>tty_ioctl(4)</code>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nelhage.com/2009/12/a-brief-introduction-to-termios-termios3-and-stty/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Brief Introduction to termios</title>
		<link>http://blog.nelhage.com/2009/12/a-brief-introduction-to-termios/</link>
		<comments>http://blog.nelhage.com/2009/12/a-brief-introduction-to-termios/#comments</comments>
		<pubDate>Tue, 22 Dec 2009 23:11:22 +0000</pubDate>
		<dc:creator>nelhage</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[termios]]></category>
		<category><![CDATA[tty]]></category>
		<category><![CDATA[unix]]></category>

		<guid isPermaLink="false">http://blog.nelhage.com/?p=14</guid>
		<description><![CDATA[If you&#8217;re a regular user of the terminal on a UNIX system, there are probably a large number of behaviors you take mostly for granted without really thinking about them. If you press ^C or ^Z it kills or stops the foreground program &#8212; unless it&#8217;s something like emacs or vim, in which case it [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re a regular user of the terminal on a UNIX system, there are
probably a large number of behaviors you take mostly for granted
without really thinking about them. If you press <code>^C</code> or <code>^Z</code> it kills or stops the foreground program &#8212; unless it&#8217;s something like emacs or vim,
in which case it gets handled like a normal keystroke. When you ssh to
a remote host, though, they go to the processes on that machine, not
the ssh process. You probably know that your shell is using
libreadline (or something similar) to give you high quality line
editing and history, but who&#8217;s responsible for the (much poorer) line editing you
get when you&#8217;re typing to a <code>cat</code> process?</p>

<p>The answer to all these questions involves the unix terminal emulation layer, and the termios interface for interacting with asynchronous communication devices (such as serial ports connected to terminals, or their virtual equivalents). This blog post will be part 1 of what will probably be a three-part introduction to tty emulation and termios in unix
(with a focus on Linux, since that&#8217;s what I know and use) and to the APIs for interacting with it, as a springboard to
understanding how these layers all work and where these behaviors come
from. Along the way, you&#8217;ll learn a bit more about customizing the behavior of these layers, which can come in handy both as a user, and if you write terminal-based applications for unix.</p>

<h2>The terminal device</h2>

<p>The primary abstraction that governs any interaction with a terminal
in Unix is a &#8220;terminal&#8221; device, or <code>tty</code> for short. In most cases these days, since you&#8217;re
not interacting with a physical terminal, you&#8217;ll be dealing with a &#8220;pseudo-terminal&#8221; (&#8220;pty&#8221; for
short &#8212; see <code>pty(7)</code>), which is a purely virtual construct. A
pseudo-terminal, simply, is a pair of endpoints (implemented as character devices in <code>/dev/</code>) that provide a bidirectional
communication channel. Whatever is written into one can be read out
the other, and vice versa. These two ends are known as the &#8220;master&#8221;
and &#8220;slave&#8221; ends. Unlike pipes or sockets, however, they don&#8217;t always pass data directly through. What makes terminal devices special is the layer that sits between the
master and slave, which can filter, transform, and act upon the streams in both directions.</p>

<p>In standard usage, the &#8220;master&#8221; pty is connected to your terminal
emulator (e.g. <code>xterm</code>), and the &#8220;slave&#8221; pty is connected to the
program being run (e.g. your shell). &#8220;Input&#8221; flows from the user into the master pty and out the slave, and &#8220;output&#8221; flows from your program into the slave and then out the master. The basic diagram for
what&#8217;s going on, then is:</p>

<p><img src="http://blog.nelhage.com/wp-content/uploads/2009/12/termios.png" alt="termios blog diagram" title="Termios Block Diagram" width="443" height="121" class="alignnone size-full wp-image-17" /></p>

<p>This diagram is a simplification in a few ways, but it still captures
most of what&#8217;s going on. </p>

<h2>What happens in the middle?</h2>

<p>That block I&#8217;ve labelled &#8220;termios&#8221; in the middle is responsible for essentially all of the behavior I listed in the first paragraph of this post. By default, it implements behavior including:</p>

<ul>
<li><p><em>Line buffering</em> &#8212; when characters come in the left, it holds on
to them until it receives a newline, at which point they are all
emitted out the right at once.</p></li>
<li><p><em>Echo</em> &#8212; when a character comes in the left, in addition to being
buffered or sent out the right, it is also sent back out the
left. This is why you can see what you&#8217;re typing.</p></li>
<li><p><em>Line editing</em> &#8212; When the <code>ERASE</code> character (<code>^?</code>, ASCII <code>0x7f</code> by
default) comes in the left, assuming that there is anything in the
input buffer, the last character in the input buffer is deleted,
and the sequence <code>"\b \b"</code> is sent out the left. <code>"\b"</code> (ASCII <code>0x08</code>)
tells your terminal to move the cursor one column to the left, so
this moves the cursor one column backwards, overwrites the last
character with a blank space, and then moves the cursor back.</p></li>
<li><p><em>Newline translation</em> &#8212; if a newline (<code>"\n"</code>, ASCII <code>0x0A</code>) comes in
the right, a carriage-return/line-feed combination (CRLF, <code>"\r\n"</code>,
ASCII <code>0x0D 0x0A</code>) is sent out the left. While most programs on
UNIX accept a bare <code>"\n"</code> as a newline, your terminal needs both &#8211;
<code>"\r"</code> tells it to move the cursor to the beginning of the line, and
<code>"\n"</code> tells it to move to the next line.</p></li>
<li><p><em>Signal generation</em> &#8212; if a <code>INTR</code> (<code>^C</code>, ASCII <code>0x3</code> by default)
comes in the left, it is discarded and a <code>SIGINT</code> is sent to the
program on the far right. Similarly, if a <code>SUSP</code> (<code>^Z</code>, ASCII
<code>0x1A</code>) comes in the left, it is discarded and a <code>SIGTSTP</code> is sent
to the program on the far right. (<code>SIGTSTP</code>, by default, stops a process. It differs from <code>SIGSTOP</code> primarily in that it can be caught and handled by a program, whereas <code>SIGSTOP</code>&#8216;s effect is unconditional)</p>

<p>This is the source of at least two of the additional
complications I mentioned to the basic diagram above:</p>

<ul>
<li>The &#8220;termios&#8221; block does not strictly sit in the middle of the
diagram. It also knows about the program(s) all the way over on
the right, and can interact with them in (certain) ways that
aren&#8217;t just sending characters to the slave pty.</li>
<li>There may be multiple programs connected to the slave
pty. Which one(s) should be allowed to actually read from it?
Which one(s) should <code>SIGINT</code> or <code>SIGTSTP</code> go to? The answers
are fairly complicated, and I don&#8217;t claim to fully understand
them, although I know some of the basic rules. I may write a
future blog post once I understand them better.</li>
</ul></li>
</ul>

<p>There is even more that happens in that box, but these are the most noticeable ones, and selected to give you a feel of how the system works. Programs using the terminal can selectively enable or disable each of these features individually, as well as all the others I haven&#8217;t mentioned. In a future post, I will look at the interfaces we can use to control
what processing does and does not happen, as well as how new <code>pty</code> pairs are created and used.</p>

<p>If this all seems somewhat arbitrary or weirdly constructed to you &#8212; well, it pretty much is. It makes sense, however, in the context of when this interface was first invented. When the <code>tty</code> layer was first coined, your &#8220;terminal&#8221; was a physical terminal &#8212; perhaps a VT100 or its ilk. C was the state of the art for programming languages, code size was expensive and libraries barely existed. Putting logic into the left side of the picture meant upgrading a physical piece of hardware. Putting logic into the right side of the picture meant putting it into every program you might want to talk to on the right side &#8212; libreadline and shared libraries didn&#8217;t really exist yet. And so, the logic went into the only place it could &#8212; the kernel, which could sit between a dumb terminal and a dumb program and mediate just enough logic to let programmer correct their typos as they worked. The kernel already had to mediate the connection, since terminals were physical devices, and there already had to be interfaces to control this layer from software, since software needed to be able to change such details as the baud rate and presence of parity or stop bits to communicate with the terminals. And so this layer that was already sitting between user programs and the console grew additional intelligence a bit at a time. And once we had terminal emulators and virtual terminals, the whole layer moved along with them, as legacy interfaces are wont to do.</p>

<p>Next time: <a href="http://blog.nelhage.com/archives/27">The <tt>termios(3)</tt> APIs.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nelhage.com/2009/12/a-brief-introduction-to-termios/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

