






        Overview
        Overview
        Overview
        Overview

             RSTS/E lends itself well to customization for a particular
        site's  requirements.  Frequently these customizations  can  be
        performed  using  DCL command procedures or  simple  Basic-Plus
        programs.   However, some customizations require  changing  the
        way RSTS handles user commands.  Such customizations cannot  be
        made using only DCL and Basic-Plus programs.

             This  presentation  will cover some  sample  customization
        cases  and  present  tools  which  can  be  used  in  your  own
        customization work.

             Please  remember  that  DEC can  only  support  unmodified
                                                             unmodified
                                                             unmodified
        versions  of the software. If you experience a problem  with  a
        utility  after  you've changed it, please  verify  the  problem
        exists  in  an unmodified version before reporting it  to  DEC.
        Additionally,  many  of  the  examples  given  depend  on   the
        (undocumented) internal formats of system items. While all have
        been tested with the latest release of RSTS/E, they may fail to
        function properly with either older or newer releases.

             A  liberal amount of time has been allotted for  questions
        and  answers from the audience.  In addition, questions may  be
        directed  to the RSTS SIG Newsletter System at (201)  915-9361.
        In addition, the sources and executables for all examples given
        are available on-line for downloading.


        Example 1 - Changing the effect of a system command
        Example 1 - Changing the effect of a system command
        Example 1 - Changing the effect of a system command
        Example 1 - Changing the effect of a system command

             Requirement:  Have  the SHOW NETWORK command  display  the
        status of all known nodes, rather than just the adjacent nodes.

             The  'tool'  we  will  use  to  investigate  the  system's
        processing of the SHOW NETWORK command is part of DCL itself  -
        the  SET  VERIFY  command.  This command  has  an  undocumented
        function which will prove helpful, but first let's look at  one
        of the documented functions:

          o It can show you the command line after symbol substitution:

             $ DISPLAY == "SHOW" ! define display as a synonym for show
             $ SET VERIFY/DEBUG  ! turn on debugging display
             $ DISPLAY NETWORK   ! issue command
             (SHOW NETWORK)      ! displays substituted command
             ... output ...

          o It can also show you the actual command that DCL issues to
            perform the task:




                                   1









             $ SET VERIFY/WATCH  ! turn on translation display
             $ SHOW NETWORK      ! issue command
             (NCP SHO ACT NOD)   ! displays actual command issued
             ... output ...

             These  two  options  can be very useful when  you  have  a
        command  procedure which isn't acting as planned.   The  /DEBUG
        option will rapidly show you if you are experiencing  undesired
        symbol  substitution.  The /WATCH option will show you  exactly
        what  command  is  being executed - in the  example  above,  it
        explains  why DECNET/E only shows active nodes rather than  all
        nodes, which would be NCP SHO KNO NOD.

             That's the problem - we're doing a show active instead  of
        a  show  known command.  What we wanted was NCP  SHO  KNO  NOD.
        This brings out an important point - strings we replace must be
        the SAME LENGTH as the originals.  Now, we'll copy the existing
        DCL.RTS to a temp file for our changes:

             $ COPY [0,1]DCL.RTS [0,1]NDCL.RTS

             Next,  we'll  invoke the SCAN program (listing at  end  of
        handout  or on the newsletter system as DU0:[49,1]SCAN.BAS)  to
        locate the text string.

             $ RUN SCAN
             Binary file search 1.20 - 17-Nov-87 KS

             File? [0,1]ndcl.rts
             Search string? ACT NOD
             Found in block 97 (000140), offset 205 (000314).
             Done...
             $

             We can compute the address used by ODT as follows:

               Disk block (in octal):  000140
             + Offset (in octal):         000314
                                       ---------
                                       000140314 (or 140314 for short)

             Now that we know the ODT address, we will need to know the
        octal values for the replacement text (ACT versus KNO).  We can
        get this by doing HELP ADVANCED ASCII.  From the chart that  is
        displayed, we see that K is 113 octal, N is 116, and O is  117.
        Now we will run the ODT program to actually modify the text  in
        our copy of the DCL run-time system.  The text in BOLD  ITALICS
                                                          BOLD  ITALICS
                                                          BOLD  ITALICS
        is what you type.

             $ run auxlib$:odt
               run auxlib$:odt
               run auxlib$:odt
             ODT  V9.4-01  RSTS V9.4-05 Newsletter Sys.
             File<MEMORY>? [0,1]ndcl.rts<LF>
                           [0,1]ndcl.rts<LF>
                           [0,1]ndcl.rts<LF>




                                   2









             [display the text to make sure we are at the right spot]
             *140314/ 041501 " AC <LF>
              140314/        "    <LF>
              140314/        "    <LF>
             140316/ 020124 " T  <LF>
                            "    <LF>
                            "    <LF>
             140320/ 047516 " NO <LF>
                            "    <LF>
                            "    <LF>
             140322/ 000104 " D  <CR>
                            "    <CR>
                            "    <CR>
             [look at the previous 4 bytes to make sure]
             *140310/ 044123 " SH <LF>
              140310/        "    <LF>
              140310/        "    <LF>
             140312/ 020117 " O  <CR>
                            "    <CR>
                            "    <CR>
             [now we will modify the ACT to KNO using the octal codes]
             *140314\ 101 113 <LF>
              140314\     113 <LF>
              140314\     113 <LF>
             140315\ 103 116 <LF>
                         116 <LF>
                         116 <LF>
             140316\ 124 117 <CR>
                         117 <CR>
                         117 <CR>
             [now let's make sure the changes were correct]
             *140314/ 047113 " KN <LF>
              140314/        "    <LF>
              140314/        "    <LF>
             140316/ 020117 " O  <CR>
                            "    <CR>
                            "    <CR>
             [all done, let's exit]
             *^Z
              ^Z
              ^Z

             Now,  make SURE that you have only changed the bytes  that
        you wanted to change.  ANY extraneous changes will cause SEVERE
        problems  sooner  or later.  In the worst case, you  might  not
        even  be  able to reboot your system!  If  you  are  ABSOLUTELY
        SURE,  issue the following command to replace the old DCL  run-
        time system:

             $ copy [0,1]ndcl.rts [0,1]dcl.rts
             OK to replace existing file DU0:[0,1]DCL   .RTS ? y
             [File [0,1]NDCL  .RTS copied to [0,1]DCL   .RTS]

             Now,  reboot your system in order for the change  to  take
        effect.  You can verify this after rebooting by re-issuing  the
        original set of commands, as follows:

             $ SET VERIFY/WATCH
             $ SHOW NETWORK
             (NCP SHO KNO NOD)

             If  you have made an error, restore DCL.RTS by  re-booting
        your  RSTS installation tape (you DO know where it is,  right?)
        and  specifying  an  UPDATE (as opposed  to  an  installation).
        Specify your system disk name and let it proceed.  Answer  'NO'
        to 'Start timesharing?'.  At the 'Option?' prompt, say  INSTALL
        monitorname,  where  monitorname  is the name  of  your  system
        monitor  (usually RSTS).  Now you may re-start your  system  as
        usual.











                                   3









        Example 2 - Changing the effect of a system command
        Example 2 - Changing the effect of a system command
        Example 2 - Changing the effect of a system command
        Example 2 - Changing the effect of a system command

             Requirement: Enhance Print/Batch Services (PBS) so that  a
        user is notified of batch job completion.

             The way to do this involves modifying the PBS server task,
        similarly to the way we modified the DCL tables above.  We want
        to  replace  the string '$_LOGOUT/BRIEF' in  PBS$:PBS.TSK  with
        another  command.  Probably the best thing to do  would  be  to
        invoke a .COM file.  Oddly enough, the string  '$_@$BATFIN.COM'
        is exactly the same length, so that is what we will replace  it
        with.  Let's use the SCAN program to find the correct place:

             $ run scan
             Binary file search 1.20 - 17-Nov-87 KS

             File? pbs$:pbs.tsk
             Search string? $_LOGOU
             Found in block 99 (000142), offset 504 (000767).
             Done...

             We can compute the address used by ODT as follows:

               Disk block (in octal):  000142
             + Offset (in octal):         000767
                                       ---------
                                       000142767 (or 142767 for short)

             Now that we know the ODT address, we will need to know the
        octal values for the replacement text.  As we did above, we can
        determine  these values from the chart in HELP ADVANCED  ASCII.
        Now we will run the ODT program to actually modify the text  in
        our  copy of the PBS task..  The text in BOLD ITALICS  is  what
                                                 BOLD ITALICS
                                                 BOLD ITALICS
        you type.

             $ run auxlib$:odt
               run auxlib$:odt
               run auxlib$:odt
             ODT  V9.4-01  RSTS V9.4-05 Newsletter Sys.
             File<MEMORY>? pbs$:pbs.tsk<LF>
                           pbs$:pbs.tsk<LF>
                           pbs$:pbs.tsk<LF>

             *142767/ 044 " $ <LF>
              142767/     "   <LF>
              142767/     "   <LF>
             142770\ 137 " _ <LF>
                         "   <LF>
                         "   <LF>
             142771\ 114 " L <LF>
                         "   <LF>
                         "   <LF>
             [look at the data to make sure we're in the right spot]
             *142771\ 114 100 <LF>
              142771\     100 <LF>
              142771\     100 <LF>
             142772\ 117 044 <LF>
                         044 <LF>
                         044 <LF>
             142773\ 107 102 <LF>
                         102 <LF>
                         102 <LF>
             142774\ 117 101 <LF>
                         101 <LF>
                         101 <LF>
             142775\ 125 124 <LF>
                         124 <LF>
                         124 <LF>
             142776\ 124 106 <LF>
                         106 <LF>
                         106 <LF>
             142777\ 057 111 <LF>
                         111 <LF>
                         111 <LF>
             143000\ 102 116 <LF>
                         116 <LF>
                         116 <LF>
             143001\ 122 056 <LF>
                         056 <LF>
                         056 <LF>
             143002\ 111 103 <LF>
                         103 <LF>
                         103 <LF>



                                   4









             143003\ 105 117 <LF>
                         117 <LF>
                         117 <LF>
             143004\ 106 115 <LF>
                         115 <LF>
                         115 <LF>
             143005\ 015 <CR>
                         <CR>
                         <CR>
             [enter the new text]
             *142770/ 040137 " _@ <LF>
              142770/        "    <LF>
              142770/        "    <LF>
             142772/ 041044 " $B <LF>
                            "    <LF>
                            "    <LF>
             142774/ 052101 " AT <LF>
                            "    <LF>
                            "    <LF>
             142776/ 044506 " FI <LF>
                            "    <LF>
                            "    <LF>
             143000/ 027116 " N. <LF>
                            "    <LF>
                            "    <LF>
             143002/ 047503 " CO <LF>
                            "    <LF>
                            "    <LF>
             143004/ 006515 " M<LF>
                            "  <LF>
                            "  <LF>
             [verify changes]
             *^Z

             Now,  make SURE that you have only changed the bytes  that
        you wanted to change.  ANY extraneous changes will cause SEVERE
        problems  sooner or later.  If you have any problems  with  PBS
        because  of this change, simply restore PBS$:PBS.TSK from  your
        most recent backup (you do have one, don't you?).

             Next,  we  will  need to create the .COM  file  in  the  $
        account.  Remember that this file will be executed by users who
        may not have requisite privileges for some operations. However,
        with  some  deviousness, you can work around this.   You  could
        also  write a program privileged <232> to accomplish  the  same
        thing.   Make  sure that the .COM file is  protected  <104>  so
        users can execute it. Below is a sample .COM file:

        $_SET NOVERIFY
        $_SET NOON
        $WHO = F$USER
        $WHICH = F$JOB
        $_IF F$PRIV("NOSEND") THEN _GOTO CANT
        $_BROADCAST/BELL 'WHO' "Batch job ''WHICH' has completed"
        $_GOTO DONE
        $CANT:
        $_IF F$SEAR("MAIL$:MAIL.HLP") .EQS. "" THEN _GOTO NOMAIL
        $_SET DATA
        $_CCL SEND "Batch job ''WHICH' has completed" TO I
        Y
        $EOD
        $_GOTO DONE
        $NOMAIL:
        $_WRITE 0 "Couldn't notify user!"
        $DONE:
        $_LOGOUT/BRIEF
        $ ! Sample .COM file to notify user of batch completion. If the
        $ ! batch job has SEND priv, then we simply send a message.
        $ ! Otherwise, if the system has DECMAIL, we will MAIL ourself
        $ ! a message. Failing in that, we write a comment to the batch
        $ ! logfile saying we can't notify the user.





                                   5









        Example 3 - Changing one sub-option of a system command
        Example 3 - Changing one sub-option of a system command
        Example 3 - Changing one sub-option of a system command
        Example 3 - Changing one sub-option of a system command

             Requirement:  Modify the SET HOST command so that  issuing
        it requires the USER1 privilege.

             Frequently, it is desirable to modify the operation of one
        of  the  'complex' DCL commands.  A good example of  a  complex
        command  is  the SET command.  This example shows how  a  Basic
        utility  can be 'inserted' in the SET command processing.   The
        system passes the SET command line to the Basic program,  which
        then  performs any desired inspection or modification  and  re-
        issues  the  command  with  a  leading  underscore  to  prevent
        infinite looping. This technique is very useful (as an example)
        for  forcing a user to specify a command line option which  SET
        usually  defaults.  This works because specifying  a  qualifier
        without  a corresponding argument will cause DCL to prompt  for
        the missing argument.

        1000    EXTEND &
                ! SET.BAS - Example of a utility to trap a suboption of a complex &
                !           DCL command (in this case, SET HOST). &
                ! &
                ! V1.0-00 - 11-May-88 - tmk &
                !
        1010    CMD$=SYS(CHR$(7%)) &
                ! Get user's SET command &
                \ CMD2$=CVT$$(CMD$,32%) &
                ! Convert to upcase &
                \ I%=INSTR(1%,CMD2$,"/") &
                \ I%=LEN(CMD2$) IF I%=0% &
                ! Get location of first option, or length if none &
                \ J%=INSTR(1%,CMD2$," HO") &
                ! Get location of HOST option - attempt 1 &
                \ GOTO 1020 IF J%<>0% &
                ! If found as <space>HO &
                \ J%=INSTR(1%,CMD2$,"   HO") &
                ! Get location of HOST option - attempt 2 &
                ! Note: The above code is "<tab>HO"
        1020    GOTO 1030 IF J%=0% &
                \ GOTO 1030 IF J%>I% &
                ! Skip if no HOST found before 1st option &
                \ A$=SYS(CHR$(6%)+CHR$(32%)+CHR$(1%)+STRING$(3%,0%)+"USER1"+CHR$(0%)) &
                \ GOTO 1030 IF MID(A$,3%,1%)=CHR$(0%) &
                ! Check for USER1 priv. Proceed if present &
                \ PRINT "?SET HOST requires USER1 privilege."+CHR$(7%)+CHR$(13%) &
                \ GOTO 32767 &
                ! Else give the error message
        1030    A$=SYS(CHR$(14%)+"$_"+CMD$) &
                ! Issue the command directly to DCL
        32767   END






                                   6









             The above would be activated by placing the command:
                  DEFINE/COMMAND/SYSTEM  SE-T  $SET.*  /PRIV
             in the [0,1]START.COM file, and the command:
                  SE*T == "CCL SET"
             in the system-wide LOGIN.COM file.


        Example 4 - Allow 'named' logins as well as by PPN
        Example 4 - Allow 'named' logins as well as by PPN
        Example 4 - Allow 'named' logins as well as by PPN
        Example 4 - Allow 'named' logins as well as by PPN

             Requirement:  Enhance  LOGIN  to allow a  username  to  be
        specified as well as a PPN. (This is known as 'VMS envy').

             The  example given here presumes that you have  DECmail-11
        for  RSTS V3.0 or newer installed on your system.  This  allows
        you  to  use your DECmail-11 username as a login name.  If  you
        don't  have  DECmail-11,  you can easily read a  text  file  of
        username-to-PPN mappings instead.

             Working  with  a COPY of LOGIN.COM and an editor  of  your
                              COPY
                              COPY
                              COPY
        choice,  change the line number of line 13001 to 13008.  Insert
        the following code immediately before that line:

        13001   OPEN "MAIL$:NAMES.SYS" FOR INPUT AS FILE #2%, &
                    RECORDSIZE 512%, MODE 8192% &
                \ FIELD #2%, 512% AS MAIWRK$ &
                \ LOGIN1$=CVT$$(LOGIN$,34%) &
                \ GOTO 13004 IF LOGIN1$="" &
                \ GET #2%, BLOCK 1% &
                \ MAIREC%=CVT$%(MID(MAIWRK$,5%,2%)) &
                ! OPEN THE MAIL NAMES FILE &
                ! CONVERT TYPED USERNAME TO UPCASE, NO SPACES OR TABS &
                ! GET THE FIRST RECORD OF MAIL USERNAMES &

        13002   GET #2%, BLOCK MAIREC% &
                \ FOR MAITMP%=33% TO 512% STEP 16% &
                \ MAINAM$=CVT$$(MID(MAIWRK$,MAITMP%,12%),160%) &
                \ GOTO 13003 IF MAINAM$=LOGIN1$ &
                \ NEXT MAITMP% &
                \ MAIREC%=CVT$%(LEFT(MAIWRK$,2%)) &
                \ GOTO 13002 UNLESS MAIREC%=0% &
                \ GOTO 13004 &
                ! READ THE FIRST USERNAME BLOCK &
                ! LOOK AT ALL THE POSSIBLE NAMES IN IT &
                ! IF WE HAVE A MATCH, EXIT &
                ! ELSE LOOK AT REST &
                ! IF NOT FOUND, DETERMINE NEXT RECORD AND LOOP IF NOT &
                !   AT END &
                ! ELSE RETURN A NON-MATCH &

        13003   LOGIN$="["+NUM1$(ASCII(MID(MAIWRK$,MAITMP%+12%,1%))) &
                   +","+NUM1$(ASCII(MID(MAIWRK$,MAITMP%+13%,1%)))+"]" &
                ! CONSTRUCT PPN FROM MAIL USERNAME ENTRY &




                                   7









        13004   CLOSE #2% &
                ! CLOSE THE MAIL NAMES FILE &


             Change the start of line 13900 as follows:

        13900   RESUME 13008 IF ERL=13001 &
                \ RESUME 13008 IF ERL=13002 &
                \ RESUME 19999 IF KB.SPAWNED% OR (NOT (LOGGED.IN%)) &
                    OR A%=0% &
                \ PRINT "?Invalid entry - try again" IF A% &


             Once  you  have  entered the patches  into  your  copy  of
        LOGIN.BAS,  compile  it with Basic-Plus 2 if you  have  it,  as
        shown below:

        $ RUN $BP2IC2
        SCALE 0
        OLD LOGIN.BAS
        COMPILE LOGIN.OBJ/OBJ/CHA/LIN/NODEB/WOR/NOCRO/NOLIS/FLAG:NODEC
        $ SW DCL
        $ TKB
        LOGIN.TSK/FP=LOGIN.OBJ,LB:BP2OTS.OLB/LB
        /
        UNITS=13
        ASG=SY:5:6:7:8:9:10:11:12
        EXTTSK=512
        LIBR=CSPLIB:RO
        //
        $ DELETE/NOLOG LOGIN.OBJ

             Note  that Basic-Plus 2 V2.4 has a bug which  prevents  it
        from  compiling  LOGIN, with or  without  these  modifications.
        Therefore, you must use either V2.3 or V2.5. If you don't  have
        BP2, you can use Basic-Plus. CSPCOM will not work, so don't use
        it!  Now, log onto your system from at least two terminals  (so
        you can recover if something goes wrong). Rename $LOGIN.TSK  to
        $LOGIN.OLD,  and copy the new LOGIN program  (either  LOGIN.TSK
        for  BP2 or LOGIN.BAC for B+) to $. Ensure it has a  protection
        code of <232>.

             Next,  ensure  that  the  DECmail-11  NAMES.SYS  file   is
        readable by all users:

             PIP MAIL$:NAMES.DAT<40>/RE

             Basic installation is now complete. You may now enter  any
        valid  MAIL  username  when logged-out, and  then  provide  the
        password  in the usual manner. If you want this new feature  to
        work when logged-in also, you will need to make some additional
        changes  because DCL will try to outsmart you by  not  allowing
        non-numeric user information in the DCL LOGIN command. You  can



                                   8









        cure  this  by  inserting  the following  two  lines  in  their
        respective files:

             In [0,1]START.COM:
             $ define/command/system LOG-IN $LOGIN.* /privilege

             In [0,1]LOGIN.COM:
             $ LOG-IN == "CCL LOGIN"

             Note   that   this   will   'break'   the   DCL    command
        LOGIN/TERMINAL.  To work around this, simply put an  underscore
        in  front  of  that  command  wherever  it  is  used,  as   so:
        _LOGIN/TERMINAL=KB1: [1,2]. This problem only happens when  you
        add the two lines for logged-in name translation.

             Name  translation  will not work in  DECNET  requests  for
        access information, as they are not handled by LOGIN.

        Example 5 - Helper .TSK file number one
        Example 5 - Helper .TSK file number one
        Example 5 - Helper .TSK file number one
        Example 5 - Helper .TSK file number one

             Requirement:  A  site  has many RSTS  systems  of  varying
        vintages,  and wants to have a common backup procedure to  back
        up  all the disks on a system to tape. The problem is that  one
        system  has  RA81's and a TU80, and another has  RK07's  and  a
        TE16.

             If  we had a list of all the disk devices and  their  pack
        ID's,  a  simple  .COM file could be  constructed  which  would
        prompt the operator for each disk.  The trick is to fish around
        in   the  RSTS/E  Internals  Manual  (either  DEC's   or   Mike
        Mayfield's)   to   determine  where  the  system   keeps   this
        information.  Once  we have that information, we  can  write  a
        program like this:

        1000    EXTEND &
                ! DSKTBL.BAS - Return first available tape unit and all mounted &
                !              disk units in DCL symbol DSKTBL. &
                ! &
                ! V1.0-00 - 11-May-88 - tmk &
                !
        1010    DIM M%(30%),M2%(30)
        1020    CHANGE SYS(CHR$(6%)+CHR$(-3%)) TO M% &
                \ M%(J%)=M%(J%)+SWAP%(M%(J%+1%)) FOR J%=5% TO 29% STEP 2% &
                \ CHANGE SYS(CHR$(6%)+CHR$(-12%)) TO M2% &
                \ M2%(J%)=M2%(J%)+SWAP%(M2%(J%+1%)) FOR J%=3% TO 29% STEP 2%
        1030    DEVCNT%=M%(5%) &
                \ UNTCNT%=M%(19%) &
                \ DEVNAM%=M2%(5%) &
                \ NUM.DISK.TYPES%=M2%(9%) &
                \ DEV.IDX%=0%
        1040    NXTDEV$=CVT%$(SWAP%(PEEK(DEVNAM%+NUM.DISK.TYPES%+DEV.IDX%))) &
                \ GOTO 1050 IF NXTDEV$="TT" &
                ! If got to TT (1st synonym), no tapes present &



                                   9









                \ GOTO 1060 IF LEFT(NXTDEV$,1%)="M" &
                ! If we have a tape, that's all we need to know... &
                \ DEV.IDX%=DEV.IDX%+2% &
                \ GOTO 1040
        1050    NXTDEV$="XX" &
                ! Indicate impossible device
        1060    DSKTBL$=NXTDEV$+"0:" &
                ! Store tape unit name &
                \ DSKLOG%=M2%(21%) &
                \ FUN% = 0% &
                \ FOR C%=0% TO NUM.DISK.TYPES%-2% STEP 2% &
                \       DEVICE.NAME$=CVT%$(SWAP%(PEEK(DEVNAM%+C%))) &
                \       FOR U%=0% TO PEEK(DEVCNT%+C%) &
                \               UNTCNT.ENTRY%=PEEK(UNTCNT%+FUN%) &
                \               DSKLOG.PTR%=DSKLOG%+(FUN%*5%) &
                \               GOTO 1070 IF UNTCNT.ENTRY%<0% &
                !               No more units for device type &
                \               GOTO 1070 IF (UNTCNT.ENTRY% AND 4096%)<>0% &
                !               Mounted non-file-structured &
                \               GOTO 1070 IF DEVICE.NAME$="DV" &
                !               Omit virtual disk, too &
                \               DSKTBL$=DSKTBL$+DEVICE.NAME$+NUM1$(U%)+":"+ &
                                RAD$(PEEK(DSKLOG.PTR%))+RAD$(PEEK(DSKLOG.PTR%+2%))+ &
                                RAD$(PEEK(DSKLOG.PTR%+4%)) &
                !               Else add to disk name string
        1070                    FUN% = FUN%+2% &
                \       NEXT U% &
                \ NEXT C% &
                \ A$=SYS(CHR$(14%)+"$DSKTBL="+CHR$(34%)+DSKTBL$+CHR$(34%))
        32767   END


             First,  the  program looks a non-disk devices  to  see  if
        there is a tape drive on the system. The first tape drive found
        will be used for the backup. If there is no tape drive, we will
        find  the 'TT' synonym for keyboards. In that case, we  set  an
        impossible  device  name  as  a flag  for  the  .COM  file  and
        continue.  Next,  the program traverses the disk  device  table
        looking for disks which are configured on the system.  It  then
        verifies  that the unit number we are looking at exists and  is
        mounted   (and  not  mounted  non-file-structured).   If   this
        requirement  is met and the disk is not the virtual  disk,  the
        device  name  and pack name are appended to  the  string.  When
        there  are  no more disk units, the string is appended  to  the
        text:
             $DSKTBL=

             which is then issued as a CCL command. Since $ is always a
        legal  CCL,  the  entire command is passed to  DCL  which  will
        create  a symbol called DSKTBL, containing the  information  we
        want.  The following .COM file uses this information to  prompt
        the operator for volumes to be backed up:




                                   10









        $ ! BAKDSK.COM - Do a BACKUP of all disks on the system (that we know about)
        $ ! 11-May-88 - Version to user 'helper' .TSK for device names
        $ _on control_c then goto escape
        $ _set nodata
        $ _set noon
        $ _ope/log/rep BAKDSK.LOG
        $ _write 0 "This procedure will back up all of the disks onto tape."
        $ _write 0 "It is suggested that you do a PURGE before proceeding."
        $ _inquire/exit=byebye isgood "Do you wish to continue? (<Y>/N)"
        $ _if f$left(f$edit(isgood,38),1) .eqs. "N" then _goto byebye
        $ _write 0 ""
        $ _run TOOLS:DSKTBL
        $ _if f$left(dsktbl,1) .nes. "M" then _goto notape
        $ tapdev=f$left(dsktbl,4)       ! name of tape drive on system
        $ dsktbl=f$mid(dsktbl,5,f$len(dsktbl))
        $nxtdsk:
        $ _if f$len(dsktbl) .eq. 0 then _goto alldun
        $ dskdev=f$left(dsktbl,4)       ! device name of current disk
        $ dsknam=f$mid(dsktbl,5,9)      ! full name (9 chars) for mounted pack
        $ dsknam=f$edit(dsknam,38)      ! trim trailing spaces
        $ dskna6=f$left(dsknam,6)       ! short name for backup set ID
        $ dsktbl=f$mid(dsktbl,14,f$len(dsktbl))
        $ _inquire/exit=byebye nxtdsk -
         "Do you wish to back up ''dskdev'''dsknam'? (<Y>/N)"
        $ if f$left(f$edit(nxtdsk,38),1) .eqs. "N" then goto nxtdsk
        $ _backup/account_data/in_label='dsknam'/initialize/listfile= -
         'dskna6'.LST/out_label='dskna6'/rewind/end=nodismount -
         'dskdev'[*,*]*.* 'tapdev''dskna6'.BCK
        $ _copy 'dskna6'.LST 'tapdev'
        $ _delete 'dskna6'.LST
        $ _dismount 'tapdev'/unload
        $ _write 0 "Please dismount this volume."
        $ _if $severity .ge. 2 then goto isitok
        $ _goto nxtdsk
        $alldun:
        $ _write 0 ""
        $ _write 0 "The backup procedure is now complete."
        $byebye:
        $ _close/log
        $ _print/queue=LP0: BAKDSK.LOG
        $ _exit
        $isitok:
        $ _write 0 "Please inspect the console log for fatal errors and"
        $ _write 0 "retry this volume if required."
        $ _goto nxtdsk
        $escape:
        $ _set noon
        $ _write 0 "?Aborted by Control-C"
        $ _goto byebye
        $notape:
        $ _write 0 "?No tape units configured on system - cannot continue."
        $ _goto byebye




                                   11










        Example 6 - Helper .TSK file number two
        Example 6 - Helper .TSK file number two
        Example 6 - Helper .TSK file number two
        Example 6 - Helper .TSK file number two

             Requirement: The same site as in the previous example  has
        a  number  of RSTS systems, all DECnetted  together.  The  site
        wants  to  have a common START.COM system  startup  file,  with
        conditional sections for system-unique items.

             The 'obvious' answer to this is to use the system  logical
        F$NODE()  to  get the DECnet/E node name.  Unfortunately,  this
        logical   is  not  defined  until  the  DECnet/E  is   started.
        Therefore,  it is unavailable at the critical early  stages  of
        system  startup.  Therefore, the following program was  written
        to look in the DECnet/E permanent parameter file and return the
        executor node name defined there:

        1000    EXTEND &
                ! GETNOD.BAS - Return the system's DECNET node name, *even* if DECnet/E &
                !              is not currently running. The node name (or null if no &
                !              network is configured) is returned in DCL symbol FNODE &
                ! &
                ! V1.0-00 - 11-May-88 - tmk &
                !
        1010    ON ERROR GOTO 1030
        1020    OPEN "[0,1]NETPRM.SYS" FOR INPUT AS FILE #1%, RECORDSIZE 512% &
                \ FIELD #1, 2% AS JUNK1$, 2% AS EXEC$, 508% AS JUNK2$ &
                \ GET #1%, RECORD 1% &
                ! Get header record &
                \ EXEC%=SWAP%(CVT$%(EXEC$))+1% &
                ! Extract pointer to Executor definition record &
                \ FIELD #1, 84% AS JUNK1$, 6% AS NODNAM$, 44% AS JUNK2$, &
                            17% AS NETFIL$, 361% AS JUNK3$ &
                \ GET #1%, RECORD EXEC% &
                ! Get Executor definition record &
                \ GOTO 1040 IF NETFIL$<>"SY0:[0,1]NSP0.SYS" &
                ! Verify we're in the right place &
                \ GOTO 1050
        1030    NODNAM$="" &
                ! If no permanent parameter file, no node name &
                \ RESUME 1050
        1040    PRINT "%Node identification may be inaccurate."
        1050    A$=SYS(CHR$(14%)+"$FNODE="+CHR$(34%)+NODNAM$+CHR$(34%))
        32767   END

             Again, a symbol (FNODE) is returned containing the current
        executor node name. The check for NSP0.SYS is a 'sanity  check'
        on the location of the node name information.  Since the format
        of  internal system information is undocumented by DEC,  it  is
        wise to include as many of these checks as needed, in the event
        that DEC changes the structure of the file.






                                   12









        Example 7 - DECmail-11 'directory assistance'
        Example 7 - DECmail-11 'directory assistance'
        Example 7 - DECmail-11 'directory assistance'
        Example 7 - DECmail-11 'directory assistance'

             Requirement:  Implement  a  user  directory  function  for
        DECmail-11.  It should include the mail name, full  user  name,
        department, title, phone number and comment fields.

             DECmail-11  uses a text file in the MAIL$:  account  named
        NAMES.DAT  as  an ASCII list of usernames.  The  DECmail  NAMES
        program converts this list into a binary file for use by  MAIL.
        One  of  the features of the NAMES program is  the  removal  of
        comment fields in the NAMES.DAT file. Therefore, we can use the
        NAMES file to contain the additional information as a  comment.
        A sample NAMES.DAT file follows:

        !  DECmail-11 user names - 21-Jan-87 - tmk
        !  Format of comment field is !department,title,phone,comment
        !  ALL commas must be in place or INFO will blow up!
        [1,4],DEC Field Service,FIELD           !System support,,N/A,
        [1,245],Paul Greene,PAUL                !Academic Computer Services,,X9381,
        [1,247],Richard Labov,RLABOV            !Off-campus,,N/A,
        [1,253],Ben Cohen,BEN                   !Academic Computer Services,,X9381,
        [1,254],Terry Kennedy,TERRY             !Academic Computer Services,Systems Manager,X283,
        [1,254],Information,INFO                !MAIL information & help,,X9381,
        [10,1],Generic MAIL sender,MAIL         !Generic MAIL sender,,,Cannot receive MAIL
        [10,2],SIS MAIL Test,SIS_TEST           !SIS MAIL test account,,,

             The  INFO  program processes this information  to  produce
        reports line the ones shown:

        $ info

        Info> dir
        Directory of users on local node
        UserID       Full username                Account   Department
        ------------ ---------------------------- --------- ---------------------------
        FIELD        DEC Field Service            [1,4]     System support
        PAUL         Paul Greene                  [1,245]   Academic Computer Services
        RLABOV       Richard Labov                [1,247]   Off-campus
        BEN          Ben Cohen                    [1,253]   Academic Computer Services
        TERRY        Terry Kennedy                [1,254]   Academic Computer Services
        INFO         Information                  [1,254]   MAIL information & help
        MAIL         Generic MAIL sender          [10,1]    Generic MAIL sender
        SIS_TEST     SIS MAIL Test                [10,2]    SIS MAIL test account
        End of requested listing.

        Info> who mail
        UserID:        MAIL
        Full username: Generic MAIL sender
        Department:    Generic MAIL sender
        Title:
        Phone no.:
        Account:       [10,1]
        Comment field: Cannot receive MAIL



                                   13









        Last login:    05-May-88 01:46 PM

        Auto answer message:
          The account you are sending mail to is a send-only account,
        and therefore cannot receive the mail you have just sent to
        it. Please use alternate means of contacting the individual.

        Info> search computer
        Listing of matching users on local node
        UserID       Full username                Account   Department
        ------------ ---------------------------- --------- ---------------------------
        PAUL         Paul Greene                  [1,245]   Academic Computer Services
        BEN          Ben Cohen                    [1,253]   Academic Computer Services
        TERRY        Terry Kennedy                [1,254]   Academic Computer Services
        End of requested listing.

        Info> ^Z

             As  you  can  see,  there  are  several  report   formats.
        Additionally, the date/time of last login and any DECmail auto-
        answer  message are displayed.  Here are the files required  to
        build the INFO task:

        10      EXTEND
        20      ! INFO.BAS - 1.00-00 02-Nov-87 - tmk - Directory pgm for DECMAIL-11 &
                !            1.10-01 05-Nov-87 - tmk - Add CCL entry, command args, &
                !                                      better help &
                !            1.20-02 17-Nov-87 - tmk - Move substringing into subrou- &
                !                                      tine, add DECNET/E support &
                ! &
                ! NOTICE - See the comments at line 11000 regarding DECnet/E support &
                ! before compiling or installing this software. &
                ! &

        100     ON ERROR GOTO 32400             ! SET STANDARD ERROR TRAP &
                \ PRINT "MAIL directory program V1.20-02 - 17-Nov-87 - tmk" &
                \ PRINT "" &
                \ PRINT "Enter 'HELP' at the Info> prompt for help." &

        110     OPEN "_KB:INFO.CMD" AS FILE #2% &
                \ NODE$=""                      ! DEFAULT TO LOCAL NODE &

        120     PRINT &
                \ GOTO 32760 IF CCLENT%<>0% &
                \ CCLENT%=0%
        125     PRINT "Info> ";                 ! PRINT PROMPT &
                \ INPUT LINE #2%, CMND$         ! GET COMMAND
        130     CLOSE #1%                       ! CLOSE MAIL NAMES FILE
        140     CMND$=CVT$$(CMND$,189%) ! MAKE IT U/C &
                \ GOTO 125 IF CMND$="" &
                \ GOTO 125 IF CMND$=" " &
                \ ARG$="" &
                \ I%=INSTR(1%,CMND$," ")        ! ANY ARGUMENTS? &



                                   14









                \ GOTO 150 IF I%=0%             ! IF NOT &
                \ ARG$=MID(CMND$,I%+1%,LEN(CMND$))
        150     GOTO 1000 IF LEFT(CMND$,1%)="H" &
                \ GOTO 2000 IF LEFT(CMND$,1%)="S" &
                \ GOTO 3000 IF LEFT(CMND$,1%)="D" &
                \ GOTO 4000 IF LEFT(CMND$,1%)="W" &
                \ GOTO 5000 IF LEFT(CMND$,1%)="V" &
                \ GOTO 6000 IF LEFT(CMND$,1%)="N" &
                \ GOTO 32760 IF LEFT(CMND$,1%)="Q" &
                \ PRINT "Unknown command '";CMND$;"'." &
                \ GOTO 120 &

        1000    ! HELP FUNCTION &
                ! &
                PRINT "" &
                \ PRINT "INFO is a program which allows you to look up users in the MAIL" &
                \ PRINT "database on this system or on other RSTS/E systems (if you have" &
                \ PRINT "the DECnet/E package) by a number of options. The options which" &
                \ PRINT "are available are:" &
                \ PRINT "" &
                \ PRINT " SEARCH -    Locate a person by department, title, name, etc." &
                \ PRINT "             You enter the text you want to look for. All rec-" &
                \ PRINT "             ords which match will be displayed. " &
                \ PRINT " DIRECTORY - Display the entire user directory on the terminal." &
                \ PRINT " WHO -       Display detailed information about a specific user" &
                \ PRINT "             on the terminal.  This is the only way to view the" &
                \ PRINT "             entire data for a user." &
                \ PRINT " NODE -      Allows you to specify a different RSTS/E system to" &
                \ PRINT "             look up users on (if you have the DECnet/E package" &
                \ PRINT "             installed).  By default,  lookups are done on your" &
                \ PRINT "             computer system." &
                \ PRINT " VERSION -   Display the version number of this program." &
                \ PRINT " QUIT -      Exit from this program." &
                \ PRINT "" &
                \ PRINT "If you wish to update your own information, simply send MAIL to" &
                \ PRINT "INFO detailing the changes you want made. Similarly, department" &
                \ PRINT "chairs may request the addition or deletion of faculty member's" &
                \ PRINT "information." &
                \ GOTO 120 &

        2000    ! SEARCH FUNCTION &
                ! &
                SCAN$=ARG$ &
                \ PRINT "Search string? "; IF SCAN$="" &
                \ INPUT LINE #2%,SCAN$ IF SCAN$="" &
                \ SCAN$=CVT$$(SCAN$,37%) &
                \ GOSUB 11000                   ! OPEN NAMES FILE
        2010    LIN%=0% &
                \ PRINT "Listing of matching users on "; &
                \ PRINT "local node" UNLESS NODE$<>"" &
                \ PRINT "node ";NODE$;"::" IF NODE$<>"" &
                \ PRINT "UserID       Full username                Account   "+ &
                "Department" &



                                   15









                \ PRINT "------------ ---------------------------- --------- "+ &
                "---------------------------"
        2020    GOSUB 10000                     ! GET RECORD & SNIP &
                \ GOTO 2030 IF SPLIT1%=0%       ! ON EOF &
                \ GOTO 2020 IF INSTR(1%,CVT$$(DATUM$,32%),SCAN$)=0% &
                \ PRINT U.ID$; &
                \ PRINT TAB(13%);U.NAME$; &
                \ PRINT TAB(42%);U.ACCT$; &
                \ PRINT TAB(52%);U.DEPT$ &
                \ LIN%=LIN%+1% &
                \ GOTO 2020 IF LIN%<19%         ! MORE ROOM ON SCREEN &
                \ PRINT "Press [RETURN] for next screen or any key to exit..." &
                \ INPUT #2%, CMND$ &
                \ GOTO 2010 IF CMND$="" &
                \ GOTO 120
        2030    PRINT "End of requested listing." &
                \ GOTO 120 &

        3000    ! DIRECTORY FUNCTION &
                ! &
                GOSUB 11000                     ! OPEN NAMES FILE
        3005    LIN%=0% &
                \ PRINT "Directory of users on ";
                \ PRINT "local node" UNLESS NODE$<>"" &
                \ PRINT "node ";NODE$;"::" IF NODE$<>"" &
                \ PRINT "UserID       Full username                Account   "+ &
                "Department" &
                \ PRINT "------------ ---------------------------- --------- "+ &
                "---------------------------"
        3010    GOSUB 10000                     ! GET RECORD & SNIP &
                \ GOTO 3020 IF SPLIT1%=0%       ! ON EOF &
                \ PRINT U.ID$; &
                \ PRINT TAB(13%);U.NAME$; &
                \ PRINT TAB(42%);U.ACCT$; &
                \ PRINT TAB(52%);U.DEPT$ &
                \ LIN%=LIN%+1% &
                \ GOTO 3010 IF LIN%<19%         ! MORE ROOM ON SCREEN &
                \ PRINT "Press [RETURN] for next screen or any key to exit..." &
                \ INPUT #2%, CMND$ &
                \ GOTO 3005 IF CMND$="" &
                \ GOTO 120
        3020    PRINT "End of requested listing." &
                \ GOTO 120 &

        4000    ! WHO FUNCTION (DOCTOR, DOCTOR...) &
                ! &
                USERID$=ARG$ &
                \ PRINT "UserID? "; IF USERID$="" &
                \ INPUT LINE #2, USERID$ IF USERID$="" &
                \ USERID$=CVT$$(USERID$,37%) &
                \ GOSUB 11000                   ! OPEN NAMES FILE
        4010    GOSUB 10000                     ! GET RECORD AND SNIP &
                \ GOTO 4060 IF SPLIT1%=0%       ! IF EOF &



                                   16









                \ GOTO 4010 IF USERID$<>MID(DATUM$,SPLIT2%+1%,SPLIT3%-SPLIT2%-1%) &
                \ PRINT "UserID: ";TAB(15%); &
                \ PRINT NODE$+"::"; IF NODE$<>"" &
                \ PRINT U.ID$ &
                \ PRINT "Full username: ";TAB(15%);U.NAME$ &
                \ PRINT "Department: ";TAB(15%);U.DEPT$ &
                \ PRINT "Title: ";TAB(15%);U.TITLE$ &
                \ PRINT "Phone no.: ";TAB(15%);U.PHONE$ &
                \ PRINT "Account: ";TAB(15%);U.ACCT$ &
                \ PRINT "Comment field: ";TAB(15%);U.COMNT$ &
                \ PRINT "Last login: ";TAB(15%);U.LSTLG$
                \ GOTO 120 IF NODE$<>""         ! NO AUTOANSWER IF REMOTE NODE
        4020    FILNAM$=U.ACCT$+"AUTOAN.MSG" &
                \ OPEN FILNAM$ FOR INPUT AS FILE #3% &
                \ PRINT "" &
                \ PRINT "Auto answer message:"
        4030    INPUT LINE #3%, MSG$ &
                \ PRINT MSG$; &
                \ GOTO 4030
        4040    CLOSE #3%
        4050    GOTO 120
        4060    PRINT "UserID not found." &
                \ GOTO 120 &

        5000    ! VERSION FUNCTION &
                ! &
                PRINT "INFO V1.20-02 - 17-Nov-87 - tmk" &
                \ GOTO 120 &

        6000    ! NODE FUNCTION &
                ! &
                NODE$=ARG$ &
                \ PRINT "Node? "; IF NODE$="" &
                \ INPUT LINE #2, NODE$ IF NODE$="" &
                \ NODE$=CVT$$(NODE$,37%) &
                \ GOTO 120 &

        10000   INPUT LINE #1%,DATUM$ &
                \ U.DEPT$="" &
                \ U.TITLE$="" &
                \ U.PHONE$="" &
                \ U.COMNT$="" &
                \ DATUM$=LEFT(DATUM$,LEN(DATUM$)-2%) &
                \ GOTO 10000 IF LEFT(DATUM$,1%)="!" &
                \ SPLIT1%=INSTR(1%,DATUM$,"],")+1% &
                \ SPLIT2%=INSTR(SPLIT1%+1%,DATUM$,",") &
                \ SPLIT3%=INSTR(SPLIT2%+1%,DATUM$,CHR$(9%)) &
                \ SPLIT3%=LEN(DATUM$)+1% IF SPLIT3%=0% &
                \ SPLIT4%=INSTR(SPLIT3%+1%,DATUM$,"!") &
                \ SPLIT5%=INSTR(SPLIT4%+1%,DATUM$,",") &
                \ SPLIT6%=INSTR(SPLIT5%+1%,DATUM$,",") &
                \ SPLIT7%=INSTR(SPLIT6%+1%,DATUM$,",") &
                \ U.ID$=MID(DATUM$,SPLIT2%+1%,SPLIT3%-SPLIT2%-1%) &



                                   17









                \ U.NAME$=MID(DATUM$,SPLIT1%+1%,SPLIT2%-SPLIT1%-1%) &
                \ U.ACCT$=LEFT(DATUM$,SPLIT1%-1%) &
                \ GOTO 10010 IF SPLIT3%=LEN(DATUM$)+1% &
                \ U.DEPT$=MID(DATUM$,SPLIT4%+1%,SPLIT5%-SPLIT4%-1%) &
                \ U.TITLE$=MID(DATUM$,SPLIT5%+1%,SPLIT6%-SPLIT5%-1%) &
                \ U.PHONE$=MID(DATUM$,SPLIT6%+1%,SPLIT7%-SPLIT6%-1%) &
                \ U.COMNT$=MID(DATUM$,SPLIT7%+1%,80%)
        10010   U.LSTLG$="<None>" &
                \ U.LSTLG$="<Not available>" IF NODE$<>"" &
                \ GOTO 10020 IF NODE$<>""       ! IF NOT SAME NODE, NO LAST LOGIN &
                \ SPLIT1A%=INSTR(1%,DATUM$,",") &
                \ PROJ%=VAL(MID(DATUM$,2%,SPLIT1A%-2%)) &
                \ PROG%=VAL(MID(DATUM$,SPLIT1A%+1%,SPLIT1%-SPLIT1A%-2%)) &
                \ MSG$=SYS(CHR$(6%)+CHR$(-25%)+CHR$(-1%)+CHR$(4%)+CHR$(PROG%)+ &
                  CHR$(PROJ%)) &
                \ GOTO 10020 IF CVT$%(MID(MSG$,9%,2%))=0% &
                \ U.LSTLG$=DATE$(SWAP%(CVT$%(MID(MSG$,9%,2%))))+ &
                  " "+TIME$(SWAP%(CVT$%(MID(MSG$,11%,2%))) AND 2047%)
        10020   RETURN                          ! RETURN WITH RECORD
        10030   SPLIT1%=0%                      ! ERROR TRAP &
                \ RETURN                        ! RETURN EOF &

        11000   ! OPEN NAMES FILE ON DESIGNATED NODE &
                ! &
                ! Note - If you don't have BP2 or DECnet/E, replace this whole &
                !        subroutine with: &
                !        OPEN "MAIL$:NAMES.DAT" FOR INPUT AS FILE #1% &
                !        If you have DECnet/E, you must change the data: &
                !        "[2,2] FOOBAR BARFOO" to the account and passwords for your &
                !        default DECnet account on the remote node. N.B. All remote &
                !        nodes must have the same account/password information. &
                ! &
                MAINAM$="MAIL$:NAMES.DAT" &
                \ MAINAM$=NODE$+'"[2,2] FOOBAR BARFOO"::'+MAINAM$ IF NODE$<>"" &
                \ OPEN MAINAM$ FOR INPUT AS FILE #1%, ORGANIZATION SEQUENTIAL, &
                  ACCESS READ &
                \ RETURN                        ! FILE OPENED, EXIT
        11010   GOTO 11020 IF NODE$=""          ! IF HAPPENED HERE &
                \ PRINT "?"+NODE$+":: is an unknown or unreachable node, or the login" &
                \ PRINT " information provided was invalid at the remote node." &
                \ NODE$=""                      ! COULDN'T OPEN, KILL NODE &
                \ GOTO 120                      ! AND DO WITHOUT
        11020   PRINT "?Unable to access MAIL$:MAIL.SYS file. Please contact" &
                \ PRINT " your system managment personnel or support staff." &
                \ GOTO 32767 &

        30000   ! CCL ENTRY &
                ! &
                ON ERROR GOTO 32400 &
                \ OPEN "_KB:INFO.CMD" AS FILE #2% &
                \ NODE$=""                      ! DEFAULT TO LOCAL NODE &
                \ CMND$=SYS(CHR$(7%))           ! GET CORE COMMON &
                \ CMND$=CVT$$(CMND$,189%)       ! CONVERT IT &



                                   18









                \ I%=INSTR(1%,CMND$," ")        ! ANY OPTIONS? &
                \ GOTO 120 IF I%=0%             ! NOPE, CONTINUE &
                \ CMND$=MID(CMND$,I%+1%,LEN(CMND$)) &
                \ CCLENT%=1% &
                \ GOTO 130 &

        32400   ! ERROR TRAP &
                ! &
                RESUME 140 IF ERL=130%          ! UNABLE TO CLOSE NAMES FILE &
                \ RESUME 10030 IF ERL=10000%    ! EOF ON NAMES FILE &
                \ RESUME 10020 IF ERL=10010%    ! NO LAST LOGIN INFO &
                \ RESUME 11010 IF ERL=11000%    ! BAD NODENAME &
                \ RESUME 4050 IF ERL=4020%      ! NO AUTOAN.MSG FILE &
                \ RESUME 4040 IF ERL=4030%      ! EOF ON AUTOAN.MSG &
                \ RESUME 32760 IF ERL=125%      ! EOF AT MAIN PROMPT &
                \ RESUME 120 IF ERR=11%         ! EOF ON USER INPUT &
                \ RESUME 32750                  ! UNKNOWN ERROR &

        32750   PRINT "?Received error ";NUM1$(ERR);" at line ";NUM1$(ERL);"."
        32760   ON ERROR GOTO 32767 &
                \ CLOSE #1%
        32767   END

        ! INFO.CMD - INFO taskbuilder command file
        SY:INFO/FP=SY:INFO/MP
        UNITS = 13
        ASG = SY:5:6:7:8:9:10:11:12
        CLSTR = DAPRES,RMSRES:RO
        //

        ! INFO.ODL - INFO taskbuilder .ODL file
                .ROOT BASIC2-RMSROT-USER,RMSALL
        USER:   .FCTR SY:INFO-LIBR
        LIBR:   .FCTR LB:BP2OTS/LB
        @LB:BP2IC7
        @LB:DAPRLX
                .END

        $! INFO.COM - Command file to build INFO
        $SWITCH DCL
        $SET VERIFY
        $SET NOON
        $RUN $BP2IC2
        SCALE 0
        OLD INFO.BAS
        SET SEQ
        ODLRMS LB:DAPRLX
        COMPILE INFO.OBJ/OBJ/CHA/LIN/NODEB/WOR/NOCRO/NOLIS/FLAG:NODEC
        $SW DCL
        $TKB @INFO






                                   19









        Appendix 1 - SCAN program listing
        Appendix 1 - SCAN program listing
        Appendix 1 - SCAN program listing
        Appendix 1 - SCAN program listing

        1000    EXTEND
        1010    ON ERROR GOTO 32000 &
                \ PRINT "Binary file search 1.20 - 16-Nov-87 KS" &
                \ PRINT
        1020    PRINT "File";
        1030    INPUT LINE F1$ &
                \ F1$=MID(F1$,1%,LEN(F1$)-2%)
        1040    PRINT "Search string"; &
        \       INPUT LINE S$ &
        \       S$ = LEFT(S$, LEN(S$) - 2%)
        1050    OPEN F1$ FOR INPUT AS FILE #1%, RECORDSIZE 1024%
        1060    FIELD #1, 511% + LEN(S$) AS I1$ &
                \ I%=1%
        1070    GET #1%, BLOCK I% &
        \       ST% = 1%
        1075    BYT%=INSTR(ST%,I1$,S$) &
                \ GOTO 1080 IF BYT%=0% &
                \ PRINT "Found in block ";NUM1$(I%);" ("; &
                \ F.NUM% = I% - 1% &
                \ GOSUB 11000 &
                \ F.NUM% = BYT% - 1% &
                \ PRINT "), offset ";NUM1$(F.NUM%);" ("; &
                \ GOSUB 11000 &
                \ PRINT ")." &
                \ ST% = BYT% + LEN(S$) &
                \ GOTO 1075
        1080    I%=I%+1% &
                \ GOTO 1070 &

        11000   REM SUBROUTINE TO PRINT IN OCTAL
        11010   IF F.NUM% < 0% &
                   THEN F.I$ = "1" &
                   ELSE F.I$ = "0" &

        11020   F.I$ = F.I$ + CHR$( (((F.NUM% AND 16384%) <> 0%) AND 4%) &
                                   +(((F.NUM% AND  8192%) <> 0%) AND 2%) &
                                   +(((F.NUM% AND  4096%) <> 0%) AND 1%) + 48%) &
                            + CHR$( (((F.NUM% AND  2048%) <> 0%) AND 4%) &
                                   +(((F.NUM% AND  1024%) <> 0%) AND 2%) &
                                   +(((F.NUM% AND   512%) <> 0%) AND 1%) + 48%) &
                            + CHR$( (((F.NUM% AND   256%) <> 0%) AND 4%) &
                                   +(((F.NUM% AND   128%) <> 0%) AND 2%) &
                                   +(((F.NUM% AND    64%) <> 0%) AND 1%) + 48%) &
                            + CHR$( (((F.NUM% AND    32%) <> 0%) AND 4%) &
                                   +(((F.NUM% AND    16%) <> 0%) AND 2%) &
                                   +(((F.NUM% AND     8%) <> 0%) AND 1%) + 48%) &
                            + CHR$(   (F.NUM% AND     7%)                + 48%) &
        \       PRINT F.I$; &
                \ RETURN &

        32000   IF ERL=1050 THEN PRINT "?That file does not exist - try again..." &



                                   20









                \ RESUME 1020
        32010   IF ERL=1070 THEN PRINT "Done..." &
                \RESUME 32767
        32020   IF ERL=1020 THEN RESUME 32767
        32030   IF ERL=1030 THEN RESUME 32767
        32040   IF ERL=1040 THEN RESUME 32767
        32050   PRINT "Received error ";NUM1$(ERR);" at line ";NUM1$(ERL);"." &
                \ RESUME 32767 &

        32767 END

        Appendix 2 - How to reach the RSTS Newsletter System
        Appendix 2 - How to reach the RSTS Newsletter System
        Appendix 2 - How to reach the RSTS Newsletter System
        Appendix 2 - How to reach the RSTS Newsletter System

             The  entire text of this article, as well as  the  related
        programs  in  both source and binary form are on the  RSTS  SIG
        Newsletter system in account [49,1].  To reach the system, dial
        (201)  915-9361 at either 300 or 1200 baud.  When you  get  the
        carrier  tone,  press  a few RETURNs until you  get  the  User:
        prompt.   Then  enter 2,1 and press RETURN.  You will  then  be
        logged  into a guest account and can access these examples.  In
        addition, the most recent RSTS SIG tapes are available on-line.

             Why  is it called the Newsletter System, you ask?   It  is
        the  preferred method for submitting articles to the  RSTS  SIG
        section  of  the DECUS US Chapter SIGs  Newsletter.   For  more
        information on Newsletter subscriptions, contact:

             DECUS Subscription Service
             291 Boston Post Road
             Marlboro, MA 01752-1850
             (617) 480-3418

























                                   21






                                                         