.TITLE USERS - DISPLAYS USERS LOGGED ON .IDENT /1.1/ .ENABL LC ;+ ; ; Free software BY ; Project Software & Development, Inc. ; ; This software is furnished for free and may be used and copied as ; desired. This software or any other copies thereof may be provided or ; otherwise made available to any other person. No title to and ; ownership of the software is hereby transferred or allowed. ; ; The information in this software is subject to change without notice ; and should not be construed as a commitment by PROJECT SOFTWARE ; AND DEVELOPMENT, INC. ; ; PROJECT SOFTWARE assumes no responsibility for the use or reliability ; of this software on any equipment whatsoever. ; ; Project Software & Development, Inc. ; 14 Story St. ; Cambridge, Ma. 02138 ; 617-661-1444 ; ; ; Title: USERS.MAC ; Author: Robin Miller ; Date: July 27, 1982 ; ; Description: ; ; This program provides an MCR command 'USERS' which displays the ; terminals logged on to the system. The user names are obtained from ; the accounting file (LB:[0,0]RSX11.SYS). The list of logged on terminals ; is obtained from the system tables thus we must be mapped to the Exec. ; ; Modification History: ; ; December 5, 1984 by Robin Miller. ; Reverse the display of the last and first names. At Project ; Software we use to login using our first name instead of our ; last name. ; ;- .ENABL AMA .NLIST BEX .MCALL ALUN$S, DIR$, EXIT$S, GMCR$, GTIM$, WTSE$S, QIOW$, QIOW$S .MCALL OPNS$R, CLOSE$, READ$, PUT$ .MCALL FINIT$, NMBLK$ .MCALL FSRSZ$, FDBDF$, FDAT$A, FDOP$A, FDRC$A, FDBF$A .SBTTL ACCOUNT FILE FORMAT (V4.0) ;+ ; ; Account file entries have the following format: ; ; Description Offset Type ; ---------------------------------- ; ! Group code .BLKB 3 ! A.GRP (ASCII) ; !--------------------------------! ; ! Member Code .BLKB 3 ! A.MBR (ASCII) ; !--------------------------------! ; ! Password .BLKB 6 ! A.PSWD (ASCII) ; !--------------------------------! ; ! Last Name .BLKB 14.! A.LNM (ASCII) ; !--------------------------------! ; ! First Name .BLKB 12.! A.FNM (ASCII) ; !--------------------------------! ; ! Date of last log on .BLKB 6 ! A.LDAT (BINARY) (dd/mm/yy hh:mm:ss) ; !--------------------------------! ; ! Total number of logons.BLKB 2 ! A.NLOG (BINARY) ; !--------------------------------! ; ! Default system device .BLKB 4 ! A.SYDV (ASCII) ; !--------------------------------! ; ! Command line inter. .BLKB 6 ! A.CLI (RAD50) ; !--------------------------------! ; ! Terminal is slaved .BLKB 2 ! A.LPRV (BINARY) AL.SLV = SLAVED ; ---------------------------------- ; ; The length of each entry is 128. bytes. ; Each account file buffer contains 4 entries (512. bytes). ; The above offsets are defined in module ACTFIL in MCR.OLB. ; ;- ; Macro to generate error messages. .MACRO ERRMSG LABEL,MSG .NCHR $$$, .PSECT $ERMSG,RO,D,REL,CON LABEL: .ASCII "MSG" .EVEN .PSECT MOV #LABEL,R1 MOV #$$$,R2 CALL OUTMSG .ENDM ; ; Local Equates: ; LF = 12 ; ASCII FOR LINE FEED CR = 15 ; ASCII FOR CARRIAGE RETURN SPACE = 40 ; ASCII FOR SPACE ACCLUN = 2 ; ACCOUNT FILE LUN ACCEFN = 2 ; ACCOUNT FILE EFN ; Status codes for return from TC.CTS characteristic. RESUME = 0 ; CTRL/Q TYPED SUSPND = 1 ; CTRL/S TYPED (SUSPEND) SUPRES = 2 ; CTRL/O TYPED (SUPPRESS) SUSSUP = 3 ; BOTH CTRL/S & CTRL/O TILUN == 5 ; TERMINAL LUN TIEFN == 5 ; TERMINAL EFN FILSIZ = 25. ; SIZE OF FILENAME BUFFER LOGENT = 16. ; TOTAL NUMBER OF ENTRIES LOGSIZ = LOGENT*2 ; SIZE OF LOGGED ON BUFFER INSIZ == 4 ; SIZE OF EACH INPUT ENTRY OUTSIZ == 80. ; SIZE OF EACH OUTPUT ENTRY USESIZ = 15. ; SIZE OF USERNAME BUFFER WRKSIZ = 50. ; SIZE OF WORK BUFFER OUTLUN == 4 ; OUTPUT FILE LUN OUTEFN == 4 ; OUTPUT FILE EFN .SBTTL STATUS BIT DEFINITIONS ; Status bit definitions: B.FULL == 1 ; FULL REPORT WANTED B.SUMM == 2 ; SUMMARY - TOTALS ONLY B.USER == 10 ; DISPLAY SPECIFIC USER B.FILE == 40 ; OUTPUTTING TO A FILE B.HDR == 100 ; WRITE HEADER MESSAGE ; The following are one shot bits. The switch ; to set them must be specified on every command line. B.ALL = B.USER ; ; Edit strings for $EDMSG. ; EDSTR: .ASCIZ /%S%12A%S%14A/ ; Firstname Lastname EDTIME: .ASCII /%Slogged on at %3Z/ ; TIME .ASCIZ /%Son%S/ EDDATE: .ASCIZ /%Y%S/ ; DATE DATTIM: .ASCIZ /%5S%Y%S%3Z/ ; DATE AND TIME FOR HEADER NODATE: .ASCIZ /dd-mmm-yy/ ; FILL FOR NO DATE .EVEN ; ; Argument block for $EDMSG -- Don't change the order. ; ARGBLK::.WORD 0 ; ADDRESS OF LASTNAME .WORD 0 ; ADDRESS OF FIRSTNAME REPCNT = <<.-ARGBLK>/2> ; # OF ADDRESSES ABOVE ARGDAT: .WORD 0 ; BINARY YEAR .WORD 0 ; BINARY MONTH .WORD 0 ; BINARY DAY ARGTIM: .WORD 0 ; BINARY HOUR .WORD 0 ; BINARY MINUTES .WORD 0 ; BINARY SECONDS .WORD 0 ; TERMINATE WITH NULL .PSECT $$ZZZZ,RW,D,REL,CON ; FORCE BUFFERS TO END OF TASK FILPTR::.WORD FILNAM ; POINTER TO FILENAME BUFFER USEPTR::.WORD USEBUF ; POINTER TO USERNAME BUFFER WRKPTR::.WORD WRKBUF ; POINTER TO WORK BUFFER FILNAM::.BLKB FILSIZ ; STORAGE FOR ASCII FILE NAME .BYTE -1 ; TERMINATOR .EVEN ; NEXT ADDRESS MUST BE EVEN LOGBUF::.BLKW LOGSIZ ; STORAGE FOR LOGGED ON USERS .WORD -1 ; TERMINATOR USEBUF::.BLKB USESIZ ; STORAGE FOR ASCII USER NAME .BYTE -1 ; TERMINATOR .EVEN ; FORCE WRKBUF TO EVEN ADDRESS WRKBUF::.BLKB WRKSIZ ; WORKING STORAGE FOR WHATEVER .BYTE -1 ; TERMINATOR BLKSTR: .ASCIZ " " ; STRING TO WRITE BLANK RECORD HEADER: .ASCII /RSX-11M Interactive Users - Total = / INTCNT: .BLKB 6 ; STORE ASCII TOTAL HERE .EVEN ; FORCE BUFF TO EVEN ADDRESS BUFF:: .BLKB LOGENT*OUTSIZ ; BUFFER FOR OUTPUT ENTRYS .EVEN .PSECT ; RETURN TO ORIGINAL PSECT ; File Directive Parameter Blocks (DPB's) FDPB: QIOW$ IO.RVB,ACCLUN,ACCEFN,,TIOSB,,<$ACTBF,$BFLEN,,,1> GMCR:: GMCR$ ; GET COMMAND LINE DPB GTIM:: GTIM$ TIMBUF ; GET DATE AND TIME TIMBUF: .BLKW 8. ; AND STORE IT HERE ATTACH: QIOW$ IO.ATT,TILUN,TIEFN,,TIOSB,, DETACH: QIOW$ IO.DET,TILUN,TIEFN,,TIOSB,, GETSTA: QIOW$ SF.GMC,TILUN,TIEFN,,TIOSB,, STABUF: .BYTE TC.CTS ; GET THE ^O STATUS STOP: .BYTE 0 ; AND STORE IT HERE STALEN = .-STABUF ; LENGTH OF BUFFER TIOSB:: .BLKW 2 ; I/O STATUS BLOCK FOR BOTH ; TERMINAL AND ACCOUNTING FILE ; Local/global variables. STATUS::.WORD B.HDR ; INITIALIZE THE STATUS WORD TOTAL:: .WORD 0 ; TOTAL # OF LOGGED ON TERMINALS FTOTAL::.WORD 0 ; TOTAL NUMBER OF USERS FOUND COUNT: .WORD 0 ; BYTE COUNT FROM ACCOUNT QIO ENTRY: .WORD 0 ; CURRENT ENTRY POINT ; IN ACCOUNT FILE BLOCK ; File Descriptor Blocks (FDB's). FSRSZ$ 1 ; STORAGE FOR 1 OPEN FILES OUTFDB:: FDBDF$ ; FDB FOR OUTPUT FILE FDAT$A R.VAR,FD.CR,,, ; VARIABLE LENGTH RECORDS FDRC$A ,BUFF,OUTSIZ ; LOCATE MODE / MAX SIZE FDOP$A OUTLUN,,DEFNB,FO.WRT!FA.NSP ; OPEN FOR WRITE FDBF$A OUTEFN,OUTSIZ,, ; INIT BLOCK BUFFER SECTION ; Default file name blocks. DEFNB: NMBLK$ USERS,LOG,,SY,0 ; DEFAULT OUTPUT FILE .SBTTL USERS - START OF USERS PROGRAM ;+ ; ; USERS - Display users logged on the system. ; ;- USERS:: MOV @#.FSRPT,R0 ; GET POINTER TO FSR TST A.DFUI(R0) ; HAS .FINIT BEEN DONE (DDT) BNE 10$ ; IF NE, YES (DO ONLY ONCE) FINIT$ ; DO THE FINIT 10$: ALUN$S #TILUN,#"TI,#0 ; ASSIGN LUN TO THE TERMINAL BCC GETCMD ; IF CC, SUCCESS DERR: MOV $DSW,R0 ; COPY THE ERROR CODE CALL WRTERR ; WRITE THE ERROR EXIT$S ; AND EXIT NOW ; Get the MCR command line. GETCMD::DIR$ #GTIM ; GET THE DATE AND TIME BCS DERR ; IF CS, DIRECTIVE ERROR DIR$ #GMCR ; GET COMMAND LINE BCS DERR ; IF CS, DIRECTIVE ERROR MOV $DSW,R3 ; COPY THE BYTE COUNT MOV #GMCR+G.MCRB,R4 ; ADDRESS OF COMMAND LINE MOV R4,R5 ; COPY THE ADDRESS ADD R3,R5 ; POINT TO LAST BYTE CLRB (R5) ; TERMINATE WITH A NULL ; Skip the task name (i.e., USERS command line). 20$: CMPB (R4),#SPACE ; FIND A SPACE ? BEQ GOTCMD ; IF EQ, YES INC R4 ; POINT NEXT BYTE SOB R3,20$ ; LOOP TO END OF LINE JMP DOIT ; NO COMMAND TO PARSE ; Got a command line, now parse it. GOTCMD:: ; ; Use TPARS to parse the command line. ; ; Inputs: ; R1 = bit 0 in the low byte controls processing of blanks/tabs: ; if 0, ignore blanks, if 1 then pass blanks and tabs. ; the high byte contains the number of characters that ; keywords are allowed to be abbreviated (0 = exact). ; R3 = the input string byte count, ; R4 = the input buffer address. ; ; Outputs: ; R3 = zero on success or ; remaining byte count on syntax error. ; R4 = end of input string or ; updated buffer address on syntax error. ; MOV #USEBUF,USEPTR ; SET USER BUFFER POINTER MOV #WRKBUF,WRKPTR ; SET WORK BUFFER POINTER BIC #B.ALL,STATUS ; CLEAR SOME STATUS BITS MOV #<400*1>,R1 ; IGNORE BLANKS, MATCH 1 CHARACTER MOV #KEYWRD,R2 ; ADDRESS OF KEYWORD TABLE MOV #START,R5 ; STARTING TRANSITION ADDRESS CALL .TPARS ; NOW DO THE PARSE BCC DOIT ; IF CC, SUCCESS ERRMSG SYNERR,<%USERS-W-SYNERR, syntax error.> JMP EXIT ; AND EXIT DOIT:: MOV #LOGBUF,R5 ; LOGGED ON BUFFER CALL GETLOG ; GET LOGGED ON USERS MOV R0,TOTAL ; SAVE TOTAL LOGGED ON USERS MOV R0,FTOTAL ; SAVE IN FOUND TOTAL ALSO ; USED IN CHKTBL ROUTINE MOV R0,R1 ; COPY THE LOGGED ON COUNT CALL WRTHDR ; WRITE THE HEADER MESSAGE BIT #B.SUMM,STATUS ; ONLY TOTALS DESIRED ? BNE EXIT ; IF NE, YES (EXIT) CALL MAKUIC ; MAKE THE TTnn: [UIC] ENTRYS CALL OPEN ; OPEN THE ACCOUNT FILE BCS 10$ ; IF CS, FAILURED ; Read the account file entrys and setup the output table. CALL READ ; SETUP THE OUTPUT ENTRYS CLOSE$ #$ACTFL ; CLOSE THE ACCOUNT FILE 10$: DIR$ #ATTACH ; ATTACH THE TERMINAL CALL CHKERR ; CHECK/DISPLAY ERRORS BCS EXIT ; IF CS, ERROR CALL WRTTBL ; WRITE THE TABLE ENTRYS DIR$ #DETACH ; DETACH THE TERMINAL EXIT:: CALL CLOFIL ; CLOSE THE OUTPUT FILE EXIT$S ; AND EXIT .SBTTL OPEN -- OPEN THE ACCOUNT FILE ;+ ; ; OPEN - Open the account file. ; ; This routine opens the account file for shared read and block I/O. ; ; Inputs: ; None. ; ; Outputs: ; C bit clear/set = success/failure. ; ;- OPEN:: OPNS$R #$ACTFL,,,#FD.RWM ; OPEN THE ACCOUNT FILE BCC 10$ ; IF CC, SUCCESS MOV F.ERR(R0),R0 ; COPY THE ERROR CODE CALL WRTERR ; AND GO REPORT IT 10$: RETURN .SBTTL READ -- READ ACCOUNT INFO INTO THE BUFFER ;+ ; ; READ - Read account information into the buffer. ; ;- READ:: MOV #FDPB,R4 ; GET FILE DPB ADDRESS MOV #1,Q.IOPL+10(R4) ; SET TO START AT VBN 1 CLR Q.IOPL+6(R4) ; CLEAR THE HIGH VBN ; Read in an accounting block. 10$: CALL DOQIO ; READ IN THE BLOCK BCS 100$ ; IF CS, ERROR OR EOF MOV TIOSB+2,COUNT ; COPY THE BYTE COUNT BEQ 50$ ; IF EQ, NOTHING READ MOV #$ACTBF,R3 ; SET THE BUFFER ADDRESS ; Process the next accounting entry. 20$: MOV #BUFF,R0 ; OUTPUT BUFFER ADDRESS MOV R3,ENTRY ; SAVE ENTRY ADRESS TSTB (R3) ; IS THERE A GROUP CODE ? BEQ 100$ ; IF EQ, NO (PRESUME NO MORE) CALL CHKTBL ; CHECK ENTRYS IN TABLE BCS 100$ ; IF CS, FINISHED TABLE 25$: MOV ENTRY,R3 ; RESTORE ENTRY ADDRESS ADD #A.LEN,R3 ; POINT TO NEXT ENTRY SUB #A.LEN,COUNT ; COMPUTE WORDS LEFT IN BUFFER BHI 20$ ; IF HI, ANOTHER ENTRY 50$: MOV #FDPB,R4 ; ADDRESS OF ACCOUNT FILE DPB ADD #$BFLEN/512.,Q.IOPL+10(R4) ; NO ERRORS, SO POINT TO NEXT VBN ADC Q.IOPL+6(R4) ; ADD IN THE CARRY (IF ANY) BR 10$ ; READ IN THE NEXT BLOCK 100$: RETURN .SBTTL WRITE -- WRITE BUFFER TO THE TERMINAL ;+ ; ; WRITE - Write a buffer to the terminal or a file. ; ; Inputs: ; R0 - Address of message to output (terminated by NULL) ; ; Outputs: ; C bit clear/set = success/failure. ; ; All registers are preserved. ; ;- WRITE:: CALL $SAVAL ; SAVE ALL REGISTERS MOV R0,R1 ; COPY THE PUT TO FILE MOV R0,R2 ; COPY BUFFER ADDRESS 10$: TSTB (R2)+ ; END OF MESSAGE ? BNE 10$ ; IF NE, MORE TO GO DEC R2 ; ADJUST FOR THE NULL SUB R1,R2 ; CALCULATE BYTE COUNT BIT #B.FILE,STATUS ; OUTPUTTING TO A FILE ? BNE 20$ ; IF NE, YES (DO PUT) ; Output to the terminal. QIOW$S #IO.WVB,#TILUN,#TIEFN,,#TIOSB,, CALL CHKERR ; CHECK/REPORT ERRORS BCS 30$ ; IF CS, HAD AN ERROR CALL CHKSUP ; CHECK FOR SUPPRESS BR 30$ ; AND CONTINUE ... ; Output to a disk file. 20$: CALL DOPUT ; PUT TO THE FILE 30$: RETURN .SBTTL DOQIO -- DO THE QIO AND CHECK FOR ERRORS ;+ ; ; DOQIO - Do the QIO and check for errors. ; ; Inputs: ; FDPB = the account file DPB must be preset. ; ; Outputs: ; C bit clear/set = success/failure. ; ; All registers are preserved. ; ;- DOQIO:: DIR$ #FDPB ; READ THE ACCOUNT FILE BCS 10$ ; IF CC, SUCCESS TSTB TIOSB ; ANY I/O ERRORS ? BPL 30$ ; IF PL, NO (SUCCESS) CMPB #IE.EOF,TIOSB ; WAS ERROR END OF FILE ? BEQ 20$ ; IF EQ, YES (EXPECTED) 10$: CALL CHKERR ; CHECK/REPORT THE ERROR 20$: SEC ; SHOW FAILURE 30$: RETURN .SBTTL FORMAT -- FORMAT ACCOUNT INFORMATION IN BUFFER ;+ ; ; FORMAT - Format account information in output buffer. ; ; Inputs: ; R0 = Address of output buffer. ; R3 - Address of account entry. ; ; Outputs: ; R0 = output buffer is formatted. ; ; All registers are preserved. ; ;- FORMAT::CALL $SAVAL ; SAVE ALL REGISTERS MOV #ARGBLK,R1 ; SET ADDR OF ARG BLOCK MOV #REPCNT,R2 ; SET THE REPEAT COUNT 10$: MOV R3,(R1)+ ; SET UP ENTRY ADDRESS SOB R2,10$ ; LOOP TILL DONE MOV #ARGBLK,R1 ; RESET ADDR OF ARG BLOCK ADD #A.FNM,(R1)+ ; " " (FIRSTNAME) ADD #A.LNM,(R1)+ ; " " (LASTNAME) MOVB A.LDAT+2(R3),(R1)+ ; SAVE YEAR SINCE 1900 CLRB (R1)+ ; HIGH BYTE UNUSED MOVB A.LDAT+1(R3),(R1)+ ; SAVE MONTH OF YEAR CLRB (R1)+ ; HIGH BYTE UNUSED MOVB A.LDAT(R3),(R1)+ ; SAVE DAY OF MONTH CLRB (R1)+ ; HIGH BYTE UNUSED MOVB A.LDAT+3(R3),(R1)+ ; SAVE HOUR OF DAY CLRB (R1)+ ; HIGH BYTE UNUSED MOVB A.LDAT+4(R3),(R1)+ ; SAVE MINUTE OF HOUR CLRB (R1)+ ; HIGH BYTE UNUSED MOVB A.LDAT+5(R3),(R1)+ ; SAVE SECOND OF MINUTE CLRB (R1)+ ; HIGH BYTE UNUSED MOV #EDSTR,R1 ; SET UP TO MOV #ARGBLK,R2 ; CALL $EDMSG CALL $EDMSG ; DO IT BIT #B.FULL,STATUS ; WANT A FULL REPORT ? BEQ 50$ ; IF EQ, NO (SHORT) ; Format the time of last logon. MOV #EDTIME,R1 ; SET UP TO MOV #ARGTIM,R2 ; CALL $EDMSG CALL $EDMSG ; FORMAT THE TIME ; Format the date of last logon. TSTB ARGDAT ; IS THERE A DATE ? BNE 30$ ; IF NE YES MOV #NODATE,R1 ; SET TO FILL WITH NO DATE 20$: MOVB (R1)+,(R0)+ ; FILL IT IN TSTB (R1) ; ARE WE DONE ? BNE 20$ ; IF NE, NO BR 50$ ; FINSIHED ... 30$: CMPB ARGDAT+4,#9. ; TWO DIGIT DATE ? BGT 35$ ; IF GT YES MOVB #'0,(R0)+ ; FILL WITH ZERO 35$: MOV #EDDATE,R1 ; SET UP TO MOV #ARGDAT,R2 ; CALL $EDMSG CALL $EDMSG ; FORMAT THE DATE ; Finally finished. 50$: CLRB (R0) ; ENSURE WE HAVE TERMINATOR RETURN .SBTTL DOPUT - DO A PUT TO THE OUTPUT FILE ;+ ; ; DOPUT - Write a record to the output file. ; ; Inputs: ; R1 = the buffer address. ; R2 = the buffer byte count. ; ; Outputs: ; Carry bit clear/set = success/failure. ; ; All registers are preserved. ;- DOPUT:: CALL $SAVAL ; SAVE ALL REGISTERS PUT$ #OUTFDB,R1,R2 ; WRITE THE OUTPUT RECORD BCC 10$ ; IF CC, SUCCESS MOV F.ERR(R0),-(SP) ; SAVE THE FCS ERROR CODE CALL CLOFIL ; CLOSE THE OUTPUT FILE MOV (SP)+,R0 ; COPY THE FCS ERROR CODE ; Output the error message (C bit set by WRTERR). CALL WRTERR ; REPORT THE ERROR MESSAGE 10$: RETURN .SBTTL BLANK - WRITE A BLANK RECORD BLANK: MOV #BLKSTR,R0 ; BLANK RECORD STRING CALL WRITE ; WRITE IT RETURN .SBTTL CLOFIL - CLOSE THE OUTPUT FILE (IF OPEN) ;+ ; ; CLOFIL - Close the output file (if open). ; ; Inputs: ; None ; ; Outputs: ; Register R0 is destroyed. ; ;- CLOFIL::TST OUTFDB+F.BDB ; IS THERE A FILE OPEN ? BEQ 10$ ; IF EQ, NO (RETURN) MOV #OUTFDB,R0 ; ADDRESS OF OUTPUT FDB CALL .TRNCL ; YES, TRUNCATE AND CLOSE BIC #B.FILE,STATUS ; SHOW OUTPUT FILE CLOSED MOV #FILNAM,FILPTR ; RESET THE FILE NAME POINTER CLRB @FILPTR ; MAKE IT A NULL STRING 10$: RETURN .SBTTL CHKSUP - CHECK FOR OUTPUT SUPPRESSED ;+ ; ; CHKSUP - Check for output suppressed (CTRL/O typed). ; ; This routine determines whether the user typed CTRL/O to suppress ; further output to the terminal. This is done so that very long ; status reports can be terminated quickly. ; ; *** The terminal must be attached to obtain the suppress status. *** ; ; Outputs: ; C bit clear/set = not-suppressed/supperessed. ; ; All registers are preserved. ; ;- CHKSUP: DIR$ #GETSTA ; GET THE STATUS BCS 100$ ; IF CS, PRESUME NOT-SUPPRESSED BITB #SUPRES,STOP ; USER WANT TO STOP OUTPUT ? BEQ 100$ ; IF EQ, NO SEC ; YES, PASS BACK STATUS RETURN 100$: CLC ; PASS BACK NOT-SUPPRESSED RETURN .SBTTL WRTHDR - WRITE THE HEADER MESSAGE ;+ ; ; WRTHDR - Write the header message, total logged on terminals. ; ; Inputs: ; R1 = the number of terminals logged on. ; ; Outputs: ; All registers are preserved. ; ;- WRTHDR: CALL $SAVAL ; SAVE ALL REGISTERS BIT #B.HDR,STATUS ; SHOULD WE WRITE HEADER ? BEQ 100$ ; IF EQ, NO (SKIP IT) MOV #INTCNT,R0 ; STORE ASCII NUMBER HERE CLR R2 ; SUPPRESS LEADING ZEROS CALL $CBDMG ; CONVERT TO DECIMAL ASCII CLRB (R0) ; TERMINATE WITH NULL CALL BLANK ; WRITE A BLANK LINE MOV #HEADER,R0 ; ADDRESS OF HEADER MESSAGE CALL WRITE ; NOW WRITE IT ; Now output the date and time. MOV #BUFF,R0 ; STORE DATE & TIME HERE MOV #DATTIM,R1 ; SET UP TO MOV #TIMBUF,R2 ; CALL $EDMSG CALL $EDMSG ; DO IT CLRB (R0) ; TERMINATE WITH NULL MOV #BUFF,R0 ; GET READY TO WRITE IT CALL WRITE ; NOW WRITE IT CALL BLANK ; WRITE ANOTHER BLANK LINE 100$: RETURN .END USERS ; TRANSFER ADDRESS