|
|
1.1 root 1: .\" @(#)t3 6.1 (Berkeley) 5/22/86
2: .\"
3: .SH
4: 3.0\ Keyword\ parameters
5: .LP
6: Shell variables may be given values
7: by assignment
8: or when a shell procedure is invoked.
9: An argument to a shell procedure of the form
10: \fIname=value\fP
11: that precedes the command name
12: causes \fIvalue\fP
13: to be assigned to \fIname\fP
14: before execution of the procedure begins.
15: The value of \fIname\fP in the invoking
16: shell is not affected.
17: For example,
18: .DS
19: user=fred\ command
20: .DE
21: will execute \fIcommand\fP with
22: \fBuser\fP set to \fIfred\fP.
23: The \fB\(mik\fR flag causes arguments of the form
24: \fIname=value\fP to be interpreted in this way
25: anywhere in the argument list.
26: Such \fInames\fP are sometimes
27: called keyword parameters.
28: If any arguments remain they
29: are available as positional
30: parameters \fB$1, $2, \*(ZZ\|.\fP
31: .LP
32: The \fIset\fP command
33: may also be used to set positional parameters
34: from within a procedure.
35: For example,
36: .DS
37: set\ \(mi\ \*(ST
38: .DE
39: will set \fB$1\fP to the first file name
40: in the current directory, \fB$2\fP to the next,
41: and so on.
42: Note that the first argument, \(mi, ensures correct treatment
43: when the first file name begins with a \(mi\|.
44: .LP
45: .SH
46: 3.1\ Parameter\ transmission
47: .LP
48: When a shell procedure is invoked both positional
49: and keyword parameters may be supplied with the call.
50: Keyword parameters are also made available implicitly
51: to a shell procedure
52: by specifying in advance that such parameters
53: are to be exported.
54: For example,
55: .DS
56: export\ user\ box
57: .DE
58: marks the variables \fBuser\fP and \fBbox\fP
59: for export.
60: When a shell procedure is invoked
61: copies are made of all exportable variables
62: for use within the invoked procedure.
63: Modification of such variables
64: within the procedure does not
65: affect the values in the invoking shell.
66: It is generally true of
67: a shell procedure
68: that it
69: may not modify the state
70: of its caller without explicit
71: request on the part of the caller.
72: (Shared file descriptors are an
73: exception to this rule.)
74: .LP
75: Names whose value is intended to remain
76: constant may be declared \fIreadonly\|.\fP
77: The form of this command is the same as that of the \fIexport\fP
78: command,
79: .DS
80: readonly name \*(ZZ
81: .DE
82: Subsequent attempts to set readonly variables
83: are illegal.
84: .SH
85: 3.2\ Parameter\ substitution
86: .LP
87: If a shell parameter is not set
88: then the null string is substituted for it.
89: For example, if the variable \fBd\fP
90: is not set
91: .DS
92: echo $d
93: .DE
94: or
95: .DS
96: echo ${d}
97: .DE
98: will echo nothing.
99: A default string may be given
100: as in
101: .DS
102: echo ${d\(mi\fB.\fR}
103: .DE
104: which will echo
105: the value of the variable \fBd\fP
106: if it is set and `\fB.\fP' otherwise.
107: The default string is evaluated using the usual
108: quoting conventions so that
109: .DS
110: echo ${d\(mi\'\*(ST\'}
111: .DE
112: will echo \fB\*(ST\fP if the variable \fBd\fP
113: is not set.
114: Similarly
115: .DS
116: echo ${d\(mi$1}
117: .DE
118: will echo the value of \fBd\fP if it is set
119: and the value (if any) of \fB$1\fP otherwise.
120: A variable may be assigned a default value
121: using
122: the notation
123: .DS
124: echo ${d=\fB.\fR}
125: .DE
126: which substitutes the same string as
127: .DS
128: echo ${d\(mi\fB.\fR}
129: .DE
130: and if \fBd\fP were not previously set
131: then it will be set to the string `\fB.\fP'\|.
132: (The notation ${\*(ZZ=\*(ZZ}
133: is not available for positional parameters.)
134: .LP
135: If there is no sensible default then
136: the notation
137: .DS
138: echo ${d?message}
139: .DE
140: will echo the value of the variable \fBd\fP if it has
141: one, otherwise \fImessage\fP is printed by the shell and
142: execution of the shell procedure is abandoned.
143: If \fImessage\fP is absent then a standard message
144: is printed.
145: A shell procedure that requires some parameters
146: to be set might start as follows.
147: .DS
148: :\ ${user?}\ ${acct?}\ ${bin?}
149: \*(ZZ
150: .DE
151: Colon (\fB:\fP) is a command
152: that is
153: built in to the shell and does nothing
154: once its arguments have been evaluated.
155: If any of the variables \fBuser, acct\fP
156: or \fBbin\fP are not set then the shell
157: will abandon execution of the procedure.
158: .SH
159: 3.3\ Command\ substitution
160: .LP
161: The standard output from a command can be
162: substituted in a similar way to parameters.
163: The command \fIpwd\fP prints on its standard
164: output the name of the current directory.
165: For example, if the current directory is
166: \fB/usr/fred/bin\fR
167: then the command
168: .DS
169: d=\`pwd\`
170: .DE
171: is equivalent to
172: .DS
173: d=/usr/fred/bin
174: .DE
175: .LP
176: The entire string between grave accents (\`\*(ZZ\`)
177: is taken as the command
178: to be executed
179: and is replaced with the output from
180: the command.
181: The command is written using the usual
182: quoting conventions
183: except that a \fB\`\fR must be escaped using
184: a \fB\\\|.\fR
185: For example,
186: .DS
187: ls \`echo "$1"\`
188: .DE
189: is equivalent to
190: .DS
191: ls $1
192: .DE
193: Command substitution occurs in all contexts
194: where parameter substitution occurs (including \fIhere\fP documents) and the
195: treatment of the resulting text is the same
196: in both cases.
197: This mechanism allows string
198: processing commands to be used within
199: shell procedures.
200: An example of such a command is \fIbasename\fP
201: which removes a specified suffix from a string.
202: For example,
203: .DS
204: basename main\fB.\fPc \fB.\fPc
205: .DE
206: will print the string \fImain\|.\fP
207: Its use is illustrated by the following
208: fragment from a \fIcc\fP command.
209: .DS
210: case $A in
211: \*(Ca\*(ZZ
212: \*(Ca\*(ST\fB.\fPc) B=\`basename $A \fB.\fPc\`
213: \*(Ca\*(ZZ
214: esac
215: .DE
216: that sets \fBB\fP to the part of \fB$A\fP
217: with the suffix \fB.c\fP stripped.
218: .LP
219: Here are some composite examples.
220: .RS
221: .IP \(bu
222: .ft B
223: for i in \`ls \(mit\`; do \*(ZZ
224: .ft R
225: .br
226: The variable \fBi\fP is set
227: to the names of files in time order,
228: most recent first.
229: .IP \(bu
230: .ft B
231: set \`date\`; echo $6 $2 $3, $4
232: .ft R
233: .br
234: will print, e.g.,
235: .ft I
236: 1977 Nov 1, 23:59:59
237: .ft R
238: .RE
239: .SH
240: 3.4\ Evaluation\ and\ quoting
241: .LP
242: The shell is a macro processor that
243: provides parameter substitution, command substitution and file
244: name generation for the arguments to commands.
245: This section discusses the order in which
246: these evaluations occur and the
247: effects of the various quoting mechanisms.
248: .LP
249: Commands are parsed initially according to the grammar
250: given in appendix A.
251: Before a command is executed
252: the following
253: substitutions occur.
254: .RS
255: .IP \(bu
256: parameter substitution, e.g. \fB$user\fP
257: .IP \(bu
258: command substitution, e.g. \fB\`pwd\`\fP
259: .RS
260: .LP
261: Only one evaluation occurs so that if, for example, the value of the variable
262: \fBX\fP
263: is the string \fI$y\fP
264: then
265: .DS
266: echo $X
267: .DE
268: will echo \fI$y\|.\fP
269: .RE
270: .IP \(bu
271: blank interpretation
272: .RS
273: .LP
274: Following the above substitutions
275: the resulting characters
276: are broken into non-blank words (\fIblank interpretation\fP).
277: For this purpose `blanks' are the characters of the string
278: \fB$\s-1IFS\s0\fP.
279: By default, this string consists of blank, tab and newline.
280: The null string
281: is not regarded as a word unless it is quoted.
282: For example,
283: .DS
284: echo \'\'
285: .DE
286: will pass on the null string as the first argument to \fIecho\fP,
287: whereas
288: .DS
289: echo $null
290: .DE
291: will call \fIecho\fR with no arguments
292: if the variable \fBnull\fP is not set
293: or set to the null string.
294: .RE
295: .IP \(bu
296: file name generation
297: .RS
298: .LP
299: Each word
300: is then scanned for the file pattern characters
301: \fB\*(ST, ?\fR and \fB[\*(ZZ]\fR
302: and an alphabetical list of file names
303: is generated to replace the word.
304: Each such file name is a separate argument.
305: .RE
306: .RE
307: .LP
308: The evaluations just described also occur
309: in the list of words associated with a \fBfor\fP
310: loop.
311: Only substitution occurs
312: in the \fIword\fP used
313: for a \fBcase\fP branch.
314: .LP
315: As well as the quoting mechanisms described
316: earlier using \fB\\\fR and \fB\'\*(ZZ\'\fR
317: a third quoting mechanism is provided using double quotes.
318: Within double quotes parameter and command substitution
319: occurs but file name generation and the interpretation
320: of blanks does not.
321: The following characters
322: have a special meaning within double quotes
323: and may be quoted using \fB\\\|.\fP
324: .DS
325: \fB$ \fPparameter substitution
326: \fB\`\fP command substitution
327: \fB"\fP ends the quoted string
328: \fB\e\fP quotes the special characters \fB$ \` " \e\fP
329: .DE
330: For example,
331: .DS
332: echo "$x"
333: .DE
334: will pass the value of the variable \fBx\fP as a
335: single argument to \fIecho.\fP
336: Similarly,
337: .DS
338: echo "$\*(ST"
339: .DE
340: will pass the positional parameters as a single
341: argument and is equivalent to
342: .DS
343: echo "$1 $2 \*(ZZ"
344: .DE
345: The notation \fB$@\fP
346: is the same as \fB$\*(ST\fR
347: except when it is quoted.
348: .DS
349: echo "$@"
350: .DE
351: will pass the positional parameters, unevaluated, to \fIecho\fR
352: and is equivalent to
353: .DS
354: echo "$1" "$2" \*(ZZ
355: .DE
356: .LP
357: The following table gives, for each quoting mechanism,
358: the shell metacharacters that are evaluated.
359: .DS
360: .ce
361: .ft I
362: metacharacter
363: .ft
364: .in 1.5i
365: \e $ * \` " \'
366: \' n n n n n t
367: \` y n n t n n
368: " y y n y t n
369:
370: t terminator
371: y interpreted
372: n not interpreted
373:
374: .in
375: .ft B
376: .ce
377: Figure 2. Quoting mechanisms
378: .ft
379: .DE
380: .LP
381: In cases where more than one evaluation of a string
382: is required the built-in command \fIeval\fP
383: may be used.
384: For example,
385: if the variable \fBX\fP has the value
386: \fI$y\fP, and if \fBy\fP has the value \fIpqr\fP
387: then
388: .DS
389: eval echo $X
390: .DE
391: will echo the string \fIpqr\|.\fP
392: .LP
393: In general the \fIeval\fP command
394: evaluates its arguments (as do all commands)
395: and treats the result as input to the shell.
396: The input is read and the resulting command(s)
397: executed.
398: For example,
399: .DS
400: wg=\\'eval who\*(VTgrep\\'
401: $wg fred
402: .DE
403: is equivalent to
404: .DS
405: who\*(VTgrep fred
406: .DE
407: In this example,
408: \fIeval\fP is required
409: since there is no interpretation
410: of metacharacters, such as \fB\*(VT\|,\fP following
411: substitution.
412: .SH
413: 3.5\ Error\ handling
414: .LP
415: The treatment of errors detected by
416: the shell depends on the type of error
417: and on whether the shell is being
418: used interactively.
419: An interactive shell is one whose
420: input and output are connected
421: to a terminal (as determined by
422: \fIgtty\fP (2)).
423: A shell invoked with the \fB\(mii\fP
424: flag is also interactive.
425: .LP
426: Execution of a command (see also 3.7) may fail
427: for any of the following reasons.
428: .IP \(bu
429: Input output redirection may fail.
430: For example, if a file does not exist
431: or cannot be created.
432: .IP \(bu
433: The command itself does not exist
434: or cannot be executed.
435: .IP \(bu
436: The command terminates abnormally,
437: for example, with a "bus error"
438: or "memory fault".
439: See Figure 2 below for a complete list
440: of UNIX signals.
441: .IP \(bu
442: The command terminates normally
443: but returns a non-zero exit status.
444: .LP
445: In all of these cases the shell
446: will go on to execute the next command.
447: Except for the last case an error
448: message will be printed by the shell.
449: All remaining errors cause the shell
450: to exit from a command procedure.
451: An interactive shell will return
452: to read another command from the terminal.
453: Such errors include the following.
454: .IP \(bu
455: Syntax errors.
456: e.g., if \*(ZZ then \*(ZZ done
457: .IP \(bu
458: A signal such as interrupt.
459: The shell waits for the current
460: command, if any, to finish execution and
461: then either exits or returns to the terminal.
462: .IP \(bu
463: Failure of any of the built-in commands
464: such as \fIcd.\fP
465: .LP
466: The shell flag \fB\(mie\fP
467: causes the shell to terminate
468: if any error is detected.
469: .DS
470: 1 hangup
471: 2 interrupt
472: 3* quit
473: 4* illegal instruction
474: 5* trace trap
475: 6* IOT instruction
476: 7* EMT instruction
477: 8* floating point exception
478: 9 kill (cannot be caught or ignored)
479: 10* bus error
480: 11* segmentation violation
481: 12* bad argument to system call
482: 13 write on a pipe with no one to read it
483: 14 alarm clock
484: 15 software termination (from \fIkill\fP (1))
485:
486: .DE
487: .ft B
488: .ce
489: Figure 3. UNIX signals\(dg
490: .ft
491: .FS
492: \(dg Additional signals have been added in Berkeley Unix. See sigvec(2) or signal(3C)
493: for an up-to-date list.
494: .FE
495: Those signals marked with an asterisk
496: produce a core dump
497: if not caught.
498: However,
499: the shell itself ignores quit which is the only
500: external signal that can cause a dump.
501: The signals in this list of potential interest
502: to shell programs are 1, 2, 3, 14 and 15.
503: .SH
504: 3.6\ Fault\ handling
505: .LP
506: Shell procedures normally terminate
507: when an interrupt is received from the
508: terminal.
509: The \fItrap\fP command is used
510: if some cleaning up is required, such
511: as removing temporary files.
512: For example,
513: .DS
514: trap\ \'rm\ /tmp/ps$$; exit\'\ 2
515: .DE
516: sets a trap for signal 2 (terminal
517: interrupt), and if this signal is received
518: will execute the commands
519: .DS
520: rm /tmp/ps$$; exit
521: .DE
522: \fIexit\fP is
523: another built-in command
524: that terminates execution of a shell procedure.
525: The \fIexit\fP is required; otherwise,
526: after the trap has been taken,
527: the shell will resume executing
528: the procedure
529: at the place where it was interrupted.
530: .LP
531: UNIX signals can be handled in one of three ways.
532: They can be ignored, in which case
533: the signal is never sent to the process.
534: They can be caught, in which case the process
535: must decide what action to take when the
536: signal is received.
537: Lastly, they can be left to cause
538: termination of the process without
539: it having to take any further action.
540: If a signal is being ignored
541: on entry to the shell procedure, for example,
542: by invoking it in the background (see 3.7) then \fItrap\fP
543: commands (and the signal) are ignored.
544: .LP
545: The use of \fItrap\fP is illustrated
546: by this modified version of the \fItouch\fP
547: command (Figure 4).
548: The cleanup action is to remove the file \fBjunk$$\fR\|.
549: .DS
550: flag=
551: trap\ \'rm\ \(mif\ junk$$;\ exit\'\ 1 2 3 15
552: for i
553: do\ case\ $i\ in
554: \*(DC\(mic) flag=N ;;
555: \*(DC\*(ST) if\ test\ \(mif\ $i
556: \*(DC then ln\ $i\ junk$$;\ rm\ junk$$
557: \*(DC elif\ test\ $flag
558: \*(DC then echo\ file\ \\\\\'$i\\\\\'\ does\ not\ exist
559: \*(DC else >$i
560: \*(DC fi
561: \*(DOesac
562: done
563: .DE
564: .sp
565: .ft B
566: .ce
567: Figure 4. The touch command
568: .ft
569: .sp
570: The \fItrap\fP command
571: appears before the creation
572: of the temporary file;
573: otherwise it would be
574: possible for the process
575: to die without removing
576: the file.
577: .LP
578: Since there is no signal 0 in UNIX
579: it is used by the shell to indicate the
580: commands to be executed on exit from the
581: shell procedure.
582: .LP
583: A procedure may, itself, elect to
584: ignore signals by specifying the null
585: string as the argument to trap.
586: The following fragment is taken from the
587: \fInohup\fP command.
588: .DS
589: trap \'\' 1 2 3 15
590: .DE
591: which causes \fIhangup, interrupt, quit \fRand\fI kill\fR
592: to be ignored both by the
593: procedure and by invoked commands.
594: .LP
595: Traps may be reset by saying
596: .DS
597: trap 2 3
598: .DE
599: which resets the traps for signals 2 and 3 to their default values.
600: A list of the current values of traps may be obtained
601: by writing
602: .DS
603: trap
604: .DE
605: .LP
606: The procedure \fIscan\fP (Figure 5) is an example
607: of the use of \fItrap\fP where there is no exit
608: in the trap command.
609: \fIscan\fP takes each directory
610: in the current directory, prompts
611: with its name, and then executes
612: commands typed at the terminal
613: until an end of file or an interrupt is received.
614: Interrupts are ignored while executing
615: the requested commands but cause
616: termination when \fIscan\fP is
617: waiting for input.
618: .DS
619: d=\`pwd\`
620: for\ i\ in\ \*(ST
621: do\ if\ test\ \(mid\ $d/$i
622: \*(DOthen\ cd\ $d/$i
623: \*(DO\*(THwhile\ echo\ "$i:"
624: \*(DO\*(TH\*(WHtrap\ exit\ 2
625: \*(DO\*(TH\*(WHread\ x
626: \*(DO\*(THdo\ trap\ :\ 2;\ eval\ $x;\ done
627: \*(DOfi
628: done
629: .DE
630: .sp
631: .ft B
632: .ce
633: Figure 5. The scan command
634: .ft
635: .sp
636: \fIread x\fR is a built-in command that reads one line from the
637: standard input
638: and places the result in the variable \fBx\|.\fP
639: It returns a non-zero exit status if either
640: an end-of-file is read or an interrupt
641: is received.
642: .SH
643: 3.7\ Command\ execution
644: .LP
645: To run a command (other than a built-in) the shell first creates
646: a new process using the system call \fIfork.\fP
647: The execution environment for the command
648: includes input, output and the states of signals, and
649: is established in the child process
650: before the command is executed.
651: The built-in command \fIexec\fP
652: is used in the rare cases when no fork
653: is required
654: and simply replaces the shell with a new command.
655: For example, a simple version of the \fInohup\fP
656: command looks like
657: .DS
658: trap \\'\\' 1 2 3 15
659: exec $\*(ST
660: .DE
661: The \fItrap\fP turns off the signals specified
662: so that they are ignored by subsequently created commands
663: and \fIexec\fP replaces the shell by the command
664: specified.
665: .LP
666: Most forms of input output redirection have already been
667: described.
668: In the following \fIword\fP is only subject
669: to parameter and command substitution.
670: No file name generation or blank interpretation
671: takes place so that, for example,
672: .DS
673: echo \*(ZZ >\*(ST.c
674: .DE
675: will write its output into a file whose name is \fB\*(ST.c\|.\fP
676: Input output specifications are evaluated left to right
677: as they appear in the command.
678: .IP >\ \fIword\fP 12
679: The standard output (file descriptor 1)
680: is sent to the file \fIword\fP which is
681: created if it does not already exist.
682: .IP \*(AP\ \fIword\fP 12
683: The standard output is sent to file \fIword.\fP
684: If the file exists then output is appended
685: (by seeking to the end);
686: otherwise the file is created.
687: .IP <\ \fIword\fP 12
688: The standard input (file descriptor 0)
689: is taken from the file \fIword.\fP
690: .IP \*(HE\ \fIword\fP 12
691: The standard input is taken from the lines
692: of shell input that follow up to but not
693: including a line consisting only of \fIword.\fP
694: If \fIword\fP is quoted then no interpretation
695: of the document occurs.
696: If \fIword\fP is not quoted
697: then parameter and command substitution
698: occur and \fB\\\fP is used to quote
699: the characters \fB\\\fP \fB$\fP \fB\`\fP and the first character
700: of \fIword.\fP
701: In the latter case \fB\\newline\fP is ignored (c.f. quoted strings).
702: .IP >&\ \fIdigit\fP 12
703: The file descriptor \fIdigit\fP is duplicated using the system
704: call \fIdup\fP (2)
705: and the result is used as the standard output.
706: .IP <&\ \fIdigit\fP 12
707: The standard input is duplicated from file descriptor \fIdigit.\fP
708: .IP <&\(mi 12
709: The standard input is closed.
710: .IP >&\(mi 12
711: The standard output is closed.
712: .LP
713: Any of the above may be preceded by a digit in which
714: case the file descriptor created is that specified by the digit
715: instead of the default 0 or 1.
716: For example,
717: .DS
718: \*(ZZ 2>file
719: .DE
720: runs a command with message output (file descriptor 2)
721: directed to \fIfile.\fP
722: .DS
723: \*(ZZ 2>&1
724: .DE
725: runs a command with its standard output and message output
726: merged.
727: (Strictly speaking file descriptor 2 is created
728: by duplicating file descriptor 1 but the effect is usually to
729: merge the two streams.)
730: .LP
731: The environment for a command run in the background such as
732: .DS
733: list \*(ST.c \*(VT lpr &
734: .DE
735: is modified in two ways.
736: Firstly, the default standard input
737: for such a command is the empty file \fB/dev/null\|.\fR
738: This prevents two processes (the shell and the command),
739: which are running in parallel, from trying to
740: read the same input.
741: Chaos would ensue
742: if this were not the case.
743: For example,
744: .DS
745: ed file &
746: .DE
747: would allow both the editor and the shell
748: to read from the same input at the same time.
749: .LP
750: The other modification to the environment of a background
751: command is to turn off the QUIT and INTERRUPT signals
752: so that they are ignored by the command.
753: This allows these signals to be used
754: at the terminal without causing background
755: commands to terminate.
756: For this reason the UNIX convention
757: for a signal is that if it is set to 1
758: (ignored) then it is never changed
759: even for a short time.
760: Note that the shell command \fItrap\fP
761: has no effect for an ignored signal.
762: .SH
763: 3.8\ Invoking\ the\ shell
764: .LP
765: The following flags are interpreted by the shell
766: when it is invoked.
767: If the first character of argument zero is a minus,
768: then commands are read from the file \fB.profile\|.\fP
769: .IP \fB\(mic\fP\ \fIstring\fP
770: .br
771: If the \fB\(mic\fP flag is present then
772: commands are read from \fIstring\|.\fP
773: .IP \fB\(mis\fP
774: If the \fB\(mis\fP flag is present or if no
775: arguments remain
776: then commands are read from the standard input.
777: Shell output is written to
778: file descriptor 2.
779: .IP \fB\(mii\fP
780: If the \fB\(mii\fP flag is present or
781: if the shell input and output are attached to a terminal (as told by \fIgtty\fP)
782: then this shell is \fIinteractive.\fP
783: In this case TERMINATE is ignored (so that \fBkill 0\fP
784: does not kill an interactive shell) and INTERRUPT is caught and ignored
785: (so that \fBwait\fP is interruptable).
786: In all cases QUIT is ignored by the shell.
787: .SH
788: Acknowledgements
789: .LP
790: The design of the shell is
791: based in part on the original UNIX shell
792: .[
793: unix command language thompson
794: .]
795: and the PWB/UNIX shell,
796: .[
797: pwb shell mashey unix
798: .]
799: some
800: features having been taken from both.
801: Similarities also exist with the
802: command interpreters
803: of the Cambridge Multiple Access System
804: .[
805: cambridge multiple access system hartley
806: .]
807: and of CTSS.
808: .[
809: ctss
810: .]
811: .LP
812: I would like to thank Dennis Ritchie
813: and John Mashey for many
814: discussions during the design of the shell.
815: I am also grateful to the members of the Computing Science Research Center
816: and to Joe Maranzano for their
817: comments on drafts of this document.
818: .SH
819: .[
820: $LIST$
821: .]
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.