UUUssseeerrr'''sss GGGuuuiiidddeee fffooorrr ttthhheee SSSoooffftttwwwaaarrreee TTToooooolllsss SSSuuubbbsssyyysssttteeemmm CCCooommmmmmaaannnddd IIInnnttteeerrrppprrreeettteeerrr (((TTThhheee SSShhheeellllll))) T. Allen Akin Terrell L. Countryman Perry B. Flinn Daniel H. Forsyth, Jr. | Jefferey S. Lee Jeanette T. Myers | Arnold D. Robbins Peter N. Wan | School of Information and Computer Science | Georgia Institute of Technology | Atlanta, Georgia 30332 | September, 1984 FFFooorrreeewwwooorrrddd The Software Tools Subsystem is a set of program development tools based on the book _S_o_f_t_w_a_r_e _T_o_o_l_s by Brian W. Kernighan and P. J. Plauger. It was originally developed for use on the Prime 400 computer in 1977 and 1978 in the form of several cooperating | user programs. The present Subsystem, the ninth version, is a | powerful tool that aids in the effective use of computing resour- ces. The command interpreter, also referred to as the "shell," is a vital part of the Subsystem. It is a program which accepts commands typed by the user on his terminal and converts them into more primitive directions to the computer itself. The user's instructions are expressed in a special medium called the "com- mand language." The greatest part of this document is involved with describing the command language and giving examples of how it is used. Three areas will be covered in the following pages. First, there is a tutorial on the use of the command language. New Sub- system users should read this chapter first. Some minimal knowledge of terminal usage is assumed; if you are unsure of yourself in this area, see Prime's published documentation and the _S_o_f_t_w_a_r_e _T_o_o_l_s _S_u_b_s_y_s_t_e_m _T_u_t_o_r_i_a_l for help. Second, there is a summary of the syntax and semantics of the command language. Experienced users should find this chapter valuable as a reference. Finally, there is a selection of application notes. This chapter is a good source of useful techniques and samples of advanced usage. Experienced users and curious beginners should find it well worthwhile. - iv - Command Interpreter User's Guide TTTuuutttooorrriiiaaalll CCCooommmmmmaaannndddsss Input to the command interpreter consists of "commands". Commands, in turn, consist of a "command name", which is the name of an executable file. A command is executed simply by entering its name. For example, ] hhheeelllppp is a command that will describe how you can obtain online documentation. Some commands may have arguments. Arguments are values sup- plied by you to the command. Arguments can be required or they may be optional in which case the system uses a default. In the above example when 'help' is invoked with no arguments the Sub- system assumes the command 'help help' (i.e. get me on-line documentation for the 'help' command). However, if you wanted on-line documentation for a specific command you would supply the command name as an argument, e.g. ] hhheeelllppp lllfff will describe the command that can be used to list information about files in a directory. Some commands may have options. Options are used to make the same command execute in slightly different ways. Options usually consist of one letter and are preceded by a dash. The command, ] hhheeelllppp ---fff fffiiillleee will list the names of commands and subroutines that may be associated with the keyword "file". The "-f" is an option and "file" is an argument. Commands, arguments and options are separated from each other by blanks. Here is a final example: ] lllfff adventure ee guide m6800 shell shell.doc subsys time_sheet words zunde ] 'Lf' is used to list the names of your files. Executed without any arguments, 'lf' prints the files in your current directory, but (like 'help') 'lf' may be used with or without arguments and options. - 1 - Command Interpreter User's Guide HHHooowww ttthhheee CCCooommmmmmaaannnddd IIInnnttteeerrrppprrreeettteeerrr LLLooocccaaattteeesss aaa CCCooommmmmmaaannnddd Recall that you can access files by their entrynames only if they are located in your current directory. Without help from the shell this would also be true for commands. That is, in order to execute 'help' you would need to have a copy of the 'help' command in your current directory or you would have to enter its full pathname so that the shell could locate it in another directory. Obviously, neither alternative is desirable. In reality, the shell uses a "variable" called "_search_rule" to find commands like "help" in other directories. Each user has his own search rule. (Refer to the section in this guide entit- led "Shell Control Variables" for more information.) The search rule tells the shell in what locations to look for commands, and if there is more than one location possible, it specifies the order in which the locations will be searched. Most new users are given the search rule that causes the command interpreter to look for commands in the following five locations in the order shown: 1. The shell's internal library for an internal command (e.g, 'stop', 'set') 2. The user's variables currently stored in memory 3. The user's current directory 4. The Subsystem library containing locally supported exter- nal commands, "=lbin=" (e.g. memo, moot) 5. The Subsystem library containing standard external com- mands, "=bin=" (e.g. 'lf', 'help') This variable is explained in more detail in the "Application Notes" section of this guide. Beware that this flexibility can get beginners (and some experienced users) into trouble. With the search rule above, the command interpreter will always look in your current directory for a command before it looks in one of the Subsystem command directories. Therefore, if you create a file having the same name as a command, the shell will try its best to execute the contents of that file. SSSpppeeeccciiiaaalll CCChhhaaarrraaacccttteeerrrsss aaannnddd QQQuuuoootttiiinnnggg Some characters have special meaning to the command interpreter. For example, try typing this command: ] eeeccchhhooo AAAlllaaasss,,, pppoooooorrr YYYooorrriiiccckkk Alas poor: not found ] 'Echo' is simply a command that types back its arguments. Obviously this example is not working as it should. The strange behavior is caused by the fact that the comma is used for dark - 2 - Command Interpreter User's Guide mysterious purposes elsewhere in the command language. (The comma actually represents a null I/O connection between nodes of a network. See the section on pipes and networks for more information.) In fact, all of the following characters are potential troublemakers: | , ; # @ > | { } [ ] ( ) _ blank The way to handle this problem is to use quotes. You may use either single or double quotes, but be sure to match each with another of the same kind. Try this command now: ] eeeccchhhooo """AAAlllaaasss,,, pppoooooorrr YYYooorrriiiccckkk;;; III kkknnneeewww hhhiiimmm wwweeellllll...""" Alas, poor Yorick; I knew him well. ] You can use quotes to enclose other quotes: ] eeeccchhhooo '''QQQuuuooottthhh ttthhheee rrraaavvveeennn::: """NNNeeevvveeerrrmmmooorrreee!!!""" ''' Quoth the raven: "Nevermore!" ] A final word on quoting: Note that anything enclosed in quotes becomes a _s_i_n_g_l_e argument. For example, the command ] eeeccchhhooo """CCCaaannn III uuussseee ttthhhaaattt iiinnn mmmyyy bbbooooookkk???""" has only one argument, but ] eeeccchhhooo CCCaaannn III uuussseee ttthhhaaattt iiinnn mmmyyy bbbooooookkk??? has seven. CCCooommmmmmaaannnddd FFFiiillleeesss Suppose you have a task which must be done often enough that it is inconvenient to remember the necessary commands and type them in every time. For an example, let's say that you have to print the year-end financial reports for the last five years. If the "print" command is used to print files, your command might look like: ] ppprrriiinnnttt yyyeeeaaarrr777444 yyyeeeaaarrr777555 yyyeeeaaarrr777666 yyyeeeaaarrr777777 yyyeeeaaarrr777888 yyyeeeaaarrr777999 If you use a text editor to make a file named "reports" that contains this command, you can then print your reports by typing ] rrreeepppooorrrtttsss No special command is required to perform the operations in this "command file;" simply typing its name is sufficient. Any number of commands may be placed in a command file. It is possible to set up groups of commands to be repeated or - 3 - Command Interpreter User's Guide executed only if certain conditions occur. See the Applications Notes for examples. It is one of the important features of the command interpreter that command files can be treated _e_x_a_c_t_l_y like ordinary commands. As shown in later sections, they are actually programs written in the command language; in fact, they are often called "shell programs." Many Subsystem commands ('e', 'fos', and 'rfl', for example) are implemented in this manner. DDDoooiiinnnggg RRReeepppeeetttiiitttiiivvveee TTTaaassskkksss --------- IIIttteeerrraaatttiiiooonnn Some commands can accept only a single argument. One exam- ple of this is the 'fos' command. "Fos" stands for "format, overstrike, and spool." It is a shorthand command for printing "formatted" documents on the line printer. (A "formatted" document is one prepared with the help of a program called a "text formatter," which justifies right margins, indents paragraphs, etc. This document was prepared by the Software Tools text formatter 'fmt.') If you have several documents to be prepared, it is inconvenient to have to type the 'fos' command for each one. A special technique called "iteration" allows you to "factor out" the repeated text. For example, ] fffooosss (((fffiiillleee111 fffiiillleee222 fffiiillleee333))) is equivalent to ] fffooosss fffiiillleee111 ] fffooosss fffiiillleee222 ] fffooosss fffiiillleee333 The arguments inside the parentheses form an "iteration group." There may be more than one iteration group in a command, but they must all contain the same number of arguments. This is because each new command line produced by iteration must have one argument from each group. As an illustration of this, ] (((eeeccchhhooo ppprrriiinnnttt fffooosss))) fffiiillleee(((111 222 333))) is equivalent to ] eeeccchhhooo fffiiillleee111 ] ppprrriiinnnttt fffiiillleee222 ] fffooosss fffiiillleee333 Iteration is performed by simple text substitution; if there is no space between an argument and an iteration group in the original command, then there is none between the argument and group elements in the new commands. Thus, file(1 2 3) is equivalent to - 4 - Command Interpreter User's Guide file1 file2 file3 Iteration is most useful when combined with function calls, which will be discussed later. III///OOO RRReeedddiiirrreeeccctttiiiooonnn Control of the sources and destinations of data is a very basic function of the command interpreter, yet one that deserves special attention. The concepts involved are not new, yet they are rarely employed to the extent that they have been used in the Subsystem. The best approach to learning these ideas is to experiment. Get on a terminal, enter the Subsystem, and try the examples given here until they seem to make sense. Above all, experiment freely; try anything that comes to mind. The Sub- system has been designed with the idea that users are intelligent human beings, and their freedom of expression is the most valuable of tools. Use your imagination; if it needs tweaking, take a look at the Application Notes in the last chapter. Programs and commands in the Subsystem do not have to be written to read and write to specific files and devices. In fact most of them are written to read from "anything" and write to "anything." Only when the program is executed do you specify what "anything" is, which could be your terminal, a disk file, the line printer, or even another program. "Anything"s are more formally known as "standard input ports" and "standard output ports." Programs are said to "read from standard input" and "write on standard output." The key point here is that programs need not take into account how input data is made available or what happens to output data when they are finished with it; the command interpreter is in complete control of the standard ports. A command we will use frequently in this section is 'copy'. 'Copy' does exactly what its name implies; it copies data from one place to another. In fact, it copies data from its first standard input port to its first standard output port. The first point to remember is that _b_y _d_e_f_a_u_l_t, _s_t_a_n_d_a_r_d _p_o_r_t_s _r_e_f_e_r_e_n_c_e _t_h_e _t_e_r_m_i_n_a_l. Try 'copy' now: ] cccooopppyyy After you have entered this command, type some random text fol- lowed by a newline. 'Copy' will type the same text back to you. (When you tire of this game, type a control-c; this causes an end-of-file signal to be sent to 'copy', which then returns to the command interpreter. Typing control-c to cause end-of-file is a convention observed by all Subsystem programs.) Since you did not say otherwise, standard input and standard output referred to the terminal; input data was taken from the terminal (as you typed it) and output data was placed on the terminal (printed by 'copy'). - 5 - Command Interpreter User's Guide Obviously, 'copy' would not be of much use if this was all it could do. Fortunately, the command interpreter can change the sources and destinations of data, thus making 'copy' less trivial. III///OOO RRReeedddiiirrreeeccctttiiiooonnn tttooo DDDiiissskkk FFFiiillleeesss ooorrr DDDeeevvviiiccceeesss Standard ports may be altered so as to refer to disk files by use of a "funnel." The greater-than sign (>) is used to represent a funnel. Conventionally, the ">" points in the direc- tion of data flow. For example, if you wished to copy the contents of file "ee" to file "old_ee", you could type ] eeeeee>>> cccooopppyyy >>>ooolllddd___eeeeee The greater-than sign must always be immediately next to its associated filename; no intervening blanks are allowed. At least one blank must separate the '>' from any command name or arguments. This restriction is necessary to insure that the com- mand language can be interpreted unambiguously. The construct "ee>" is read "from ee"; ">old_ee" is read "toward old_ee." Thus, the command above can be read "from ee copy toward old_ee," or, "copy from ee toward old_ee." The process of changing the file assignment of a standard port by use of a funnel is called "I/O redirection," or simply "redirection." It is not necessary to redirect both standard input and standard output; either may be redirected independently of the other. For example, ] eeeeee>>> cccooopppyyy can be used to print the contents of file "ee" on the terminal. (Remember that standard output, since it was not specifically redirected, refers to the terminal.) Not surprisingly, the last variation of 'copy', ] cccooopppyyy >>>ooolllddd___eeeeee is also useful. This command causes input to be taken from the terminal (until an end-of-file is generated by typing a control- c) and placed on the file "old_ee". This is a quick way of creating a small file of text without using a text editor. It is important to realize that _a_l_l _S_u_b_s_y_s_t_e_m _p_r_o_g_r_a_m_s _b_e_h_a_v_e _u_n_i_f_o_r_m_l_y _w_i_t_h _r_e_g_a_r_d _t_o _r_e_d_i_r_e_c_t_i_o_n. It is as correct to redirect the output of, say, 'lf' ] lllfff >>>fffiiillleee___llliiisssttt as it is to redirect the output of 'copy'. Recall that special pathnames which begin with "/dev" may refer to peripheral devices. For example, by redirecting output to "/dev/lps" you can print a file on the line printer. - 6 - Command Interpreter User's Guide ] cccaaattt mmmyyyfffiiillleee >>>///dddeeevvv///lllpppsss Although the discussion has been limited to one input port and one output port up to this point, more of each type are available. In the current implementation, there are a total of six; three for input and three for output. The highest-numbered output port is generally used for error messages, and is often called "ERROUT"; you can "capture" error messages by redirecting this output port. For example, if any errors are detected by 'lf' in this command ] lllfff 333>>>eeerrrrrrooorrrsss then the resulting error messages will be placed on the file "errors". Final words on redirection: there are two special-purpose redirection operators left. They are both represented by the double funnel ">>". The first operator is called "append:" ] lllfff >>>>>>llliiisssttt causes a list of files to be placed _a_t _t_h_e _e_n_d _o_f (appended to) the file named "list". The second operator is called "from com- mand input." It is represented as just ">>" with no file name, and causes standard input to refer to the current source of com- mands. It is useful for running programs like the text editor | from "scripts" of instructions placed in a command file. See the | Application Notes for examples. III///OOO RRReeedddiiirrreeeccctttiiiooonnn tttooo ooottthhheeerrr CCCooommmmmmaaannndddsss The last section discussed I/O redirection --- the process of making standard ports refer to disk files or devices, rather than just to the terminal. This section will take that idea one step further. Frequently, the output of one program is placed on a file, only to be picked up again later and used by another program. The command interpreter simplifies this process by eliminating the intermediate file. The connection between programs that is so formed is called a "pipe," and a linear array of programs communicating through pipes is called a "pipeline." Suppose that you maintain a large directory, containing drafts of various manuals. Each draft is in a file with a name of the form "MANxxxx.rr", where "xxxx" is the number of the manual and "rr" is the revision number. You are asked to produce a list of the numbers of all manuals at the first revision stage. The following command will do the job: ] lllfff ---ccc ||| fffiiinnnddd ...000111 | "lf -c" lists the names of all files in the current directory, in | a single column. The "pipe connection" (vertical bar) causes this listing to be passed to the 'find' command, which selects those lines containing the string ".01" and prints them. Thus, - 7 - Command Interpreter User's Guide the pipeline above will print all filenames matching the con- ventional form of a first-revision manual name. The ability to build special purpose commands cheaply and quickly from available tools using pipes is one of the most valuable features of the command interpreter. With practice, surprisingly difficult problems can be solved with ease. For further examples of pipelines, see the Applications Notes. Combinations of programs connected with pipes need not be linear. Since multiple standard ports are available, programs can be and often are connected in non-linear networks. (Some networks cannot be executed if the programs in the network are not executed concurrently. The command interpreter detects such networks, and prints a warning message if they cannot be per- formed.) Further information on networks can be found in both the reference and applications chapters of this guide. III///OOO RRReeedddiiirrreeeccctttiiiooonnn fffooorrr aaa GGGrrrooouuuppp ooofff CCCooommmmmmaaannndddsss It is sometimes necessary to change the standard port environment of many commands at one time, for reasons of con- venience or efficiency. The "compound node" (a set of networks surrounded by curly braces) can be used in these situations. As an example of the first case, suppose that you wish to generate a list of manual names (see the last example) in either the first or the second stage of revision. One way to do this is to generate the list for the first revision stage, place it on a file using a funnel, then generate a list for the second revision stage and place it on the end of the same file using an "append" redirector. A compound node might simplify the procedure thusly: ] {{{ lllfff ---ccc ||| fffiiinnnddd ...000111;;; lllfff ---ccc ||| fffiiinnnddd ...000222 }}} >>>llliiisssttt The first network finds all manuals at the first revision stage, and the second finds all those at the second stage. The networks will execute left-to-right, with the output of each being placed on the file "list," thus generating the desired listing. With iteration, the command can be collapsed even farther: ] {{{ lllfff ---ccc ||| fffiiinnnddd ...000(((111 222))) }}} >>>llliiisssttt This combination of iteration and compound nodes is often useful. Efficiency becomes a consideration in cases where successive long streams of data are to be copied onto a file; if the "append" redirector is used each time, the file must be reopened and repositioned several times. Using a compound node, the out- put file need be opened only once: ] {{{ (((fffiiillleee111 fffiiillleee222 fffiiillleee333)))>>> cccooopppyyy }}} >>>aaallllll___fffiiillleeesss This complex example copies the contents of files "file1," "file2," and "file3" into the file named "all_files." - 8 - Command Interpreter User's Guide III///OOO RRReeedddiiirrreeeccctttiiiooonnn tttooo aaa CCCooommmmmmaaannnddd AAArrrggguuummmeeennnttt As mentioned before, some commands may have arguments. The standard output of a command (or a series of commands) can be used as an argument(s) by using the "function call" mechanism. For example, recall the situation illustrated in the section on pipes and networks; suppose it is necessary to actually print the manuals whose names were found. This is how the task could be done: ] ppprrriiinnnttt [[[lllfff ---ccc ||| fffiiinnnddd ...000111]]] The function call is composed of the pipeline "lf -c | find .01" and the square brackets enclosing it. The output of the pipeline within the brackets is passed to 'print' as a set of arguments, which it accesses in the usual manner. Specifically, _a_l_l the lines of output from the pipeline are combined into _o_n_e set of arguments, with spaces provided where multiple lines have been collapsed into one line. 'Print' accepts multiple arguments; however, suppose it was necessary to use a program like 'fos', that accepts only one argument. Iteration can be combined with a function call to do the job: ] fffooosss ((([[[lllfff ---ccc ||| fffiiinnnddd ...000111]]]))) This command formats and prints all manuals in the current direc- tory with revision numbers "01". Function calls are frequently used in command files, particularly for accessing arguments passed to them. Since the sequence "lf -c | find pattern" occurs very frequently, it is a good candidate for replacement with a command file; it is only necessary to pass the pattern to be matched from the argument list of the command file to the 'find' command with a function call. The following command file, called 'files', will illustrate the process: lf -c | find [arg 1] "arg 1" retrieves the first command file argument. The function call then passes that argument to 'find' through its argument list. 'Files' may then be used anywhere the original network was appropriate: ] fffiiillleeesss ...000111 ] ppprrriiinnnttt [[[fffiiillleeesss ...000111]]] ] fffooosss ((([[[fffiiillleeesss ...000111]]]))) VVVaaarrriiiaaabbbllleeesss It has been claimed that the command language is a programming language in its own right. One facet of this - 9 - Command Interpreter User's Guide language that has not been discussed thus far is the use of its variables. The command interpreter allows the user to create variables, with scope, and assign values to them or reference the values stored in them. Certain special variables are used by the command interpreter in its everyday operation. These variables have names that begin with the underline (_). One of these is '_prompt', which is the prompt string the command interpreter prints when requesting a command. If you object to "]" as a prompt, you can change it with the "set" command: ] ssseeettt ___ppprrrooommmpppttt === """OOOKKK,,, """ OK, ssseeettt ___ppprrrooommmpppttt === """%%% """ % ssseeettt ___ppprrrooommmpppttt === """]]] """ ] You may create and use variables of your own. To create a variable in the current scope (level of command file execution), use the "declare" command: ] dddeeeccclllaaarrreee iii jjj kkk sssuuummm Values are assigned to variables with the 'set' command. The command interpreter checks the current scope and all surrounding scopes for the variable to be set; if found, it is changed, otherwise it is declared in the current scope and assigned the specified value. Variables behave like small programs that print their current values. Thus the value of a variable can be obtained by simply typing its name, or it can be used in a command line by enclosing it in brackets to form a function call. The following command file (which also illustrates the use of 'if', 'eval', and 'goto') will count from 1 to the number given as its first argument: declare i set i = 1 :loop if [eval i ">" [arg 1]] goto exit fi i set i = [eval i + 1] goto loop :exit Note the use of the "eval" function, which treats its arguments as an arithmetic expression and returns the expression's value. This is required to insure that the string "i + 1" is interpreted as an expression rather than as a character string. Also note | that 'fi' terminates the 'if' command. | When setting a variable to a string containing unprintable | characters, you may use a special mnemonic form to prevent having - 10 - Command Interpreter User's Guide | to type the literal characters. For example | set crlf = "" | sets the variable 'crlf' to a literal carriage return followed by | a linefeed. There are times when this is not desirable, so to | prevent the interpretation of the string, simply escape the start | the start on the mnemonic with the Subsystem escape character (an | '@'). To set set the variable 'crlf' to the literal string | "" you would type | set crlf = "@@" | The quotes in these two cases are necessary, otherwise the shell | would try to interpret the '>' as an I/O redirector. If the | string between the "<>" characters is not a legal ASCII mnemonic, | no substitution will be made and the string will be passed | unchanged. IIInnnttteeerrrrrruuuppptttsss,,, QQQuuuiiitttsss aaannnddd EEErrrrrrooorrr HHHaaannndddllliiinnnggg MMMeeeccchhhaaannniiisssmmmsss Normally, if you interrupt a program, it will terminate and the next thing you will see is the Subsystem's prompt for your next command. However, by defining the shell control variable "_quit_action" in your "=varsdir=/.vars" file, the fault handler will, upon detection of the interrupt, prompt you as to whether to abort the current program, continue, or call Primos. For program errors, the fault handler will always ask whether you want to abort the program, continue, or call Primos (regardless | of whether "_quit_action" is defined or not). The Application | Notes discuss how to go about creating shell variables (which are | kept in "=varsdir=/.vars" for storage between login sessions). CCCooonnncccllluuusssiiiooonnn This concludes the tutorial chapter of this document. Despite the fact that a good deal of material has been presented, much detail has been omitted. The next chapter is a complete summary of the capabilities of the command interpreter. It is written in a rather technical style, and is recommended for reference rather than self-teaching. The last chapter is a set of examples that may prove helpful. As always, the best approach is simply to sit down at a terminal and try out whatever you wish to do. Should you have difficulty, further tutorials are available, and the 'help' command can be consulted for quick reference. - 11 - Command Interpreter User's Guide SSSuuummmmmmaaarrryyy ooofff SSSyyynnntttaaaxxx aaannnddd SSSeeemmmaaannntttiiicccsss This section is the definitive document for the syntax and corresponding semantics of the Software Tools Subsystem Command Interpreter. It is composed of several sub-sections, each cover- ing some major area of command syntax, with discussions of the semantic consequences of employing particular constructs. It is not intended as a tutorial, nor is it intended to supply mul- titudinous examples; the other sections of this document are provided to fill those needs. CCCooommmmmmaaannndddsss ::= [ { ; } ] The "command" is the basic unit of communication between the command interpreter and the user. It consists of any number of networks (described below) separated by semicolons and terminated by a newline. The networks are executed one at a time, left-to- right; should an error occur at any point in the parse or execu- tion of a network, the remainder of the is ignored. The null command is legal, and causes no action. The command interpreter reads commands for interpretation from the "command source." This is initially the user's terminal, although execution of a command file may change the assignment. Whenever the command source is the terminal, and the command interpreter is ready for input, it prompts the user with the string contained in the shell variable '_prompt'. Since this variable may be altered by the user, the prompt string is selec- table on a per-user basis. NNNeeetttwwwooorrrkkksss ::= { { } } ::= , | ::= [ ] '|' [ ] [ . ] ::= ::= | $ |