.autoparagraph .flag bold .enable bold .title \\vsh - a virtual shell for ^^VAX/VMS .chapter ^*\\vsh - a virtual shell for ^^VAX/VMS\* .center by .blank .center Camillo Bongiovanni .center Via Massena, 12 .center 10100 Torino (ITALY) .center ph._# 011/542173 .blank 3 .center ^*A\\bstract^^\* ^*Vsh\* is a command language interpreter for VMS systems. It incorporates all the features of DCL and an ^*history\* mechanism; most of the features of ^*vsh\* are designed more for interactive VMS users. .page .header level 1 ^*I\\ntroduction^^\* .spacing 2 A ^*shell\* is a command language interpreter. ^*Vsh\* is the name of a particular command interpreter on VAX/VMS. The primary purpose of ^*vsh\* is to translate command lines typed at a terminal into system actions, such as invocation of other programs. ^*Vsh\* is a user program, just like any one might write. Hopefully, ^*vsh\* will be a very useful program for everyone in interacting with the VAX/VMS Operating System. Many words in this document are shown in ^*boldface\*. These are important words; names of commands, and words which have special meaning in discussing the shell and VMS. .header level 1 ^*T\\erminal usage of the shell^^\* .header level 2 ^*The basic notion of commands\* A ^*shell\* acts mainly as a medium through which other ^*commands\* are invoked. The shell is thus distinguished from the command interpreters of other systems both by the fact that it is just a user program, and by the fact that it is used almost exclusively as a mechanism for invoking other programs. Commands in the VMS system may be followed by a list of strings or ^*words\* as arguments. Thus the command create datafile.dat .skip consists of two words. The first word ^*create\* names the command to be executed, in this case the create program that creates a file. The rest of the words of the command are given to the command itself to execute. In this case we specified also the word ^*datafile.dat\* which is interpreted by the ^*create\* program to be the name of the file that has to be created. In normal terminal usage we might use the ^*create\* command as follows. .spacing 1 .literal 1> create datafile.dat one two three ^Z 2> .end literal .spacing 2 Here we typed data to be stored in the named file and ended them with a control-z which sent an end-of-file to the create program. The create program then stored our data into the file 'datafile.dat'. The strings '1> ' and '2> ' were printed by the shell to indicate that input was needed. After typing the '1> ' prompt the shell was reading command input from our terminal. We typed a complete command ^*create datafile.dat\*. The shell then executed the ^*create\* command with ^*datafile.dat\* as argument. The create program then read input from our terminal until we signaled an end-of-file after which the shell noticed that create had completed and signaled us that it was ready to read from the terminal again by printing the '2> ' prompt. This is the essential pattern of all interaction with VMS through the shell. A complete command is typed at the terminal, the shell executes the command and when this execution completes prompts for a new command. If you run the editor for an hour, the shell will patiently wait for you to finish editing and obediently prompt you again whenever you finish editing. .header level 2 ^*Output to files\* Many commands may read input or write output to files rather than simply taking input and output from the terminal. Each such command could take special words as arguments indicating where the output is to go. It is simpler, and usually sufficient, to connect these commands to files to which they wish to write, within the shell itself, and just before they are executed. Thus let us suppose we wish to save the current user list in a file called 'whois.on'. The command show users .skip will print the current user list on our terminal. This is because our terminal is the default ^*standard output\* for the show users command and the command prints the list on its standard output. The shell let us redirect the ^*standard output\* of a command through a notation using the ^*metacharacter\* '>' and the name of the file where output is to be placed. Thus the command show users > whois.on .skip runs the ^*show users\* command in an environment where its standard output is the file 'whois.on' rather than our terminal. Thus this command places the current user list in the file 'whois.on'. It is important to know that the ^*show users\* command was unaware that its output was going to a file rather than to our terminal. The shell performed this ^*redirection\* before the command began executing. .header level 2 ^*Metacharacters\* The shell has a number of special characters (like '>') which indicates special functions. We say these notations have ^*syntactic\* and ^*semantic\* meaning to the shell. In general, most characters which are neither letters nor digits have special meaning to the shell. Note that the shell is only reading input when it has notified this with its prompt, thus metacharacters will normally have effect only then. We need not worry about placing shell metacharacters in a text we are storing via the ^*create\* command. .header level 2 ^*Input from files_; pipelines\* We learned above how to route the standard output of a command to a file. It is also possible to route the standard input of a command from a file. This is not often necessary since most commands will read from a file given as argument. We can give the command more < datafile.dat .skip to run the ^*more\* command with standard input, where the command normally reads, from the file 'datafile.dat'. We would more likely say more datafile.dat .skip letting the ^*more\* command open the file 'datafile.dat' for input itself since this is less to type. We should note that if we just typed more .skip then the more program would read lines from its ^*standard input\*. Since we did not ^*redirect\* the standard input, it would read lines as we typed them on the terminal until we typed a control-z to generate an end-of-file. A most useful capability is the ability to combine the standard output of one command with the standard input of the next, i.e. to run the commands in a sequence known as a ^*pipeline\*. .skip For instance the command directory /owner .skip produces a full listing of the files in the current directory, including their owner uic; this output could be very long. If we are interested in learning which of these files are owned by a particular uic, let us say [20,110], we may wish to have the lines of this list containing the specified uic. We could look at the many options of ^*directory\* to see if there was an option to do this but would eventually discover that there is not. Instead we can use a simple option of the ^*grep\* command, combining it with ^*directory\* to get what we want. The ^*grep\* command searches its standard input for a pattern, thus directory / owner | grep 20,110 .skip specifies that the output of the ^*directory\* command run with the option /owner is to be ^*piped\* to the command ^*grep\*. This would give us a list of those lines containing the pattern ^*20,110\*. The metanotation introduced above is called the ^*pipe\* mechanism. Commands separated by '|' characters are connected together by the shell and the output of each is run into the input of the next. The leftmost command in a pipeline will normally take its standard input from the terminal and the rightmost will place its standard output to the terminal. .header level 2 ^*The shell's history list\* The shell can mantain an history list into which it places the words of previous commands. It is possible to use a metanotation to reintroduce commands or words of commands. This mechanism can be used to repeat previous commands or to correct minor typing mistakes in commands. The following figure gives a sample session involving typical usage of the history mechanism of the shell. In this example we have a very simple FORTRAN program which has a bug in it in the file 'bug.for', which we 'type' out on our terminal. We then try to compile it, referring to the file again as '!$', meaning the last argument of the previous command. Here the '!' is the history mechanism invocation character, and the '$' stands for the last argument. The shell echoed the command, as it would have been typed without use of the history mechanism, and then executed it. .test page 50 .spacing 1 .literal 1> type bug.for type *,'hello! stop end 2> fortran !$ fortran bug.for %FORT-E-MISSAPOS, Missing apostrophe in character constant [type *,'hello!] in module BUG$MAIN at line 1 %FORT-E-ENDDIAGS, SYS$GRP02:[SOFTDEV.MIMMO.GAMES.VSH.DOC]BUG.FOR;1 completed with 1 diagnostic 3> edit !$ edit bug.for 1 type *,'hello! *s/!/!'/ 1 1 type *,'hello!' 1 substitution *exit SYS$GRP02:[SOFTDEV.MIMMO.GAMES.VSH.DOC]BUG.FOR;2 3 lines 4> !f fortran bug.for 5> link bug.obj 6> run bug hello! FORTRAN STOP 7> !4 /list/noobject fortran bug.for /list/noobject 8> proint bug %DCL-W-IVVERB, unrecognized command \PROINT\ bug 9> ^oi^i^ print bug Job 6134 entered on queue STAMPA 10> !! /queue=printer_2 print bug /queue=printer_2 Job 13 entered on queue PRINTER_2 11> .end literal .spacing 2 .page The compilation yelded error diagnostics so we now run the editor on the file we were trying to compile, fix the bug, and run the compiler again, this time referring to to this command simply as '!f', which repeats the last command which started with the letter 'f'. If there were other commands starting with 'f' done recently we could have said '!for' or even '!fo:p' which would have printed the last command starting with 'fo' without executing it. After this recompilation we ran the linker, in order to obtain a 'bug.exe' executable image; we then ran this resulting file, to see that its output was correct. To make a listing of the program we compile the source again (executing command number four), adding an extra '/list/noobject' to tell the compiler to make a 'bug.lis' listing file without generating object code. Then we tried to send this listing to the printer via the 'print' command, but mispelled it as 'proint'. To correct this we used a shell substitute, placing the old text and new text between '_^' characters. Finally, we repeated the same command with '!!', but sent it to the queue 'PRINTER_2'. There are other mechanisms available for repeating commands. An ^*history\* command will print out a a number of previous commands with numbers by which they can be referenced; there are also other, less useful, ways to select commands and arguments to include in a new command. A complete description of all these mechanisms is given in the vsh manual pages in the ^*Vsh Users Manual.