Annotation of 43BSDTahoe/new/help/src/cshell/internals, revision 1.1.1.1

1.1       root        1: .TI CSHELL/INTERNALS
                      2: Internal Operation of the C Shell
                      3: 
                      4: 
                      5: The whole point of the shell is to find programs and start them running.
                      6: When you enter a command it searches for a program to do your bidding,
                      7: starts it running, stands by idly until it completes, and then prints
                      8: a prompt for another command.
                      9: It continues this read-execute-prompt cycle indefinitely, stopping
                     10: only when you logout or the computer goes down.
                     11: 
                     12: Ultimately the shell's purpose is to take a user command and put it
                     13: in the form Unix requires for starting execution of new
                     14: programs:  execl( PROGFILE, ARG0, ARG1, ARG2, ..., 0 ).
                     15: For example, if your command were "nroff -ms myfile", the shell's job
                     16: would be to execl( "/usr/bin/nroff", "nroff", "-ms", "myfile", 0 ),
                     17: where "/usr/bin/nroff" tells Unix in which file to find the nroff program.
                     18: In this case the shell had very little work to do.
                     19: If your next command were "!! | lpr ; wc * > ~/wcout",
                     20: the shell would have much more work to do and end up with 3 execl calls
                     21: bearing little resemblance to your command.
                     22: This is important because what the shell winds up sending to execl
                     23: as arguments are what the programs involved really see.
                     24: 
                     25: A program that is executing, as opposed
                     26: to one that is stored in a file, is called a process.
                     27: When you login, Unix finds the C shell program in the file "/bin/csh"
                     28: and starts it running as a process on your terminal.
                     29: The same happens to everyone else when they login,
                     30: but each of the resulting processes is independent and has
                     31: no knowledge of any other processes except those it might create.
                     32: Thus you have your own shell when you login, and can
                     33: in fact personalize it to some extent.
                     34: 
                     35: In a little greater detail than before,
                     36: here is what the C shell does with a command.
                     37: To illustrate this suppose you enter the command
                     38: .br
                     39:        % nroff -ms chap* > outfile
                     40: .br
                     41: Your shell process ...
                     42: 
                     43: [1] reads the command and breaks it into separate
                     44: command words:  "nroff", "-ms", "chap*" ">", "outfile";
                     45: 
                     46: [2] makes new command words if necessary:  in this case replaces the
                     47: command word "chap*" by all filenames beginning with "chap",
                     48: for example, "chapintro", "chapter1", "chapter2";
                     49: 
                     50: [3] finds a file (assumed to contain the program)
                     51: named by the first command word:  "/usr/bin/nroff";
                     52: 
                     53: [4] makes a copy of itself -- a child process -- which will later be
                     54: transformed into the nroff process.
                     55: 
                     56: Here the child and parent processes do different things.
                     57: 
                     58: [5] The child sets up input and output, removing command words which
                     59: indicate redirection:  in this case opens a file
                     60: called "output" to which all future output from this child
                     61: process will be written instead of the terminal and removes
                     62: the words ">" and "outfile" from your command;
                     63: 
                     64: [6] the child transforms itself into the program found in step 3 above
                     65: using execl:  execl( "/usr/bin/nroff", "nroff", "-ms", "chapintro",
                     66: "chapter1", "chapter2", 0 );
                     67: 
                     68: [7] the child dies, either because it is done or there was an error,
                     69: at which point the Unix kernel removes all
                     70: traces of it and sends a signal of this event to the parent process;
                     71: 
                     72: [8] the parent process meanwhile literally waits idly for the child
                     73: process to finish, and then issues a prompt for another command.
                     74: 
                     75: Each of these steps have interesting and important ramifications.
                     76: Some are explained below, others are mentioned below and explained
                     77: elsewhere.
                     78: 
                     79: [1] Reads the command and breaks it into separate command words.
                     80: 
                     81: This step (lexical analysis) is needed to get the command words
                     82: (arguments) into the execl format.
                     83: It gives the typist some flexibility while imposing some restrictions.
                     84: In particular, the shell breaks the line into separate words
                     85: at blanks and tabs, treating multiple blanks and tabs as if they
                     86: were one blank.
                     87: So, for example, if you accidentally type extra blanks at
                     88: the beginning or end of the command, or between words, the
                     89: shell will probably do what you had in mind.
                     90: On the other hand, if you leave out blanks between two adjacent
                     91: arguments, it will go ahead and bundle them up as one word.
                     92: For example, the shell considers the command
                     93: .br
                     94:        % nroff-ms                myfile
                     95: .br
                     96: as having only two words, the name of the command being "nroff-ms",
                     97: then tries unsuccessfully to locate the program (step 3)
                     98: in a file of that name and responds with
                     99: .br
                    100:        nroff-ms: Command not found.
                    101: .br
                    102: The last argument would have been correctly interpreted as "myfile".
                    103: To add another twist, the command
                    104: .br
                    105:        nroff -ms-o1,5 myfile
                    106: .br
                    107: would be execl'd successfully (step 6) but would provoke
                    108: an error message from nroff.
                    109: 
                    110: One additional rule says that any one of the
                    111: characters &|;<>() is considered a separate word,
                    112: except when one of &|<> appear doubled, in which case
                    113: the doubled character is one word.
                    114: For example, the commands
                    115: .br
                    116:        % neqn    <paper|nroff -ms>>   outfile&
                    117: .br
                    118:        % neqn < paper | nroff -ms >> outfile &
                    119: .br
                    120: are interpreted identically, each consisting of 9 words.
                    121: 
                    122: On the other hand, if you want a blank, tab, or one of &|;<>()
                    123: to be considered part of another word, you must surround
                    124: it with quote marks of the type ", `, or ', or precede it with a \\
                    125: (use of \\ is also termed quoting).
                    126: If you want a carriage-return (newline) to be part of a word,
                    127: you must surround it with quote marks AND precede it with a \\,
                    128: since preceding it with a \\ and
                    129: not using quote marks is treated as a blank.
                    130: 
                    131: Beware.
                    132: Strictly speaking, quoting prevents the shell from interpreting
                    133: the quoted characters according to its usual practice, and this discussion
                    134: only mentions how the usual practice is suspended with respect
                    135: to word separation.
                    136: There are other much more profound side-effects of quoting depending on both
                    137: the quoted and the quoting characters.
                    138: The documentation is perhaps more unyielding, incomplete, and confusing
                    139: on this issue than on any other.
                    140: 
                    141: [2] Makes new command words if necessary.
                    142: 
                    143: The C Shell recognizes a large variety of characters and constructs
                    144: as having special meanings and substitutes other words in their place.
                    145: This means that if your command line contains any of them,
                    146: as in "!! | lpr ; wc * > ~/wcout" from before,
                    147: the resulting call (or calls) to execl (step 6) may be the result
                    148: of sweeping changes made in this step.
                    149: Note that the programs being called never see your original command
                    150: and never have to know anything about the special characters.
                    151: Consequently, the same substitution rules apply to ALL programs called
                    152: from the shell (for example, "lpr", "vi", "nroff", etc.).
                    153: 
                    154: Substitutions are classified by type and are applied in a definite order.
                    155: The shell scans command words for characters or constructs of the first type,
                    156: making substitutions if it finds any.
                    157: Then it takes the resulting command words and scans them to find and make
                    158: substitutions of the second type, if any, and so forth.
                    159: Here is a list of substitution types in order with an indication of the kinds
                    160: of special characters that will trigger them.
                    161: 
                    162: .nf
                    163: .ta 8n 16n 24n 32n 40n 48n 56n 64n
                    164: Type           Triggered By            Typical Uses
                    165: -------------------------------------------------------------------
                    166: History                !event, ^old^new        re-use earlier commands
                    167: Alias          first command word      re-name commands
                    168: Variable       $var, $#var, $var[n]    scripts, personalized shell
                    169: Command                `shell command`         use command output as args
                    170: Filename       *, ?, [], {}, ~         abbreviate groups of files
                    171: Input/Output   <, >, |, <<, >>, $<     re-route input and output
                    172: Expressions    ( x <>=!~+-*/()&|^ y )  arithmetic and branching
                    173: .fi
                    174: 
                    175: In the hands of a sober, well-informed user, substitutions are very
                    176: useful:  (1) they can save tremendous amounts of typing, (2) they
                    177: need only be learned for the shell, since all programs called by
                    178: users have to go through the shell, and (3) they make it possible
                    179: to write programs consisting of shell commands.
                    180: 
                    181: In the wrong hands, however, substitutions can be a tricky.
                    182: To help you practice, the shell provides a way for you to see
                    183: exactly what it comes up with just before it calls execl.
                    184: The command "set echo" will cause it to print your command after
                    185: all substitutions have been made, just before calling execl.
                    186: To avoid the danger of executing a possibly incorrect command, you
                    187: can test whether a construct will end up the way you think
                    188: just by entering it as an argument to the "echo" command.
                    189: The "echo" command does nothing more than print its arguments
                    190: on the terminal and like all commands is subject to substitutions.
                    191: So, for example, "echo *" prints the words that would result,
                    192: on any command line, from substituting for * (which lists all your files).
                    193: 
                    194: [3] Finds a file named by the first command word.
                    195: 
                    196: The whole point of the shell is to run programs other than itself,
                    197: such as "vi", "cc", "troff", etc.
                    198: Occasionally there is a need for a command that the shell can perform
                    199: internally, that is, without locating a program file or
                    200: creating another process.
                    201: So in this step the shell usually tries to locate a file containing the
                    202: program named by the first command word, but not before checking
                    203: to see if it belongs to the set of commands built-in to itself.
                    204: 
                    205: If a command is non-built-in, the shell scans a list of directories
                    206: called the searchpath, which may be personalized for each user.
                    207: It appends the first command word to the first directory on
                    208: the list and checks to see if the resulting file name exists.
                    209: If not, it checks the second directory in a similar fashion,
                    210: and so forth, until a file is found, and that file name is
                    211: used when execl is called in step 6.
                    212: In the case that no file is found, the shell reports this
                    213: and prompts for another command.
                    214: 
                    215: If your searchpath becomes garbled, usually because you were
                    216: experimenting with it, the shell may not find some or all of
                    217: the usual non-built-in commands.
                    218: Besides panicking, there are two things to do.
                    219: Fortunately, the command to correct the searchpath is built-in
                    220: and can still be used, but only if you recognize that
                    221: that is the problem.
                    222: Also, if the first command word begins with a /, the shell
                    223: considers it to be the name of the program file to execute,
                    224: for example, the command "/usr/ucb/vi .cshrc" would work.
                    225: 
                    226: If a command is built-in, the shell bypasses steps 4, 6, 7, and 8,
                    227: which reduces run time greatly, and performs the command in its own way.
                    228: For the sake of efficiency, a built-in command is preferred to a
                    229: non-built-in command if they perform the same function, and that is
                    230: why some of the built-in commands were created.
                    231: Other commands were built-in because they would not have worked
                    232: otherwise, due to the way that processes
                    233: disappear completely in step 7; in particular, if a command is
                    234: needed to change the behavior of your shell from that point on,
                    235: a non-built-in command would only be able to change the characteristics
                    236: of a child process of your shell, the shell process that will read
                    237: your next command when the child dies leaving no trace of the change.
                    238: 
                    239: The "echo" command, for example, is built-in to the C shell
                    240: because it is used so often.
                    241: A quick and ugly way to list the files in your directory,
                    242: without using the "ls" command, is to type "echo *".
                    243: A very quick way to create a one line file, without "vi",
                    244: is "echo This is a one line file. > oneliner".
                    245: Some commands that have to be built-in are "cd", "set",
                    246: "alias", and "history".
                    247: Unfortunately, most built-in commands do not have separate manual
                    248: sections, so the command "man set" will yield nothing, while "man csh"
                    249: will tell you about "cd" after printing the first 9 pages or so.
                    250: Ironically, "man echo" will display a manual page because users
                    251: of the Bourne shell do not have a built-in "echo" command.
                    252: 
                    253: [4] Makes a copy of itself -- a child process.
                    254: 
                    255: The Unix kernel requires the C shell -- in fact, requires
                    256: all programs that run other programs -- to use execl.
                    257: Unfortunately, that causes the process running the new program
                    258: to die when it is done.
                    259: Your shell therefore has to create a new process to do the execl
                    260: in order that the old process survive to prompt you for the
                    261: next command.
                    262: The only way to create a new process on Unix, though, is for
                    263: an existing process to make a copy of itself by executing
                    264: a program statement called fork.
                    265: The new and old processes are identical except that one knows
                    266: it is a parent and the other knows it is a child, and
                    267: the internal code of the program for both processes can
                    268: take different branches on the basis of this information.
                    269: This step is time-consuming, and the documentation sometimes
                    270: mentions useful ways to avoid having to fork new processes,
                    271: for instance, by using built-in commands.
                    272: 
                    273: [5] The child sets up input and output.
                    274: 
                    275: In this step, the command words are scanned for special input or
                    276: output redirection constructs.
                    277: When these constructs have been interpreted, they are removed
                    278: from the list of command words.
                    279: Any output file specified is created if it does not already exist.
                    280: If the file or directory does not have the correct permissions,
                    281: or an input file does not exist, the shell, not the program named
                    282: by the first command word, issues an error message and prompts
                    283: for another command.
                    284: The program to be run has no knowledge that its inputs and outputs
                    285: have been changed.
                    286: 
                    287: In the presence of a pipe between commands, the shell removes the
                    288: pipe constructs from the command line after first breaking it up
                    289: into separate subcommands.  Each of these subcommands is processed
                    290: like any other command, with a separate fork and execl for each.
                    291: The main difference is that the parent sets up input and output
                    292: between processes and has them all started up before beginning
                    293: to wait on any of them.
                    294: 
                    295: [6] The child transforms itself into the program found in step 3.
                    296: 
                    297: This is where the child does the execl, but not precisely.
                    298: For simplicity I did not mention that the actual call is
                    299: of the form:  execve( PROGFILE, ARG0, ARG1, ARG2, ..., 0 , ENV0, ENV1,
                    300: ENV2, ..., 0 ).
                    301: The new arguments (after the first 0) contain definitions of
                    302: all the current process's environment variables.
                    303: These may contain any information the user may choose
                    304: to store in them using the built-in command "setenv" and
                    305: have the property that besides input/output redirection, the
                    306: current directory, and a handful of other data,
                    307: they are some of the very few things
                    308: that can be inherited by the new program after execl.
                    309: 
                    310: [7] The child dies.
                    311: 
                    312: Processes can finish normally or abnormally,
                    313: but all of them die eventually.
                    314: For example, when you leave "vi" by typing ZZ, or when
                    315: "nroff" stops because of a macro/diversion overflow,
                    316: then the associated processes die.
                    317: Your shell itself is a process which dies when you logout.
                    318: 
                    319: When the child process running the new program dies,
                    320: the Unix kernel sends a signal to the parent process (your shell)
                    321: notifying it of the event.
                    322: 
                    323: [8] The parent waits for the child to die, then prompts the user.
                    324: 
                    325: In the meantime, the parent process has executed a program statement
                    326: called wait which just puts it on hold until Unix
                    327: sends a signal notifying the shell that the child has died.
                    328: If you had entered an & at the end of the original command,
                    329: your shell would not wait for notification of the child's death
                    330: but would print the child's process number and then
                    331: prompt you for the next command.
                    332: That procedure is called backgrounding a process.
                    333: 
                    334: While the C shell is waiting for the child (only on 4.1 or 4.2 BSD Unix)
                    335: you can type ^Z to wakeup the parent and
                    336: freeze the child for the time being.
                    337: At that point you could enter other commands to shell and
                    338: at a later time you could issue commands to resume execution,
                    339: kill it altogether, or resume execution in the background.
                    340: This useful feature is called job control.
                    341: 
                    342: 
                    343: jak

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.