Abstract
This document is designed to give the reader a quick-and-dirt view of the SOS Command Interpreter (CI for short) and execs on the DMS-100 switch. It is not designed to replace reading of the pertinent DIS documents. The document covers the basic CI commands as well as numerous examples of using SOS execs, and many of the "secret" features and Murphitic surprises awaiting the unwary.
The following conventions are used in this manual:
Commands as you would type them in are always shown in CAPITALS, preceded with a greater-than: ">". If there is an optional parameter, it will be shown in braces: "{blah}". Comments are indicated out to the right of a line and will start with a double-dash: "--".
You should not enter the comments. Thus, the line:
>READ OPERPROF -- start up the profile
Means to enter the command "READ OPERPROF". You do not enter the ">" or the comment "-- start up the profile" at any time.
Parameters which are variable values are usually indicated with the greater-than and less-than and in lower case letters: "<blah-blah>".
For example:
>QFLAG <user-sys>
The possible values for user-sys are given by the use of braces. For example:
Where, <user-sys> = {ATV, AUTOVON, D250, XYZ, etc.}
Here, the term "etc" stands for "et cetera" or "and so forth" and is not an option. Usually, a help command will be available to explain what the legal options are.
In this document, I always use <BREAK> to indicate the break key.
I will also use the "^" in place of the caret.
Overview
To many the mere word (acronym) SOS evokes terror, disgust, yea even a tight feeling in the left shoe. However, we must be of strong will for (though nasty the subject be) many must use SOS.
The perspective of this paper is not so much the operation of SOS itself (of which much has been written and said), but on how to use the SOS features to implement "programming" execs. Thus, if you want to know how the scheduler works, or how to interface your CIBINCOMs to SOS or CIP, look elsewhere. There are several good DIS documents and a couple of video tapes on that subject.
Thus, we are only concerned with the rather nasty "computer" type operations -- not the operation of SOS as an operating system. We are like BASIC programmers trying to print the first ten integers:
(BASIC) (SOS) 10 FOR I = 1 TO 10 1 -> II 20 PRINT I REPEAT 10 (PRINT II;(II+1)->II) 30 NEXT I
Logging In and Getting Started
When you log in, the SOS creates a user area of memory within which your execs and files will reside. Also, when you log out, that area of memory continues to exist. Only if you UNPERMIT a user (i.e., erase the user log on) will you wipe out files, etc. (Of course, if the switch is re-booted during your absence, then those files are lost also.)
To log on:
--- Enter user name and password: >ALPHA ALPHA -- already permitted --- Enter user name: -- security version >ALPHA --- Enter password: >ALPHA
Of course, if the user is not permitted, you may need to go to the operator console and enter:
>PERMIT ALPHA ALPHA 2 5000 ALL
or something like that.
A Few Useful Keys
You may have noticed by now that CI doesn't like the arrow keys. With that in mind, here are some substitute key sequences, as well as some other handy keystrokes. Like in any other ASCII environment, "<CTRL> H" means "hold down the control key and hit H."
Note: If you're getting a lot of "Stack Overflow" messages while messing around on the switch, you probably need to increase your stack size. To do that, you will have to re-PERMIT yourself, with a larger number for the stacksize field (5,000 in the example above). 10,000 is the limit. That's what I always use.
The SOS Editor (Introduction)
Well, since there are files on the system, we need some way of creating and changing them -- enter the SOS editor. It is a little primitive (not full-screen) -- however, we can do a lot with it by using SOS macros within the editor. How?? Read on.
To proc it up:
>EDIT myfile (or whatever) .... edit commands .... ....................... ... and to exit: >QUIT -- discards input --- NO failsafe! >FILE SFDEV -- files the changed file in RAM
Directory Structure While in EDIT
When a user name is permitted, a permanent area of memory is allocated. This same SFDEV (RAM) is always accessed when the user logs in. The user always has read-write access to the memory. Upon entering the EDIT command, the SOS Command Interpreter (CI) creates a temporary linkage to a read only directory. It will be layered on top of your existing directory and you can then access the EDIT commands (INPUT, TYPE, UP, etc.).
Thus, you might try this:
>EDIT JUNK NEW FILE -- SOS tells you that the file doesn't exist >LISTST -- to show the directory structure... EDITDIR CE01,8071 RO ALPHA CE01,C047 RW PROGDIR CE01,C004 RO SYSDIR CE01,2002 RO ROOTDIR CE01,4001 RO STDIRS CE01,A01E RO
SOS puts the copy of the EDIT directory on top. And even though it is Read Only (RO), you can still create macro commands in your Read/Write (RW) directory "USERS.ALPHA" that use the edit commands.
EDIT <filename>
Let us say that we want to create a junkfile called "MYJUNK" to play with. We enter:
>EDIT MYJUNK -- enter the editor, filename is MYJUNK NEW FILE -- the editor says the file is a new one EDIT: -- prompt to remind us we are in EDIT > -- prompt for the next edit command
We want some stuff in the file, so we use the INPUT command.
>INPUT
INPUT MODE:
> -- Now we can enter our lines. To exit
-- we enter an extra carriage return.
>Mary had a little lamb.
>Sally lives here.
>> -- i'll use ">>" for double carriage return
EDIT:
>
Now we want to see what we entered, so use the TYPE, UP, and DOWN commands:
>UP 1 >TYPE 33 >DOWN 11 >DOWN END -- special variable will put us at the bottom of the file
Also we can change text on the current line with the CHANGE command:
>CHANGE 'Mary' 'Sammy'
Sammy had a little lamb.
or
>CHANGE 'Marry' 'Sammy'
STRING NOT FOUND -- EDIT couldn't find the string
>
We must always use the apostrophe ('), so things sometimes get a bit messy:
>INPUT INPUT MODE: >Don't you know? >> >CHANGE 'Don''t' 'Didn''t' Didn't you know? >CHANGE '''t' '-t' Didn-t you know?
The general rule is to use an extra apostrophe for the one in the text.
Or we can delete the whole mess with the DELETE command. The DELETE command doesn't output anything except the new current line (if it changes).
Both DELETE and CHANGE always refer to the current line, which can be displayed by the TYPE 1 command. UP and DOWN move you through the text files.
CHANGE and DELETE have "until" features:
>DELETE 'zotto' -- Delete all lines from here until
-- the search string "zotto" is found.
-- If it doesn't exist then nothing is zapped.
>CHANGE GLOBAL 'a' 'A' -- Goes from current line to end of file.
or
>CHANGE 3 'a' 'A' -- change 3 times on the same line:
MAry hAd A little lamb.
| | |
The line number of the current line in the editor is stored in a special variable called LINE:
>TYPE 1 Mary had a little lamb. >PRINT LINE 1 >DOWN 1 Sally lives here. >PRINT LINE 2
The current line's contents are always copied to a special variable called LINESTR:
>PRINT LINESTR Sally lives here.
TOP and END move you quickly through the file. To search for a string, we can use DOWN with a string:
>TOP -- The editor will always reserve a dummy
-- blank line at the top of your file.
>DOWN 'lives'
Sally lives here. -- Or you might get an error message
-- STRING NOT FOUND.
>UP 'lamb'
Mary had a little lamb. -- UP with a search string
Commands can be strung out on the same line with the ";" (just like SOS commands):
>TOP;DOWN 'here';TYPE 333 -- Go back to the top of file,
-- go down until the string 'here'
-- is found, and type the next 333
-- lines (or until End-of-File).
or
>TOP
>DOWN 'here'
>TYPE 333
By the way, there is another form of INPUT... INPUT B. This will input the data before the current line. Sort of handy from time to time.
>FILE SFDEV -- save our file in RAM (SFDEV) >FILE D010TEST1 -- save our file on disk volume D010TEST1
EDIT Macros
Since the EDIT directory is on top of ours, which is on top of the system and program directories, we can still use SOS to create commands -- and while in edit, these can be very powerful:
>EDIT MYJUNK -- If the file already exists, we won't
-- get the "NEW FILE" message here.
>COMMAND CM COMMAND -- Define a shorter version of the
-- command declaration command.
>CM D DOWN -- short form for DOWN
>CM U UP -- short form for UP
>CM T TYPE -- short form for TYPE
>CM BOT END -- XEDIT users like "BOT" not "END"
>CM CH CHANGE -- short form for CHANGE
>CM CHA CHANGE -- three-letter version
>CM DEL DELETE -- short form for DELETE
>CM PUT1 (LINESTR->XX1) -- store the current line in a temp variable "XX1"
>CM GET1 (INPUT XX1) -- and input it after the current position.
Example:
>EDIT LAMBS NEW FILE: >INPUT INPUT MODE: >Mary had a little lamb. >Sally lives here. >> -- extra carriage return, exits input mode >TOP;DOWN 1 Mary had a little lamb. >PUT1 -- XX1 now equals 'Mary had a little lamb.' >END >GET1 -- store it as the new last line, and... >TOP;T 5555 -- show the file: Mary had a little lamb. Sally lives here. Mary had a little lamb.
Neato, eh? Of course, we could write a macro to put an unlimited number of lines, but let's wait until later.
SOS Fundamentals
What's the Difference Between NT40 and SuperNode Switches?
This is a really broad question, but I'm going to try to sum it up in a page or so.
First, let's talk about how a switch works. A captive office is basically two parts: the network and the switch. The network is a collection of peripherals (each of which is driven by its own microprocessor). The switch is the master computer which, among other things, sets up connections between peripherals so they can talk to one another.
With this in mind, I'll try to explain the life of a simple phone call. The call comes into the switch on a trunk/line. The peripheral says, "Hey, I just got a call. I better tell the switch." So it sends a message to the switch. A little volley goes on and eventually the peripheral tells the switch what digits were dialed. The switch figures out where to send the call next and sets up the connection between the incoming and outgoing peripherals. This connection is set up in the network. From here on out, the peripherals talk to each other without any help from the switch until the call ends.
This is why, once you get a call up, you can do anything to the switch you want to and the call stays up. You can restart warm, restart cold, whatever. The peripherals never even know it.
Now that we have that out of the way, we can get on with the real question.
The NT40 is a proprietary processor developed by Northern Telecom specifically for digital telephony applications. This processor is, of course, the heart of what we call NT40 switches.
A few years ago, someone decided it would be a really neat idea to base a switch around a 68020. That's where SuperNode came from. But the differences don't end there. SuperNode is actually two computers instead of just one. (Two... two... two computers in one!) It's made up of a CM (Computing Module) and an MS (Message Switch).
One of the results of this arrangement is that images are about twice as large for SuperNodes as for NT40s, and consequently take about twice as long to boot. Enter the SLM.
SLM stands for System Load Module. An SLM consists of a Winchester disk and a magnetic-tape cartridge. The SLM is used to contain all images for a SuperNode, as opposed to the NT40 which stores images on the regular disk drives. The overall result is that the SLM tapes boot many times faster than the normal tapes, and the SLM drives leave that much more room on the regular disk drives.
The only other major difference from a user standpoint is the way you boot the two machines. NT40 switches are booted using the thumbwheel on the front of the switch. SuperNodes are booted from the Reset Terminal. The procedures are described in detail in the "Booting from Disk or Tape" section.
That about covers it. Any additional questions you have about SuperNode versus NT40 are probably covered in the DMS-100 SuperNode System Description (SYSDESC). If you're curious about SLMs, look a little further down in the "SLM Stuff" section.
A Few Things to Know Before Writing Execs
SOS Data Types
Basically, there are several unusual data types that cause all sorts of problems:
And, of course, since Protel is heavily typed, it is hard to get the computer to convert them back and forth. For some conversions there exist functions, for others not:
12->TWELVE -- TWELVE is a decimal value of 12
PRINT (HEXTOSTR TWELVE) -- print the form-feed
or
PRINT (HEXTOSTR #0C) -- actual hex value "#"
So we have a function "HEXTOSTR" to do the conversion. We'll see others later.
Variables & Values
There are several types of variables in SOS and these include:
You see, all entities have a partype associated with them and we can find out what that is with the PARTYPE built-in function:
>1->II >PRINT (PARTYPE II) 1
We can, of course, assign values. For example:
>'abc'->VARX >32767->MAXINT
Now we come to a very important aspect. The so-called "goes-into".
The Goes-Into "->"
To assign a variable, we use two characters instead of just 1:
BASIC: BBB = 33 SOS: 33->BBB
Now a very interesting thing occurs, and that is that the number of spaces on each side of the goes-into must be the same:
123-> XYZ -- does nothing at all!! 123 ->XYZ -- does nothing at all!! 123 -> XYZ -- ok 123->XYZ -- ok 123 -> XYZ -- ok
This can be tricky, so either use no spaces or at least one space on each side.
Comparison and Relational Operators
Of course, SOS has IFs, UNTILs, and WHILEs, and what would an IF, UNTIL, or WHILE be without comparison and relational operators? Here are the comparison operators:
Comparator Symbol
Less Than <
Greater Than >
Less Than or Equal <=
Greater Than or Equal >=
Equal =
Not Equal ^=
These are the relational operators:
Relator Symbol
AND &
OR |
EXCLUSIVE OR !
As with the goes-into, SOS is kinda picky about how many spaces are on each side of a comparator or a relational operator. The rule for comparators is the same as that for the goes-into. At least one space on both sides or no spaces on either side.
The relational operators are different, though. With them, the number of spaces on the left don't matter, but there must be at least one space on the right. Don't ask me. I just work here.
Let's look at some examples:
IF ((x>y) & (w=1)) THEN (... -- do it fine.
IF ((x > y) & (w = 1)) THEN (... -- ok by me.
IF ((x > y)& (w = 1)) THEN (... -- no prob.
IF ((x > y)& (w = 1)) THEN (... -- ok fine.
IF ((x > y)&(w = 1)) THEN (... -- won't work!!!
(need a space after the &)
IF ((x>y) &(w=1)) THEN (... -- won't work!!!
(need a space after the &)
IF ((x> y)&(w=1)) THEN (... -- won't work!!!
(uneven spacing around > )
IF ((x>y)&(w =1)) THEN (... -- won't work!!!
(uneven spacing around = )
Numeric Variables
Numeric variables are always signed 16-bit integers. This means that the limit of an integer is between -32,768 and 32,767.
Thus, the following are examples:
123 -> AVAR
32767->BVAR
-32760 -> JVAR
All arithmetic is integer and must conform to these range restrictions.
String Variables
String variables are always enclosed in the single-quotes mark (apostrophe):
'here is a string' -> MY_STRING 'Joe''s pizza'->$PARLOR_MESG
The rule in general is that you use one extra ' in the middle of a string. Thus, the following do the following:
>PRINT $PARLOR_MESG Joe's pizza >'''x'''->QUOTO >PRINT QUOTO 'x'
The extra extra ' is required due to the fact that the first one is the delimiter. Anyway, you can fool around with it until you get the hang of it. We saw some examples of that back in the editor discussion.
NUMTODECSTR, NUMTOHEXSTR, HEXTOSTR, & DECSTRTONUM
SOS is pretty flaky about consistently providing type-conversion, so here we go:
>123->NUMBER >(NUMTODECSTR NUMBER) -> STRING >(DECSTRTONUM STRING) -> SAMENUMBER >(NUMTOHEXSTR NUMBER) -> STRING2 >PRINT NUMBER STRING STRING2 SAMENUMBER 123 123 007B 123 >PRINT (HEXTOSTR 12)
Would produce a CONTROL-L (form-feed in ASCII)
Simple SOS Commands
The keyword for a command declaration is COMMAND. (Very catchy, eh?)
>COMMAND FF (PRINT (HEXTOSTR 12))
This would give us a short form of the form-feed command.
Now let us look at a fancy version of form-feed:
>COMMAND FF (PRINT (HEXTOSTR 12)) >PRINT '***** DEBUGGING RLT ' >DATE;PRINT ' ')
Notice two or three things:
A command starts with a "(" and must end with a ")".
Continuations on the next line can go on for quite a while (as long as you don't over-flow the token parm area -- 255 max when input interactively. Otherwise, 2,048 in a file).
The ";" can be used within a command just as it can be on a line for separating commands.
Now, lets look at a neato command:
>COMMAND NEATO ((SYMTOSTR @1)->$PARM1; >IF ($PARM1='OK')THEN( >PRINT '-- It''s ok with me.' >)ELSE( >PRINT '-- Not ok.') )
Things get complicated fast in SOS, so let's look at it blow by blow.
Any string parm passed into a command is automatically converted to a symbol. Numeric values are not. They are left as numerics.
The IF statement can have an ELSE, but it stops scanning after the THEN is completed. That is why I put the closing ")" for the THEN on the next line. The following has no ELSE clause:
>COMMAND NOT_NEATO ((SYMTOSTR @1)->$PARM1; >IF ($PARM1='OK')THEN( >PRINT '-- It''s ok with me.') >ELSE( >PRINT '-- Not ok.) )
Yes, SOS strikes again! Since you closed out the THEN clause at the end of the "ok with me" line, the scanner just ignores the ELSE and its clause on the next two lines. It only makes sure that you have a final closing ")" to balance the very first one in the very first line.
Since commands give us more power, they also require more support. We will now look at some of the functions built in to help with commands.
SYMTOSTR & STRTOSYM
As we have seen, string parms that are passed to a command are converted to a SYMBOL type of variable. So we must convert them to strings to compare or print them.
>COMMAND NEATO ((SYMTOSTR @1)->$PARM1;... etc.)
The first parm is stored in the variable @1, #2 in @2, etc. Thus, after execution of NEATO, we could print the variables where we have transferred the values:
>NEATO HOWDY >PRINT $PARM1 HOWDY
We can use this to "parse" a line:
>COMMAND ALTER ((SYMTOSTR @1)->$IX_TABLE; >(SYMTOSTR @2)->$IX_CLLI; >(SYMTOSTR @3)->$IX_FIELD;(SYMTOSTR @4)->$IX_VAL) >COMMAND SHOW_ALT (PRINT '-- ALTER-PARMS: ' $IX_TABLE; >PRINT $IX_CLLI $IX_FIELD $IX_VAL)
And, I could use them thusly:
>ALTER trkgrp mdal2wdtgs01 authfld $3334444 >SHOW_ALT -- ALTER-PARMS: trkgrp mdal2wdtgs01 authfld $3334444
An interesting thing to note is the need for a non-numeric as the first character of field four. This is because the numeric value would not be transformed into a symbol, while a string value would!! This means that the (SYMTOSTR @4) would fail to get a proper input variable -- and give a "parameter of wrong type" message. Ah, SOS -- how wonderful. There is a way out of this by using the PARTYPE function. Since PARTYPE returns the parameter type (as an integer), we could use this in an IF statement to do the proper conversion.
Sometimes we want to concatenate strings, so we may need to do several conversions into strings, and then do the concatenations:
>1->II >'TM8 '->$CKT >$CKT+(NUMTODECSTR II) -> $TM8_SHELF >PRINT $TM8_SHELF TM8 1
Usually, I will put an extra set of parentheses around stuff to be concatenated. Also, note that string concatenation is one of the slowest things SOS does!
Well, since we can do a symbol to string, why not a string to a symbol? No sooner said than done. Study this:
>1->II
>33 -> VAR33
>('VAR'+(NUMTODECSTR II)) -> VAR_NAME
>22 -> (STRTOSYM VAR_NAME)
>PRINT VAR33 VAR1
33 22
Here's what happens:
So we can create variables out of thin air. Sort of like an array. Consider the following:
>1->II
>REPEAT 10 (II -> (STRTOSYM ('NUM'+(NUMTODECSTR II));
(II+1) -> II)
This will do the same as:
>1 -> NUM1 >2 -> NUM2 >3 -> NUM3 ... >10 -> NUM10
This is indeed an array. Not only that, but the thing can be used to execute using variables passed into a command!
>COMMAND PUT_LINE (
>LINESTR -> (STRTOSYM ('XLINE'+(NUMTODECSTR II)))
>(II+1)->II)
>COMMAND GET_LINES (
>REPEAT II (
>INPUT (STRTOSYM ('XLINE'+(NUMTODECSTR II))
>);0->II) )
We need only initialize the II value, and then we can use it in EDIT. So the ability to build symbols from strings is one of the most important aspects. Still...
Symbols & Devices
Since we can build the symbol of what something is in a variable, we can pass to a variable something other than a plain old string or number. Consider:
>'D010TEST' -> $VOL_NAME -- Create a string with the
-- name of a disk volume in it.
>(STRTOSYM $VOL_NAME) -> $VOL -- A symbol is created!
>DSKUT
>LISTVOL $VOL ALL -- List the files on the given volume!
Notice, however, that were we to try and do the following...
>PRINT $VOL device -- the same as >PRINT D010TEST >PRINT $VOL_NAME D010TEST -- just what we put in the var >LISTVOL $VOL_NAME ALL Wrong type: <volume name> DEVICE name
Wherein SOS is telling us that "$VOL_NAME" is not in the root directory as a symbol representing a disk volume. This is one of the differences between a string and a symbol.
RINDEX & LINDEX -- Parm Pointers
LINDEX and RINDEX tell you how many parameters appear to the left and right of your command, respectively. For example:
>COMMAND DOIT (PRINT (LINDEX);PRINT (RINDEX)) >DOIT A B C 0 3 >A DOIT B C 1 2
You can use this to make sure that the user enters the correct number of parameters to your command, and maybe even give them a little more descriptive error message than SOS's helpful: "@ -- Parameter 1 does not exist".
Many people also use LINDEX to see if they should print help information. If the user typed "HELP cmd", LINDEX would be 1.
This brings up another interesting point about SOS. Notice that, in our second example above, the command DOIT was executed even though it was not the first thing in the command line (ooh, aah!). What SOS actually does is scan the line from left to right and execute the first command it finds.
Like many things in SOS, this is potentially disastrous. Say, for example, you had a command DOIT. Say, also for example, that you were in table IOC (a rather important table), positioned on a particularly important tuple (like the one that contains all the terminals). Now, say you were to type:
>DIOT DELETE -- Note the misspelling :)
I think you get the point.
The SOS Commands -- Attack of the CI Commands
Now children, are you all nice and cozy? Well, good. Once upon a time, there was a DIS document that described the commands that SOS allowed you to use. It was a document, and it did exist (long after the fires of Mordor had been quelled). Then, one day it up and disappeared! But, then it wasn't really very useful, so no one really noticed that it was gone (until some poor novice was scanning the DIS disk looking for it). So, here is a tale of SOS CI commands. (With examples, yet!)
By the way, the only existing document on SOS that is in DIS is the Northern Telecom Publication (NTP) 297-1001-509, DMS-100 Family Command Reference Manual. Use the following to get a copy of it:
>DIS INDEX >PRINT N1001509 LISTING I >CP SP PRT CLO FORM XHDP (or however you print stuff at your site)
It is a bit dated, and somewhat more like a dictionary. However, I will quote a bit from it.
Survey of the Commands
I couldn't decide if I should put the commands in here in logical order or in alphabetical order, so I finally decided on both! This section is the one that is logical. The others are alphabetical. By necessity, there are some commands that I talk about quite a bit, and others that I don't really get into very much at all.
Logging On, and Stuff Like That
Commands discussed:
TERMDEV, LOGIN, LOGOUT, FORCEOUT
You must always make sure the terminal is configured correctly in table TERMDEV. Its baud rate, etc. should match the setting on your terminal:
MAP 0 8 CYB B1200 CL 1X67BC NONE N NONE ALL
would be the entry for a Cybernex terminal. The device name is "MAP", which is the default for the operator position. For a printer, the entry would be:
PRT0 0 9 KSR B1200 CL 1X67BC NONE N NONE ALL
For a VTxxx (VT100, VT220, etc.), the entry would be:
MAP 0 8 VT100 B1200 CL 1X67BC NONE N NONE ALL
Then, you log in. You get the switch's attention by hitting the break key. In this document, I always use <BREAK> to indicate that key.
<BREAK>
? -- This is the standard prompt.
?LOGIN -- Then, you enter LOGIN after the "?". The switch
-- will then prompt you for your user name and
-- password if there is no default user for your
-- terminal.
>LOGOUT -- Zap. You are logged out. All commands,
-- variables, and directories that you had
-- defined disappear.
Another handy command is:
>FORCEOUT <user>
Which will forcibly logout another user. There is no warning, so use it with caution. The user does get a message something like "Logged out by user".
Detached User LOGIN
This brings us to the topic of detached users (about which I will have a whole lot to say later). If you are already logged in, you can use the LOGIN command with the following format:
>LOGIN <user> <password> <profile> <device>
See the discussion under the LOGIN command for more details.
MSG & SETLOGMSG
MSG is used to send a message to another (or all optionally) user(s):
>MSG MAP4 'Are you ready for lunch?'
When we use the MSG command, we have to know who is logged on. We can use the PRINT USERS command to find out.
SETLOGMSG allows you to set the message that will be displayed at log on. Also, if you hit return twice in a row, you will get the log message displayed (along with a prompt showing where you are):
> > CI: BCS-18ZO RMT with TATS AUG-12-85 No Patches >
PRINT USERS, SHOW USERS
PRINT USERS -- shows all users who are logged in.
SHOW USERS -- shows all users who have been permitted.
PERMIT & UNPERMIT
PERMIT allows you to add a user name that the switch will recognize at login. For example:
>PERMIT MAP3 MAP3 2 8000 ALL -- or something like that
Now, someone can go to a terminal and log in as MAP3.
UNPERMIT just does the opposite of PERMIT. For example:
>UNPERMIT MAP3 -- erases a user name from existence
These have an interesting property. The user name has nothing to do with the device. However, if it happens that a user name has been permitted that has exactly the same spelling as a device name, and then you go to log on at that device -- you won't be prompted for name or password!
PROFILE & NOPROFILE
You can set up a user profile for each login user name with the PROFILE command. You have one chance to override the default profile at login time. After you login, the very first command you enter must be NOPROFILE. Otherwise, you will automatically execute the associated login profile the first time you hit return after logging in. For example:
<BREAK> ?LOGIN --- Enter user name and password: >BETA BETA --- User BETA logged in on 1PRT0 on Jan 31, 1993. >NOPROFILE -- this should disable the profile
The <BREAK> Key with HT, HX and RT
If a long listing is coming out and you want to discard the output, you can hit the break key and enter "HT" after the "?". Then, if you want to look at the output again (before the output is done), you can hit break again and enter "RT" after the new "?".
These are modeled after VM/CMS's Halt Typing (HT) and Resume Typing (RT) commands. Of course, there are problems. For example, if you have a record link going to a device (e.g., RECORD START ONTO PRT0), then even though you have entered the HT, the listing still continues to PRT0. (It may be a little bit faster since the line doesn't actually have to be output to two different devices.)
To kill the current program you are running, use the break with either "HX" or "HXX". These "Halt Execution". Sometimes it takes a few moments to clear, but you will usually get a message like "User process stopped." followed by a prompt.
Disk Stuff
Well, of course the switch has a disk drive... it's a computer, isn't it? It's used for pretty much the same things on the switch as it is on any other computer... storing junk and retrieving it fairly quickly.
In this little section, I'll discuss some of the things you can do with the disk, along with some of the pitfalls of working with the disk.
Commands discussed:
DSKALLOC
DSKALLOC is a handy little increment that does all the low-level stuff that make the disk drive on the switch useful.
Just like on a PC, the disk must be formatted before it's any good to anybody. This is done with the REINIT command in DSKALLOC. Within DSKALLOC, you can also partition the disk drive into several "volumes" using the ADD and DELETE commands. You can even make the volumes accessible only to certain users using the DIRADD and DIRDEL commands.
I'm not going to go into detail about DSKALLOC here, since you probably shouldn't be using it anyway. That's a job for the maintenance guys. If you're really curious, look in NTP 297-1001-526.
DSKUT
In general, if you want to do anything relating to the disk (print files, create files, copy files, etc.), you need to use DSKUT.
Probably the most valuable command in DSKUT is LISTVOL. LISTVOL allows you to list the files on a given disk, which puts pointers to them in your read-write directory, which makes the files accessible to you. If you want to READ, PRINT, COPY, or EDIT a file, you have to use LISTVOL to do it.
Like the entries in SFDEV, the files on disk know who owns them. So, you can have several different files with the same name on the same disk, but SOS is able to keep them straight because it knows who owns them. If you just do a:
>LISTVOL D010CNTFL
you would get only the files that you own. If you do a:
>LISTVOL D010CNTFL OPERATOR
you would get only the files that OPERATOR owns. If you do a:
>LISTVOL D010CNTFL ALL
you would get all the files on the volume.
This brings up an important point. If you do a LISTVOL and get more than one file listed with the same name, SOS will only remember the last one that popped up. So be careful.
This gets to be even more of a pain, because if you file a new version of a file that was already there, the older version is not erased. It's still sitting out there, and if you do a LISTVOL, it will show up as an "*** older duplicate ***", and these can be a real pain to get rid of. Of course, if you do a LISTVOL and the last copy of the file that pops up is an "*** older duplicate ***", that's the only one SOS knows about.
But, enough about LISTVOL. There are several other little goodies in DSKUT. You can get information about a volume or a file (SHOWVOL and SHOWFL) and erase files (ERASEFL). If you're messing with the boot volume, you can even mess with the current image (SETBOOT, SHOWBOOT, and CLEARBOOT).
Getting a File on the Disk
There are only three ways I know of to get a file on the disk. The first is to COPY it there. You can copy files from SFDEV, from other disk volumes, or from tape.
The second way is to EDIT a file and FILE it on disk. EDIT is the SOS file editor. You start off by EDITing a file that doesn't exist, putting some stuff in it, and issuing the FILE command:
>FILE D010CNTFL
The third way is to take an image using the DUMP command.
Tape Stuff
Of course, if you really want your data to be safe, you'll back it up to tape every once in a while. (Maintenance has this nasty habit of reformatting disks when they develop problems.)
In this section, I'll briefly discuss how to get stuff onto and off of a tape.
Commands discussed:
Mounting the Tape
Of course, the first thing you have to do when using a tape is mount it. To do that, you go to the tape drive, put your tape on the wheel, and manually thread the tape onto the takeup reel. (Autoloading? What's that?) There should be a diagram on the tape drive to show you how to do that.
You then hit the LOAD button. The tape will spin for a few seconds and stop. The LOAD light will come on when it stops. You then hit the ONLINE button.
You've now done all the manual work involved in mounting the tape. The switch still doesn't know it's there, though. You have to issue the MOUNT command... like this:
>MOUNT 0 or >MOUNT 1 or >MOUNT 10 depending on the name of your tape drive
That's the simple form. We'll get to the more complicated forms in a minute.
Anyway, the switch now knows that there's a tape there. You're ready to go.
Getting Files from Tape to Disk
To get files from tape to disk, you mount the tape just as outlined in the "Mountng the Tape" section. The next step is to get all the files on the tape into your symbol table. This requires the use of the LIST command:
>LIST T0
Notice that the tape drive is now prefaced with a "T". Why? Who knows. It's just one of those Walter Cronkite things: "That's the way it is."
Be forewarned: unlike LISTVOL or LISTSF, no filenames will appear on the screen when you use the LIST command.
Anyway, once you've done that, you use the COPY command to pull the files off and put them where you want them:
>COPY FILE1 D010CNTFL >COPY FILE2 SFDEV
See? No problem.
Getting Files from Disk to Tape
Getting files from tape to disk is just a little more complicated at first. Specifically, you have to erase the tape before you mount it:
>ERASTAPE 0 >MOUNT 0
Now, you use the COPY command, much the same as you would to copy from tape to disk:
>COPY FILE1 T0 >COPY FILE2 T0
Demounting the Tape
This is pretty easy. To demount the tape, just type:
>DEMOUNT T0
The tape will rewind back to the LOAD position. To take the tape off, hit the ONLINE button, then hit the REWIND button. No problem.
The only trick is that the DEMOUNT command has to be issued at the same terminal where you issued the MOUNT command.
There are a couple of special cases, though. If you forget to do the DEMOUNT command, you can't screw anything up. When you go to the tape drive and hit the ONLINE button, it'll just ignore you.
The other case is if you do a restart without DEMOUNTing a MOUNTed tape. In this case, the switch no longer knows the tape is mounted, so just go over and hit the ONLINE and REWIND buttons.
Booting from Tape and Imaging to Tape
Yes, you can boot from tape and take an image to tape. Both are discussed in "Images" section. Just thought you'd like to know.
SLM Stuff
What's an SLM? Well, it's a combination disk drive and tape drive. Basically, someone decided it would be neat to use those new high-density cartridge tapes, and someone else decided it would be a good idea to have a disk drive used strictly for storing images, so they put them both in one box and called it an SLM. To see one, just open the cabinet doors on your nearest SuperNode. The SLMs are the things with the big slots in them toward the bottom. If you don't see it, go around to the other side.
I'm going to try to explain how you use an SLM in terms of how you use a regular disk drive. Ok, you know that switches have one regular disk drive per side and that those drives are identified as D000 and D010. There can be several logical volumes on a single drive (IMAGE, CNTFL, PMLOADS, etc.), so to identify a particular volume on a particular drive, you do something like D010CNTFL or D000IMAGE.
Well, SLMs work kind of the same way. Each SLM contains two devices: a disk drive and a tape drive. The disk drive is S00D or S01D and the tape drive is S00T or S01T. SLM disks also have volumes. However, the only volume I've ever seen on an SLM disk in the lab is IMAGE. So, you have S01DIMAGE and S00DIMAGE.
Now, SLMs are supposed to be the only things you use for images and booting on a SuperNode. They're the only things you can DUMP to or \BOOT from. The disks act pretty much like regular disks, though. You can COPY things to or from one, EDIT things and FILE them on one, and just generally treat one like another disk drive. The exception to that is that DSKUT doesn't access an SLM. The corollary to DSKUT for an SLM is DISKUT. DISKUT will be explained a little further down.
The SLM tape drive is an interesting beast. It doesn't behave much like the reel tape drives. It's used strictly for backing up files and booting. You can't even use the COPY command on it. To get files onto it, you have to use the DISKUT BACKUP command, and to get them off, you have to use the DISKUT RESTORE command.
I will spend the remainder of this section talking about how to use the SLM disk and tape drives.
Commands discussed:
DISKADM
DISKADM is the SLM version of DSKALLOC. From within DISKADM, you can create and delete volumes on an SLM disk, display disk and volume information, format the disk, and reinitialize a volume.
As you can see, DISKADM is a pretty hazardous little utility. If you really think you'll ever need this thing, look in NTP 297-1001-509. It's the only thing I've found that talks about DISKADM.
DISKUT
DISKUT performs all the same basic functions on an SLM as DSKUT performs on a regular disk. In addition, it has a couple of commands to MOUNT and DEMOUNT those tape cartridges (INSERTTAPE and EJECTTAPE).
One of the largest differences between the operation of DSKUT and DISKUT is the way they handle images. On an NT40 switch, the IMAGE volume of a drive is assumed to contain only images, so when you want to see what images are available, you just do a LISTVOL on the IMAGE volume of the disk. Not so with a SuperNode.
An SLM contains all images on a SuperNode, but those images can be spread out over multiple volumes on the SLM. So, to keep everything straight, each SLM device has two Image Tables Of Contents (ITOC) associated with it. One ITOC contains an entry for every MS load, and the other contains an entry for every CM load. When you dump an image, entries are automatically generated in the appropriate ITOCs. But, if you were to put an image on an SLM from a reel tape (yuck), you would have to use the SETBOOTFL command to update the ITOC.
The reason for having an ITOC is so that the switch can look for other loads to boot if it can't boot the ACTIVE load. So, if you try to boot the switch from SLM and the image fails its reload restart, the switch will go down the ITOC list looking for a load to boot. If you want to know the full search order the switch goes through, look at SLMUG in DIS. It goes through the whole thing.
You can also control which image is booted with SETBOOTFL and CLEARBOOTFL, and see which image is current with LISTBOOTFL.
If you want to manipulate the cartridge tape drive, you can use BACKUP to back up either single files or whole volumes from the SLM disk, and then RESTORE to get them back off again. This brings up an interesting point. When you BACKUP an entire volume, everything is put in one file on the tape. If you want to see the names of the individual files, you have to use the BVOL option of the LISTFL command in DISKUT.
You can see what volumes are available with LISTVOLS, and then there are some other commands to manipulate files. (RENAMEFL, DELETEFL, and CLEARVOL)
I could give you more information here, but since it's already in the dictionary section, I'll just refer you there.
DUMP
The DUMP command on a SuperNode switch has a few more options than the DUMP command on an NT40. In short, since there is more than one CPU on a SuperNode, you can dump each one individually. If you do a:
>Q DUMP
you will see all the extra options at the end, after the VERBOSITY option.
These are optional parameters, so if you don't specify anything the default is TOTAL, which will dump the active CM and MS.
"How will it differentiate between the CM and MS loads on the disk?" you ask. It will simply tag "_CM" and "_MS" onto the ends of the respective images.
Images
Just what the heck is an image, anyway? Well, an image is a bit-for-bit copy of the contents of memory on the switch at a given point in time, and since all the switch's software and data is kept in memory, that can be quite a bit of stuff.
Images can reside on tape or on disk, and they're put there with the DUMP command. They are reloaded by use of the thumbwheel on the switch.
Basically, what happens when you use the DUMP command is that all the switch's used memory is copied to tape or disk in such a manner that the switch is able to reload the data in exactly the same place later on. It will then continue on about its business, starting at the point immediately following the point where the image was taken.
Usually, you will want to take an image right after you've made some major changes in the datafill on the switch (so that you don't lose it), or right before you do something that could mess the switch up so bad that you'd have to reload from disk or tape (like loading a module that could cause a restart loop).
"Ok, so now I know how to take an image. But how do I boot with it once I've taken it?"
Booting from Disk or Tape
This is one item that's as different as night and day between NT40 and SuperNode. Take your pick.
Booting the NT40
Booting the NT40 from disk or tape involves using that funny little thumbwheel on the front of the switch. (Scary, huh!) The general formula is:
The desired number on the thumbwheel in step 10 depends on what device you want to boot from:
A --> Side 0 tape drive B --> Side 1 tape drive C --> Side 0 disk drive D --> Side 1 disk drive
In the case of most (99%) of the split switches, step 10 involves turning the thumbwheel to E and hitting RESET if you're trying to boot side 1 of the switch. This step is not necessary when booting side 0.
If you're using an unsplit switch in the lab, chances are when you look at the front of the switch, one of the sides will be switched to "DEACT" and the other will be switched to "ACT". When booting these switches, step 12 is never necessary. Just go to the "DEACT"ed side, do the thumbwheel-reset routine, and flip both "ACT/DEACT" switches at the same time. (The "ACT" one to "DEACT" and the "DEACT" one to "ACT".)
If all went well, the display on the side you booted will start at E9, go to E8, and then start "spinning". (You'll know what I mean when you see it.) If it doesn't work, try it again. If it still doesn't work, scream for help.
Note to the novice: Never ever boot a switch without making sure that everyone using the switch knows you're going to and has given you the go-ahead. And, for heaven's sakes, be sure to boot the right switch. Everyone's booted somebody else's switch at least once, and, believe me, it's not a good way to make friends with your co-workers.
Booting SuperNode
The SuperNode, unlike the NT40, uses a terminal interface to boot the system. The functionality of this terminal is similar to that of the CC thumbwheel and toggle switch of the NT40. This interface is known as a Reset Terminal InterFace (RTIF).
Now, the thing about booting SuperNode is that there are currently no split SuperNodes. That makes booting a little trickier, because the side you boot has to be ACTIVE, and the other side has to be INACTIVE.
The way you tell the difference is to go to the RTIF (that's the terminal next to the video selector A-B box) and find a CM. Just turn the knob until you see "CM 0" or "CM 1" at the top of the screen. Right beside that, it will say either "active" or "inactive".
If both sides are active, you'll need to type in:
>\JAM >YES
to make one side inactive. Then you can boot the other side. If both sides are inactive, you'll need to type in:
>\RELEASE JAM
to activate one side.
After you've gotten one side active and the other inactive, you're ready to boot. If you're booting from SLM tape, you should now put your tape in one of the slots located at the bottom of the front of the SuperNode cabinet. If you're booting from SLM disk, you can skip this step (obviously).
Now, you're ready to boot. Here's what you do:
>\OVERRIDE >\BOOT SLM1 T (or SLM0 if it's the one being used) >YES (SLM0 T or SLM1 T) for booting from cartridge tape (SLM0 or SLM1) for booting from the disk
After the switch boots (takes about 15 minutes) you will need to place the splitter cards for SuperNode into their proper slots if the switch is split. The exact procedure for this differs for each lab. If you're doing this for the first time, either ask the person who told you to boot the switch what to do, or call maintenance if you're all alone.
A Dictionary of the SOS Commands
Dictionary Format
Each entry looks like the following. I try to give a brief summary of the essentials first.
------------------------------------------------------------
COMMAND NAME
All Known Formats : >command <parm>
>different format
Opposite Command : The "inverse" of it
Associated Commands : Other commands
E.G. : >command, as you might enter it
>maybe even another example
------------------------------------------------------------
Then I go ahead and discuss the command in a more or less random manner. There may be warnings for the unwary, or even examples. And, the stuff may ramble on endlessly. The whole idea is to present as many ideas as possible as to how you actually use the command. This material may duplicate (in intent) the ideas contained elsewhere. And that is good, for there are no other examples other than on the switch execs themselves. Have fun!
------------------------------------------------------------
ATTACH
All Known Formats : >ATTACH <directory name>
>ATTACH <directory> ABOVE <dir-name>
Opposite Command : DETACH
Associated Commands : DETACH, DIRECTORY, LISTST
E.G. : >DIRECTORY USER_DIR1 -- create the dir
>ATTACH USER_DIR1 -- and attach it
------------------------------------------------------------
It is almost certain that without the good old ATTACH command (and its two best pals DETACH and DIRECTORY), little serious work could be done in the world of Regression. The main idea is that you can create your own read-write directories and put them on top of other directories, you can attach to other user directories, etc. It's like the LINK or GU commands used in VM/CMS.
One example is to override the infamous TATS QUIT command. (There is no failsafe, so you can quite easily exit TATS and you have to start all over.)
>LOGIN
>BETA BETA -- login as BETA user name and password
>TATS -- This will create the two or three
-- topmost directories that TATS uses.
>DIRECTORY REGDIR
>ATTACH REGDIR -- It is now the topmost directory
REGDIR CE01.2025 RW
TATSUSERDIR CE01.600E RO
TATSRWDIR CE01.800D RO
TATSDIR CE01.8006 RO
BETA CE01.C047 RW
PROGDIR CE01.C004 RO
SYSDIR CE01.2002 RO
ROOTDIR CE01.4001 RO
STDIRS CE01.A01E RO
>COMMAND QUIT (PRINT '*** To quit, enter: TATS_QUIT')
>COMMAND TATS_QUIT (ERASE QUIT;QUIT ALL;CRT_QUIT)
The idea is that our new command will be encountered before the version in the TATSDIR directory. Thus, we can create and attach our own directories. We can also attach other user directories:
>LOGIN -- login as OPERATOR >OPERATOR OPERATOR >'hi there' -> SECRET_MSG >LOGIN -- at another terminal, login as BETA >BETA BETA >ATTACH USERS.OPERATOR -- attach the operator's directory >LISTST OPERATOR CE01.2025 RO BETA CE01.C047 RW PROGDIR CE01.C004 RO SYSDIR CE01.2002 RO ROOTDIR CE01.4001 RO STDIRS CE01.A01E RO >PRINT SECRET_MSG hi there >
------------------------------------------------------------
CIPROMPT
All Known Formats : >CIPROMPT SETPROMPT ON
>CIPROMPT SETPROMPT OFF
>CIPROMPT SETABORT <string>
>CIPROMPT SETQUERY <string>
Opposite Command : No opposite command
Associated Commands : None
E.G. : >CIPROMPT SETPROMPT OFF
>CIPROMPT SETABORT QUIT
>CIPROMPT SETQUERY EXPLAIN
------------------------------------------------------------
There are three separate and distinct uses for this command. I'll save the best for last.
First, there's the SETABORT use. You know when you put the wrong thing in and CI prompts you for a parameter to the command you typed in and you type "ABORT" to make it stop asking you? Well, with SETABORT, you can change "ABORT" to something else. For instance, you could say:
>CIPROMPT SETABORT NEVERMIND
Then, when you were prompted for a parameter, you could type "NEVERMIND" and CI would leave you alone.
Second, there's the SETQUERY flavor. You know when you want to know the format of a command, like LIST, and you type "Q LIST"? Well, with SETQUERY, you can change "Q" to something else. For instance, you could say:
>CIPROMPT SETQUERY TELLMEABOUT
Then, when you want to know about the LIST command, you type "TELLMEABOUT LIST".
Finally, and most importantly, there's the SETPROMPT flavor. This is most useful in SOS execs. Ever written a SOS exec and used a command wrong inside a loop? Me, too. You look at your terminal and you see is "invalid bla bla bla" scrolling up the screen. Well, with the CIPROMPT SETPROMPT command, you can stop that mess.
CIPROMPT SETPROMPT OFF sets things up so that CI only asks you to correct your input once. So, if you're writing an exec that contains a command that just might blow up, SETPROMPT to OFF and just put a blank line after the command in your exec. That way, if the command blows up, the blank line shuts CI up and your exec can continue on the next line.
------------------------------------------------------------
CLEARST
All Known Formats : >CLEARST
Opposite Command : No opposite command
Associated Commands : ERASE (erases one symbol)
ATTACH, DETACH
E.G. : >CLEARST
------------------------------------------------------------
This handy little command clears your symbol table. Your symbol table is the table in your own private CI process that keeps track of variables you've defined, commands you've defined, and files you know about through LISTSF or LISTVOL.
CLEARST detaches all directories except STDIR, ROOTDIR, SYSDIR, PROGDIR, and the user directory.
------------------------------------------------------------
COMMAND
All Known Formats : >COMMAND <user-command> ()
>COMMAND <user-command> (text...)
>COMMAND <user-command> <file name>
Opposite Command : (very complicated, so watch closely)
Associated Commands : ERASE (erases the command)
E.G. : >COMMAND REM () -- dummy command like %
>COMMAND FF (PRINT (HEXTOSTR 12)) -- gen a form-feed
>COMMAND ZOT XZOT_EXEC_FILE -- references an exec
------------------------------------------------------------
COMMAND is the most powerful of the SOS commands. In a sense, all of this document is about the COMMAND command. Here are a few examples:
>COMMAND REM ()
Then, in a file, you can have lots of comments without ever generating a single prompt message (log message):
>REM % any comments (Just use the "%" as the first >REM % character, and leave a blank after the REM.)
The SELECT (CASE) command:
>COMMAND SEL (@(@1+2))
(one of the great mysteries of nature!)
>COMMAND KVALS (IF ((RINDEX) < (2)) THEN ( PRINT '*** ERR - Missing parms: <filter-time> <retries>' PRINT '*** Format is: >KVALS ### ###' )ELSE( @1->$KV_FTIME;@2->$KV_RETRIES PRINT '--- K-Values are now: ' $KV_FTIME $KV_RETRIES) )
Here the command has a built-in help facility!
In the following example, we want to create a high-speed tokenized exec:
>EDIT XTI_FUNC
>INPUT
IF ((RINDEX) < (2)) THEN (
PRINT '*** TI-FUNC, missing parms: ADD/DEL tuple'
READ PREVIOUS)
%
(SYMTOSTR @1) -> $OPT
%
IF ($OPT='ADD') THEN (
TYPEIN 'ADD TUPLE '+(SYMTOSTR @2)
READ PREVIOUS)
%
IF ($OPT='DEL') THEN (
TYPEIN 'DELETE TUPLE '+(SYMTOSTR @2)
READ PREVIOUS)
%
PRINT '*** ERR -- Bad option: ' $OPT
PRINT '*** Must either be ADD or DEL'
>>
>FILE D010CNTFL -- put the file out on disk
>COMMAND TIFUNC XTI_FUNC
After we enter the COMMAND command, if there are any errors, SOS may not in fact tell us!! If we have an extra opening parenthesis, we may get the "TOKENIZING AREA FULL" and the CI system will ignore all the rest of the stuff in the file, until we either get to EOF or get an extra ")".
In order to display the character string that makes up a command you need to be very desperate, because it is more complicated than on the surface it seems it should be. But according to all sources that I know there is no other way, yet, to do this. Anyway, first you need to have a command that you want to display, lets call it NEATO. Then you need to invoke LISTST to determine the name of your Read Write (R/W) directory. Assuming that you logged onto the switch using ADMIN as your userid, LISTST might generate the following:
>COMMAND NEATO (PRINT 'This is a simple command') >LISTST TABDIR 2B01, 60B9 RO ADMIN 2B01, 20BB RW PROGDIR 2B01, A0C5 RO SYSDIR 2B01, 60C7 RO ROOTDIR 2B01, 40C8 RO STDIRS 2B01, 40BA RO
Notice that the ADMIN directory has RW to the left of it. Next you should print the R/W directory. On the SuperNode, it might look like this:
>PRINT ADMIN INPUT Device Copy 1802 OUTPUT Device Copy 1802 NEATO List Orig 005890D8
and on the NT40 it might look like this:
>PRINT ADMIN INPUT Device Copy 1804 OUTPUT Device Copy 1804 NEATO List Orig 900618
Notice that the number on the far right of the NEATO command is an address, either an NT40 three byte address, or an S/DMS four byte address. This address is actually a pointer to a structure in CI called TOKENS. The first element of the structure is a descriptor of token information, and the second element is a descriptor of the characters making up the command itself. So if you haven't guessed what your about to do, then I will go ahead and tell you: Go into debug and display the silly thing. On the NT40, given that a descriptor is three words long, the follow debug statements will do it for you:
>DEBUG debug mode >DI 900618.3 (&0) N=80 CHAR 8F7FE3: ..COMMAND..NEATO..PRINT..This is a simple co 8F7FF9: mmand...............................
Notice that this is only the characters making up the command, not tokens. This means that quotes and parentheses will not show up, but @ signs and other characters will show up. On the S/DMS it will look like this:
>DEBUG debug mode >DI 005890D8.8@ N=50 CHAR 0058B9F0: ..COMMAND..NEATO..PRINT..This is a simple co 0058BA1C: mmand.
On the S/DMS, the descriptor is eight bytes long, so offset the address by eight, then dereference it, and display the result in CHARacters. The N=80 or N=50 is completely arbitrary, and depends on the length of the command. It is possible that you will miss it the first time and need to increment some more.
------------------------------------------------------------
COPY
All Known Formats : >COPY <filename> <device>
>COPY <filename> <new-fname> <device>
Opposite Command : No opposite command
Associated Commands : COPYFILE (I think has disappeared)
LIST/TLIST, LISTSF, LISTVOL
E.G. : >COPY my_sf_file D010TEST2 -- copy to disk
------------------------------------------------------------
See the discussion under MOUNT, as that is where I talk about copying files to tape.
Whenever you use one of the LIST commands (LIST <tape>, LISTSF, or LISTVOL <vol-name>), you create a current pointer to each file. This means that if you had three separate files, each with the same name, and each one on a different device (e.g., SFDEV, tape, and D010TEST2), only the last one you reference is actually "known". So when you do a COPY, it always refers to the current file and that's that. Well, almost.
Let's say we have a file in SFDEV called PIZZA, and we can do the following:
>LISTSF
PIZZA
>COPY PIZZA D010TEST2 -- there is now a copy of our file on disk
>COPY PIZZA NEW_PIZZA D010TEST2 -- and now another
-- copy out there
>MOUNT 0 FORMAT 'MYTAPE'
ok
>COPY PIZZA T0 -- Can't change the name when
>DEMOUNT T0 -- we copy out to tape.
>COPY PIZZA OLD_PIZZA D010TEST2
*** Error -- device off-line
Ooops, we forgot that whenever we access a tape, that becomes our new source from the file. To recover, we must do a LISTSF and then copy.
By the way, you can create duplicate files on the disk volumes, which are terribly inconvenient.
------------------------------------------------------------
DATE
All Known Formats : >DATE
Opposite Command : No opposite command
Associated Commands : SETDATE, TIME, SETTIME
E.G. : >DATE
Date is TUE. 19/AUG/1986 18:02:40
------------------------------------------------------------
Actually, DATE gives you the time as well, which suggests the following little exec:
>EDIT XGET_DATE
>INPUT
SEND SINK
ERASESF XXTEMP_FILE -- Erase any old copy of the temp
ABORT -- file we will use for output.
%
SEND SFDEV XXTEMP_FILE -- re-direct the output to file
DATE -- issue the date command
SEND PREVIOUS -- back to sink (will close file)
EDIT XXTEMP_FILE -- edit the file and extract the
DOWN 1 -- string with the date info
LINESTR -> $DATESTR
QUIT
(SUBSTR $DATESTR 15 12) -> $DATE -- use the substring
(SUBSTR $DATESTR 28 8) -> $TIME -- function to get them
%
ERASESF XXTEMP_FILE
SEND PREVIOUS -- continue output to disk, exit and..
>>
>FILE D010CNTFL -- put the file out on disk
>READ XGET_DATE
>PRINT $TIME $DATE
18:02:30 19/AUG/1986
Neat-o, eh?
------------------------------------------------------------
DEBUG
All Known Formats : >DEBUG
Opposite Command : No opposite command
Associated Commands : Beats me
E.G. : >DEBUG
------------------------------------------------------------
DEBUG is an obnoxious little module that has no help and refuses to tell you what commands it recognizes. Even worse, it is not an increment, so once you're in DEBUG you're stuck with only DEBUG's commands (whatever they are) until you QUIT out of it.
Actually, I've never used DEBUG, so I don't have much to say about it. There is a document in DIS about it (DEBUG LISTING). Basically, it is a program to debug Protel modules on the switch. It lets you set breakpoints, trace through your program, display variables... all that nifty poop. If you think you might need or want it, print out the manual. Then you'll know more than me.
------------------------------------------------------------
DECSTRTONUM
All Known Formats : >DECSTRTONUM <string>
Opposite Command : NUMTODECSTR
Associated Commands : HEXTOSTR, NUMTODECSTR, NUMTOHEXSTR
E.G. : >PRINT (DECSTRTONUM '123')
123
------------------------------------------------------------
DECSTRTONUM takes a string containing an integer and converts it to an integer. Thus, in the example above, the string '123' was converted to the integer 123.
NUMTODECSTR goes the other way. That is, it takes an integer and converts it to a string. Like converting the integer 123 to the string '123'.
------------------------------------------------------------
DEMOUNT
All Known Formats : >DEMOUNT T##
Opposite Command : MOUNT
Associated Commands : LIST, TLIST, MOUNT, LOGUTIL
E.G. : >DEMOUNT T0
>DEMOUNT T10
------------------------------------------------------------
Used to demount a tape when you are done with it. For more info, see the discussion under MOUNT.
By the way, the DEMOUNT must be performed from the exact same user terminal where the MOUNT command was issued.
------------------------------------------------------------
DETACH
All Known Formats : >DETACH <directory-name>
Opposite Command : No opposite command
Associated Commands : ATTACH, DIRECTORY, LISTST
E.G. : >DETACH MY_DIR
------------------------------------------------------------
See also the discussions under the associated commands.
The DETACH command disconnects the indicated directory from your current symbol table. Note that the directory and all its contents still exists. It is just no longer visible when you do a LISTST. Also note that the entry still exists in the R/W directory wherein you created the directory; i.e., you still have a pointer to it, even though it is not attached. You can then later re-attach it. However, if you do a DETACH and then an ERASE on the directory name... guess what? Yep, all of the contents of the directory are destroyed forever. You can then re-attach it -- but it will of course be empty.
>DIRECTORY MY_DIR >ATTACH MY_DIR >COMMAND DOOZY (PRINT '** doozy **') -- created in MY_DIR >DETACH MY_DIR
The command DOOZY is temporarily unknown. However, if we then re-attach the directory, all of its contents can again be accessed.
------------------------------------------------------------
DIRECTORY
All Known Formats : >DIRECTORY <dir-name>
Opposite Command : No opposite command
Associated Commands : ATTACH, DETACH, LISTST, PRINT
E.G. : >DIRECTORY MY_DIR
>ATTACH MY_DIR
------------------------------------------------------------
>DIRECTORY MY_DIR >ATTACH MY_DIR >3 -> XYZ >'GOFORIT' -> ABC >PRINT MY_DIR XYZ Int Copy 3 ABC String Copy 'GOFORIT'
Thus the entries are created in the topmost read/write directory, and you can always access them with the (USERS.dir.dir.variable) format.
------------------------------------------------------------
DISKADM
All Known Formats : >DISKADM
Opposite Command : No opposite command
Associated Commands : FORMATDISK, DISPLAYDISK, CREATEVOL,
DELETEVOL, REINITVOL, DISPLAYVOLS,
See Also : DISKUT
E.G. : >DISKADM
------------------------------------------------------------
DISKADM is an increment which is mainly used to format and configure the SLM disk drives in a SuperNode switch. This is an extremely dangerous increment to be in if you're inexperienced.
Since this is so touchy, I'm not even going to explain it any further here. If you really need to know, look in NTP 297-1001-509. That's the only place I've seen it explained.
------------------------------------------------------------
DISKUT
All Known Formats : >DISKUT -- special disk utility
Opposite Command : No opposite command
Associated Commands : BACKUP, RESTORE, CLEARBOOTFL,
SETBOOTFL, LISTBOOTFL, CLEARVOL,
LISTVOLS, DELETEFL, LISTFL, RENAMEFL,
INSERTTAPE, EJECTTAPE
See Also : DISKADM
E.G. : >DISKUT;LISTVOLS S01D;QUIT
>DISKUT;LISTFL S01DIMAGE;QUIT
------------------------------------------------------------
DISKUT is similar to DSKUT, but it works only on SLM devices.
Like DSKUT, DISKUT is an increment. You enter the increment like this:
>DISKUT
and get out of it like this:
>QUIT
I don't want to spend a lot of time in this top-level section. The real fun is in the subcommands. So let's get to it. You'll see something new in there: abbreviations. This is the only place I know of on the switch where the commands have abbreviations that the switch recognizes. They're listed with each command.
Before you go in there, though, I want to give you a little glossary so you'll know what the parameters mean:
Oh, yeah... there's one more thing that makes this increment unique among all the commands on the DMS-100. It actually has good help. In fact, the help on the switch is actually better than any other documentation I've found for the increment. Make use of it. In fact, you might even want to print it out if you're going to be using DISKUT a lot. Use HELP <command> FULL. It gives you even more stuff.
Well, that's about it. Let the fun begin!!
------------------------------------------------------------
BACKUP
Abbreviation : BA
Format : BACKUP FILE <dev-vol> <filename> (<tape filename>)
or : BACKUP VOLUME <dev-vol> <backup volume name>
------------------------------------------------------------
This command allows you to back things up onto those cute little tape cartridges. You can back up individual files or entire volumes. The only trick is that both the disk volume and the tape have to be in the same SLM. So you can't back up volume S01DIMAGE onto tape S00T.
Also, notice that the tape filename in the first version of the command is optional. If you don't specify, the filename on the tape will be the same as the filename on the disk.
One final note: when you back up an entire volume, BACKUP puts all the files together into a single file. When you use restore, everything is unpacked back into individual files.
For example:
>BACKUP FILE S00DVOL1 MYFILE % copies myfile onto tape S00T >BACKUP VOLUME S00DVOL1 MYVOL % copies entire volume onto tape
In the SuperNode environment, backing things up is very important. People tend to erase things from the SLM disks pretty often, so once you get an image from loadbuild configured properly, be sure and back it up onto tape if you intend to use it again.
------------------------------------------------------------
RESTORE
Abbreviation : RE
Format : RESTORE FILE <dev-vol> <filename>
or : RESTORE VOLUME <dev-vol> <backup volume name>
------------------------------------------------------------
This command is the opposite of the BACKUP command. It allows you to pull files from tape onto the SLM. Again, the disk and the tape have to be on the same SLM.
Examples:
>RESTORE FILE S00DVOL1 MYFILE % copies myfile from tape S00T
% onto S00DVOL1
>RESTORE VOLUME S00DVOL1 MYVOL % copies entire volume MYVOL
% from tape onto the disk volume
% S00DVOL1
The only catch is that when you restore volumes, the destination volume has to be empty. Otherwise, RESTORE will refuse to restore.
------------------------------------------------------------
CLEARBOOTFL
Abbreviation : CBF
Format : CLEARBOOTFL <device> <boot table> ALL
ACTIVE
FILE <volume> <filename>
------------------------------------------------------------
Look familiar? Look a lot like CLEARBOOT? Well, there are some very important differences.
The fundamental thing to remember is that, since SuperNode is actually two computers, there are two active loads: the CM load and the MS load. CLEARBOOTFL clears these loads separately. This, of course, aids you greatly in screwing yourself on those late nights when it's crucial that you don't screw yourself.
Here are some examples:
>CLEARBOOTFL S00D CM ALL % clears all CM loads on S00D
>CLEARBOOTFL S00D MS ACTIVE % clears the active MS load
% on S00D
>CBF S01D CM FILE IMAGE SMC_29_RTM_CM % clears only the
% SMC_29_RTM_CM CM
% load on S01DIMAGE
See? No problem. Remember, though, that CLEARBOOTFL does not erase the file. It only removes the entry from the ITOC for that device. You have to use the DELETEFL command to erase it.
------------------------------------------------------------
SETBOOTFL
Abbreviation : SBF
Format : SETBOOTFL <dev-vol> <filename> <boot table>
<entry number> ACTIVE
REGULAR <-- default
Where <entry number> is the entry in the ITOC where the
file name and volume name is to be placed (1 to 15).
Where ACTIVE specifies that the file is to be the active
boot file.
Where REGULAR adds the file to the ITOC without making
it the active boot file.
------------------------------------------------------------
Not much to explain on this one. It just puts an entry in the ITOC for the file you specify. If you specify the ACTIVE option, the file you enter becomes the active boot file. REGULAR is the default, though.
Examples:
>SBF S01DIMAGE SMC_29_RTM_CM CM 1 ACTIVE % adds SMC_29_RTM_CM
% to the CM boot table
% for S01D and makes it
% the active boot file
>SBF S00DIMAGE MS_TEST_LOAD MS 5 % adds MS_TEST_LOAD to the MS
% boot table for S00D, but
% leaves the active boot file
% alone
------------------------------------------------------------
LISTBOOTFL
Abbreviation : LBF
Format : LISTBOOTFL <device> <boot table> ALL
ACTIVE <-- default
Where ACTIVE specifies that only the ACTIVE boot file for
the device is to be listed.
Where ALL specifies that the entire contents of the ITOC
be listed.
------------------------------------------------------------
As the name implies, LISTBOOTFL lists the contents of the ITOC for the given device and boot table. It's sort of analagous to the SHOWBOOT command in DSKUT.
Examples:
>LISTBOOTFL S01D CM ALL
Image Table Of Contents for CM on SLM, unit 1:
ITOC Volume File
Entry Name Name
Number
------ -------- -----------------
1 IMAGE MCI_29BN_CT_CM
2 IMAGE MSMC29BP_E250E_CM
>LISTBOOTFL S01D CM ACTIVE
Image Table Of Contents for CM on SLM, unit 1:
Active Boot File Device: DISK
Active Boot File Volume: IMAGE
Active Boot File File: MSMC29BP_E250E_CM
------------------------------------------------------------
CLEARVOL
Abbreviation : CVOL
Format : CLEARVOL <dev-vol>
------------------------------------------------------------
Yes, this command is just as dangerous as it sounds. It deletes every file from the volume you specify. There are two failsafes, though. It will ask for confirmation before actually doing it, and it will refuse to clear the volume if any of the files are registered in the ITOC.
Example:
>CVOL S01DIMAGE *** WARNING *** Clearing a volume will destroy all files stored on the volume. Do you want to clear volume S01DIMAGE (Yes/No)? >YES Volume S01DIMAGE has been cleared.
Whew!! Gives me the heebie-jeebies just thinking about it.
------------------------------------------------------------
Abbreviation : LV
Format : LISTVOLS <device> {FULL}
------------------------------------------------------------
This will give you extensive information about all the volumes on the SLM device you specify. If all you want to see is the names of the volumes available, PRINT ROOTDIR will give you that. LISTVOLS tells you all sorts of stuff about each volume. It'll tell you even more stuff if you use the FULL option. If you want the details, look in NTP 297-1001-509 for the complete poop.
Example:
>LISTVOLS S01D
Volume information for SLM disk 1
Volume Volume Modify Total No. of ITOC
Name Status Date No. of Open Files
Y/M/D Files Files
-------- --------- -------- ------ ------ -----
IMAGE OPENED 89/08/03 4 0 4
------------------------------------------------------------
DELETEFL
Abbreviation : DDF
Format : DELETEFL <dev-vol> <filename>
------------------------------------------------------------
Pretty self-explanatory, really. There are a couple of exceptions, though. If the file you're trying to delete appears in an ITOC, you have to CLEARBOOTFL it out before deleting it. The other exception is that you can't DELETEFL a file that's been marked as read-only or non-erasable.
Sorry, but I don't know anything about marking files as read-only or non-erasable. This is the first time I've seen it mentioned.
Example:
>DELETEFL S01DIMAGE MCI_29BP_CM
------------------------------------------------------------
LISTFL
Abbreviation : LF
Format : LISTFL <dev-vol> {FULL | BVOLS}
------------------------------------------------------------
This command allows you to list the files on a specified volume. In this case, volumes also include tapes. If you want to list all files on a tape, you use S01T or S00T as the <dev-vol>. Actually, you shouldn't do a LISTFL on a tape unless you have a lot of time to kill. It's extremely slow.
If you do have a lot of time to kill, and the tape has entire volumes backed up on it, you might want to use the BVOLS option. That will list all the individual files backed up from each volume.
Also, if regular LISTFL doesn't give you all the stuff you wanted to know, you can always use the FULL option to get more info.
Anyway, just like LISTVOL or LIST, LISTFL takes the filenames it finds and puts then in your symbol table, so you can READ them or COPY them or whatever.
Examples:
>LISTFL S01DIMAGE File information for volume S01DIMAGE. File File File In Name Org. Code ITOC -------------------------- ---- ---- ---- MSMC29BP_E250E_MS IMG 0 YES MSMC29BP_E250E_CM IMG 0 YES MCI_29BN_CT_MS IMG 0 YES MCI_29BN_CT_CM IMG 0 YES MYFILE OTH 0 YES
------------------------------------------------------------
RENAMEFL
Abbreviation : RNF
Format : RENAMEFL <dev-vol> <old filename> <new filename>
------------------------------------------------------------
Now here's a little command I wish DSKUT had. It does exactly what it sounds like it does... changes the name of an existing file. Of course, if the file is registered as a boot file in an ITOC, you can't rename it.
Example:
>RENAMEFL S01DWORK MYFILE YOURFILE % renames MYFILE to YOURFILE
------------------------------------------------------------
INSERTTAPE
Abbreviation : IT
WRITELABEL <label name> RET <-- default
Format : INSERTTAPE <device> CHECKLABEL <label name> NORET
READLABEL <-- default
Where <label name> is up to six characters long.
------------------------------------------------------------
This is the equivalent of doing a MOUNT for a tape cartridge. Each tape cartridge has a label name of up to six characters.
READLABEL is the default. It looks for the label name and tells you what it finds. If there is no label, this is a good indication that the tape has not been written to.
If you choose the WRITELABEL option, all existing files on the tape are destroyed.
CHECKLABEL could come in handy if you forget to label the outside of the tape. If the label on the tape doesn't match the one you said to check for, the INSERTTAPE command is aborted. That way, you don't have to do an EJECTTAPE afterwards.
One more thing. When you do an INSERTTAPE, the tape will automatically be retensioned for you. If you don't want this to be done, you can use the NORET option. I'll probably get in trouble for this, but I highly recommend the NORET option. The tape is retensioned every time you do an EJECTTAPE anyway, and I think doing it on an INSERTTAPE is overkill. Just my opinion.
------------------------------------------------------------
EJECTTAPE
Abbreviation : ET
Format : EJECTTAPE <device> WAIT <-- default NOWAIT
------------------------------------------------------------
This command is analogous to a DEMOUNT for a cartridge tape. It's rather deceptively named, though, because the tape doesn't actually pop out of the slot when it's done. You have to pull it out by hand.
Do yourself a favor and use the NOWAIT option. Otherwise, you'll end up sitting there for about five minutes waiting for the tape to retension. If you use NOWAIT, it'll still retension, but you don't have to wait for it.
Example:
>EJECTTAPE S01T NOWAIT % demounts the side 1 tape cartridge.
------------------------------------------------------------
DSKALLOC
All Known Formats : >DSKALLOC <unit number>
Opposite Command : No opposite command
Associated Commands : DISPLAY, ADD, REINIT, DELETE, DIRADD,
DIRDEL, UPDATE, QUIT
See Also : DSKUT
E.G. : >DSKALLOC 1
------------------------------------------------------------
DSKALLOC is CI increment which is used mainly to partition and format the hard disk on the switch. As such, it is very dangerous in the hands of the inexperienced.
In order to use DSKALLOC on a drive, the drive must be manual-busy. To accomplish this, use MAPCI as follows:
>MAPCI;MTC;IOD;IOC 0;CARD 1;BSY
This, of course, depends on the actual IOC and CARD number where your particular disk drive resides.
The associated commands listed above are the commands available in the DSKALLOC increment. I'm not going to discuss DSKALLOC any further here. If you really think you're ever going to use it, print out NTP 297-1001-526.
------------------------------------------------------------
DSKUT
All Known Formats : >DSKUT -- special disk utility
Opposite Command : No opposite command
Associated Commands : LISTVOL, SHOWVOL, SHOWFL, RENAMEFL,
ERASEFL, SETBOOT, SHOWBOOT,
CLEARBOOT, QUIT
And : ROOTDIR
Also See : DSKALLOC
E.G. : >DSKUT;LISTVOL D010CNTFL ALL;QUIT
>DSKUT;SHOWVOL D010CNTFL
------------------------------------------------------------
>PRINT ROOTDIR -- One of the fastest ways to see what all
-- volumes have been allocated to your disk drive.
DSKUT is a CI increment (sort of like LOGUTIL) that gives you some ability to see what all files are on your disk volumes. It also allows you to create and destroy not only your own files, but files from other people. And you can also create disk files with duplicate names, etc.
Naturally, there were plans to revise and update the system. However, there just hasn't been time. So, we must learn to live with it. Now, this section is rather lengthy (especially since I kept referring you here from various other commands), so you might want to take a break before digging in.
>DSKUT -- this puts you in the disk utility sub-system >QUIT -- gets you out
Actually, it is difficult to find out what all is allocated with this sub-system, so we use two tricks:
>PRINT ROOTDIR
This, of course, prints out all of the devices and should give you a list of the disk volumes which have been allocated.
The second trick to getting the volumes is to do this:
>MAPCI NODISP;MTC;IOD;IOC 0;CARD 1;ALLOC or >MAPCI ;MTC;IOD;IOC 0;CARD 1;ALLOC
Not only does this give you the list of the volumes, but whether or not any user has any files open on them. In fact, this is the routine you have to use to re-allocate the volumes (see the discussion under DSKALLOC).
Next on our grand tour are the more "normal" things that we all want to do with a disk (or do to it as the case may be):
>DSKUT;LISTVOL D010CTS ALL UNI14_5LOOPS SBS15_5LOOPS STD_PROF >QUIT
Now, as we know from the LISTST and LISTSF commands, the LISTVOL command makes the various files known to our symbol table. That is, there may well be a file called "SIDE_0" over on the disk under the volume D010MAINT, but unless we do a LISTVOL D010MAINT ALL, we will never know it. So, LISTVOL makes a copy of the file's location in our directory. This means that we can access it as if it were in SFDEV.
>READ STD_PROF -- execute the file directly from disk. >COPY STD_PROF SFDEV -- copy the file to SFDEV (temp storage)
The main difference between DISK files and SFDEV is this:
SFDEV files: Remain on the user memory as long as we do not un-permit the user or reboot.
DISK files: Should be fairly robust, but you should always back them up on tape if you want to keep them. Better yet, move copies up to the IBM. Better yet even, do both.
Once we are in DSKUT, we can do a help and use the various commands:
>DSKUT DSKUT: >HELP DSKUT
From here on out, I'll discuss the various commands available in DSKUT (listed in the header as associated commands).
------------------------------------------------------------ LISTVOL Format : >LISTVOL <device> ALL | <username> ------------------------------------------------------------
LISTVOL lists all files on the given volume which belong to the given user. If no username is given, the default is yourself. LISTVOL also puts pointers in your directory to the files it lists, so that you can do things with those files.
Say, for instance, that you sat down at OPERATOR one day, edited a file, and filed it on D010CNTFL. The next day, you went back to OPERATOR and tried to PRINT the file:
>DSKUT DSKUT: >PRINT MYFILE File not found >LISTVOL D010CNTFL -- Lists all files on D010CNTFL MYFILE -- that OPERATOR created. >PRINT MYFILE -- it's found this time ....
You would have to do the LISTVOL before MYFILE could be found and printed.
Now, let's have some fun.
>DSKUT
>LISTVOL D010CNTFL ALL -- all files on D010CNTFL
>LISTVOL D010CNTFL BETA -- all files on D010CNTFL that
-- BETA created
>LISTVOL D010CNTFL -- all files on D010CNTFL that you created
------------------------------------------------------------ SHOWVOL Format : >SHOWVOL <volume> ALL ------------------------------------------------------------
SHOWVOL shows you some information on the disk. ALL is an optional parameter which will give you additional information that you probably don't need. SHOWVOL without ALL will show you the volume size (in blocks), the number of files on the volume, and the amount of free space remaining on the volume (also in blocks). For example:
>SHOWVOL D010IMAGE -- basic information or >SHOWVOL D010IMAGE ALL -- more detailed information
------------------------------------------------------------ SHOWFL Format : >SHOWFL <filename> ALL ------------------------------------------------------------
SHOWFL gives information about the specified file. ALL is an optional parameter to give you some more information that you probably don't need.
Entering SHOWFL <filename> will tell you the number of records in the file, the date and time it was last modified, and format (fixed or variable length) and length of the records. For example:
>SHOWFL MYFILE -- for information on MYFILE or >SHOWFL MYFILE ALL -- for more information
------------------------------------------------------------ RENAMEFL Format : >RENAMEFL <volume> <old file name> <new file name> ------------------------------------------------------------
Note: When you do HELP DISKUT, this command will be listed. However, it applies to the SLM and, thus, is only available on SuperNode. Personally, I have never had occasion to use this command, so if you need more information on it look at the NTP document 297-1001-509.
------------------------------------------------------------ ERASEFL Format : >ERASEFL <file name> ------------------------------------------------------------
Erases a file. (Self-explanatory, really).
Actually, there is a quirk. If the same file name occurs on more than one volume, the volume you LISTVOL'd last is the one the file is deleted from.
------------------------------------------------------------ SETBOOT Format : >SETBOOT <boot file name> ------------------------------------------------------------
On any NT40 switch, there is an image volume which contains one or more bootable software loads. SETBOOT allows the user to specify which image is to be loaded when the switch is booted from that volume.
For example, let's say you had a volume D000IMAGE on a switch which contained two loads: one for Sprint (USS29BC) and one for MCI (MCI29BC). If you wanted to boot the MCI load, you would do the following:
>DSKUT DSKUT: >LISTVOL D000IMAGE ALL MCI29BC USS29BC >SETBOOT MCI29BC
The next time you boot from the side 0 disk, MCI27BC will be loaded.
------------------------------------------------------------ SHOWBOOT Format : >SHOWBOOT <volume> ------------------------------------------------------------
SHOWBOOT tells you which is the active image on the specified disk volume. For example, if you did a SHOWBOOT after the SETBOOT above, SHOWBOOT would tell you that MCI29BC is the active image.
------------------------------------------------------------ CLEARBOOT Format : >CLEARBOOT <volume> ------------------------------------------------------------
CLEARBOOT clears the current boot file indicator for the volume specified. For example, if you did a CLEARBOOT after the SETBOOT above, D000IMAGE would still contain both boot files, but neither would be current. Consequently, if you tried to boot the switch from the side 0 disk, you would get an error.
------------------------------------------------------------
DUMP
All Known Formats :
| MATE | UPDATE {SILENT}
>DUMP <filename> <volume> | ACTIVE | RETAIN {TERSE}
| DEBUG | {VERBOSE}
| UNSAFE |
Opposite Command : No opposite command
Associated Commands : RESTART, SHOWBOOT, SHOWBOOT
E.G. : >DUMP MCI29BJ D010IMAGE ACTIVE UPDATE
>DUMP USS29BJ D010IMAGE MATE RETAIN
>DUMP TRES29BJ T0 ACTIVE UPDATE -- dump to tape
------------------------------------------------------------
The dump command is used to "take an image". This means copying the contents of all used memory to disk or tape so that you can reload the switch at a later time and start where you left off. Actually, the above are not all the known formats of the DUMP command. As important as this command is, the only place I've found reference to it is NTP Supplement 297-1001-509.
The filename and device are pretty much self-explanatory.
Of the four options of the next parameter, I am only going to discuss the first two. If you want to know anything about DEBUG or UNSAFE, you'll have to look in NTP 297-1001-509 or find someone else who knows.
MATE and ACTIVE simply refer to which side of the switch you want to dump in an unsplit switch. Since most of the labs are split, you will probably use ACTIVE most of the time. However, if you were on an unsplit switch, you could use MATE to dump the side of the switch that is inactive.
If you choose the UPDATE option, the image you just took will be rebooted whenever anyone boots from the device you just DUMPed to. If you choose the RETAIN option, the image which was active remains active.
One more little hint: when you dump to tape, always make the dump UPDATE. Otherwise, you won't be able to boot with the tape.
Addendum for SuperNode
SuperNode's DUMP has one more option tagged onto the end. The SCOPE option. Since SuperNode has more than one CPU, there is a SCOPE option so you can dump whichever image you want. The options are rather lengthy, and I don't know what a lot of them do, but if you do a:
>Q DUMP
on your nearest SuperNode, it'll give you the full story. The options I do understand are:
CM -- dumps the CM load (ACTIVE or MATE from above)
MS {0|1} -- dumps the MS load
TOTAL -- default... dumps CM and MS
If you use the TOTAL option, the dump will use the filename you specified and tag on "_CM" for the CM load and "_MS" for the MS load, so you'll end up with two files.
When you do a DUMP on a SuperNode, it's automatically recorded in the ITOC.
------------------------------------------------------------
ELSE (See the discussion under IF)
E.G. : IF (X=3) THEN (
PRINT '--- Ah-ha, X is three.'
) ELSE (PRINT '--- Well, X is certainly not 3.')
------------------------------------------------------------
------------------------------------------------------------
ERASE
All Known Formats : >ERASE <symbol>
>ERASE <command>
Opposite Command : No opposite command
Associated Commands : ERASESF, ERASEFL (DSKUT), EDIT,
COMMAND (used to create new ones), etc
E.G. : >COMMAND REM () -- dummy command like %
>ERASE REM -- Zappo... it's gone
------------------------------------------------------------
This command is mainly used to erase an existing command. That is so that we can redefine it. Note that a new definition does not override the older one. You have to ERASE a command to redefine it.
------------------------------------------------------------ ERASEFL All Known Formats : >ERASEFL <filename> ------------------------------------------------------------
See discussion under DSKUT.
------------------------------------------------------------
ERASESF
All Known Formats : >ERASESF <filename>
Opposite Command : No opposite command
Associated Commands : LISTSF, ERASE
E.G. : >ERASESF MYFILE -- deletes it from SFDEV
------------------------------------------------------------
ERASESF erases a file from the user's RAM work area SFDEV. In order to erase a file, you must do a LISTSF to get an entry for that file in your user directory.
------------------------------------------------------------
EXECUTE
All Known Formats : >EXECUTE <filename>
Opposite Command : No opposite command
Associated Commands : READ
E.G. : >EXECUTE MYFILE
------------------------------------------------------------
This command is thoroughly nifty. It's basically like the read command, except with error checking. It will load your SOS exec up and execute it, but it will abort execution if one of the commands gives a bad return code.
If you want the full information, there is a short DIS document about EXECUTE named "W190" (really descriptive). It'll tell you all you need to know.
------------------------------------------------------------
FAILMESSAGE
All Known Formats : >FAILMESSAGE <type>
Where type is one of:
{SHORT, LONG, ALL, SAVE, PREVIOUS}
Opposite Command : No opposite command
Associated Commands : None
E.G. : >FAILMESSAGE SAVE
>FAILMESSAGE PREVIOUS
------------------------------------------------------------
FAILMESSAGE determines the amount of information to be given when a command fails. It is usually set to LONG, which gives you the error message and the command which was attempted:
>LISTSF ALL BLABLA Either incorrect parameter or wrong number of parameters LISTSF -- Wrong number of parameters
SHORT gives you the error text, but not the attempted command, and ALL gives you the route to the failed command in addition to all information given with LONG. SAVE saves the current setting (to be reinstated with PREVIOUS) and sets FAILMESSAGE to LONG.
I've just given you all the information in NTP 297-1001-509, so if you want to know more, play with it.
------------------------------------------------------------
HEXTOSTR
All Known Formats : >HEXTOSTR #nn
Where 'nn' is any hexadecimal number
Opposite Command : No opposite command
Associated Commands : NUMTODECSTR, SYMTOSTR, STRTOSYM,
DECSTRTONUM
E.G. : >PRINT (HEXTOSTR #61)
a
------------------------------------------------------------
HEXTOSTR is one of many data conversion commands provided to allow the user (that's you) to convert data from one form to another. Unfortunately, there is no facility for converting string data directly to hex.
Always remember to put the "#" in front of the number. If you don't, you get some really strange results.
------------------------------------------------------------
HT
All Known Formats : >HT
Opposite Command : RT
Associated Commands : RT, HXX, HX
E.G. : ><BREAK>
?HT
------------------------------------------------------------
HT is used in the same way as it is used in VM/CMS. If you do something that generates a lot of output (like LISTVOL D010CNTFL ALL) and you don't want to see all the output, just do a <BREAK> HT. It's like doing a SEND SINK in the middle of the command. When the command finishes, you will get a command prompt and everything will be back to normal.
The inverse of HT is RT. If you decide that you want to see how far along the command is after you've done an HT, you can do a <BREAK> RT and the output will resume.
------------------------------------------------------------
HX
All Known Formats : >HX
Opposite Command : No opposite command
Associated Commands : HXX, HT, RT
E.G. : ><BREAK>
?HX
User process stopped.
------------------------------------------------------------
HX is used in the same way as it is used in VM/CMS. If you get yourself in trouble (like an infinite loop in a SOS exec), you can do a <BREAK> HX to get yourself out of it. It stops your user process and resets it, so that you end up back at a CI prompt.
------------------------------------------------------------
HXX
All Known Formats : >HXX
Opposite Command : No opposite command
Associated Commands : HX, HT, RT
E.G. : ><BREAK>
?HXX
User process stopped.
------------------------------------------------------------
As far as I can tell, this does the same thing as HX.
------------------------------------------------------------
IF
All Known Formats : >IF (expr) THEN (cmds) {ELSE (cmds)}
Opposite Command : No opposite command
Associated Commands : UNTIL, WHEN
E.G. : >IF (A=1) THEN (DATE;LOGOUT) ELSE (PRINT 'Howdy)
------------------------------------------------------------
IF is discussed much more in depth in the "SOS Exec" section. Briefly, IF works much the same as in any programming language. The expression in parentheses is evaluated and, based on the outcome, either the THEN or the ELSE command lists are executed.
The SOS IF command supports compound expressions, expressions ANDed and ORed together. Each expression is in the form <comparand> <comparator> <comparand>.
The comparands can be variables (A), functions (SYMTOSTR @1), or literal values (1, 'ON').
Logical expressions can be combined with relational operators to form compound expressions.
Now, for some examples:
>1->A >IF (A=1) THEN (PRINT 'then') -- the ELSE is optional then >IF (A>1) THEN (PRINT 'then') ELSE (PRINT 'else') else >COMMAND DOIT (IF ((SYMTOSTR @1)='THEN') -- using a > THEN (PRINT 'then' -- function call > ) ELSE (PRINT 'else')) >DOIT THEN then >DOIT BLABLA else >COMMAND DOIT2 (IF ((RINDEX=0) | (LINDEX>0)) -- complex > THEN (PRINT DOIT2_HELPF -- expression > )ELSE(READ DOIT2_EXEC)) -- using or
------------------------------------------------------------ LEAVE All Known Formats : >LEAVE Opposite Command : No opposite command Associated Commands : QUIT ------------------------------------------------------------
LEAVE is the same as QUIT. See QUIT.
------------------------------------------------------------
LINDEX
All Known Formats : >IF (LINDEX=0) THEN ...
Opposite Command : RINDEX
Associated Commands : RINDEX
E.G. : >IF (LINDEX = 1) THEN (PRINT 'Help information')
------------------------------------------------------------
No, this is not a cheap substitute for the leading window cleaner. LINDEX stands for Left Index. It tells you how many parms there are to the left of the command. It always applies to commands. Its main use seems to be for the help facility;
>COMMAND BERLIOZ (IF (LINDEX=1) THEN (PRINT BERLIOZ_HELPF > )ELSE(READ XBERLIOZ_XEC) )
That way if the user enters >HELP BERLIOZ, they will see the file BERLIOZ_HELPF. Otherwise, the file "XBERLIOZ_XEC" is run.
Some fancy things can be done with it.
------------------------------------------------------------
LIST
All Known Formats : >LIST <tape drive designator>
Opposite Command : No opposite command
Associated Commands : MOUNT, DEMOUNT, TLIST
E.G. : >MOUNT 0 -- mount the tape on drive 0
>LIST T0 -- list all the files on the tape
------------------------------------------------------------
LIST is an older form of TLIST. It is used to read record-by-record the entire tape, so as to give a list of the files on that tape. See also the discussion under the TLIST command.
LIST is very important since it does not require that the first file on the tape be the special "TAPE$DIR" file (as does TLIST). Further, LIST will allow you to copy the files from the tape directly to disk. Here is the recipe:
See the discussion under MOUNT for how to create the tape shown here.
>MOUNT 0 >LIST T0 MY_FILE MY_DATA_INFO SEND_HELPF >COPY MY_FILE D010TEST2 -- copy the files to disk >COPY MY_DATA_INFO D010TEST2 >COPY SEND_HELPF D010TEST2 >DEMOUNT T0
Now we notice that the first file on the tape is not the good old TAPE$DIR (which is what is created on the IBM with XDMSTAPE exec). When we use the TLIST, we can only move the files to SFDEV (not to a disk volume like D010TEST2, etc).
------------------------------------------------------------
LISTSF
All Known Formats : >LISTSF {ALL | username}
Opposite Command : No opposite command
Associated Commands : ERASESF
E.G. : >LISTSF ALL
>LISTSF OPERATOR
------------------------------------------------------------
LISTSF lists all files on SFDEV owned by the given user (default is you). If ALL is specified, it lists all files on SFDEV owned by any user.
Like LISTVOL, LISTSF makes an entry for each file in your read-write directory. Also like LISTVOL, if there is more than one file listed with the same name, the current entry in your directory will be the last one listed. Et tu, LISTSF?
------------------------------------------------------------
LISTST
All Known Formats : >LISTST
Opposite Command : No opposite command
Associated Commands : PRINT, DIRECTORY, ATTACH, DETACH
E.G. : >LISTST
------------------------------------------------------------
LISTST shows you all the directories current available to you in the order they will be searched.
The PRINT command will list the contents of any of those directories. The notable exception to this is when you autologin (like when you login at MAP4 with the username MAP4). Then, when you do a LISTST, one of your directories will be MAP4. But when you try to PRINT that directory, the switch will respond "device". In order to get the contents of the directory, you have to fully qualify it:
>PRINT (USERS.MAP4)
------------------------------------------------------------
LISTVOL
All Known Formats : >LISTVOL <volume> {ALL | username}
Opposite Command : No opposite command
Associated Commands : DSKUT, SHOWVOL, LISTSF
E.G. : >LISTVOL D010CNTFL -- all your files
>LISTVOL D010TEST2 OPERATOR -- all the operator's files
------------------------------------------------------------
See discussion under DSKUT.
------------------------------------------------------------ LOAD All Known Formats : >many and varied Opposite Command : UNLOAD Associated Commands : See the DIS document OSA10 LISTING ------------------------------------------------------------
LOAD is a command not for the faint of heart. If you don't know what it is, you probably don't need it. If you know what it is and need to know more about it, look at the DIS document "OSA10 LISTING".
------------------------------------------------------------
LOGIN
All Known Formats :
At a Terminal : ?LOGIN
Detached : >LOGIN <username> <password> <profile> <device>
Opposite Command : LOGOUT
Associated Commands : PERMIT, UNPERMIT
E.G. : <BREAK> -- hit the break key
?LOGIN
Enter user name and password:
>BETA BETA
User logged in on MAP4 at 3:30PM Aug-3-89
CI:
> -- ready for action
------------------------------------------------------------
Before you can log in, user name and password must be permitted. The usual protocol is to have the password the same as the name; e.g., "BETA" user name and "BETA" password.
At a MAP that is already logged in (say the OPERATOR terminal):
>PERMIT BRAND BRAND 3 8000 ALL (See the permit command)
Login at a Terminal
Go to an unused terminal and enter:
<BREAK> -- hit the break key ?LOGIN Enter user name and password: >BRAND BRAND User logged in on MAP4 at 3:30PM Aug-3-89 >
Detached User Login
The detached users are much like the disconnected users on the IBM. They don't have a terminal. The point of having a detached user is so you can get something done in the background while you do other things at your terminal.
The recipe for logging in a detached user is the following:
At a terminal you've logged in to, enter
>PERMIT DETUSER DETUSER 2 8000 ALL
At this point, I have created a logon user name and password called "DETUSER". There is nothing magic about the name. It can be "ZAPPA" or "BOZO" or anything you want.
Now I'm going to create a profile for the detached user to run.
>EDIT TPROF -- edit a profile EDIT: >INPUT MSG ALL "--- Hi! I''m a detached user.' LISTSF ALL MAPCI;MTC;IOD;IOC 0;CARD 0 RTS CARD 1 RTS QUIT ALL MSG ALL '--- The tape & disk drives are now inservice.' >> >FILE SFDEV
Now, I will stream the detached user "DETUSER" with an initial logon profile of TPROF (which I must be able to access... but since I just created it, I certainly can access it).
>LOGIN DETUSER DETUSER TPROF SFDEV
I have never tried using any device other than SFDEV.
Now, after a few moments (depending on how the switch is running), we would get a message on every logged on console:
MSG FROM DETUSER --- hi! i'm a detached user MSG FROM DETUSER --- the tape & disk drives are now inservice
Of course, promptly after that the user dies, since we didn't give him much to do. But you can see the potential.
------------------------------------------------------------
LOGOUT
All Known Formats : >LOGOUT
Opposite Command : LOGIN
Associated Commands : PERMIT, UNPERMIT, FORCEOUT
E.G. : >LOGOUT
User logged out on MAP4 at 3:31PM Aug-3-89
------------------------------------------------------------
The LOGOUT command terminates your session. When you log out, the files that you have saved on disk or in SFDEV are still there. However, the variables, commands, and directories you have created will disappear.
------------------------------------------------------------
LOGUTIL
All Known Formats : >LOGUTIL
Opposite Command : No opposite command
Associated Commands : SUPPRESS, RESUME, THRESHOLD,
STARTDEV, STOPDEV
------------------------------------------------------------
LOGUTIL is an increment which enables several commands related to the log system. The commands listed as associated commands are just a few of the commands LOGUTIL recognizes.
If you want to do any really fancy stuff with logs, you need to look in DIS under the heading "LOG SYSTEM" to find the document most suited to your purposes.
For now, here are a few quickies:
>LOGUTIL -- go into the increment >STARTDEV 1PRT0 -- to start logs to a device >STOPDEV 1PRT0 -- to stop logs going to a device
To set all the logs on, you go through MAPCI:
>MAPCI;MTC;IOC;CDR;SETLOG ALL >QUIT ALL
To suppress all logs of a particular type:
>SUPPRESS PM -- dangerous since you might lose important info >SUPPRESS PM 108 -- still dangerous
Better to just set them at a threshold (e.g., print only every 20th report of this type):
>THRESHOLD 20 PM 14 reports thresholded >RESUME PM -- to "un-threshold" reports
------------------------------------------------------------
MOUNT
All Known Formats : >MOUNT 0 -- to read
>MOUNT 0 FORMAT 'mytape' -- to write
Opposite Command : DEMOUNT
Associated Commands : LIST, TLIST, COPY
E.G. : >MOUNT 0
>TLIST T0
>READ BUILD$LOAD
------------------------------------------------------------
MOUNT makes the switch recognize a tape you have mounted on a tape drive. The following is an example of how to copy files from tape to disk.
>MOUNT 0 >LIST T0 MY_FILE MY_DATA_INFO SEND_HELPF >COPY MY_FILE D010TEST2 -- copy the files to disk >COPY MY_DATA_INFO D010TEST2 >COPY SEND_HELPF D010TEST2 >DEMOUNT T0
Now, let's copy files from disk to tape.
>ERASETAPE 0 >MOUNT 0 >LIST T0 >COPY MY_FILE T0 -- copy the files to tape >COPY MY_DATA_INFO T0 >COPY SEND_HELPF T0 >DEMOUNT T0
By the way, the TLIST command is similar to the LIST command. However, TLIST does not allow you to copy files from tape directly to disk. (To SFDEV only.) That's why I usually use the LIST command.
------------------------------------------------------------
MSG
All Known Formats : >MSG <user | ALL> '<message>'
Opposite Command : No opposite command
Associated Commands : None
E.G. : >MSG OPERATOR 'Please demount your tape.'
Message sent to 1 user(s).
>MSG ALL 'Cold restart in 1 minute. Anybody object???'
Message sent to 12 user(s).
Message from MAP4 Yes. I am in the middle of a DMOPRO
>MSG MAP4 'How long do you think it''ll be?'
Message from MAP4 About another 10 mins.
>MSG MAP4 'OK. Tell me when you''re done.'
Message from MAP4 Ok.
------------------------------------------------------------
Enough said? Well, not quite. If the other user is a detached user, we can use the MSG command to tell us that certain tasks have been completed. (See the example under LOGIN).
------------------------------------------------------------
NOPROFILE
All Known Formats : >NOPROFILE -- must be the first thing
-- typed after login
Opposite Command : No opposite command
Associated Commands : LOGIN, PROFILE
E.G. : <BREAK>
?LOGIN
Enter user name and password:
>BETA BETA
CI:
>NOPROFILE <-- will override a login profile
>
------------------------------------------------------------
This is used to override a login profile that has been set up for the user name. It must be typed immediately after the login process is completed. Otherwise, you will execute the login profile (if there has been one assigned). Sometimes a good thing, other times dangerous. Depends on what the profile is supposed to do for you. Some profiles save your life. Others are just plain dumb.
------------------------------------------------------------
NUMTODECSTR
All Known Formats : >NUMTODECSTR <integer>
Opposite Command : DECSTRTONUM
Associated Commands : HEXTOSTR, NUMTOHEXSTR
E.G. : >PRINT (NUMTODECSTR 25)
25
------------------------------------------------------------
NUMTODECSTR is one of many data conversion commands provided to allow the user (that's you) to convert data from one form to another. NUMTODECSTR takes an integer and converts it to a string. Thus, in the example above, the integer 25 was converted to the string '25'.
DECSTRTONUM goes the other way. That is, it takes a string and converts it to an integer. Like converting the string '25' to the integer 25.
------------------------------------------------------------
NUMTOHEXSTR
All Known Formats : >NUMTOHEXSTR <integer>
Opposite Command : No opposite command
Associated Commands : HEXTOSTR, NUMTODECSTR, DECSTRTONUM
E.G. : >PRINT (NUMTOHEXSTR 123)
007B
------------------------------------------------------------
Like its brothers (listed above), NUMTOHEXSTR does data conversion. It takes an integer and converts it to a 4-digit hexadecimal number in string form. Confused? What I mean is, in the above example, the integer 123 is converted to the string '007B'. The result is a string, not an integer.
Unfortunately, there is no command opposite to NUMTOHEXSTR.
------------------------------------------------------------
PAR
All Known Formats : >PAR <integer>
Opposite Command : No opposite command
Associated Commands : COMMAND
E.G. : >PAR 1
------------------------------------------------------------
The PAR command (more easily recognized as "@") is the facility for passing parameters to user-defined commands. Allow me to illustrate:
>COMMAND DOIT (PRINT PAR 1) >'HOWDY' -> A >DOIT A HOWDY
The reason for the two different formats ("PAR" versus "@") is illustrated in the PAR functions section.
------------------------------------------------------------
PARNAME
All Known Formats : >PARNAME <symbol>
Opposite Command : No opposite command
Associated Commands : PARTYPE, SYMTOSTR
E.G. : >PARNAME @1
------------------------------------------------------------
This command is similar to the SYMTOSTR command in that it converts a symbol into a character string. The difference is that SYMTOSTR gives you the string representation of the contents of the variable. PARNAME gives you the string representation of the variable name.
Take, for example, this set of commands and responses:
>COMMAND DOIT (PRINT (PARNAME @1)) >DOIT HOWDY HOWDY >DOIT D010CNTFL D010CNTFL
To illustrate the difference between PARNAME and SYMTOSTR, look at this:
>(3+4)->A >PRINT (SYMTOSTR A) 7 >PRINT (PARNAME A) A
As you can see, this is a pretty useful command. The strange thing is that it doesn't appear in any of the documents I've found. It's not in NTP 297-1001-509 or NTP Supplement 297-1001-509, anyway. I got it out of an eight year old document in DIS called "OSLD2". Good stuff, though.
------------------------------------------------------------
PARTYPE
All Known Formats : >PARTYPE <symbol>
Opposite Command : No opposite command
Associated Commands : PARNAME
E.G. : >PARTYPE VAR1
------------------------------------------------------------
This function returns an integer which indicates the type of the parameter passed in. The types and their corresponding values come from the module CITYPES and are as follows:
Type Value Returned
null 0
integer 1
unsigned integer 2
double integer 3
unsigned double integer 4
boolean 5
string 6
file 7
directory 8
program 9
increment 10
cibincom 11
interp command(?) 12
list command 13
non-res command 14
device 15
pointer 16
non-res increment 17
long word 18
This could be really useful for making sure parameters are of the correct type. For example:
>COMMAND DOIT (IF ((PARTYPE @1) ^= 1) THEN ( >PRINT 'Sorry. Only integers allowed.' >) ELSE ( >PRINT (3 + @1)))
Important point:
If the parameter you pass to PARTYPE doesn't exist (i.e. should return 0), PARTYPE will blow up. That means that control structure you're in (IF, WHILE, etc.) will also blow up. This makes PARTYPE rather hazardous to the robustness of your exec. Below is an example of how to get around this problem in a simple IF statement:
FALSE->CHECK IF ((PARTYPE SCMSTOSOS) = 13) THEN (TRUE->CHECK;QUIT) PRINT ' ' IF (^CHECK) THEN (PRINT 'You are not in NCMS.')
Notice that there is no ELSE to the IF in the second line of this exec. Normally, you would expect this segment to be written like this:
IF ((PARTYPE SCMSTOSOS) = 0) THEN (PRINT 'You are not in NCMS.')
But, if the statement were written this way, PARTYPE would blow up the IF command before the THEN was ever reached. Thus, the problem. Just keep it in mind.
------------------------------------------------------------
PERMIT
All Known Formats : >PERMIT <username> <password> {priority} {stksize} {language} {cmdclass}
Opposite Command : UNPERMIT
Associated Commands : LOGIN
E.G. : >PERMIT BETA BETA 4 8000 ENGLISH ALL
>PERMIT ALPHA ALPHA ENGLISH ALL
------------------------------------------------------------
PERMIT allows you to add to the list of authorized users on the switch. The custom is to make the username and password the same. (That makes it easier to guess your way in.)
Priority values range from 1 to 4 with 4 being the highest. 4 is also the default.
Stacksize values range from 1,500 to 10,000. The default is 5,000.
Language can be either ENGLISH or FRENCH.
Command Class determines which commands are available to the user. I've always used ALL.
Remember that both real users and detached users have to be permitted.
------------------------------------------------------------
PRINT
All Known Formats : >PRINT {HEX | DEC} <item>
Where 'item' is one of:
expression, integer, string, symbol,
filename, directory, booleans
Opposite Command : No opposite command
Associated Commands : LISTST, LISTSF, LISTVOL, LIST
------------------------------------------------------------
Oh, goody!! Now, this is a really neat command. You can do all sorts of nifty things with it. For one thing, you can PRINT just about anything you can think of, and you can even get the hexadecimal value of it.
The best way I can think of to show you the true niftiness of this command is to do some examples. So here goes!!
>DIRECTORY MYDIR
>ATTACH MYDIR
>1->A
>PRINT MYDIR -- example of printing a directory
A Int Copy 1
>PRINT A -- example of printing a symbol
1
>PRINT HEX A -- example of printing a hex value
#0001
>'abc'->ABC
>PRINT ABC
abc
>PRINT HEX ABC -- example of printing the hex
#616263 -- value of a string
>LISTST -- you've seen this one before
MYDIR CE01,8071 RW
MAP4 CE01,C047 RW
PROGDIR CE01,C004 RO
SYSDIR CE01,2002 RO
ROOTDIR CE01,4001 RO
STDIRS CE01,A01E RO
>PRINT MAP4 -- Oops... this is a directory, but
device -- PRINT evaluates it first as a device.
>PRINT (USERS.MAP4) -- there... we fully qualified it
B Int Copy 1
>PRINT ((4*4)+(6/3)) -- yes, CI does support mathematical
18 -- expressions, including parentheses
-- and +, -, *, /
>1->A;2->B
>PRINT (A+B) -- it even works with variables
3
>TRUE->BOOLVAR -- boolean variables, too
>PRINT BOOLVAR
TRUE
>FALSE->BOOLVAR
>PRINT BOOLVAR
FALSE
>PRINT HEX (A+B) -- and will even return hex values
#0003
>EDIT MYFILE -- input a file to print
EDIT:
>INPUT
INPUT:
>First line
>Second line
>Third line
>>
EDIT:
>FILE SFDEV
CI:
>LISTSF -- have to do this so PRINT can find MYFILE
MYFILE
>PRINT MYFILE -- PRINT that puppy
First line
Second line
Third line
There now... wasn't that fun?
------------------------------------------------------------
PROFILE
All Known Formats : | LOGIN | <filename> |
>PROFILE | AUTO | |
| RESTART | CLEAR |
Opposite Command : No opposite command
Associated Commands : LOGIN, RESTART, NOPROFILE
E.G. : >PROFILE LOGIN CLEAR -- clears current login profile
>PROFILE LOGIN MYFILE -- sets up a new login profile
------------------------------------------------------------
This is the command that makes it possible for you to set up a login profile (a SOS exec to be executed when you login). There are two other forms of it that need discussion first, though.
AUTO is used only by the DMS-100 emulator on the IBM. I have never used it, so if you need it, look somewhere else.
RESTART is used on the switch, presumably to make the switch execute the given SOS exec at every restart. I have never used this, either, but it looks pretty straight-forward.
So much for that discussion. Now, on to the stuff I have done... LOGIN profiles.
As the example above indicates, clearing out a login profile is as simple as entering >PROFILE LOGIN CLEAR. Setting up a new profile is just about as easy. You just enter PROFILE LOGIN and the file name you want to execute as the profile.
The PROFILE command has another nifty feature. If you just enter >PROFILE LOGIN, you will know whether a login profile has been set up. If there is none, you will get a message that looks something like "LOGIN PROFILE IS NIL".
Now, if you did a >PROFILE LOGIN and there was a login profile in effect, you would expect to see the filename, right? Oh, well... no such luck. All you get is a 12-digit hexadecimal number, which bears no obvious relation to the file name.
Anyway, it's a neat command. It can come in useful for various things. If you use the same username every time, and nobody else uses that username, you could customize your environment somewhat... a few special abbreviations for often used commands, etc. If the switch you're using is an unusual beast (like an EIOC or something), you might want to use the login profile to make it look more civilized. Maybe make the operator profile do some things like datafilling the rest of the terminals and bringing them up.
Food for thought.
------------------------------------------------------------
QUIT
All Known Formats : >QUIT
>QUIT ALL
>QUIT <nlevels>
>QUIT <increment>
Opposite Command : No opposite command
Associated Commands : LEAVE
E.G. : >QUIT 3 -- quits out 3 levels
>QUIT MAPCI -- quits out of MAPCI
------------------------------------------------------------
QUIT is used everywhere. It is the all-purpose escape hatch. Again, the best way for me to do this is to give you a bunch of examples, so here goes:
CI: >TABLE TERMDEV TABLE TERMDEV: >TABLE TRKGRP TABLE TRKGRP: >MAPCI MAPCI: >QUIT 2 -- quit 2 of the 3 levels TABLE TERMDEV: CI: >TABLE TERMDEV TABLE TERMDEV: >TABLE TRKGRP TABLE TRKGRP: >MAPCI NODISP MAPCI: >MTC MTC: >IOD IOD: >IOC IOC: >QUIT -- quit 1 level IOD: >QUIT MAPCI -- quit MAPCI increment TABLE TRKGRP: >QUIT ALL -- quit all the way back to CI CI:
------------------------------------------------------------
READ
All Known Formats : >READ <filename>
>READ PREVIOUS -- clear read stack
>READ INPUT -- reads from keyboard
Opposite Command : No opposite command
Associated Commands : EXECUTE
E.G. : >READ MYEXEC -- read the file "MYEXEC"
>(READ PREVIOUS;READ MYSELF) -- recursive read
------------------------------------------------------------
This is the command that reads an exec file. That is, if you edit and fill a file full of commands, you can file it away and READ it at any time.
The READ <filename> is the most powerful format, as it gives you a full-fledged macro processing facility. The READ PREVIOUS is like the RETURN in BASIC. It returns to the previous calling exec. READ INPUT is useful for getting interactive input from the user from inside an exec file. I'll go into that later.
Enough talk... let's see some action:
>EDIT ONE_FILE >EDIT TWO_FILE
>INPUT >INPUT
1:: PRINT '-- Here goes' PRINT '-- Two-file here'
2:: 1 -> XLEVEL PRINT 'Do da, do da'
3:: READ TWO_FILE IF (XLEVEL=1) THEN (
4:: PRINT '-- And again' READ PREVIOUS)
5:: 2 -> XLEVEL PRINT 'More of the same'
6:: READ TWO_FILE READ PREVIOUS
7:: PRINT 'All done.'
>> >>
>FILE SFDEV >FILE SFDEV
And now, let's execute it:
>READ ONE_FILE -- Here goes Line 1 of ONE_FILE -- Two-file here Line 1 of TWO_FILE Do da, do da Exiting at line 4 of TWO_FILE -- And again Back at line 4 of ONE_FILE -- Two-file here Line 1 of TWO_FILE again Do da, do da Line 2 of TWO_FILE again More of the same About to exit TWO_FILE, line 6 All done. Exiting ONE_FILE
By the way, I didn't really need that final READ PREVIOUS in line 6 of TWO_FILE. SOS automatically does a READ PREVIOUS after the End-of-File. Either way, it's neat!
Of course you can do recursion. Just step this way:
>EDIT PREAMBLE >EDIT DO_FOREVER
>INPUT >INPUT
1:: PRINT '-- Here we go' % Do this until II>LIMIT
2:: 1 -> II IF (II > LIMIT) THEN
3:: 5 -> LIMIT (READ PREVIOUS)
4:: READ DO_FOREVER PRINT '--- II: ' II
5:: PRINT '-- Bye for now' (1+II)->II
6:: (READ PREVIOUS;
7:: READ DO_FOREVER)
>> >>
>FILE SFDEV >FILE SFDEV
It's pretty easy to see what is going to happen, but how??? Well, you see, the whole key is the statement in lines 6 and 7 of the DO_FOREVER exec. Since it is in parentheses, the SOS CI interpreter will sort of store it aside until it gets the closing parenthesis. Then it will do the READ PREVIOUS, which "clears the stack" as far as the call to DO_FOREVER is concerned. The next READ DO_FOREVER is then the only pending call. So, the exit in lines 2 and 3 finally returns to the caller that is on the stack. Namely, PREAMBLE.
READ INPUT is pretty neat, but can be awkward if you're not used to it. Let's look at a portion of an example exec:
COMMAND CM1 (@1 -> VARIABLE1;READ PREVIOUS) PRINT 'Enter the first variable using the CM1 command.' PRINT 'syntax: CM1 <variable1>' READ INPUT
What this does is create a command, CM1, which will put its first parameter into VARIABLE1. The exec then prompts the user to use the CM1 command to enter VARIABLE1. It then does a READ INPUT, which tells the switch to temporarily stop reading input from the file and start reading from the terminal. Of course, the drawback to doing this is that you are giving up control of execution to the user until they decide to use the CM1 command. They could also just enter "READ PREVIOUS" and control would be returned to the exec without VARIABLE1 being initialized. Anyway, it does add a new dimension to what you can do.
Well, that's about it as far as READ is concerned. If you're confused, go to the switch and try these little jewels. Just keep playing around and you'll get the hang of it. That's what I do.
------------------------------------------------------------
RECORD
All Known Formats : >RECORD QUERY
>RECORD START ONTO <device>
>RECORD START FROM <device>
>RECORD START FROM <device> ONTO <dev>
>RECORD STOP ONTO <device>
>RECORD STOP FROM <device>
>RECORD STOP FROM <device> ONTO <dev>
Opposite Command : No opposite command
Associated Commands : SEND, LOGUTIL (STARTDEV/STOPDEV)
E.G. : >RECORD START ONTO PRT0 -- send console output
>RECORD START ONTO MAP3 -- to various devices
>RECORD START FROM TATSIM2 ONTO PRT1
------------------------------------------------------------
The whole idea is to create a fork for re-directing the I/O, but not disconnecting its original direction. That is, if we use SEND PRT1, all our console output goes to that device. However, if we use RECORD START ONTO PRT1, we still get the output on our terminal, in addition to getting a copy on the printer!
There are several bad things about RECORD. You must stop the recording on the very same device that started it. Also, SOS does not check to see if the recording is already started by another user. Thus, you can do the following:
At MAP1: >RECORD START ONTO PRT1 At MAP3: >RECORD START FROM MAP1 ONTO PRT1
And this will of course create two streams, and when you want to stop them, you should do the following:
>RECORD QUERY From MAP1 ONTO PRT1 Started by MAP1 From MAP1 ONTO PRT1 Started by MAP3 At MAP1: >RECORD STOP ONTO PRT1 At MAP3: >RECORD STOP FROM MAP1 ONTO PRT1
That is the only way to stop it. Also, if you start the recording and then log out, the recording link is stopped if and only if your userid and the terminal ID are different. For example:
If in table TERMDEV, there is an entry for the printer called PRT1, and you have previously PERMITed PRT1 as a username, then when you login on the PRT1 device, you get a message like this:
PRT1 logged in on device PRT1 6:33:22 Aug-21-89
Now, if someone starts a record start onto that device, it will continue even if you log out.
However, if you log in on a device called PRT2 (in table TERMDEV), and there is not a permitted user called PRT2, then you are prompted for a user-name. Call it BETA. And then when someone does a record start onto BETA (the user name), it will terminate when BETA logs out.
What actually happens is that you can do a RECORD START onto either a device or a user name. In case of a device and a user with the same name, RECORD will assume you mean the device.
------------------------------------------------------------
REPEAT
All Known Formats : >REPEAT ### (any commands)
Opposite Command : No opposite command
Associated Commands : <BREAK> HX -- cancels execution
E.G. : >MAPCI;MTC;TRKS;TTP;POST D DTC 0 1 1 -- post a trunk
>REPEAT 24 (BSY;BSY INB;NEXT) -- BSY INB ALL
------------------------------------------------------------
REPEAT can also be nested (with care). It will not start executing until all "("'s are matched with ")"'s.
>EDIT ADD_MY_CKTS -- create a file... just watch
>INPUT
ADD_CKT CKT? DTC 0 1 ?
>> -- exit input mode
>REPEAT 23 (INPUT LINESTR) -- Remember that LINESTR
-- always contains the
>TOP;TYPE 555 -- current line. See the
TOF -- 24 copies of the same
ADD_CKT CKT? DTC 0 1 ? -- line.
ADD_CKT CKT? DTC 0 1 ?
....
ADD_CKT CKT? DTC 0 1 ?
EOF
>DOWN 1 -- position on the line
ADD_CKT CKT? DTC 0 1 ?
>1->II
>REPEAT 24 (CHANGE 2 '?' (NUMTODECSTR II);
> (II+1)->II;DOWN 1) -- zzzzzzap
>TOP;TYPE 555 -- voila!!
TOF
ADD_CKT CKT1 DTC 0 1 1
ADD_CKT CKT2 DTC 0 1 2
ADD_CKT CKT3 DTC 0 1 3
....
ADD_CKT CKT24 DTC 0 1 24
EOF
>FILE -- save it quick
*** FILE --- NO WRITE VOLUME SPECIFIED -- oops
>FILE D010TRAFVOL
Neater-er and neater-er!
------------------------------------------------------------
RESTART
All Known Formats : >RESTART WARM
>RESTART COLD
>RESTART RELOAD
>RESTARTBASE -- one word!!
Opposite Command : No opposite command
Associated Commands : None
E.G. : >RESTART COLD
Confirm (YES or NO)
>YES
------------------------------------------------------------
The RESTART is really the same as a boot on most other systems, or an IPL in VM/CMS. It re-initializes the software.
>RESTART WARM -- used to clear up minor problems >RESTART COLD -- to clear up major problems >RESTART RELOAD -- to clear up really major problems >RESTARTBASE -- used in dire circumstances indeed!
Otherwise, you can use the control switch on the CPU itself:
If you're really interested, the "SuperNode System Description" has a section devoted to restarts. It goes into all the gory details. Come to think of it, if you don't fully understand that section, you probably shouldn't be messing with RESTART anyway.
------------------------------------------------------------
RINDEX
All Known Formats : >IF (RINDEX=0) THEN ...
Opposite Command : LINDEX
Associated Commands : LINDEX
E.G. : >IF (RINDEX < 3) THEN (PRINT 'Too few parms')
------------------------------------------------------------
RINDEX is a function which returns the number of parameters to the right of the command. For example, if someone entered the command:
>HOWDY A B C D
and HOWDY did an RINDEX, 4 would be returned.
RINDEX is mainly used in commands with a variable number of parameters so that the command knows how many to read in.
------------------------------------------------------------
SEND
All Known Formats : >SEND <device>
>SEND SINK
>SEND PREVIOUS
>SEND SFDEV
>SEND SFDEV <filename>
>SEND <disk-vol> <filename>
Opposite Command : No opposite command
Associated Commands : RECORD, LOGUTIL (STARTDEV/STOPDEV), <BREAK> HT
E.G. : >SEND PRT1 -- redirect all output to a printer
------------------------------------------------------------
SEND is used to create a total branch point in your output, so that it either goes to another device, a file, or the bit bucket. For example:
>SEND PRT1
would send all of your output to PRT1 (and you cannot see what you're doing). You probably should enter:
>RECORD START ONTO PRT1
instead.
Now, let's look at some other examples:
>SEND PREVIOUS -- Re-direct the output to where it was
-- going before the last SEND command was
-- issued.
>SEND SINK -- discard all output
>SEND SFDEV -- send output to the file CONSOLE in SFDEV
>SEND SFDEV MY_LIST -- Same as above, but name of file
-- will be "MY_LIST".
>ERASESF CLLI_LIST -- destroy any old copy of the file
>TABLE CLLI
>SEND SFDEV CLLI_LIST
>LIST ALL
>SEND PREVIOUS
This is called "capturing data". All of the junk that would normally be sent to your terminal is sent to the file. Make sure that you do an "ERASESF" first so that the output does not append to the file or create problems.
>EDIT CLLI_LIST 13 -- go look at the file, truncate
-- at column 13
>END;PRINT LINE -- get the size of the file
138
>TOP;DOWN 1 -- get ready to make an exec
MDAL2WDTGS01
>REPEAT 138 (CHANGE '' 'POS ';DOWN 1) -- prefix each
>TOP;TYPE 2
TOF
POS MDAL2WDTGS01
>FILE
And to use it, say in trunk group,
>TABLE TRKGRP TABLE TRKGRP: >READ CLLI_LIST
Of course, for TRKSGRP or TRKMEM, we need the sub-group number. However, we could go into table TRKMEM, send to a file, capture all the stuff, and then we edit the file, truncate the output, and save the file.
Then, to make a trunk deleter, we could do the following:
>TABLE TRKMEM
>SEND SFDEV DEL_TRKS
>LIST ALL
>SEND PREVIOUS
>EDIT DEL_TRKS 18 -- go look at the file, truncate at column 18
>END;PRINT LINE -- get the size of the file.
142
>TOP;DOWN 1 -- get ready to make an exec
>REPEAT 142 (CHANGE '' 'DELETE ';DOWN 1)
>FILE
>TABLE TRKMEM
>OVE;VERIFY OFF
>READ DEL_TRKS -- Zappo... away go all the trunks which
-- have been previously set to INB at
-- the TTP level.
>QUIT
------------------------------------------------------------
SETDATE
All Known Formats : >SETDATE date month year
Opposite Command : No opposite command
Associated Commands : DATE
E.G. : >SETDATE 31 7 89 -- July 31, 1989
>SETDATE 1 2 90 -- February 2, 1990
------------------------------------------------------------
You'd think they would know better, but the year is only two digits. 19xx is assumed. Oh, well.
------------------------------------------------------------
SETTIME
All Known Formats : >SETTIME hours minutes
Opposite Command : No opposite command
Associated Commands : TIME, DATE
E.G. : >SETTIME 9 00 -- set time for 9:00am
>SETTIME 21 00 -- set time for 9:00pm
------------------------------------------------------------
I think that about covers it.
------------------------------------------------------------
SHOWFL
All Known Formats : >SHOWFL <filename>
Opposite Command : No opposite command
Associated Commands : DSKUT, LISTVOL, PRINT
E.G. : >LISTVOL D010CNTFL ALL
>SHOWFL GET_ALTLIB_READY
------------------------------------------------------------
See discussion under DSKUT.
------------------------------------------------------------
SHOWVOL
All Known Formats : >SHOWVOL <volume>
>SHOWVOL <volume> ALL
Opposite Command : No opposite command
Associated Commands : DSKUT, LISTVOL, LISTST
E.G. : >SHOWVOL D010CNTFL -- short display
>SHOWVOL D010IMAGE ALL -- long display
------------------------------------------------------------
See discussion under DSKUT.
------------------------------------------------------------
SLEEP
All Known Formats : >SLEEP <seconds>
Opposite Command : No opposite command
Associated Commands : None
E.G. : >SLEEP 3 -- wait 3 seconds before continuing
------------------------------------------------------------
'nuff said.
------------------------------------------------------------ TAPE All Known Formats : >Too many to go into here. Opposite Command : No opposite command Associated Commands : MOUNT, DEMOUNT, LIST, TLIST ------------------------------------------------------------
The TAPE command is a very powerful command which allows you to do all sorts of unusual things to a tape. You can rewind it without DEMOUNTing it, you can read an EBCDIC file off the tape and translate it to ASCII at the same time, you can enter data on a tape one record at a time, erase files off a tape, etc.
If you're going to be doing a lot of stuff with tapes, you should probably get familiar with this command. A full explanation is in document NTP 297-1001-509 (of course). You might even want to take a look at NTP 297-1001-118 (DMS-100 Family Magnetic Tape Reference Manual). It tells you all about the block structure and all that.
------------------------------------------------------------
TAPECONFIRM
All Known Formats : >TAPECONFIRM ON
>TAPECONFIRM OFF
Opposite Command : No opposite command
Associated Commands : MOUNT
------------------------------------------------------------
This is a silly little command, but it does come in handy occasionally. You know, when do something like:
>MOUNT 0 FORMAT
and the switch makes you enter the name of the first file on the tape to confirm that you really want to format the tape? Well, if you say:
>TAPECONFIRM OFF
you don't have to enter the file name. This may not sound like it's worth an entire command, but it does make it a lot easier when you mount tapes with long file names.
------------------------------------------------------------
THEN (See the discussion under IF)
E.G. : IF (X=3) THEN (
PRINT '--- Ah-ha, X is three.'
) ELSE (PRINT '--- Well, X is certainly not 3.')
------------------------------------------------------------
------------------------------------------------------------ TIME All Known Formats : >TIME Opposite Command : No opposite command Associated Commands : DATE, SETTIME ------------------------------------------------------------
TIME displays the time in hours, minutes, and seconds.
------------------------------------------------------------
TLIST
All Known Formats : >TLIST <tape drive>
Opposite Command : No opposite command
Associated Commands : MOUNT, DEMOUNT, LIST
E.G. : >MOUNT 0
>TLIST T0
------------------------------------------------------------
TLIST is basically a fast version of LIST. You can't always use it, though. When you mount a tape, sometimes you'll see the message, "First file = TAPE$DIR...". If you see that message, you can use TLIST. TAPE$DIR is created by many different utilities, including XDMSTAPE on the IBM. It is a list of the files on the tape. TLIST reads that list into your CI process symbol table so that you can access the files on the tape.
The reason TLIST is usually preferred over LIST is that LIST traverses the used portion of the tape looking for files. If you have a lot of files on the tape, this could take a while. TLIST takes just a few seconds. As far as I can tell, there is no reason to use LIST instead of TLIST when it's possible to use TLIST. If anybody knows of any advantages in using LIST over using TLIST, let me know.
------------------------------------------------------------
UNLOAD
All Known Formats : >UNLOAD <module name>
>UNLOAD <module name> DISPLAY
>UNLOAD <module name> NOINFORM
>UNLOAD <module name> NOWARN
>UNLOAD <module name> NOERROR
Opposite Command : LOAD
Associated Commands : See DIS document OSA10 LISTING
------------------------------------------------------------
UNLOAD is one of those commands you shouldn't use unless you absolutely know what you're doing. If you think you need to know more about this command, DIS "OSA10 LISTING".
------------------------------------------------------------
UNPERMIT
All Known Formats : >UNPERMIT <username>
Opposite Command : PERMIT
Associated Commands : SHOW USERS, PRINT USERS, FORCEOUT
E.G. : >FORCEOUT OPERATOR
>UNPERMIT OPERATOR
------------------------------------------------------------
UNPERMIT discontinues a username on the DMS-100, thus revoking their access to the switch. UNPERMIT will not work as long as the user is logged in. However, if you use FORCEOUT to log the user out, you can then UNPERMIT him.
------------------------------------------------------------
UNTIL
All Known Formats : >UNTIL (expr) (cmds)
Opposite Command : No opposite command
Associated Commands : IF, WHILE
E.G. : >UNTIL (A=10) ((A+1)->A;PRINT A)
------------------------------------------------------------
The UNTIL command works the same as an UNTIL statement in any high-level language (Protel included). It is a loop statement with an exit test at the end. Thus:
>1->A;UNTIL (A=10) ((A+1)->A;PRINT A)
would print the numbers 2 through 10, and:
>10->A;UNTIL (A=10) ((A+1)->A;PRINT A)
would execute forever, since the first A=10 test is done after (A+1)->A has been executed.
------------------------------------------------------------
WHILE
All Known Formats : >WHILE (expr) (cmds)
Opposite Command : No opposite command
Associated Commands : IF, UNTIL
E.G. : >WHILE (A<10) ((A+1)->A;PRINT A)
------------------------------------------------------------
The WHILE command works the same as a WHILE statement in any high-level language (Protel included). It is a loop statement with an exit test at the beginning. Thus:
>1->A;WHILE (A<10) ((A+1)->A;PRINT A)
would print the numbers 2 through 10, and:
>10->A;WHILE (A<10) ((A+1)->A;PRINT A)
wouldn't print anything, since the first A=10 test is done before (A+1)->A is been executed.
NCMS -- A Special Note
"Why in the world are you talking about that dinosaur, NCMS? Don't you know that everyone uses MPCNET now?" Well, not everyone. I know they have it in RTP, I think they have it in Meriline, and I'm almost certain they have it in Carling (they have everything in Carling). However, we don't have it in Richardson yet. Until MPCNET is universal, this section will remain. Since I'm in Richardson, I can't really tell you much about MPCNET, but the MPCNET user's guide (DIS "REF JPF") is probably what you really need. If you want to see what little I know about MPCNET, see the MPCNET section.
Now, everyone knows how to use NCMS. The real problem is with the transfer of files.
>DSKUT >LISTVOL D010TEST1 ALL MY_OWN_EXEC MY_OWN_EXEC_DATA >LISTSF MOVE_UP >PRINT MOVE_UP % $FILE=MOVE_UP (Exec to move all my files up to the IBM) COMMAND NCPY (PRINT (SYMTOSTR @1);SOSTOCMS @1 @2 @3) % NCPY MY_OWN_EXEC MY_OWN_EXEC SOS_EXEC NCPY MY_OWN_EXEC_DATA MY_OWN_EXEC_DATA SOS_EXEC
Now, the only problem is that on the IBM, we can only have 8-character names, so that the first file will actually appear as "MY_OWN_E SOS_EXEC", and when the next file, "MY_OWN_EXEC_DATA" tries to come in --- BLAMMO!! So, it is necessary to make sure that the destination file names are of the right length. Thus, the two NCPY lines in the exec above should be something like:
NCPY MY_OWN_EXEC MY_EXEC SOS_EXEC NCPY MY_OWN_EXEC_DATA MYX_DATA SOS_EXEC
Now, we can >READ MOVE_UP and it should do a lot better.
NCMS -- Wonderlink Between the Switch and the IBM
When you are on the switch, you can use NCMS to link back to the IBM. Normally, the link will be up when you try to use it. If not, see the next page. If the link is up, the following procedure should log you into the IBM:
>NCMS
>SMODE -- get to the IBM
>RCH or TEX -- depending on whether you want
-- on BNRRCH or BNRTEX
<BREAK>
?HX -- you now have about 1 minute to log in to the IBM
>NCMS -- since HX threw you all the way back to CI
>SMODE -- back to the IBM again
>L <vmid> -- log into the IBM
><password>
....
>SMODE -- get back to the switch
>SCMSTOSOS <fn> <ft> <sos fn> <volume> -- from IBM to switch
or
>SOSTOCMS <sos fn> <fn> <ft> -- from switch to IBM
When you're done, be sure to use:
>CMSLOGOFF
while you're in switch mode to log you off the IBM.
The process is different if you want to copy a module across to be loaded on the switch. Instead of SCMSTOSOS, you use GETLOAD, or GL for short. It goes something like this:
>GL MYMOD
This will put your module in SFDEV. Then you can use the LOAD command to load it.
Common Problems and Mistakes with NCMS
>TABLE DLCDEV
>LIST ALL
DLCNUM IOCNO IOCCKTNO BAUD EQPEC
---------------------------------------
0 2 0 B4800 1X67BA
If the data isn't there, you will have to add it.>MAPCI;MTC;IOD;IOC 2;CARD 0 >BSY;OFFL;BSY;TST;RTS
>NCMS 1instead of:
>NCMSThis format just tells NCMS to use the DLC on side 1.
Any time the link acts balky, reset it and log back in.
The Ultimate NCMS Sin
This part gets a little technical on the VM/CMS side. If you don't know what it means, you probably don't need to know about it.
Many people use VM facilities like WAKEUP to trap console I/O. Many people also DISCONNECT rather than logging off sometimes. If both of these apply to you, you may have some trouble with NCMS.
If you're disconnected and are using WAKEUP, and you log in via NCMS, you have one command before NCMS freezes and you have to do a <BREAK> HX. Make it a good one. Use this one: IPL CMS PARM AUTOCR. This will, of course, restart your VM session, and whatever installs your WAKEUP stuff should be smart enough to know better when it sees that you're not on a full-screen terminal.
If you forget and hang NCMS, do not use PRIVREQ to log yourself off the IBM. I have experienced the consequences of this once. When we queried the userid on VM, it was listed as PENDING LOGOFF. We had to get network services to get the userid logged off, and it took a system IPL of the IBM to get the IBM to release the NCMS link. REALLY NASTY STUFF!!!
A <BREAK> HX is infinitely preferable.
MPCNET -- What Little I Know
Speculation
Sorry, folks, but, never having had the opportunity to use MPCNET myself, there's not a lot I can offer you in the way of instruction. This section is basically a brief overview of MPCNET, with comparisons to NCMS. I'll even throw in a few speculations, but I won't guarantee any of them. If you want to know about the commands themselves, you need to be looking in the MPCNET user's guide. That's "JPF" in DIS.
What is MPCNET, anyway? Well, basically, it's NCMS, only better. MPCNET is a 19.2 kbps link between the switch and another machine (currently, only IBM mainframes are supported: fnref REFID=spec.). That's four times as fast as current NCMS speeds.
Besides the speed increase, there are a few other nifty features MPCNET has over NCMS. First, more than one person can use MPCNET at the same time. So you can be logged in on BNRTEX while your buddy's logged in on BNRRCH from the same switch. There can be up to 255 simultaneous sessions on each switch. I'm not an expert, but I can't see how more than one person could log in to the same IBM over the same link at the same time:fnref REFID=spec., so that may be a limitation.
Second, you don't have any limit on the number of records you can transfer over the link. If you've ever tried to transfer something large over NCMS, you know how painful it can be to be almost done and have NCMS abort because it thought there were too many records. Don't have to worry about that with MPCNET!! If you want to transfer the encyclopedia Britannica over the link, go for it!!
Third, you can transfer SuperNode modules over the link. Unless I'm mistaken, there is no facility for that in NCMS:fnref REFID=spec.. With MPCNET, just issue the magic GL68K command, and it happens!
Well, that just about exhausts my knowledge of MPCNET. I hope it helped somewhat.
SOS Execs
SOS execs, like execs on other systems, are basically files containing a list of commands to be executed by the system's command interpreter.
This section is devoted to showing you some of the finer points of exec writing in the DMS-100 environment. For your reading enjoyment, many examples of SOS execs (which actually work!!) have been included.
There are two ways to invoke execs. The orthodox way is by use of the READ command, like so:
>READ MYEXEC
The other way to invoke an exec involves the use of the COMMAND command, like this:
>COMMAND DOIT MYEXEC -- Look, Mom!! No parentheses!! >DOIT -- does a READ on MYEXEC
Now, you may ask yourself, "What difference does it really make?" Well, here's some food for thought:
>EDIT GOFORIT
>INPUT
PRINT 'here I am'
PRINT (SYMTOSTR @1) (SYMTOSTR @2) (SYMTOSTR @3)
>>
>FILE SFDEV
>LISTSF
>READ GOFORIT A B C
READ -- Wrong number of parameters -- oops...
-- can't pass parms
>COMMAND DOIT GOFORIT
>DOIT A B C
here I am
A B C
So, you can see that making a command point to an exec makes it much easier to pass information into the exec.
Well, enough of this. I'm spoiling all the surprises!! On with the show.
Exec Files, Some Simple Examples
Let's say that we want to make up some files that will do lots of neat things for us. For example, let's edit and save the following files into SFDEV:
>EDIT PART1
>INPUT
% $FILE=PART1 (Example of an exec file) RLT JUN-21-86
PRINT '-- Hi-ho part-one fans... here we go'
COMMAND PIXXY ((SYMTOSTR @1)->$PARM1;
PRINT '-- Parm-1 set: ' $PARM1)
COMMAND HELP_PART (PRINT PART_HELPF)
COMMAND PART_HELP (PRINT PART_HELPF)
0 -> II
READ PART2
>>
>FILE SFDEV
>EDIT PART2
>INPUT
% $FILE=PART2 (Example of an exec-file) RLT JUN-21-86
PRINT '-- PART2 here. To store an alpha parm, enter:'
PRINT '-- >PIXXY <value>'
PRINT ' '
PRINT '-- For help, enter: >HELP_PART'
PRINT --- To reinitialize, enter: >READ PART1'
PRINT ' '
>>
>FILE SFDEV
>EDIT PART_HELPF
>INPUT
% $FILE=PART_HELPF RLT JUN-21-86
PRINT ' '
PRINT ' O N - L I N E H E L P FOR: PART'
PRINT ' '
PRINT ' The PART family of commands are used to'
PRINT ' illustrate basic practices of writing SOS'
PRINT ' execs. They don''t really do anything at all.'
PRINT ' The following commands are available:'
PRINT ' '
PRINT ' >PIXXY <alpha-parm> -- will store $PARM1'
PRINT ' >HELP_PART -- prints this info'
PRINT ' '
PRINT ' To re-initialize the PART system, enter:
PRINT ' '
PRINT ' >READ PART1'
PRINT ' '
>>
>FILE SFDEV
So, on the previous page we see a little family of execs. And how cute they are, too! This is about the bare-bones of what I consider essential to any family of execs. We have a start-up exec (PART1), a main driver exec (PART2), and a baby-bear exec, er, ah, the help file (PART_HELPF) which is invoked by either HELP_PART or PART_HELP (in case the user forgets the format). There is a slicker way to do on-line help, but we won't get into that yet.
Thus, for our PIXXY command, we might use the following as the help file:
% $FILE=PIXXY_HELPF RLT JUN-21-86 PRINT ' ' PRINT ' O N - L I N E H E L P FOR: >PIXXY' PRINT ' ' PRINT ' The PIXXY command allows the user to store any' PRINT ' alpha parm in the variable $PARM1' PRINT ' ' PRINT ' USAGE: >PIXXY <parm> PRINT ' '
And to activate the command, we would add the following to PART1:
COMMAND HELP_PIXXY (PRINT PIXXY_HELPF) COMMAND PIXXY_HELP (PRINT PIXXY_HELPF)
Now, on to bigger things:
Fool-Proof Execs: In-Line HELP for Commands
To help the user, you can install an in-line help in the command itself. In the following command, the "guts" are in the ELSE clause. The help is in the first part.
COMMAND START ( IF ((RINDEX) = (0)) THEN ( PRINT 'COMMAND START NEEDS 1 PARAMETER:'; PRINT ' <CIRCUITNAME>|<ALL>' )ELSE( START_FUNC -> FUNCTION; (SYMTOSTR @1) -> DIRNAME; READ PROCREQ )
The way this one works is to see if there is no parm entered on the line. This means that the user needs help. Of course, we can also check for the word "HELP" to the left of the command:
>HELP START
In this case, we need to check the left-index (LINDEX) instead:
COMMAND START (
IF ((LINDEX) = (1)) THEN (
IF ((SYMTOSTR @-1) = 'HELP') THEN (
PRINT 'COMMAND START NEEDS 1 PARAMETER:';
PRINT ' <CIRCUITNAME>|<ALL>'
))ELSE(
START_FUNC -> FUNCTION;
(SYMTOSTR @1) -> DIRNAME;
READ PROCREQ
)
Actually, the way most commands determine whether or not to print help is to use LINDEX to see if there's anything before the name of the command on the line. If so, assume it's a "Q" or a "HELP" and print the help file. This keeps it consistent with system commands (commands someone wrote in Protel, compiled, and loaded onto the switch).
Fool-Proof Execs: Interactive Execs
This isn't a very safe thing to do in a SOS exec, but I'll show it to you anyway because you might come up with a better use for it.
You've already seen how, by making a command invoke an exec, you can pass parameters to the exec. But what if you have a rather complex exec and you want to ask the user a question in the middle of it? How do you do that? Well, you do it verrry carefully!
A maneuver like this requires rather tricky use of the READ command. Specifically, the "READ INPUT" variety of the READ command. Now, what "READ INPUT" actually does is tell CI to start looking at the terminal for input. Very much like the "shell" commands you can use in some PC programs to jump into a DOS session without leaving the original program. That means that your exec is suspended until a "READ PREVIOUS" occurs, at which point it takes up where it left off. However, with careful planning and voluminous prompting of the user, it is possible to minimize your risk. Observe the following portion of an exec:
>EDIT COPYSF
>INPUT
% $FILE=COPYSF (Example of an exec) v-1.00 BLH NOV-10-89
PRINT 'How many files to copy?'
PRINT 'Enter "NUMFILES n"'
COMMAND NUMFILES (@1 ->NUMFL; -- Command to allow the user
READ PREVIOUS) -- to specify num of files
READ INPUT -- transfer control to the user.
COMMAND FILEDEV (@1->FNAME; -- Command to allow the user
@2->DEV; -- to specify file name and
READ PREVIOUS) -- destination device.
REPEAT NUMFL (
PRINT 'What''s the next filename and device?'
PRINT 'Enter "FILEDEV <filename> <device>"'
READ INPUT
COPY FNAME DEV
)
As you can see, when you use this method, you are depending on the user to enter what you tell him when you tell him. Does it work? Yes. Is it risky? Oh, yeah!! But it is an interesting concept.
Fool-Proof Execs: WHILE and UNTIL Loops
As you may have noticed, the previous version of COPYSF is rather limiting in that you have to tell it how many files you want to copy before you copy them. Of course, a much better way to do this would be to loop until the user signalled you to stop.
With that in mind, look at this new and improved version of COPYSF which uses the UNTIL command:
>EDIT COPYSF
>INPUT
% $FILE=COPYSF (Example of an exec) v-1.00 BLH NOV-10-89
COMMAND FILEDEV (@1->FNAME; -- Command to allow the user
@2->DEV; -- to specify file name and
READ PREVIOUS) -- destination device.
UNTIL (((SYMTOSTR FNAME) = 'NONE') & ((SYMTOSTR DEV) = 'NONE')) (
PRINT 'What''s the next filename and device?';
PRINT 'Enter "FILEDEV <filename> <device>"';
PRINT 'Enter "FILEDEV NONE NONE" to quit.';
READ INPUT;
COPY FNAME DEV
)
Of course, in this example, if the user changes his mind up front and enters "NONE NONE" the first time through, the exec will fail miserably. That's why God (or IBM or somebody) invented the WHILE loop. Take a look at the final version of COPYSF which doesn't fail quite so easily:
>EDIT COPYSF
>INPUT
% $FILE=COPYSF (Example of an exec) v-1.00 BLH NOV-10-89
COMMAND FILEDEV (@1->FNAME; -- Command to allow the user
@2->DEV; -- to specify file name and
READ PREVIOUS) -- destination device.
PRINT 'What''s the first filename and device?'
PRINT 'Enter "FILEDEV <filename> <device>"'
PRINT 'Enter "FILEDEV NONE NONE" to quit.'
READ INPUT
WHILE (((SYMTOSTR FNAME) ^= 'NONE') & ((SYMTOSTR DEV) ^= 'NONE')) (
COPY FNAME DEV;
PRINT 'What''s the next filename and device?';
PRINT 'Enter "FILEDEV <filename> <device>"';
READ INPUT
)
Now you're an expert on WHILE, UNTIL, and READ INPUT. How do you feel? Well, take some aspirin, and maybe it'll go away.
Now, wouldn't it be nice if we could just do away with that silly FILEDEV command and specify everything on the command line?
Fool-Proof Execs: The PAR Function
You've seen PAR before. You remember the "@" symbol you use to reference parameters? Well, the PAR function does that same thing, but by looking at the following exec, you can see the advantage of the PAR function in certain situations. This differs from the previous examples in that, because I'll be using parameters, the exec actually defines a command to do the work.
>EDIT COPYSFEXEC
>INPUT
% $FILE=COPYSFEXEC (Example of an exec) v-1.00 BLH NOV-10-89
ERASE COPYSF
COMMAND COPYSF (
2 -> NUMPARMS %% -- I'll use this as an index to my parms
WHILE ((RINDEX) >= (NUMPARMS)) (
COPY (PAR (NUMPARMS-1)) (PAR (NUMPARMS));
NUMPARMS + 2 -> NUMPARMS
)
)
You can see how using PAR instead of @ allows me to use NUMPARMS as an index to which parm I want to look at. So, there's one more little tidbit of information to stuff into your brain!
Fool-Proof Execs: Using Flags
Now, let's return to our previously scheduled program, PART1. Geez... I can hardly remember that far back. Consider a new version of PART1:
>EDIT PART1
>INPUT
% $FILE=PART1 (Example of an exec) v-1.01 RLT JUN-21-86
PRINT '-- Hi-ho part-one fans... here we go...'
0->$REINIT_FLAG
$REINIT_OK -> $REINIT_FLAG
IF ($REINIT_FLAG = 0)THEN(PRINT '*** TO REINIT, ENTER:';
PRINT ' >REINIT_PART';PRINT ' ')
COMMAND REINIT_PART (1->$REINIT_OK;READ PART1)
COMMAND PIXXY (......
.........
0->II
0->$REINIT_OK
READ PART2
In this case, we have a fool proof means that the PART2 exec will not be accidentally re-read. Let's say that we were to try and re-read the PART1 exec again.
There is only one more little detail, and that is "What is the value of $REINIT_FLAG the very first time PART1 is read?" Actually, it is probably undefined (unless the user accidentally gave it a value). For this reason, SOS will print a message like "undefined value as parameter -1". To hide this from the user, so that s/he won't get too disturbed, we usually put all of the definitions in a "SEND SINK .... SEND PREVIOUS" block. This will send the output (from error messages, prints, etc.) to the bit bucket (known as the SINK in SOS -- remember SOS BILGE?). So our exec now looks like this:
% $FILE=PART1 (Example of an exec) v-1.01 RLT JUN-21-86 PRINT '-- Hi-ho part-one fans... here we go...' 0->$REINIT_FLAG SEND SINK $REINIT_OK -> $REINIT_FLAG SEND PREVIOUS
Fool-Proof Execs: Erase It Before You Define It
So far, we have assumed that we are running a perfectly debugged system. Ho, ho, ho! There is just one problem with that. What if we (yes, we, ourselves) are trying to debug these confounded commands, and we re-run the PART1 exec -- after we have changed the definition of a command in the file. SOS will not change the definition!!! This means that, even though we have made a change to the PART1 file, and re-read the file, the old definition is all SOS knows about.
For this reason, it is always a good idea to erase the old commands at the beginning of the file that defines them. And then define them anew. Of course, the first time we read the file, we will get an "undefined symbol" error (obviously there is nothing to erase). So, we simply put the ERASE command in the SEND SINK .... SEND PREVIOUS block as well:
% $FILE=PART1 (Example of an exec) v-1.01 RLT JUN-21-86 PRINT '-- Hi-ho part-one fans... here we go...' 0->$REINIT_FLAG SEND SINK ERASE HELP_PART HELP_PIXXY PIXXY REINIT_PART ERASE ZZZZ_CMD $REINIT_OK -> $REINIT_FLAG SEND PREVIOUS
This way the user is not bothered by all those pesky SOS warnings.
In a related topic, remember at the first of this section where I showed you how to make a command invoke an exec so that the exec can take parameters? Well, if you change that exec and re-file it, the command is still pointing where the old version used to be. Consequently, you need to ERASE the command and define it again every time you change the exec. Details, details, details!!
$$PUSH and $$POP (Examples)
Now, let's look at a very useful set of execs that we will define within the edit environment:
1 : % $FILE=AUX_CMDS (Helpful editor cmds) RLT JUL-24-86
2 : SEND SINK
3 : ERASE $$GET $$GETX $$GETSIZE $$MAKEEND $$POPALL
4 : ERASE $$POPX $$PUSHX $$PUT $$RECOVER STACK
5 : EDIT JUNKX
6 : COMMAND $$PUSHX ((1+XPTRX)->XPTRX;
7 : ('XTEMP'+(NUMTODECSTR XPTRX))->VARX;
8 : (LINESTR -> (STRTOSYM XVARX)) )
9 : %
10 : COMMAND $$PUT (@1->II;REPEAT II ($$PUSHX;DOWN 1))
11 : %
12 : COMMAND $$POPX (IF ((XPTRX) >= (1)) THEN (
13 : INPUT (STRTOSYM ('XTEMP'+(NUMTODECSTR XPTRX)));
14 : (XPTRX-1)->XPTRX))
15 : %
16 : COMMAND $$GETX (IF ((IPTRI) <= (XPTRX)) THEN (
17 : INPUT (STRTOSYM ('XTEMP'+(NUMTODECSTR IPTRI)));
18 : (IPTRI+1)->IPTRI))
19 : %
20 : COMMAND $$POPALL (IF ((XPTRX) >= (1)) THEN (
21 : XPTRX->II;REPEAT II ($$POPX)) ELSE (
22 : PRINT '** NO PARMS ON STACK') )
23 : %
24 : COMMAND $$GET (IF ((XPTRX) >= (1)) THEN (
25 : 1->IPTRI;XPTRX->XHOLDXPTR;REPEAT XPTRX ($$GETX)
26 : 0->XPTRX;
27 : PRINT '--- ' XHOLDXPTR ' pulled from stack.';
28 : PRINT ' Use $$RECOVER_STACK to do an un-get'
29 : )ELSE(PRINT '** NO PARMS ON STACK') )
30 : %
31 : COMMAND $$RECOVER_STACK (IF ((XHOLDXPTR) > (XPTRX))
32 : THEN(XHOLDXPTR->XPTRX;
33 : PRINT '--- Recovered ' XHOLDXPTR ' from stack.'
34 : )ELSE(PRINT '*** Stack is already at maximum.') )
35 : %
36 : COMMAND $$GETSIZE (SEND SINK;END;LINE -> $SIZE;TOP;
37 : SEND PREVIOUS;PRINT '-- File has ' $SIZE ' lines.')
38 : %
39 : COMMAND $$MAKEEND (END;
40 : INPUT '%% END -> END %%%% END OF FILE')
41 : %
42 : QUIT
43 : SEND PREVIOUS
44 : %%%% VALUES & VARS %%%%
45 : 0 -> IPTRI; 0 -> XPTRX; 0 -> XHOLDXPTR
46 : 0 -> II
47 : 0 -> $SIZE
Now, let's look in some detail at this exec.
First of all, in line 1 we have a comment telling what the name of the exec is, "$FILE=file-name". I have gotten in the habit of saying "$FILE=". Then, I can use the editor to locate the beginning of file easily. Notice that I have a brief explanation (not much help here), then my initials, and the last date I changed it.
At line 2, I send the output to the SINK (bit bucket). This way, the user won't see the silly "EDIT:" prompt that will blip up every time the exec creates a command.
Lines 3 and 4 erase the commands I am about to create. This way, any old, spurious definitions for those commands will be sure to be erased.
In lines 5 and 42 we enter and exit the editor. I only want to make sure that the commands are properly linked, so I will edit a dummy file (JUNKX) and then create the commands, and then just quit out of the editor.
In lines 6 through 8, I define a nifty little command to simulate pushing the line the editor is currently on into a stack. In reality, I increment a counter (XPTRX) and then build up the name of a variable into which I will store the current line's contents. Let's say that XPTRX was initially 0. In that case:
(1+XPTRX)->XPTRX would set it equal to 1. Then, the nested "(NUMTODECSTR XPTRX)" turns the integer into a string, giving '1' from the value 1. Next, I build the name of the variable in the symbol XVARX:
'XTEMP'+'1'->XVARXSo line 7 makes XVARX = 'XTEMP1'.
And then, in line 8, I create a symbolic reference to this string variable: (STRTOSYM XVARX) which would accomplish the same thing as if I had typed in "LINESTR -> XTEMP1".
And LINESTR is, of course, the editor system variable wherein the contents of the current line are always stored (done internally by the editor).
Thus, we have the first 72 characters of the current line stored in a variable called XTEMP1. And it is parameterized based on the current value of XPTRX. This leads us to...
Line 10, where we make a multiple store command called $$PUT. To use it, we position ourselves in the editor and enter >$$PUT 5 -- which would store the next five lines for us. Now, notice two things. First, the parm 5 is a numeric value and is not converted to a symbol (as would be the case in general). Next, the value appears inside the $$PUT command as "@1" (since it is the first parm passed to it when we evoke the command). Next, I store the value in a temporary variable called "II" and use it to start a repeat loop: $$PUSHX and then move down one line in the file.
Before we go too much further, I should make it clear that when we READ the file on the second previous page, none of these commands is actually executed. The only thing that is done is to create a new definition in your read/write directory that you can use later (at any time up until you logout). That is what the "COMMAND" command does. It creates a new command! Now, back to our file...
So, of course, what we store, we can retrieve. To do this, you just do the inverse of what the $$PUSHX did by decrementing the pointer XPTRX. Of course, we need to be careful that it isn't negative or zero:
12 : COMMAND $$POPX (IF ((XPTRX) >= (1)) THEN (
That is, if and only if XPTRX is still greater than 0, dothe following:
First, build the variable's name back up: 'XTEMP1' or whatever (in the case where XPTRX = 1).
Then, convert the string to a symbol so that when we INPUT it, we get the VALUE of the variable, not the name of the variable. For example, if we were to do the following, this is what we would see:
>PRINT XPTRX 1 >PRINT (NUMTODECSTR XPTRX) 1 -- we can't see it, but this is really '1' >PRINT ('XTEMP'+(NUMTODECSTR XPTRX)) XTEMP1 >PRINT (STRTOSYM ('XTEMP'+(NUMTODECSTR XPTRX))) Mary had a little lamb.And there it is, the value of the line that we stored when we were editing the file. (Assuming things went something like on the next page.)
And finally in line 14, we decrement the counter XPTRX.
Now, the only problem with the $$POPX command is that the lines will come out in the opposite order in which we put them in! (Just like any good push-pop stack should.) So, we create a "normal" command $$GET, which will correspond to our $$PUT <nlines> command:
24 : COMMAND $$GET (IF ((XPTRX) >= (1)) THEN ( 25 : 1->IPTRI;XPTRX->XHOLDXPTR;REPEAT XPTRX ($$GETX) 26 : 0->XPTRX; 27 : PRINT '--- ' XHOLDXPTR ' pulled from stack.'; 28 : PRINT ' Use $$RECOVER_STACK to do an un-get' 29 : )ELSE(PRINT '** NO PARMS ON STACK') )
Well, that's a mouthful! First, in line 24, we check for stack underflow (i.e., a negative value for XPTRX). Then we save a copy of XPTRX (just in case we want to cheat and get them again later). Notice that we use XPTRX as the value of the repeat in line 25, and the thing we repeat is itself another previously created command:
16 : COMMAND $$GETX (IF ((IPTRI) <= (XPTRX)) THEN (
17 : INPUT (STRTOSYM ('XTEMP'+(NUMTODECSTR IPTRI)));
18 : (IPTRI+1)->IPTRI))
Here, you will notice that I used "IPTRI" instead of "XPTRX" just to make sure that things don't get trashed. Further, I check that there is no underflow by comparing IPTRI to XPTRX. One thing to note is that the IF statement does take a considerable time to execute. If I was going to do lots of this stuff, I probably would be better off taking it out and checking it only in the $$GET command.
Anyway, the $$GETX command is pretty straightforward, and it insures us of getting the lines in the correct order.
Lines 27 and 28 tell us what's going on. And, again, an important note is that if we close up the "THEN" clause on line 26 without opening the "ELSE(", the SOS CI parser will fail to ever evaluate the ELSE clause:
OK: IF (condition-of-some-sort) THEN (
things to do if true;
more things; and more things)ELSE( <------+
things to do if false) |
|
BAD: IF (condition-of-some-sort) THEN ( |
things to do if true; |
more things; and more things) |
ELSE(things to do if false) |
|
In the second case, the ELSE clause will NEVER (EVER) |
be executed!!! The SOS strangeness strikes again. |
So, programmers, leave those pending parentheses open |
ON THE SAME LINE. -->----------------------------------+
Yes, yes, all well and good. But how do I use those commands??? |La questione excellente!
>READ AUX_CMNDS -- first we read the exec
>EDIT LAMB_FILE -- edit our favorite file and
>INPUT -- put some junk in it
INPUT MODE:
>Mary had a little lamb.
>Little lame lamb.
>Whose degree was in maths.
>> -- hit an extra return to exit input mode
EDIT:
>TOP
>DOWN 1
>$$PUT 2
>END
>$$GET
--- 2 pulled from stack.
Use $$RECOVER_STACK to do an un-get
>TOP;TYPE 999
TOF:
Mary had a little lamb.
Little lame lamb.
Whose degree was in maths.
Mary had a little lamb.
Little lame lamb.
EOF:
>
>END;INPUT '%%' -- go to the end and enter a marker
>$$RECOVER_STACK -- retrieve the holding pointer
--- Recovered 2 from stack
>$$GET
--- 2 pulled from stack.
Use $$RECOVER_STACK to do an un-get
>TOP;TYPE 999 -- and let's see the file now...
TOF:
Mary had a little lamb.
Little lame lamb.
Whose degree was in maths.
Mary had a little lamb.
Little lame lamb.
%%
Mary had a little lamb.
Little lame lamb.
EOF
Pretty nifty, eh? By the way, you can put several commands on a line like that using the good old ";" between them: TOP;TYPE 3333.
Fool-Proof Execs: Setting Up Your Execs As A System
Plan your work and work your plan. This really applies to SOS execs since there may be several different environments, etc. To handle this, it's usually a good idea to separate things. Specifically, it's a good idea to put command and variable definitions in a separate file from the actual execs. For example:
This is the first file, which really starts up the system. Notice that I READ the initialization procs to set up various parms.
% $FILE=XINIT_RAMSES (Start up RAMSES) RLT MAY-21-85 PRINT '---- RAMSES ----' READ XRAM_CMND_INIT % ------ THIS ROUTINE IS USED ON THE RAMSES TERMINAL READ XRAM_HDW_INIT READ XRAM_USRS_INIT % ---- SYSTEM VARIABLES FOR THE RAMSES TERMINAL ITSELF '<NULL>'->$NULL 'ACTIVE'->$ACTIVE $ACTIVE->$RX_ALIVE .......... PRINT '------------------- RAMSES is up.' MSG ALL '--------- RAMSES started.'
Let's look at a couple of the initialization procs:
% $FILE=XRAM_HDW_INIT RLT MAY-21-85
% THE HARDWARE VARS ARE STORED HERE FOR D250-COMB CONFIG
3->$RX_NPOOLS
%
'TM8 2'->$RX_XX1
'TM8 3'->$RX_YY1
%
'TM8 4'->$RX_XX2
'TM8 5'->$RX_YY2
%
'TM8 6'->$RX_XX3
'TM8 7'->$RX_YY3
%
.............
% $FILE=XRAM_CMND_INIT RLT JUN-1-85
COMMAND CM COMMAND
CM $$NTDS NUMTODECSTR
CM $$SP (SEND PREVIOUS)
CM $$SS (SEND SINK)
CM QUERY_PM (RECORD START ONTO PRT1;MAPCI NODISP;MTC;PM;
POST TM8 $RX_TM8;QUIT ALL;RECORD STOP ONTO PRT1)
............
By planning your execs carefully, you can restrict where the changes need to be made to one specific file. For example, all commands are defined in the self-same file. However, there may be times when you need to create commands linked to a given sub-system (e.g., EDIT, CRTSIM, DSKUT, etc.). This means that defining a command before the sub-system is up will do you no good. To get around this, we use directories to create working environments. Read on...
Fool-Proof Execs: Using Directories
When you create a directory, you are creating an artificial partition in your SFDEV memory. The neat thing about a directory is that when you create new commands, they automatically go into the TOP-MOST read/write directory. This means that you can override existing system commands or earlier definitions.
This does create some problems. For example, let's say that you have read the standard profile (STD_PROF) to define commands for the editor, and one of the commands is "D" for "DOWN". Then, when you proc up PMIST with the PUPI file, if there is a new read/write directory on top and it redefines "D" as "dump buffer", you can't get to your old "D" = "DOWN" command. You can, but you must specify the directory path; eg, USERS.MAP3.D instead of DOWN. Well, let's get on with it...
Fool-Proof Execs: Using Other People's Directories
As we saw earlier, we can specify the directory path name. This makes it easy to use commands and things from other people's directories. You just fully qualify the directory path. Say, for instance, that you're MAP1 and MAP3 has some nifty doodle new command in his UTILDIR that he wants you to try out. You don't have to put the command in your own directory to try it out. You can just type:
>USERS.MAP3.UTILDIR.NIFTYCMD
Of course, if that command expects certain variables to exist and they exist in MAP3's directory, NIFTYCMD won't work.
That does bring up another interesting point, though, because variables also exist in directories. So, if you wanted to know the contents of the variable HISVAR in user MAP3's directory, just type:
>PRINT (USERS.MAP3.UTILDIR.HISVAR)
Neat, huh?
Of course, if you wanted easy access to everything in the directory, you could always pull this little trick:
>ATTACH USERS.MAP3.UTILDIR
Now, if all this has gotten you really jazzed about directories, you might want to go back to the ATTACH section and read about the ATTACH command. It gets into some of the neat stuff you can do with directories.
Conclusions
Well, hopefully, you now know enough about SOS and CI and execs to do some reasonably productive things on the switch. I want to take a few lines here to recommend a few other documents in DIS which contain useful information. Some of these are referenced in this document, and some are not:
CPGUIDE Call Processing Guide for the DMS-250 OSA10 SOS Loader Reference Manual OSLC COPY Command on NT40 W190 EXECUTE Command DW114 Restarts OSG SOS Editor DCML1 Log System - User View OSNC NCMS N1001509 DMS-100 Family Command Reference Manual (NTP 297-1001-509) S1001509 DMS-100 Family Supplement 10 of Commands Manual (NTP 297-1001-509) N1001526 DMS-100 Family Disk Maintenance Subsystem Reference Manual (NTP 297-1001-526) SLMUG SuperNode System Load Module SLM User's Guide N1001118 DMS-100 Family Magnetic Tape Reference Manual (NTP 297-1001-118) JPF DMS-100 MPCNET User's Guide SYSDESC DMS SuperNode System Description