Mercurial > hg > Members > kono > nitros9-code
view docs/nitros9guide/chap4.chapter @ 1515:30c1d42f3913
Added comments, slow optimization progress
author | boisy |
---|---|
date | Thu, 22 Jan 2004 18:42:14 +0000 |
parents | b00cf13c9f61 |
children |
line wrap: on
line source
<chapter> <title>Advanced Features of the Shell</title> <para> The basic shell functions were introduced in a prior chapter in order to provide an understanding of how basic NitrOS-9 commands work. In this section the more advanced capabilities of the shell are discussed. In addition to basic command line processing, the shell has functions that facilitate: </para> <itemizedlist mark="square"> <listitem><para> I/O redirection (including filters) </para></listitem> <listitem><para> Memory Allocation </para></listitem> <listitem><para> Multitasking (concurrent execution) </para></listitem> <listitem><para> Procedure File Execution (background processing) </para></listitem> <listitem><para> Execution Control (built-in commands) </para></listitem> </itemizedlist> <para> There is a virtually unlimited combination of ways these capabilities can be used, and it is impossible to give more than a representative set of examples in this manual. You are therefore encouraged to study the basic rules, use your imagination, and explore the possibilities on your own. </para> <section> <title>A More Detailed Description Command Line Processing</title> <para> The shell is a program that reads and processes command lines one at a time from its input path (usually your keyboard). Each line is first scanned (or "parsed") in order to identify and process any of the following parts which may be present: </para> <itemizedlist mark="square"> <listitem><para> A program, procedure file, or built-in command name ("verbs") </para></listitem> <listitem><para> Parameters to be passed to the program </para></listitem> <listitem><para> Execution modifiers to be processed by the shell </para></listitem> </itemizedlist> <para> Note that only the verb (the program or command name) need be present, the other parts are optional. After the verb has been identified, the shell processes modifiers (if any). Any other text not yet processed is assumed to be parameters and passed to the program called. </para> <para> Unless the verb is a "built-in command", the shell will run the program named as a new process (task). It then deactivates itself until the program called eventually terminates, at which time it gets another input line, then the process is repeated. This happens over and over until an end-of-file condition is detected on the shell's input path which causes the shell to terminate its own execution. </para> <para> Here is a sample shell line which calls the assembler: </para> <screen> asm sourcefile l -o >/p #12k </screen> <para> In this example: </para> <informaltable frame="none"> <tgroup cols="2"> <colspec colwidth="2in"/> <colspec colwidth="3in"/> <tbody> <row> <entry>asm</entry> <entry>is the verb</entry> </row> <row> <entry>sourcefile l -o</entry> <entry>are parameters passed to <command>asm</command></entry> </row> <row> <entry>>/p</entry> <entry>is a modifier which redirects the output (listing) to the system's printer</entry> </row> <row> <entry>#12K</entry> <entry>is a modifier which requests that the process be assigned 12K bytes of memory instead of its (smaller) default amount.</entry> </row> </tbody> </tgroup> </informaltable> <para> The verb must be the first name in the command line. After it has been scanned, the shell first checks if it is a "built-in" command. If it is, it is immediately executed. Otherwise, the shell assumes it is a program name and attempts to locate and execute it. </para> </section> <section> <title>Execution Modifiers</title> <para> Execution modifiers are processed by the shell before the program is run. If an error is detected in any of the modifiers, the run will be aborted and the error reported. Characters which comprise modifiers are stripped from the part(s) of the command line passed to the program as parameters, therefore, the characters reserved for use as modifiers ( # ; ! < > & ) cannot be used inside parameters, but can be used before or after the parameters. </para> <section> <title>Alternate Memory Size Modifier</title> <para> When command programs are invoked by the shell, they are allocated the minimum amount of working RAM memory specified in the program's module header. A module header is part of all executable programs and holds the program's name, size, memory requirements, etc. Sometimes it is desirable to increase this default memory size. Memory can be assigned in 256-byte pages using the modifier "#n" where n is the decimal number of pages, or in 1024 byte increments using the modifier "#nK". The two examples below behave identically: </para> <screen> OS9: copy #8 file1 file2 (gives 8*256 = 2048 bytes) OS9: copy #2K file1 file2 (gives 2*1024 = 2048 bytes) </screen> </section> <section> <title>I/O Redirection Modifiers</title> <para> The second kind of modifier is used to redirect the program's "standard I/O paths" to alternate files or devices. Well-written NitrOS-9 programs use these paths for routine I/O. Because the programs do not use specific file or device names, it is fairly simple to "redirect" the I/O to any file or device without altering the program itself. Programs which normally receive input from a terminal or send output to a terminal use one or more of the standard I/O paths as defined below: </para> <para> STANDARD INPUT: This path normally passes data from the terminal's keyboard to the program. </para> <para> STANDARD OUTPUT PATH: This path is normally used to output data from the program to the terminal's display. </para> <para> STANDARD ERROR OUTPUT PATH: This path is used to output routine status messages such as prompts and errors to the terminal's display (defaults to the same device as the standard output path). NOTE: The name "error output" is sometimes misleading since many other kinds of messages besides errors are sent on this path. </para> <para> When new processes are created, they inherit their parent process' standard I/O paths. Therefore, when the shell creates new processes, they usually inherit its standard I/O paths. When you log-on the shell's standard input is the terminal keyboard; the standard output and error output is the terminal's display. When a redirection modifier is used on a shell command line, the shell will open the corresponding paths and pass them to the new process as its standard I/O paths. There are three redirection modifiers as given below: </para> <informaltable frame="none"> <tgroup cols="2"> <colspec colwidth="0.4in"/> <colspec colwidth="3in"/> <tbody> <row> <entry><</entry> <entry>Redirect the standard input path</entry> </row> <row> <entry>></entry> <entry>Redirect the standard output path</entry> </row> <row> <entry>>></entry> <entry>Redirect the standard error output path</entry> </row> </tbody> </tgroup> </informaltable> <para> When redirection modifiers are used on a command line, they must be immediately followed by a pathlist describing the file or device the I/O is to be redirected to or from. For example, the standard output of <command>list</command> can be redirected to write to the system printer instead of the terminal: </para> <screen> OS9: list correspondence >/p </screen> <para> Files referenced by I/O redirection modifiers are automatically opened or created, and closed (as appropriate) by the shell. Here is another example, the output of the <command>dir</command> command is redirected to the file <filename>/D1/savelisting</filename>: </para> <screen> OS9: DIR >/D1/savelisting </screen> <para> If the <command>list</command> command is used on the file <filename>/D1/savelisting</filename>, output from the <command>dir</command> command will be displayed as shown below: </para> <screen> OS9: list /d1/savelisting Directory of . 10:15:00 myfile savelisting file1 </screen> <para> Redirection modifiers can be used before and/or after the program's parameters, but each modifier can only be used once. </para> </section> </section> <section id="sec4.3"> <title>Command Separators</title> <para> A single shell input line can request execution of more than one program. These programs may be executed sequentially or concurrently. Sequential execution means that one program must complete its function and terminate before the next program is allowed to begin execution. Concurrent execution means that several programs are allowed to begin execution and run simultaneously. </para> <section id="sec4.3.1"> <title>Sequential Execution</title> <para> Programs are executed sequentially when each is entered on a separate line. More than one program can be specified on a single shell command line by separating each <replaceable>program name</replaceable> <replaceable>parameters</replaceable> from the next one with a ";" character. For example: </para> <screen> OS9: copy myfile /d1/newfile ; dir >/p </screen> <para> This command line will first execute the <command>copy</command> command and then the <command>dir</command> command. </para> <para> If an error is returned by any program, subsequent commands on the same line are not executed (regardless of the state of the "x" option), otherwise, ";" and "return" are identical separators. </para> <para> Here are some more examples: </para> <screen> OS9: copy oldfile newfile; del oldfile; list newfile OS9: dir >/d1/myfile ; list temp >/p; del temp </screen> <para> All programs executed sequentially are in fact separate, child processes of the shell. After initiating execution of a program to be executed sequentially, the shell enters the "wait" state until execution of the called program terminates. </para> </section> <section id="sec4.3.2"> <title>Concurrent Execution</title> <para> The second kind of separator is the "&" which implies concurrent execution, meaning that the program is run (as a separate, child process), but the shell does not wait for it to complete before processing the next command. </para> <para> The concurrent execution separator is therefore the means by which multiprogramming (running two or more programs simultaneously) is accomplished. The number of programs that can run at the same time is not fixed: it depends upon the amount of free memory in the system versus the memory requirements of the specific programs. Here is an example: </para> <screen> OS9: dir >/p& &007 OS9: </screen> <para> This command line will cause shell to start the <command>dir</command> command executing, print the process ID number (&007), and then immediately display the "OS9:" prompt and wait for another command to be entered. Meanwhile the <command>dir</command> command will be busy sending a directory listing to the printer. You can display a "status summary" of all processes you have created by using the <command>procs</command> command. Below is another example: </para> <screen> OS9: dir >/p& list file1& copy file1 file2 ; del temp </screen> <para> </para> <para> Because they were followed by "&" separators, the <command>dir</command>, <command>list</command>, and <command>copy</command> programs will run concurrently, but the <command>del</command> program will not run until the <command>copy</command> program has terminated because sequential execution (";") was specified. </para> </section> <section id="sec4.3.3"> <title>Pipes and Filters</title> <para> The third kind of separator is the "!" character which is used to construct "pipelines". Pipelines consist of two or more concurrent programs whose standard input and/or output paths connect to each other using "pipes". </para> <para> Pipes are the primary means-by which data is transferred from process to process (interprocess communications). Pipes are first-in, first-out buffers that behave like mass-storage files. </para> <para> I/O transfers using pipes are automatically buffered and synchronized. A single pipe may have several "readers" and several "writers". Multiple writers send, and multiple readers accept, data to/from the pipe on a first-come, first-serve basis. An end-of-file will occur if an attempt is made to read from a pipe but there are no writers available to send data. Conversely, a write error will occur if an attempt is made to write to a pipe having no readers. </para> <para> Pipelines are created by the shell when an input line having one or more "!" separators is processed. For each "!", the standard output of the program named to the left of the "!" is redirected via a pipe to the standard input of the program named to the right of the "!". Individual pipes are created for each "!" present. For example: </para> <screen> OS9: update <master_file ! sort ! write_report >/p </screen> <para> In the example above, the program <command>update</command> has its input redirected from a path called <filename>master_file</filename>. Its standard output becomes the standard input for the program <command>sort</command>. Its output, in turn, becomes the standard input for the program <command>write_report</command>, which has its standard output redirected to the printer. </para> <para> All programs in a pipeline are executed concurrently. The pipes automatically synchronize the programs so the output of one never "gets ahead" of the input request of the next program in the pipeline. This implies that data cannot flow through a pipeline any faster than the slowest program can process it. Some of the most useful applications of pipelines are jobs like character set conversion, print file formatting, data compression/decompression, etc. Programs which are designed to process data as components of a pipeline are often called "filters". The <command>tee</command> command, which uses pipes to allow data to be simultaneously "broadcast" from a single input path to several output paths, is a useful filter. </para> </section> </section> <section> <title>Command Grouping</title> <para> Sections of shell input lines can be enclosed in parentheses which permits modifiers and separators to be applied to an entire set of programs. The shell processes them by calling itself recursively (as a new process) to execute the enclosed program list. For example: <screen> OS9: (dir /d0; dir /d1) >/p </screen> gives the same result as: <screen> OS9: dir /d0 >/p; dir /d1 >/p </screen> except for the subtle difference that the printer is "kept" continuously in the first example; in the second case another user could "steal" the printer in between the <command>dir</command> commands. </para> <para> Command grouping can be used to cause a group of programs to be executed sequentially, but also concurrently with respect to the shell that initiated them, such as: </para> <screen> OS9: (del file1; del file2; del file3)& </screen> <para> A useful extension of this form is to construct pipelines consisting of sequential and/or concurrent programs. For example: </para> <screen> OS9: (dir CMDS; dir SYS) ! makeuppercase ! transmit </screen> <para> Here is a very practical example of the use of pipelines. Recall that the <command>dsave</command> command generates a procedure file to copy all the files in a directory. The example below shows how the output of <command>dsave</command> can be pipelined to a shell which will execute the NitrOS-9 commands as they are generated by <command>dsave</command>. Assume that we want to copy all files from a directory called <filename class="directory">WORKING</filename> to a directory called <filename class="directory">ARCHIVE</filename>: </para> <screen> OS9: chd /d0/WORKING; dsave /d0/ARCHIVE ! shell -p </screen> </section> <section id="sec4.5"> <title>Built-in Shell Commands and Options</title> <para> When processing input lines, the shell looks for several special names of commands or option switches that are built-in the shell. These commands are executed without loading a program and creating a new process, and generally affect how the shell operates. They can be used at the beginning of a line, or following any program separator (";", "&", or "!"). Two or more adjacent built-in commands can be separated by spaces or commas. </para> <para> The built-in commands and their functions are: </para> <informaltable frame="none"> <tgroup cols="2"> <colspec colwidth="1.5in"/> <colspec colwidth="3.5in"/> <tbody> <row> <entry><command>chd</command> <replaceable>pathlist</replaceable></entry> <entry>change the working data directory to the directory specified by the pathlist.</entry> </row> <row> <entry><command>chx</command> <replaceable>pathlist</replaceable></entry> <entry>change the working execution directory to the directory specified by the pathlist.</entry> </row> <row> <entry><command>ex</command> <replaceable>name</replaceable></entry> <entry>directly execute the module named. This transforms the shell process so it ceases to exist and a new module begins execution in its place.</entry> </row> <row> <entry><command>w</command></entry> <entry>wait for any process to terminate.</entry> </row> <row> <entry>* <replaceable>text</replaceable></entry> <entry>comment: "text" is not processed.</entry> </row> <row> <entry><command>kill</command> <replaceable>Proc ID</replaceable></entry> <entry>abort the process specified.</entry> </row> <row> <entry><command>setpr</command> <replaceable>Proc ID</replaceable> <replaceable>priority</replaceable></entry> <entry>changes process' priority.</entry> </row> <row> <entry>x</entry> <entry>causes shell to abort on any error (default)</entry> </row> <row> <entry>-x</entry> <entry>causes shell not to abort on error</entry> </row> <row> <entry>p</entry> <entry>turns shell prompt and messages on (default)</entry> </row> <row> <entry>-p</entry> <entry>inhibits shell prompt and messages</entry> </row> <row> <entry>t</entry> <entry>makes shell copy all input lines to output</entry> </row> <row> <entry>-t</entry> <entry>does not copy input lines to output (default)</entry> </row> </tbody> </tgroup> </informaltable> <para> The change directory commands switch the shell's working directory and, by inheritance, any subsequently created child process. The <command>ex</command> command is used where the shell is needed to initiate execution of a program without the overhead of a suspended <command>shell</command> process. The name used is processed according to standard shell operation, and modifiers can be used. </para> </section> <section id="sec4.6"> <title>Shell Procedure Files</title> <para> The shell is a reentrant program that can be simultaneously executed by more than one process at a time. As is the case with most other NitrOS-9 programs, it uses standard I/O paths for routine input and output. specifically, it requests command lines from the standard input path and writes its prompts and other data to the standard error path. </para> <para> The shell can start up another process also running the shell by means of the <command>shell</command> command. If the standard input path is redirected to a mass storage file, the new "incarnation" of the shell can accept and execute command lines from the file instead of a terminal keyboard. The text file to be processed is called a "procedure file". It contains one or more command lines that are identical to command lines that are manually entered from the keyboard. This technique is sometimes called "batch" or "background" processing. </para> <para> If the <replaceable>program name</replaceable> specified on a shell command line can not be found in memory or in the execution directory, shell will search the data directory for a file with the desired name. If one is found, shell will automatically execute it as a procedure file. </para> <para> Execution of procedure files have a number of valuable applications. It can eliminate repetitive manual entry of commonly-used sequences of commands. It can allow the computer to execute a lengthy series of programs "in the background" while the computer is unattended or while the user is running other programs "in the foreground". </para> <para> In addition to redirecting the shell's standard input to a procedure file, the standard output and standard error output can be redirected to another file which can record output for later review or printing. This can also eliminate the sometimes-annoying output of shell messages to your terminal at random times. </para> <para> Here are two simple ways to use the shell to create another shell: </para> <screen> OS9: shell <procfile OS9: procfile </screen> <para> Both do exactly the same thing: execute the commands of the file <filename>procfile</filename>. To run the procedure file in a "background" mode you simply add the ampersand operator: </para> <screen> OS9: procfile& </screen> <para> NitrOS-9 does not have any constraints on the number of jobs that can be simultaneously executed as long as there is memory available. Also, the procedure files can themselves cause sequential or concurrent execution of additional procedure files. Here's a more complex example of initiating two processing streams with redirection of each shell's output to files: </para> <screen> OS9: proc1 T >>stat1& proc2 T >>stat2& </screen> <para> Note that the built-in command "T" (copy input lines to error output) was used above. They make the output file contain a record of all lines executed, but without useless "OS9" prompts intermixed. The "-x" built-in command can be used if you do <emphasis>not</emphasis> want processing to stop if an error occurs. Note that the built-in commands only affect the shell that executes them, and not any others that may exist. </para> </section> <section id="sec4.7"> <title>Error Reporting</title> <para> Many programs (including the shell) use NitrOS-9's standard error reporting function, which displays an error number on the error output path. The standard error codes are listed in the <xref linkend="errorcodes"/> of this manual. If desired, the <command>printerr</command> command can be executed, which replaces the smaller, built-in error display routine with a larger (and slower) routine that looks up descriptive error messages from a text file called <filename>/dd/sys/errmsg</filename>. Once the <command>printerr</command> command has been run it cannot be turned off. Also, its effect is system-wide. </para> <para> Programs called by the shell can return an error code in the CPU's "B" register (otherwise B should be cleared) upon termination. This type of error, as well as errors detected by the shell itself, will cause an error message to be displayed and processing of the command line or procedure file to be terminated unless the "-x" built-in command has been previously executed. </para> </section> <section id="sec4.8"> <title>Running Compiled Intermediate Code Programs</title> <para> Before the shell executes a program, it checks the program module's language type. If its type is not &CPU; machine language, shell will call the appropriate run-time system for that module. Versions of the shell supplied for various systems are capable of calling different run-time systems. Most versions of shell call Basic09 when appropriate, and Level Two versions of shell can also call the Pascal P-code interpreter (PascalN), or the CIS Cobol runtime system (RunC). </para> <para> For example, if you wanted to run a Basic09 I-code module called <command>adventure</command>, you could type the command given below: </para> <screen> OS9: basic09 adventure </screen> <para> Or you could accomplish the same thing by typing the following: </para> <screen> OS9: adventure </screen> </section> <section id="sec4.9"> <title>Setting Up Timesharing System Procedure Files</title> <para> NitrOS-9 systems used for timesharing usually have a procedure file that brings the system up by means of one simple command or by using the system <filename>startup</filename> file. A procedure file which initiates the timesharing monitor for each terminal is executed to start up the system. The procedure file first starts the system clock, then initiates concurrent execution of a number of processes that have their I/O redirected to each timesharing terminal. </para> <para> Usually one <command>tsmon</command> command program is started up concurrently for each terminal in the system. This is a special program which monitors a terminal for activity. When a carriage return character is typed on any of these terminals, the <command>tsmon</command> command initiates the <command>login</command> command program. If a user does not enter a correct password or user number in three tries, the <command>login</command> command will be aborted. Here's a sample procedure file for a 4-terminal timesharing system having terminals names <quote>TERM</quote>, <quote>T1</quote>, <quote>T2</quote>, and <quote>T3</quote>. </para> <programlisting> * system startup procedure file echo Please Enter the Date and Time setime </term printerr tsmon /t1& tsmon /t2& tsmon /t3& </programlisting> <para> NOTE: This <command>login</command> procedure will not work until a password file called <filename>/DD/SYS/PASSWORD</filename> has been created. For more information, please see the <command>login</command> command description. </para> <para> The example above deserves special attention. Note that the <command>setime</command> command has its input redirected to the system console "term", which is necessary because it would otherwise attempt to read the time information from its current standard input path, which is the procedure file and not the keyboard. </para> </section> </chapter>