Donation?

Harley Hahn
Home Page

Send a Message
to Harley


A Personal Note
from Harley Hahn

Unix Book
Home Page

List of Chapters

Table of Contents

List of Figures

Chapters...
   1   2   3
   4   5   6
   7   8   9
  10  11  12
  13  14  15
  16  17  18
  19  20  21
  22  23  24
  25  26

Glossary

Appendixes...
  A  B  C
  D  E  F
  G  H

Command
Summary...

• Alphabetical
• By category

Unix-Linux
Timeline

Internet
Resources

Errors and
Corrections

Endorsements


INSTRUCTOR
AND STUDENT
MATERIAL...

Home Page
& Overview

Exercises
& Answers

The Unix Model
Curriculum &
Course Outlines

PowerPoint Files
for Teachers

Chapter 7...

Using the Keyboard With Unix

In Chapter 6, we talked about the differences between the GUI (graphical user interface) and the CLI (command line interface). Starting with this chapter, and for the rest of the book, we will be concentrating on the CLI, the traditional way to use Unix.

There are several ways in which you can use the CLI. When you work with your own computer, you can use a virtual console or a terminal window (including the Konsole program). We discussed the details in Chapter 6. When you work with a remote host, you can connect via the ssh program, which will act as a terminal emulator for you. Regardless of how you get to a Unix command line, once you are there, it always works the same way (more or less).

If you are using a GUI-based system, I would like you to be familiar with several topics from Chapter 6 before you read this chapter: virtual consoles, terminal windows, and how to select and paste. With a GUI, understanding these ideas is crucial to using the CLI well.

Jump to top of page

The First Unix Terminals

When Unix was first developed by Ken Thompson and Dennis Ritchie (see Chapter 2), they used Teletype ASR33 terminals (see Chapter 3). The Teletype ASR33 was an electromechanical device, originally developed to send and receive text messages. It had a keyboard for input and a built-in printer for output. It also had a paper tape punch, which could store data by punching holes on paper tape, as well as a paper tape reader, which could read data from punched tape.

The ASR33's capabilities made it suitable to use as a computer terminal. In fact, from the mid-1960s to the mid 1970s, virtually all non-IBM computer systems used an ASR33 for the console. This was true of the PDP minicomputers used by Thompson and Ritchie, so it was natural that these devices should become the very first Unix terminals (see box).

The Teletype ASR33

The ASR33, manufactured by the Teletype Corporation, was introduced in 1963. There were three Teletype 33 models: the RO, KSR and ASR. Of the three Teletype 33s, the ASR was by far the most popular.

The RO (Receive-Only) had a printer but no keyboard. As such, it could receive messages, but not send them.

The KSR (Keyboard Send-Receive) had both a printer and a keyboard, and could send and receive messages. The outgoing messages were typed by hand on the keyboard.

The ASR (Automatic Send-Receive) had a printer, a keyboard, and a paper tape punch/reader. Like the KSR, the ASR could send and receive messages. However, with the ASR the outgoing text could be generated in two ways. It could be typed at the keyboard by hand, or it could be read automatically from pre-punched paper tape (hence the name "Automatic"). It was these combination of features that made the ASR33 useful as a computer terminal.

The Teletype ASR 33 terminal weighed 56 pounds, including a 12-pound stand. If you had bought one from DEC in 1974, it would have cost you $1,850, plus a $120 installation fee and $37/month maintenance. In 2008 dollars, that's $8400 for the machine, $550 for the installation, and $170/month for maintenance.

You can see photos of an ASR33 in Chapter 3. Figures 3-1 and 3-2 show the machine. Figure 3-3 is a close-up of the paper tape punch/reader.

The keyboard of the ASR33 was originally designed to send and receive messages, not to control the operation of a computer. As such, Thompson and Ritchie had to adapt Unix to work with the ASR33 keyboard. What is interesting is that the basic system they devised worked so well, it is still used today.

As you would expect, the keyboard of the Teletype contained keys for the 26 letters of the alphabet, the digits 0-9, as well as the most common punctuation symbols. However, there were also a few special keys that were used to provide the functions necessary to send and receive messages (see Figure 7-1). The most important such keys were < Esc>, <Ctrl>, <Shift>, <Tab> and <Return>.

Figure 7-1: The keyboard of the Teletype ASR33.

For our purposes, the most interesting keys on the Teletype ASR33 keyboard are as follows. In the second row from the top, the RETURN key is on the far right. The LINE FEED key is to the left of RETURN. In the second row from the bottom, the RUB OUT key is third from the right. The CTRL key is on the far left. In the bottom row, the two SHIFT keys on either end. Note that there is no backspace key.

The <Ctrl> (Control) key was especially useful because, like the <Shift> key, it could be combined with other keys to form new combinations. For example, by holding down the <Ctrl> key and pressing one of the letters or numbers, you could send a signal such as <Ctrl-A>, <Ctrl-B>, <Ctrl-C>, and so on.

What Thompson and Ritchie did was to incorporate the use of these keys into their basic design of the operating system. To do this, they wrote Unix so that certain signals could be used to control the operation of a program as it was running. For example, the signal called intr (interrupt) was used to terminate a program. To send the intr signal, you pressed <Ctrl-C>.

In technical terms, when there is an equivalence between two things, we say that there exists a MAPPING between them. When we create such an equivalence, we say that we MAP one thing onto the other. For example, if we say that A is mapped onto B, it means that, when we use A, it is the same as using B.

The idea of mapping is an important concept, one that you will meet again and again as you use computers. In this case, we can say that, within Unix, the <Ctrl-C> character is MAPPED onto the intr signal. This is the same as saying that when we press <Ctrl-C>, it has the effect of sending the intr signal.

In a moment, we'll talk about the Unix signals in detail. In fact, my main goal in this chapter is to explain the important signals and their keyboard mappings. First, however, I want to take a moment to talk about nomenclature.

Jump to top of page

Teletypes and the Unix Culture

As you use Unix, you will find that many conventions are based on the technology of the 1970s, the time during which the first versions of Unix were developed. In particular, the world of Unix abounds with ideas that are based on the characteristics of the early terminals. This is why I have made a point of talking about Teletypes (the original terminals) and VT100s (the most popular terminals), both in this chapter and in Chapter 3.

In this section, I'd like to take a quick detour to mention two such conventions that you will encounter a great deal.

The first convention to which I want to draw your attention is the abbreviation "tty" (pronounced "tee-tee-why"). During the many years that Teletype machines were in use, they were referred to as TTYs. This custom was adopted into Unix and, even though it has been a long time since Teletypes were used, the word "tty" is often used as a synonym for a Unix terminal. In particular, you will see this term a lot in Unix documentation and in the names of programs and commands. Here are some examples:

• Within a Unix system, each terminal has its own name. The command to display the name of your terminal is tty. (Try it and see what you get.)

• The stty ("set tty") command can be used to display or change the settings of your terminal.

• The getty ("get tty") program is used to open communication with a terminal and start the login process.

The second convention I want to mention relates to the idea of printing. Teletype terminals had two ways to output data. They could print data on a continuous roll of 8½ inch paper for a human to read(*), and they could punch data on 1-inch wide paper tape for a machine to read. If you take a look at Figure 3-2 in Chapter 3, you can see both the roll of printer paper (in the center) and the roll of paper tape (to the left).

* Footnote

In case you are curious, Teletypes printed output on continuous rolls of 8½ inch paper, which could be up to 5 inches in diameter. The machine printed 10 characters/inch, with a maximum line length of 72 characters. The vertical spacing was 6 lines/inch. The printing was in one color, normally black.

Because output was printed, it became the custom within Unix to use the word PRINT to describe the outputting of information. At the time, this made sense because output was, literally, printed on paper. What is interesting, however, is that, even when more modern terminals became available and data was displayed on monitors, the word "print" was still used, and that is still the case today.

Thus, within Unix documentation, whenever you read about printing data, it almost always refers to displaying data. For example, the tty I mentioned above displays the internal name of your terminal. If you look up this command in the Linux version of the online Unix manual (see Chapter 9), you will see that the purpose of tty is to "print the file name of the terminal connected to standard input".

Here is another example. As you work within the Unix file system, the directory in which you are working at the current time is called your "working directory". (We'll cover these ideas in Chapter 23.) The command to display the name of your working directory is pwd, which stands for "print working directory".

At this point, it only makes sense to ask: If "print" means "display", what term do we use when we really mean print?

There are two answers to this question. First, in some cases, "print" is used to refer to real printing and the meaning is clear by context.

At other times, you will see the term "line printer" (itself an anachronism) or the abbreviation "lp". When you see this, you can consider it a synonym for "printer". For example, the two most important commands to print files are named lp and lpr. (lp comes from System V; lpr comes from Berkeley Unix.)

Jump to top of page

Termcap, Terminfo and curses

As I explained in Chapter 3, Unix was designed as a system in which people used terminals to access a host computer. One of the most important problems that Unix developers had to overcome was that each type of terminal had its own characteristics and used its own set of commands. For example, although all display terminals have a command to clear the screen, the command may not be the same for all terminals.

So, what do you do if you are writing a program and at a particular point, you need to clear the screen of the user's terminal? How would you know what command to send to the terminal, when the actual command depends on what type of terminal is being used?

It doesn't make sense to require every program to know every command for every type of terminal. This would be an enormous burden for software developers.(*) Moreover, what would happen when a new terminal was introduced? How could it be made to work properly with existing programs?

* Footnote

Even as long ago as 1980, most terminals supported well over 100 different commands.

The solution was to collect descriptions of all the different types of terminals into a database. Then, when a program wanted to send a command to a terminal, it could be done in a standardized manner by using the information in the database. (We'll talk more about how it works in a moment.)

The first system of this nature was created by Bill Joy, one of the fathers of Berkeley Unix (see Chapter 2). In 1977, when Joy was a graduate student and he put together 1BSD, the first official version of Berkeley Unix, he included a system for managing the display screen of various types of terminals. In mid-1978, he released 2BSD with a more elaborate version of this system, which he named TERMCAP ("terminal capabilities"). The first important program to use Termcap was the vi editor (see Chapter 22), also written by Joy.

Using Termcap from within a program was a lot of work. To make it easier, another Berkeley student, Ken Arnold, developed a programming interface he called curses. (The name refers to "cursor addressing".) curses was designed to carry out all the functions that were necessary to manage a screen display, while hiding the details from the programmer.

Once a programmer learned how to use curses, he could write programs that would work with any type of terminal, even those that had yet to be invented. All that was required was that the terminal should have an entry in the Termcap database. The first program to use Termcap was a popular text-based game called Rogue (see box).

The First Use of curses and Termcap:
The Game of Rogue

The first program to use curses and Termcap to control the display screen was Rogue, a single-player, text-based fantasy game in the genre of Dungeons & Dragons.

To play Rogue, you would take on the role of an adventurer in an enormous dungeon. At the beginning of the game, you are at the top level of the dungeon. Your goal is to fight your way to the bottom of the dungeon, where you can pick up the Amulet of Yendor. You must then return to the top, bringing the amulet with you. Along the way, you encounter monsters, traps, secret doors and treasures.

At the time Rogue was developed, there was another single-player fantasy game, Adventure, that was very, very popular among programmers. (In fact, I remember playing it on an old Texas Instruments print terminal, connected to a Unix computer over a slow phone line.) Adventure was the same each time you played it but, with Rogue, the dungeon and its contents were generated randomly. This meant that the game was always different. In addition, because Rogue used curses, it was able to draw simple maps, something Adventure was not able to do.

The authors of Rogue were Michael Toy, Glenn Wichman and, later, Ken Arnold. The first version of the game was written for Berkeley Unix and, in 1980, Rogue was included with 4.2BSD. 4.2BSD was so popular that, within a short time, Rogue was available to students around the world.

If you were to look at the first version of Rogue, you would find it incredibly primitive. However, it was much more sophisticated than any previous computer game and, at the time, was considered to be very cool. Eventually, Rogue was ported to a variety of other systems, including the PC, Macintosh, Amiga and Atari ST.

Today, Rogue is still around and, in its modern incarnation, is played by people around the world. If you are interested in taking a look at one of the more interesting legacies from the early days of Unix, search for "Rogue" on the Internet.

In order to work effectively, the Termcap database had to contain technical information for every variation of every terminal that might be used with Unix, and all this data was contained in a single file. Over the years, as many new terminals became available, the Termcap file grew so large as to become unwieldy to maintain and slow to search.

At the time, curses was being enhanced by the programmers at Bell Labs for System III and, later, for System V Release 1 (see Chapter 2). To improve the performance of curses, the Bell Labs programmers replaced Termcap with a new facility called TERMINFO ("terminal information"). Terminfo stored its data in a series of files, one for each terminal type. The files were organized into 26 directories named a through z, all of which were kept in a single Terminfo directory. (This will make sense after you read Chapter 23.) The Terminfo design was so flexible that it is still used today. For example, within Linux, the information for the generic VT100 terminal is stored in the file named:

/usr/share/terminfo/v/vt100

The location of the master Terminfo directory can vary from one system or another. In case you want to look for it on your system, the most common names are:

/usr/share/terminfo/
/usr/lib/terminfo/
/usr/share/lib/terminfo/
/usr/share/misc/terminfo

The biggest problem with Terminfo was that AT&T, which owned Bell Labs, would not release source code (see Chapter 2). This meant that, although System V had Terminfo and a better version of curses, the hacker community did not have access to it. They had to make do with the older, less powerful Termcap-based facility.

To overcome this limitation, in 1982, a programmer named Pavel Curtis began to work on a free version of curses, which he called ncurses ("new curses"). ncurses had very limited distribution until it was taken over by another programmer, Zeyd Ben-Halim, in 1991. In late 1993, Ben-Halim was joined by Eric Raymond, and together they began to work on ncurses in earnest.

Throughout the early 1990s, ncurses had a lot of problems. However, in time, as other people joined the effort, the problems were solved and ncurses and Terminfo emerged as an enduring standard.

Today, Terminfo has replaced Termcap permanently. However, to maintain compatibility with very old programs, some Unix systems still have a Termcap file, even though it is obsolete and its use is deprecated(*).

* Footnote

If something is deprecated, it means that, although you can use it, you shouldn't, because it is obsolete.

You will often see the term "deprecated" in computer documentation, especially in the programming world, where things change quickly. When you see such a note, you should take it as a warning that the feature may be eliminated in future versions of the product.

Would you like to see what Termcap or Terminfo information looks like? The Termcap database is easy to display because it consists of plain text, stored as one long file. If your system has a Termcap file, you can display it by using the following command:

less /etc/termcap

The less program displays a file, one screenful at a time. We will talk about less in detail in Chapter 21. For now, I'll tell you that, once less starts:

• To move forward one screenful, press <Space>.
• To move backward one screenful, press <B>.
• To quit, press <Q>.
• To display help, press <H>.
• To jump to the Termcap entry for the VT100, type /^vt100 and press <Return>.

(The / (slash) character means "search", and the ^ (caret) character means "at the beginning of a line".)

Terminfo data is compiled (that is processed into a non-textual format), which means that you can't look at it directly. Instead, you must use a special program, called infocmp, to read the data and render it into plain text. (If your system doesn't recognize the infocmp command, it probably means that ncurses is not installed.)

To use infocmp, just specify the name of the terminal whose information you want to see. For example, to display the Terminfo data for the VT100 terminal, use the command:

infocmp vt100 | less

The | (vertical bar) character sends the output of the command to less, in order to display the output one screenful at a time.

To display the Terminfo data for whatever terminal you are currently using, use the command name without a terminal name:

infocmp | less

If you are running Linux on a PC, you will see one of two possibilities. From a terminal window, such as the Konsole program (see Chapter 6), you will have a terminal of type xterm, an X Terminal. From a virtual console (also see Chapter 6), you will have a terminal of type linux, which is like a VT220, the color version of the VT100.

Jump to top of page

How Does Unix Know What
Type of Terminal You Are Using?

As you can see from the preceding discussion, it is important that Unix know what type of terminal you are using. Before the late 1990s, that could be a problem. There were a lot of different terminals and, it was up to you to tell the system exactly which type you were using. Doing so required you to learn how to use various technical commands.

Today that is not necessary for two reasons. First, many people use Unix on their own PC. When you do so, the "terminal" is built into the computer, and Unix knows about it as a matter of course.

When you connect to a remote host — over a local network, the Internet, or via a phone line — you use a terminal emulation program, not a real terminal. These days, such programs are able to tell the remote host what terminal they are emulating, so you don't have to worry about the details.

Although it would be possible for a program to emulate any type of terminal, in practice there are only four types you will see today. The two most common are the VT100 and xterm. The VT100 is the well-known text-based terminal we discussed at length in Chapter 3. xterm is an X Terminal, the standard graphics terminal also discussed in Chapter 3. To a lesser extent, you may see two other terminals emulated: the VT220, a color version of the VT100; and the 3270, used with IBM mainframes. (If you use Linux, you may see a terminal type of "linux". This is essentially a VT220.)

To keep track of what type of terminal you are using, Unix uses what is called a ENVIRONMENT VARIABLE. A environment variable is an entity with a name and a value, which is always available to the shell and to any programs you may run. In particular, there is a environment variable TERM whose value is set to the type of terminal you are using.

At any time, you can display the value of any environment variable by using the command echo, followed by a $ (dollar sign) character and the name of the variable. For example, to see the value of the TERM variable, enter:

echo $TERM

This will show you the type of terminal you are using right now.

We will discuss environment variables in more detail in Chapter 12. For now, if you are curious, here is a command you can use to display the values of all the environment variables within your shell.

printenv

The name of this command, printenv, stands for "print environment variables". You will remember that, earlier in the chapter, I explained that it is the custom in Unix to use the word "print" as a synonym for "display".

— hint —

You will remember that, as I explained in Chapter 4, Unix distinguishes between lower-and uppercase letters. For example, in Unix, the name harley is completely different than the name Harley.

Because lowercase is easier to type, it is the custom to use it almost exclusively for names, including userids, commands, and files. This is why, for example, although you may see the userid harley, you will never see Harley or HARLEY.

The main exception to this rule is with respect to environment variables. It is the tradition that, within the shell, environment variables are given uppercase names, such as TERM. This allows us to tell at a glance that what we are looking at is, indeed, an environment variable.

Jump to top of page

The Modifier Keys; The <Ctrl> Key

The <Ctrl> key (the name stands for "Control") was a feature on the early Teletype terminals I mentioned at the beginning of the chapter. In the picture of a Teletype keyboard in Figure 7-1, the <Ctrl> key is the leftmost key in the second row from the bottom. As the name implies, this key was used to control the operation of the Teletype. When Unix was created, the <Ctrl> key was adopted by the Unix developers and integrated into the system in several important ways, which we will discuss in a moment.

To use the <Ctrl> key, you hold it down (like the <Shift> key) and press another key, usually a letter. For example, you might hold down <Ctrl> and press the <A> key.

There are 26 such combinations based on the alphabet — <Ctrl>+<A> through <Ctrl>+<Z> — as well as a couple of others that you might run into. Because it is awkward to write "Ctrl" over and over again, the Unix community uses a shorthand notation: the character ^ (the caret). When you see this character next to another character, it means "hold down the <Ctrl> key". For example, ^A means hold down <Ctrl> and press the <A> key. You might also see the notation <Ctrl-A> or C-a, which means the same thing.

By convention, we always write a <Ctrl> combination using an uppercase letter. For instance, we write ^A, never ^a. Using uppercase letters makes such combinations easy to read: compare, for example, ^L to ^l. However, it's not a real uppercase letter so, when you use a <Ctrl> combination, do not press the <Shift> key.

To get used to this notation, take a look at the following example. This is part of the output from an stty command we will meet later in the chapter.

erase  kill  werase  rprnt  flush  lnext
^H     ^U    ^W      ^R     ^O     ^V

susp   intr  quit  stop    eof
^Z/^Y  ^C    ^\    ^S/^Q   ^D

The output of the stty command tells us which keys to press to send certain signals. The details aren't important for now. What I want you to notice is the notation. In this example, we see that to send the erase signal you use ^H. That is, you hold down <Ctrl> and press <H>. For the kill signal, you use ^U, for werase, you use ^W, and so on.

The <Ctrl> key is an example of what are called MODIFIER KEYS. These are keys that you hold down while you press another key. For example, when you type ^H, the <Ctrl> key "modifies" the <H> key.

On a standard PC keyboard, the modifier keys are <Shift>, <Ctrl> and <Alt>. <Shift> is used for two purposes: to type uppercase letters, and to type the top character on a two-character key. For example, to type the & (ampersand) character on a U.S. keyboard, you press <Shift-7>. <Ctrl> is used to type special signals, in the way I explained above. The <Alt> key is the newest of the modifier keys. Since it was not around when Unix was developed, it is not a part of the standard Unix keyboard. Thus, you don't need it to use the standard Unix CLI (command line interface). However, as we discussed in Chapter 6, the <Alt> key is used by the GUI.

Jump to top of page

The Unix Keyboard Signals

The original Unix design assumed that people used terminals to connect to a host computer. More than three decades later, that is still the case, even when you are running Unix on your own PC(*). Over the years, there have been many different types of terminals with many different types of keyboards, and Unix has been able to work with them all. This is because Unix uses a system of keyboard mappings that is so flexible, it can be made to work with any particular keyboard.

* Footnote

As we discussed in Chapter 6, when you run Unix on your own computer, each virtual console and each terminal window is a separate terminal, all of which are connected to the same host computer.

To control the operation of programs as they run, Unix uses a set of keyboard signals. Although the signals are standard, the actual keys you press to send the signals can be changed as necessary. That is what creates the flexibility. For example, there is a signal called intr (interrupt) that tells a process to abort. If you enter a command that takes a long time to finish, you can stop it by sending it the intr signal.

The concept of the intr signal is built into the definition of Unix. What is not built into Unix is the actual key that you press to send this signal. In theory, you could use any valid key or key combination, and it can vary from one terminal to another.

With most terminals, ^C (Ctrl-C) is mapped to the intr signal. In other words, to stop a program, you would press ^C. With a few terminals, the <Delete> key is mapped to the intr signal. With one of these terminals, you would press <Delete> to abort a program. In either case, if you don't like the keyboard mapping, you can change it.

Normally, you wouldn't change the Unix keyboard mappings, but you can, and that is what makes the system so adaptable. In the next few sections I will describe the important keyboard signals and how you use them. I will then show you how to find out which keys are used on your particular terminal, and how you can change them if you want.

Understanding the keyboard signals and how to use them is one of the basic skills you need to use the Unix CLI.

Jump to top of page

Signals to Use While Typing:
erase, werase, kill

There are three keyboard signals you can use as you are typing: erase, werase and kill. erase deletes the last character you typed; werase deletes the last word you typed; kill deletes the entire line.

To send the erase signal, you press either the <Backspace> or <Delete> key, depending on your keyboard and its mappings. Take a look at the large key in the top right-hand corner of the main part of your keyboard. In almost all cases, this will be the key that is mapped to erase. As you are typing, you can erase the last character you typed by pressing this key.

With most terminals and with a PC, you would use the <Backspace> key. With a Macintosh, you would use the <Delete> key. If you are using a Sun computer whose keyboard has both keys next to one another, use the <Delete> key (the one on top).

— hint —

With most keyboards, you press <Backspace> to send the erase signal. With a Macintosh, you press <Delete>. The important thing is that you use whichever key works on your particular keyboard.

You may remember that, in Chapter 4, I mentioned that some keyboards have an <Enter> key while others have a <Return> key. It's the same idea. Unix only cares about the signal that is sent when you press the key. As long as you press the right key, Unix doesn't care what it is named.

Throughout this book, when I refer to the <Backspace> key, I mean either <Backspace> or <Delete>, whichever is used on your system. Similarly, when I refer to the <Return> key, I mean either <Return> or <Enter>, whichever is on your keyboard.

Here is an example of how to use the erase signal. Say that you want to enter the date command (to display the time and date), but you spell it wrong, datx. Before you press the <Return> key, press <Backspace> (or <Delete>) to erase the last letter and make your correction:

datx<Backspace>e

On your screen, the x will disappear when you press <Backspace>. If you want to delete more than one character, you can press <Backspace> as many times as you want.

The next signal, werase, tells Unix to erase the last word you typed. The werase key is usually ^W. This key is useful when you want to correct one or more words you have just typed. Of course, you can always press <Backspace> repeatedly, but ^W is faster when you want to erase whole words.

Here is an example. You are a spy and you want to use the less program to display the contents of three files named data, secret and top-secret. The command to use is:

less data secret top-secret

You type the command but, before you press the <Return> key, you notice that another spy is standing behind you, casually looking over your shoulder. You decide that you had better not display the secret and top-secret files. Press ^W twice to erase the last two words:

less data secret top-secret^W^W

On your screen, first the word top-secret and then the word secret will disappear. You can then press <Return> to run the command.

The third signal to use while typing is kill. The kill key is usually ^X or ^U, depending on how your system is set up. This signal tells Unix to erase the entire line.

For example, let's say that you are just about to display the contents of the three files I mentioned above. You type the command but, before you press <Return>, someone runs in the room and tells you they are giving away free money at the bank. Thinking quickly, you erase the command by pressing ^X (or ^U):

less data secret top-secret^X

On your screen, the entire line disappears. You can now log out and run to the bank. (Of course, you would never leave your terminal logged in, even to rush out to get free money.)

For reference, Figure 7-2 summarizes the keyboard signals to use when typing.

Figure 7-2: Keyboard signals to use while typing

Signal Key Purpose
erase<Backspace>/<Delete>erase last character typed
werase^Werase last word typed
kill^X/^Uerase entire line

— hint —

The kill keyboard signal does not stop programs. It only erases the line you are typing. To stop a program, use the intr signal, which will be either ^C or <Delete>.

Jump to top of page

The Strangeness of <Backspace>
and <Delete>

As I mentioned earlier, Unix was designed to use the basic keys that were available on the early Teletype terminals: the letters of the alphabet, numbers, punctuation, the <Shift> keys, a <Return> key, and the <Ctrl> key. Indeed, to this day, you can still use the Unix CLI with only these basic keys.

Modern keyboards have other keys, such as <Backspace>, <Alt>, <PageUp>, <PageDown>, the function keys, the cursor control (arrow) keys, and so on. The most interesting of these keys is the <Backspace> key (<Delete> on a Macintosh). To understand why this key is so interesting, we need to take a trip back in time to revisit our old friend, the Teletype ASR33, the very first Unix terminal. Along the way, we'll prepare ourselves to solve The Case of the Mysterious ^H.

As you will remember, the Teletype had more than a keyboard and printer; it also had a paper tape punch and a paper tape reader. The punch was used to punch holes in the tape, and the reader was used to read holes and interpret them as data.

Paper tape was 1-inch wide and came in rolls 1,000 feet long. Each position on the tape could store 1 byte (8 bits) of data by punching holes in any of 8 positions. The tape could hold 10 bytes per inch. When the tape was read, the presence or absence of holes was interpreted as a binary (base 2) number: a hole was a one; no hole was a zero. (If you don't understand binary arithmetic, don't worry about it.)

By now you may be asking yourself, why is this important to a modern-day Unix system? The answer is: the physical configuration of the paper tape in 1970 had a direct influence on how the <Backspace> key works today on your computer. Here is why.

Imagine you are using a Teletype machine, and you are typing information that is being punched onto paper tape. Each time you type a character, the machine punches a combination of holes onto the tape. These holes correspond to the ASCII code (see Chapter 19) for the character you typed. You are doing fine until you accidentally make a mistake. Now what do you do?

With a modern PC, you would simply press the <Backspace> key. The cursor on your monitor would then move back one position, and the character you just typed would be erased from the screen. However, life isn't so simple when you have just punched the wrong pattern of holes in a piece of paper.

The solution had two parts and involved special Teletype commands. First, you would press <Ctrl-H> which would send a BS (backspace) command to the paper tape punch. This caused the punch to move back to the previous line where the error occurred. Then you pressed the <Rubout> key which sent the DEL command. This caused the punch to make holes in every one of the 8 positions.

The reason this worked is that the paper tape reader was programmed to skip over any characters that had all 8 holes punched. In the language of base 2, we would say that the paper tape reader ignored any binary patterns consisting of all ones.

Thus, by overpunching a character with 8 holes — that is, by turning whatever binary code happened to be there into 8 ones — you effectively erased the character. This is why the key to do this was named "Rubout". (You can imagine making a mistake with a pencil and rubbing it out with an eraser.)

Thus, to the early Unix developers, there were two different operations that went into erasing a mistake: backspacing with ^H and rubbing out with <Rubout>. The question they faced was, which key should be mapped to the erase signal, ^H or <Rubout>? They chose ^H.

Within a short time, computer companies started to make terminals with a <Backspace> key. For convenience, this key was programmed to be the same as pressing ^H so, when you made a typing mistake, you could erase it by pressing either <Backspace> or ^H, both of which were mapped to the erase signal.

In later years, the name of the <Rubout> key was changed to <Delete>, which only made sense. Eventually, some Unix companies (notably Sun Microsystems) decided to add an actual <Delete> key to their keyboards. Like the old <Rubout> key, <Delete> generated the DEL code (the one that was originally used to "erase" a character on paper tape). These same companies then decided to use the DEL code, instead of ^H, for backspacing.

Thus, it came to pass that, with some keyboards, you pressed <Backspace> to erase a character while, with others, you pressed <Delete>. In the first case, <Backspace> was the same as ^H, the key that, on a Teletype, sent the BS code. In the second case, <Delete> was the same as <Rubout>, the key that, on a Teletype, sent the DEL code.

To make matters more confusing, there was a problem when Unix documentation was written. There was an easy way to represent the BS code, ^H, but there was no easy way to represent the DEL code. To solve this problem, the designation ^? was chosen to represent DEL.

Unlike ^H, however, ^? is not a real key combination. That is, you can't hold down the <Ctrl> key and press ? (question mark). ^? is simply a two-character abbreviation that means "whichever key on your keyboard that sends the code that used to be called DEL".

To make things even more confusing, in later years some Unix systems were configured so that the <Backspace> key works the same as ^? (DEL), not ^H (BS). In such cases, ^?, not ^H, is mapped to erase.

So here is the situation. If you have a <Backspace> key on your keyboard, it will be mapped to erase. This is the case with PCs. If you do not have a <Backspace> key, you will have a <Delete> key that will be mapped to erase. This is the case with Macintoshes.

If you are using a Sun computer with both a <Backspace> and <Delete> key, the <Backspace> key will be the same as ^H, and the <Delete> key will be the same as ^?. One of these keys will be mapped to erase. Try both and see which one works.

In order to get around the ^H/^? confusion, some Unix systems define an extra signal called erase2. This is the case with FreeBSD, for example.

erase2 has the same effect as erase. That is, it erases the last character you typed. The difference is that ^H maps to one of the signals — erase or erase2 — and ^? maps to the other. In this way, your <Backspace> key will always work properly, regardless of whether it sends ^H or ^?.

— hint —

When the first IBM PC was introduced in August 1981, it came with a brand new keyboard. This keyboard (which is almost the same as the one we use today), had several new keys, such as <Insert>, <Delete>, <PageUp>, <PageDown>, and so on.

It is important to realize that the <Delete> key on the PC keyboard is not the same as the <Delete> key on the old terminals, or on the Macintosh or Sun computers. It is a completely different key.

If you have a PC, you can prove this to yourself. Type something at the Unix command line, but don't press the <Return> key. Now press <Backspace> a few times. Notice that the last few characters are erased. This is because, on your computer, <Backspace> is the same as either ^H or ^?, whichever one happens to be mapped to erase.

Now press <Delete> (the key next to <Insert>). It does not erase the previous character, because it is not mapped to the erase signal.

Jump to top of page

The Case of the Mysterious ^H

You are using your PC to connect to a remote Unix host over a network. You are typing and, all of a sudden, someone throws a red and white plastic Betty Boop doll at your head. This startles you and, when you look back at the screen, you notice you have made a typing mistake.

You press <Backspace> a few times but, instead of erasing the last few characters, you see:

^H^H^H

You look at the screen with amazement. Why did the <Backspace> display ^H instead of erasing? After all, isn't ^H mapped to the erase signal?

The answer is, on your computer, <Backspace> is the same as ^H, and ^H is mapped to erase. This is why, on your machine, <Backspace> works fine.

On the remote host, however, ^? is mapped to erase. When you press the <Backspace> key, you are sending ^H which, on the remote host, is meaningless. That is why, on the remote host, <Backspace> does not work.

You have four choices. First, you can use other keys to fix your typing mistakes. Instead of using <Backspace> to erase one character at a time, you can use ^W to erase an entire word, or ^X/^U to erase the entire line.

Second, you can look for a key that will send ^? to the remote host. On many systems, <Ctrl-Backspace> will do the job. Try it and see if it works. (If you are using a Macintosh, try <Option-Backspace>.)

Third, you can change the configuration of the program you are using to make the connection. Most communication programs will let you control whether <Backspace> sends ^H or a ^?. If your program lets you do this, you can configure it so that, whenever you connect to this particular host, <Backspace> sends ^? instead of ^H.

Finally, you can change the mapping on the remote host itself so ^H, not ^? maps to the erase signal. Once you do this, will work just fine. This is usually the best solution, especially if you are going to use the remote host a lot.

To make the change, all you need to do is place one specific command in the initialization file that gets executed each time you log in to the remote host. Here is the command.

stty erase ^H

(We will discuss the stty command in more detail later in the chapter.)

The name of the file in which you put this command varies depending on what shell you are using. If you use Bash (the default shell for Linux systems) or the Korn Shell, put the command in your .profile file. If you use the C-Shell, put the command in your .login file. In both cases, the "." (period) is part of the file name. (We'll discuss these files in Chapter 14.)

Jump to top of page

Stopping a Program: intr

There are several signals that you can use to stop or pause a program. These signals are intr, quit, stop and susp. We will discuss each one in turn. Interestingly enough, as you will see, the stop signal isn't the one that stops a program.

On most systems, the intr key is ^C. On some systems, you use the <Delete> key instead. Try both and see which one works for you.

The intr (interrupt) signal actually has two uses. First, you can use it to stop a program dead in its tracks. For example, say you enter a command that is taking so long to finish that you decide to stop waiting. Just press ^C. The remote command will abort, and you will be back at the shell prompt.

Some programs are programmed to ignore the intr signal. In such cases, there will always be a well-defined way to end the program (some type of "quit" command). By ignoring the intr signal, the program keeps you from causing damage by pressing ^C inadvertently. We say that the program TRAPS the intr signal.

For example, consider what happens if you are editing a file with the vi text editor (Chapter 22) and you press ^C. vi traps the intr signal and does not stop. In order to stop the program you need to use the vi quit command. If vi had not trapped the intr signal, pressing ^C would abort the program, and you would lose all the data that was not yet saved.

Note: You may sometimes see the intr key referred to as the "break" key. If you use a PC, you may know that ^C acts as a break key under Microsoft Windows for command line programs. As you can see, this idea (along with many others) was taken from Unix.

The second use for the intr signal arises when you are typing a Unix command at the shell prompt. If you are typing a command and you change your mind, you can press ^C instead of <Return>. Pressing ^C will cancel the command completely.

Be sure that you do not confuse the intr key (^C/<Delete>) with the kill key (^U/^X). When you are typing a command, intr cancels the command, while kill erases all the characters on the line. Effectively, this has the same result: whatever you were typing is discarded, and you can enter a new command.

However, only intr will stop a program. In spite of its name, kill will not kill.

Jump to top of page

Another Way to Stop a Program: quit

Aside from intr (^C), there is another keyboard signal, quit, that will stop a program. The quit key is usually ^\ (<Ctrl-Backslash>).

What is the difference between intr and quit? Not much. In the olden days, quit was designed for advanced programmers who needed to abort a test program. When you pressed ^\, it not only stopped the program, but it also told Unix to make a copy of the contents of memory at that instant. This information was stored in a CORE FILE, that is, a file with the name of core (the old name for computer memory). A programmer could then use special tools to analyze the core file to figure out what went wrong.

Today, programmers have better tools to debug programs and, on most systems, the quit signal does not generate a core file, although core files are still used within some programming environments to help debugging. If you are not actively debugging a program and a file named core mysteriously appears in one of your directories, it means that a program you were running aborted with a serious error(*). Unless you really want the file, you can erase it. In fact, you should erase it, because core files are rather large and there is no reason to waste the space.

* Footnote

The most common cause is a segmentation fault. This occurs when a program attempts to access memory that is not allocated to the program, for example, by the improper use of a pointer. (A pointer is a variable that points to something else.)

What's in a Name?

Core file


In the early days of computing, computer memory was constructed from electro-mechanical relays and, later, vacuum tubes. In 1952, a new technology called CORE MEMORY was first used in an experimental version of the IBM 405 Alphabetical Accounting Machine. (The 405, which was IBM's high-end tabulator, was a very old device, dating back to 1934.)

The new type of memory was constructed using tiny, round, hollow magnetic devices called CORES, measuring about 0.25 inch (6.4 mm) in diameter (see Figure 7-3). A large number of cores were arranged in a lattice with several electrical wires running through each core. By changing the current in the wires, it was possible to modify the magnetic properties of individual cores to either "off" or "on". This made it possible to store and retrieve binary data.

Over the years, magnetic core memory was improved and, by the 1960s, it was the mainstay of the IBM's flagship System/360. Eventually, technology advanced, and magnetic core memory was replaced by semiconductors (transistors) and integrated circuits, leading to today's fast, high-density memory chips. However, because the first modern computers used core memory, the word CORE became a synonym for "memory", a term that has survived to this day.

In the olden days, debugging was a particularly difficult process, especially when a program aborted unexpectedly. One technique programmers used was to have the operating system print a copy of the contents of memory used by a program at the time the program aborted. This was called a CORE DUMP, and was printed on paper. A core dump could take up many pages of paper and took great skill to interpret.(*)

When Unix was developed, this technique was continued. However, instead of printing a core dump on paper, Unix saved the data in a special file with the name of core. If you were testing a program, you could force it to abort and create a core file by pressing ^\ (the quit key). Although the old-time Unix programmers had to learn how to interpret core files, they are rarely used today because much better debugging tools are available.

* Footnote

As an undergraduate at the University of Waterloo, Canada, I worked as a systems programmer at the Computing Center, which maintained two, large IBM mainframes. From time to time, I would watch the more experienced system programmers use a large, multi-page core dump to track down an elusive bug. To my young, untutored eye, the process of reading a core dump was both mysterious and awe-inspiring.

Figure 7-3: Magnetic core memory

A close-up photo of the first magnetic core memory, used in an experimental version of the IBM 405 Alphabetical Accounting Machine in 1952. The individual cores were tiny, having a diameter of about 0.25 inch (6.4 mm). Over the years, core memory was improved and, during 1960s, it was the mainstay of IBM's flagship line of computers, the IBM System/360. Eventually, core memory was replaced by semiconductors, which were themselves replaced by modern integrated circuits.

Jump to top of page

Pausing the Display: stop, start

When a program writes a line of output to the bottom of your screen and all the other lines move up one position, we say they SCROLL upward. If a program produces output too fast, data will scroll off the top of the screen before you can read it.

If you want to see an example of this, use one of the following commands. The dmesg command, which we met in Chapter 6, shows you all the messages that were displayed when the system booted. Alternatively, you can use the cat command to display the Termcap file:

dmesg
cat /etc/termcap

The cat command, which we will meet in Chapter 16, concatenates data and sends it to the default output location, or "standard output". In this case, cat copies data from the file /etc/termcap to your display. However, the copying is so fast that most of the data scrolls off the screen before you can read it, which is the purpose of this example.

In such cases, you have three choices. First, if the lost data is not important, you can ignore it. Second, you can restart the program that generates the data and have it send the output to a so-called paging program like less (Chapter 21) that will display the output one screenful at a time. This is what we did earlier in the chapter when we used the command:

less /etc/termcap

With dmesg, we would use a different command that makes use of the | (vertical bar) character. This is called the "pipe symbol", and we will discuss it in Chapter 15. The idea is to reroute the output of dmesg to less.

dmesg | less

Finally, you can press the ^S key to send the stop signal. This tells Unix to pause the screen display temporarily. Once the display is paused, you can restart it by pressing ^Q to send the start signal. To remember, just think of "S" for Stop and "Q" for Qontinue.

Using ^S and ^Q can be handy. However, you should understand that ^S only tells Unix to stop displaying output. It does not pause the program that is executing. The program will keep running and will not stop generating output.

Unix will store the output so that none will be lost and, as soon as you press ^Q, whatever output remains will be displayed. If a great many lines of new data were generated while the screen display was paused, they will probably whiz by rapidly once you press ^Q.

For this reason, you may find that it is just too difficult to press the ^S and ^Q keys fast enough. If this is the case, you should use less to control the output.

By the way, you might be wondering, why were ^S and ^Q chosen to map to the start and stop signals? It does seem like an odd choice. The answer is, on the Teletype ASR33, <Ctrl-Q> sent the XON code, which turned on the paper tape reader; <Ctrl-S> sent the XOFF code, which turned it off.

— hint —

If your terminal ever locks up mysteriously, try pressing ^Q. You may have pressed ^S inadvertently and paused the display.

When everything seems to have stopped mysteriously, you will never cause any harm by pressing ^Q.

Jump to top of page

The End of File Signal: eof

From time to time, you will work with programs that expect you to enter data from the keyboard. When you get to the point where there is no more data, you indicate this by pressing ^D which sends the eof (end of file) signal.

Here is an example: In Chapter 8, I discuss the bc program which provides the services of a built-in calculator. Once you start bc, you enter one calculation after another. After each calculation, bc displays the answer. When you are finished, you press ^D to tell bc that there is no more data. Upon receiving the eof signal, the program terminates.

Jump to top of page

The Shell and the eof Signal

In Chapter 2, I explained that the shell is the program that reads your Unix commands and interprets them. When the shell is ready to read a command, it displays a prompt. You type a command and press <Return>. The shell processes the command and then displays a new prompt. In some cases, your command will start a program, such as a text editor, that you will work with for a while. When you end the program, you will be returned to the shell prompt.

Thus, in general terms, a Unix session with the CLI (command line interface) consists of entering one command after another.

Although the shell may seem mysterious, it is really just a program. And from the point of view of the shell, the commands you type are just data that needs to be processed. Thus, you can stop the shell by indicating that there is no more data. In other words, you can stop the shell by pressing ^D, the eof key.

But what does stopping the shell really mean? It means that you have finished your work and, when the shell stops, Unix logs you out automatically. This is why it is possible to log out by pressing ^D. You are actually telling the shell (and Unix) that there is no more work to be done.

Of course, there is a potential problem. What if you press ^D by accident? You will be logged out immediately. The solution is to tell the shell to trap the eof signal. How you do this depends on what shell you are using. Let's take each shell in turn — Bash, the C-Shell, and the Korn Shell — and you can experiment with your particular shell.

Jump to top of page

Bash: Trapping the eof Signal

Bash is the default shell with Linux. To tell Bash to ignore the eof signal, you use as environment variable named IGNOREEOF. (Notice there are two Es in a row, so be careful when you spell it.) Here is how it works.

IGNOREEOF is set to a particular number, which indicates how many times Bash will ignore ^D at the beginning of a particular line before logging you out. To set IGNOREEOF, use a command like the following. (You can use any number you want instead of 5.)

IGNOREEOF=5

To test it, press ^D repeatedly, and count how many ^Ds are ignored until you are logged out.

When IGNOREEOF is set and you press ^D, you will see a message telling you that you can't log out by pressing ^D. If you are working in the login shell (that is, the shell that was started automatically when you logged in), you will see:

Use "logout" to leave the shell.

If you are working in a subshell (that is, a shell that you started after you logged in), you will see:

Use "exit" to leave the shell.

If, for some reason, you want to turn off the IGNOREEOF feature, just set it to 0:

IGNOREEOF=0

To display the current value of IGNOREEOF , use:

echo $IGNOREEOF

To set IGNOREEOF automatically each time you log in, put the appropriate command in your .profile file (see Chapter 14).

Jump to top of page

Korn Shell: Trapping the eof Signal

The Korn shell is the default shell on various commercial Unix systems. In addition, the default shell for FreeBSD is almost the same as the Korn shell.

To tell the Korn Shell to ignore ^D, you set a shell option named ignoreeof. (Notice there are two es in a row, so be careful when you spell it.) To do this, use the command:

set -o ignoreeof

Once you do, if you press ^D, you will see a message telling you that you can't log out by pressing ^D:

Use "exit" to leave shell.

If, for some reason, you want to turn off the ignoreeof option, use:

set +o ignoreeof

To display the current value of ignoreeof , use:

set -o

This will show you all the shell options and tell you whether or not they are off or on.

To set ignoreeof automatically each time you login, put the appropriate set command in your .profile file (see Chapter 14).

Jump to top of page

C-Shell: Trapping the eof Signal

To tell the C-Shell to ignore ^D, you set a shell variable named ignoreeof. (Notice there are two es in a row, so be careful when you spell it.) To do this, use the command:

set ignoreeof

Once you do, if you press ^D, you will see a message telling you that you can't log out by pressing ^D. If you are working in the login shell (that is, the shell that was started automatically when you logged in), you will see:

Use "logout" to logout.

If you are working in a subshell (that is, a shell that you started after you logged in), you will see:

Use "exit" to leave csh.

(csh is the name of the C-Shell program.)

If, for some reason, you want to turn off the ignoreeof feature, use:

unset ignoreeof

To display the current value of ignoreeof , use:

echo $ignoreeof

If ignoreeof is set, you will see nothing. If it is not set, you will see:

ignoreeof: Undefined variable.

To set ignoreeof automatically each time you login, put the set command in your .cshrc file (see Chapter 14).

Jump to top of page

Displaying Key Mappings: stty -a

So far, I have mentioned a number of keyboard signals, each of which corresponds to some key on your keyboard. These are shown in Figure 7-4. The key mappings I have shown are the most common ones, but they are changeable.

Figure 7-4: Summary of important keyboard signals

Signal Key Purpose
erase<Backspace>/<Delete>erase last character typed
werase^Werase last word typed
kill^X/^Uerase entire line
intr^Cstop a program that is running
quit^\stop program and save core file
stop^Spause the screen display
start^Qrestart the screen display
eof^Dindicate there is no more data

To display the key mappings on your system, use the following command.

stty -a

stty is the "set terminal" command; -a means "show me all the settings".

The stty command displays several lines of information about your terminal. The only lines we are interested in are the ones that show the keyboard signals and the keys to which they are mapped. Here is an example from a Linux system:

intr = ^C; quit = ^\; erase = ^?; kill = ^U;
eof = ^D; eol = <undef>; eol2 = <undef>;
start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R;
werase = ^W; lnext = ^V; flush = ^O;

And here is an example from a Free BSD system:

discard = ^O; dsusp = ^Y; eof = ^D; eol = <undef>;
eol2 = ; erase = ^?; erase2 = ^H; intr = ^C;
kill = ^U; lnext = ^V; quit = ^\; reprint = ^R;
start = ^Q; status = ^T; stop = ^S; susp = ^Z; werase = ^W;

Notice that the FreeBSD example has an erase2 signal.

As you can see, there are several signals I did not cover. Most of these are not important for day-to-day work, and you can ignore them.

— hint —

In Chapter 26, we will discuss how to pause and restart programs that are running. At the time, you will see that you can pause a program by pressing ^Z, which is mapped to the susp (suspend) signal. Once you pause a program with ^Z, it stops running until you restart it by entering the fg (foreground) command.

So if you are ever working and, all of a sudden, your program stops and you see a message like Suspended or Stopped, it means you have accidentally pressed ^Z.

When this happens, all you have to do is enter fg, and your program will come back to life.

Jump to top of page

Changing Key Mappings: stty

If you would like to change a key mapping, use the stty command. Just type stty, followed by the name of the signal, followed by the new key assignment. For example, to change the kill key to ^U, enter:

stty kill ^U

Important: Be sure to type the <Ctrl> key combination as two separate characters, not as a real <Ctrl> combination; stty will figure it out. For example, in this case, you would type the ^ (caret) character, followed by the U character. You would not type <Ctrl-U>.

When you use stty with the name of a <Ctrl> character, it is not necessary to type an uppercase letter. For instance, the following two commands will both work:

stty kill ^u
stty kill ^U

Just remember to type two separate characters.

Strictly speaking, you can map any key you want to a signal. For example, you could map the letter K to the kill signal. Either of these commands will do the job:

stty kill k
stty kill K

Of course, such a mapping would only lead to problems. Every time you pressed the <K> key, Unix would erase the line you were typing! What an interesting trick this would be to play on a friend.(*)

* Footnote

You didn't read it here.

Normally, we would use only <Ctrl> combinations for mappings. In fact, in almost all cases, it's better to just leave things the way they are, and stick with the standard key assignments.

Here is one situation, however, where you may want to make a change. Let's say you often connect to a remote host over a network and, on that host, the erase key is ^?. However, your Backspace key sends a ^H. To make life more convenient, you map ^H to erase. This allows you to press <Backspace> to delete a character.

stty erase ^H

Here is the opposite example. You connect to a remote host on which ^H is mapped to erase. However, your <Backspace> (or <Delete>) key sends ^?. Use stty to change the mapping as follows:

stty erase ^?

Remember, the notation ^? does not refer to an actual <Ctrl> key combination. ^? is a two-character abbreviation for "whichever key on your keyboard sends the DEL code".

If you decide to mess around with keyboard mappings, you can use the command I described above to check them:

stty -a

Alternatively, you enter the stty command by itself:

stty

This will display an abbreviated report, showing only those mappings that have been changed from the default.

Jump to top of page

Command Line Editing

As you type on the command line, the cursor points to the next available location. Each time you type a character, the cursor moves one position to the right.

What do you do when you make a mistake? As we discussed earlier in the chapter, you press the <Backspace> key, erase one or more characters, and type the new ones.

However, what if you want to fix a mistake at the beginning of the line, and you have already typed 20 characters after the mistake? Certainly you can press <Backspace> 21 times, fix the mistake, and retype the 20 characters. However, there is an easier way.

With most (but not all) shells, you can simply use the left-arrow key, which I will call <Left>. Each time you press this key, it moves your cursor to the left without erasing anything. You can then make the changes you want and press <Return>.

Try this example, using the echo command. (echo simply displays the value of whatever you give it.) Type the following:

echo "This is a test!"

Now press <Return>. The shell will display This is a test! Now type the following, but do not press <Return>:

echo "Thus is a test!"

Before you press <Return>, you need to change Thus to This. Your cursor should be at the end of the line, so press <Left> repeatedly until the cursor is just to the right of the u in Thus. Press <Backspace> once to erase the u, and then type i. You can now press <Return>, and you should see the correct output.

This is an example of what is called COMMAND LINE EDITING, that is, changing what is on the command line before you send it to the shell. Notice that you did not have to move the cursor to the end of the line before you pressed <Return>.

— hint —

When you press <Return>, the characters that are on the command line are sent to the shell to be interpreted. Because the cursor does not generate a character, the shell doesn't care where the cursor is when you send it a command.

This means that, when you are command line editing, you can press the <Return> key from anywhere in the line. The cursor does not have to be at the end of the line.

All modern shells support some type of command line editing, but the details vary from one shell to another. For that reason, we will leave the bulk of the discussion to later in the book, when we talk about each individual shell. For now, I'll teach you the three most important techniques. Try them and see if they work with your particular shell.

First, as you are typing, you can use the <Left> and <Right> arrow keys to move the cursor within the command line. This is what we did in our example above.

Second, at any time, you can press <Backspace> to erase the previous character. With some shells, you can also use the <Delete> key to erase the current character. (The <Delete> key I am talking about is the one you find on a PC keyboard, next to the <Insert> key.)

Third, as you enter commands, the shell keeps them in an invisible "history list". You can use the <Up> and <Down> arrow keys to move backward and forward within this list. When you press <Up>, the current command vanishes and is replaced by the previous command. If you press <Up> again, you get the command before that.

Thus, you can press <Up> one or more times to recall a previous command. If you go too far, press <Down> to move down in the list. You can then edit the line to your liking, and resubmit it by pressing <Return>.

What's in a Name?

Destructive backspace, Non-destructive backspace


When you press the <Backspace> key, it moves the cursor one position to the left while erasing a character. When you press the <Left> arrow key, it moves the cursor to the left without erasing a character.

In a sense, the two actions are similar in that they both move the cursor backwards. The only difference is whether or not anything is erased. To capture this idea, you will sometimes see the terms "destructive backspace" and "non-destructive backspace" used.

A DESTRUCTIVE BACKSPACE occurs when the cursor moves back and characters are erased. This is what happens when you press the <Backspace> key.

A NON-DESTRUCTIVE BACKSPACE occurs when the cursor moves back but nothing is changed. This is what happens when you press the <Left> key.

Jump to top of page

Return and Linefeed

Earlier in the chapter, we discussed how the way in which Unix handles the <Backspace> key can be traced back to the original Unix terminal, the Teletype ASR33. More specifically, there were two Teletype codes (BS and DEL) that were involved in erasing a character on paper tape. The Unix developers chose one of these codes to use for the erase signal.

Interestingly enough, they had the same type of choice when it came to deciding what should happen with the <Return> key. Moreover, the decision they made regarding the <Return> key turned out to be much more important than the one they made with the <Backspace> key. This is because the code they chose is used — not only with the <Return> key — but as a special marker that goes at the end of every line in a text file. To begin our discussion, we need to, once again, go back in time to the Teletype ASR33.

The Teletype ASR33 had a print head that used a ribbon to print characters on paper. As characters were printed, the print head moved from left to right. When the print head got to the end of a line, two things had to happen. First, the paper had to be moved up one line; second, the print head, which was attached to a "carriage", had to be returned to the far left.

To make the Teletype perform these actions, there were codes embedded in whatever data was being printed. The data could come from the keyboard, from an incoming communication line, or from the paper tape reader.

The first code, CR (carriage return), returned the carriage to its leftmost position. The second code, LF (linefeed), caused the paper to be moved up one line. Thus, the sequence CR-LF performed the actions necessary to prepare to print a new line.

From the keyboard, you would send a CR code by pressing either the <Return> key or ^M. (They were equivalent.) You would send the LF code by pressing either the <Linefeed> key or ^J. (If you look at Figure 7-1 earlier in the chapter, the <Return> key is at the far right of the second row from the top. The <Linefeed> key is one position to the left.)

When the Unix developers came to use the Teletype as a terminal, they created two signals based on the CR and LF codes. The CR code became the RETURN signal. The LF code became the LINEFEED signal.

So now, let us ask a question: When you type at a Unix terminal, what happens when you press the <Return> key? Before I can answer that, I need to talk a bit about how Unix organizes plain text into files.

Jump to top of page

The Importance of Newline

As we have discussed, Unix uses two signals based on the old Teletype: return and linefeed. From the keyboard, you send return by pressing ^M and linefeed by pressing ^J.

Since return and linefeed are really the same as ^M and ^J, we usually refer to them as characters, rather than signals. Here is how they are used in three different situations.

First: When files contain textual data, we usually divide the data into lines. In Unix, we use a ^J character to mark the end of each line. When we use ^J in this way, we refer to it as a newline character, rather than linefeed. Thus, when a program reads data from a file, it knows it has reached the end of a line when it encounters a newline (that is, a ^J character).

Second: When you are typing characters at a terminal, you press <Return> at the end of the line. Doing so sends the return character, that is, ^M.

Third: When data is displayed, it is sent to your terminal one line at a time. At the end of each line, the cursor must be moved to the beginning of the next line. As with the Teletype, this involves two separate actions: a "carriage return" to move the cursor to the beginning of the line, followed by a "line feed" to move the cursor down one line. For the "carriage return" Unix sends a return character (that is, ^M). For the "linefeed", Unix sends a linefeed character (that is, ^J). Thus, when data is displayed, each line must end with ^M^J.

One of the most elegant features of Unix is that data typed at the keyboard is treated the same as data read from a file. For example, say you have a program that reads a series of names, one per line. Such a program can read the names either from a file on your disk or from the keyboard. The program does not need to be written in a special way to have such flexibility. This feature, called "standard input", is built into Unix. Standard input allows all Unix programs to read data in the same way, without having to worry about the source of the data. (We will discuss this idea in Chapter 15.)

In order for standard input to work properly, every line of data must end with a newline. However, when you type characters at the keyboard, they come in with a return at the end of the line, not a newline. This creates a problem.

Similarly, when Unix programs output data, they can make use of "standard output". This allows all programs to write data in the same way, without having to worry about where the data is going.

When data is written to a file, each line must end with a newline character (that is, ^J). However, when data is written to the terminal, each line must end with return+newline (^M^J). This creates a second problem.

These problems are reconciled in two ways. First, as you type, whenever you press <Return>, Unix changes the return into a newline. That is, it changes the ^M into ^J.

Second, when data is being written to the terminal, Unix changes each newline to a return+linefeed. That is, it changes ^J to ^M^J.

Here is a quick summary to help you make sense of all this:

  1. return = ^M.
  1. linefeed = newline = ^J.
  1. In general, every line of text must end with a newline.
  1. When you press the <Return> key, it sends a return character, which Unix automatically changes to a newline.
  1. To display data on a terminal, each line must end with the sequence of characters: return+linefeed. Thus, as data is sent from a file to the terminal to be displayed, Unix automatically changes the newline at the end of each line to return+linefeed.

At first, this may seem a bit confusing. Eventually, you will come to see that it all makes perfect sense, at which time you will know that you have finally started to think in Unix.

— hint —

Within text files, Unix marks the end of each line with a ^J (newline) character. Microsoft Windows, however, does it differently. Windows marks the end of each line with a ^M^J. (In Unix terms, that would be return+linefeed.)

Thus, when you copy text files from Unix to Windows, each ^J must be changed to ^M^J. Conversely, when you copy files from Windows to Unix, each ^M^J must be changed to ^J.

When you use a program to copy files between two such computers, the program should know how to make the changes for you automatically. If not, there are utility programs available to do the job.

Jump to top of page

An Important Use for ^J:
stty sane, reset

Unless you are a programmer, it is not really necessary to master all the technical details regarding return and newline. Just remember to press <Return> at the end of each line and let Unix do the work.

However, there are some situations in which understanding these ideas is helpful. On rare occasions, the settings for your terminal may become so messed up that the terminal does not work properly. In such cases, there are two commands you can use to reset your terminal settings to reasonable values: stty sane or reset.

In rare cases, you may find that when you try to enter one of these commands by pressing <Return>, the return to newline conversion will not work, and Unix will not accept the command. If this happens, simply press ^M instead of <Return> This will work because the two keys are essentially the same.

The solution is to press ^J (the same as newline), which is all Unix wants anyway. Thus, when all else fails, typing one of the following commands may rejuvenate your terminal. Be sure to type ^J before and after the command. You can try it now if you want; it won't hurt anything.

<Ctrl-J>stty sane<Ctrl-J>
<Ctrl-J>reset<Ctrl-J>

You might ask, if that is the case, can you press ^J instead of <Return> to enter a command at any time? Of course — try it.

To show you how useful these commands can be, here is a true story.

I have a friend Susan who was helping someone with a Linux installation. They were working with a program that allows you to choose which options you want included in the kernel. The program needed a particular directory that did not exist, so Susan pressed ^Z to pause the program. She now had an opportunity to create the directory.

However, it happened that the program — in order to keep the display from changing — had disabled the effect of the return character. This meant that, whenever Susan entered commands, the output would not display properly.

(Remember, when Unix writes data to the terminal, it puts return+linefeed at the end of every line. What do you think happens when only the linefeed works?)

Susan, however, is nothing if not resourceful. She entered the reset command and, in an instant, the terminal was working properly. She then created the directory she needed, restarted the installation program, and lived happily ever after.

Jump to top of page

The Fable of the Programmer
and the Princess

A long time ago, there lived a young, handsome, charming programmer (you can tell this is a fable), who won the love of a beautiful princess. However, the night before their wedding, the princess was kidnapped.

Fortunately, the princess had the presence of mind to leave a trail of pearls from her necklace. The programmer followed the trail to a remote corner of the lawless Silicon Valley, where he discovered that his love was being held captive in an abandoned technical support center by an evil Vice President of Marketing.

Thinking quickly, the programmer took a powerful magnet and entered the building. He tracked down the princess and broke into the room where the VP of Marketing stood gloating over the terrified girl.

"Release that girl immediately," roared the programmer, "or I will use this magnet and scramble all your disks."

The VP pressed a secret button and in the blink of an eye, four more ugly, hulking vice presidents entered the room.

"On the other hand," said the programmer, "perhaps we can make a deal."

"What did you have in mind?" said the VP.

"You set me any Unix task you want," answered the programmer. "If I do it, the princess and I will go free. If I fail, I will leave, never to return, and the princess is yours."

"Agreed," said the VP, his eyes gleaming like two toady red nuggets encased in suet. "Sit down at this terminal. Your task will have two parts. First, using a single command, display the time and date."

"Child's play," said the programmer, as he typed date and pressed the <Return> key.

"Now," said the VP, "do it again." However, as the programmer once again typed date, the VP added, "—but this time you are not allowed to use either the <Return> key or ^M."

"RTFM, you ignorant buffoon!" cried the programmer, whereupon he pressed ^J, grabbed the princess, and led her to his waiting Ferrari and a life of freedom.

Jump to top of page



Exercises

Review Question #1:

Why is it a Unix convention to use the abbreviation "tty" to refer to terminals?

Review Question #2:

Why is it a Unix convention to use the word "print" to refer to displaying data on a monitor?

Review Question #3:

What does the term "deprecated" mean?

Review Question #4:

How does Unix know which terminal you are using?

Review Question #5:

Which key do you press to erase the last character you typed? The last word? The entire line?

Applying Your Knowledge #1:

By default, the erase key is the <Backspace> key (or on a Macintosh, the <Delete> key). Normally, this key is mapped to ^H or, less often, ^?. Use the stty command to change the erase key to the uppercase letter "X".

Once you do this, you can erase the last character you typed by pressing "X". Test this.

What happens when you press a lowercase "x"? Why?

Now use stty to change the erase key back to the <Backspace> (or <Delete>) key. Test to make sure it worked.

For Further Thought #1:

One way to logout is to press ^D (which sends the eof signal) at the shell prompt. Since you might do this by accident, you can tell the shell to ignore the eof signal. Why is this not the default?

What does this tell you about the type of people who use Unix?

For Further Thought #2:

In Chapter 1, I mentioned that the first version of Unix was developed by Ken Thompson, so he could run a program called Space Travel. In this chapter, I explained that the first program to use Termcap (terminal information database) and curses (terminal manager interface) was a text-based fantasy game called Rogue, written by Michael Toy and Glenn Wichman.

Creating a new operating system and experimenting with a brand new set of interfaces are both extremely time-consuming, difficult tasks. What do you think motivated Thompson and, later, Toy and Wichman to take on such challenging work for what seem to be trivial reasons?

If you were managing a group of programmers, what motivations do you think they would respond to (aside from money)?

Jump to top of page