.TITLE WHO - LIST WHO IS IN ACCOUNT FILE .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: WHO.MAC (previously USERS.MAC) ; Author: Robin Miller ; Date: July 21, 1982 ; ; Description: ; ; This program is to provide an MCR command 'WHO' which displays the names ; and UIC'S that are in the account file. This is useful for finding the ; names of users to send MAIL to for example. It gets all its information ; from the account file LB:[0,0]RSX11.SYS. It is privileged but not mapped ; to the Executive. ; ; ; Modification History: ; ;- .ENABL AMA .NLIST BEX .MCALL ALUN$S, DIR$, EXIT$S, WTSE$S, QIOW$, QIOW$S .MCALL OPNS$R, CLOSE$, READ$, PUT$ .MCALL GCMLB$, GCML$ .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 DEPTH = 1 ; DEPTH OF COMMAND FILES CMDLUN = 3 ; COMMAND INPUT LUN CMDSIZ = 82. ; SIZE OF COMMAND LINE BUFFER TILUN == 5 ; TERMINAL LUN TIEFN == 5 ; TERMINAL EFN CLISIZ = 7. ; SIZE OF CLI BUFFER DEVSIZ = 7. ; SIZE OF DEVICE BUFFER FILSIZ = 25. ; SIZE OF FILENAME BUFFER HLPSIZ = 70. ; SIZE OF HELP BUFFER USESIZ = 15. ; SIZE OF USERNAME BUFFER WRKSIZ = 50. ; SIZE OF WORK BUFFER OUTLUN == 4 ; OUTPUT FILE LUN OUTEFN == 4 ; OUTPUT FILE EFN OUTSIZ = 80. ; SIZE OF OUTPUT BUFFER .SBTTL STATUS BIT DEFINITIONS ; Status bit definitions: B.FULL == 1 ; FULL REPORT WANTED B.GRP == 2 ; DISPLAY SPECIFIC GROUP B.UIC == 4 ; DISPLAY SPECIFIC UIC B.USER == 10 ; DISPLAY SPECIFIC USER B.CLI == 20 ; DISPLAY SPECIFIC CLI B.FILE == 40 ; OUTPUTTING TO A FILE B.HDR == 100 ; WRITE HEADER MESSAGE B.TRL == 200 ; WRITE TRAILER MESSAGE B.DEV == 400 ; DISPLAY SPECIFIC DEVICE B.HELP == 1000 ; USER WANTED SOME HELP ; The following are one shot bits. The switch ; to set them must be specified on every command line. B.ALL = B.GRP!B.UIC!B.USER!B.CLI!B.DEV!B.HELP ; ; Edit strings for $EDMSG. ; EDSTR: .ASCII /%4A:%S/ ; SYSTEM_DISK .ASCII /[%3A,%3A]%S/ ; [UIC] .ASCII /%14A%S%12A/ ; LASTNAME FIRSTNAME .ASCIZ /%SCLI=%2R%S/ ; COMMAND LINE INTERPRETER EDDATE: .ASCIZ /%Y%S/ ; DATE EDTIME: .ASCIZ /%3Z%2S%U/ ; TIME / LOGINS NODATE: .ASCIZ /dd-mmm-yy/ ; FILL FOR NO DATE .EVEN ; ; Argument block for $EDMSG. ; ARGBLK::.WORD 0 ; ADDRESS OF SYSTEM_DISK .WORD 0 ; ADDRESS OF GROUP .WORD 0 ; ADDRESS OF MEMBER .WORD 0 ; ADDRESS OF LASTNAME .WORD 0 ; ADDRESS OF FIRSTNAME REPCNT = <<.-ARGBLK>/2> ; # OF ADDRESSES ABOVE .WORD 0 ; CLI NAME IN RADIX-50 .WORD 0 ; AND THE SECOND HALF 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 ; BINARY LOGINS .WORD 0 ; TERMINATE WITH NULL .PSECT $$ZZZZ,RW,D,REL,CON ; FORCE BUFFERS TO END OF TASK CLIPTR::.WORD CLIBUF ; POINTER TO CLI BUFFER DEVPTR::.WORD DEVBUF ; POINTER TO DEVICE BUFFER FILPTR::.WORD FILNAM ; POINTER TO FILENAME BUFFER HLPPTR::.WORD HLPBUF ; POINTER TO HELP BUFFER USEPTR::.WORD USEBUF ; POINTER TO USERNAME BUFFER WRKPTR::.WORD WRKBUF ; POINTER TO WORK BUFFER CLIBUF::.BLKB CLISIZ ; STORAGE FOR CLI NAME .BYTE -1 ; TERMINATOR DEVBUF::.BLKB DEVSIZ ; STORAGE FOR DEVICE NAME .BYTE -1 ; TERMINATOR FILNAM::.BLKB FILSIZ ; STORAGE FOR ASCII FILE NAME .BYTE -1 ; TERMINATOR SPNBUF::.ASCII %HELP WHO % ; MCR COMMAND TO SPAWN HLPBUF::.BLKB HLPSIZ ; STORAGE FOR HELP TOPIC .BYTE -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: .ASCIZ /RSX-11M Accounting File Entrys:/ TRAILR: .ASCII /Total number of selected entrys = / SELCNT: .BLKB 6 ; STORE ASCII NUMBER HERE .EVEN BUFF:: .BLKB 100. ; BUFFER FOR ACCOUNTING ENTRY .EVEN .PSECT ; RETURN TO ORIGINAL PSECT ; File Directive Parameter Blocks (DPB's) FDPB: QIOW$ IO.RVB,ACCLUN,ACCEFN,,TIOSB,,<$ACTBF,$BFLEN,,,1> 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!B.TRL ; INITIALIZE THE STATUS WORD DEVNUM::.WORD 0 ; DEVICE UNIT NUMBER GRPNUM::.WORD 0 ; BINARY GROUP NUMBER TO LIST UICNUM::.WORD 0 ; BINARY UIC NUMBER TO LIST ENTCNT: .WORD 0 ; NUMBER OF ENTRYS SELECTED COUNT: .WORD 0 ; BYTE COUNT FROM ACCOUNT QIO ENTRY: .WORD 0 ; CURRENT ENTRY POINT ; IN ACCOUNT FILE BLOCK ; Get Command Line control block. GCLBLK::GCMLB$ DEPTH,WHO,CMDBUF,CMDLUN,,CMDSIZ CMDBUF::.BLKB CMDSIZ ; INPUT COMMAND BUFFER ; File Descriptor Blocks (FDB's). FSRSZ$ 2 ; STORAGE FOR 2 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$ WHO,RPT,,SY,0 ; DEFAULT OUTPUT FILE .SBTTL WHO -- ACCOUNT FILE REPORT GENERATOR ;+ ; ; WHO - Account file report generator. ; ;- WHO:: 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 BCS 20$ ; IF CS, ERROR ALUN$S #CMDLUN,#"TI,#0 ; ASSIGN THE COMMAND LUN BCC GETCMD ; IF CC, SUCCESS 20$: MOV $DSW,R0 ; COPY THE ERROR CODE CALL WRTERR ; WRITE THE ERROR EXIT$S ; AND EXIT NOW .ENABL LSB GETCMD::MOV #GCLBLK,R0 ; ADDRESS OF CONTROL BLOCK GCML$ ; GET A COMMAND LINE BCC GOTCMD ; IF CC, GOT A COMMAND CMPB #GE.EOF,G.ERR(R0) ; END OF FILE DETECTED ? BNE 10$ ; IF NE, NO JMP EXIT ; YES, EXIT ; For the errors GE.IOR & GE.OPR, F.ERR in the FDB has the error code. 10$: CMPB #GE.IOR,G.ERR(R0) ; I/O ERROR DETECTED ? BEQ 20$ ; IF EQ, YES CMPB #GE.OPR,G.ERR(R0) ; FILE OPEN ERROR ? BEQ 20$ ; IF EQ, YES CMPB #GE.BIF,G.ERR(R0) ; SYNTAX ERROR ? BEQ 30$ ; IF EQ, YES CMPB #GE.MDE,G.ERR(R0) ; MAX @ DEPTH EXCEEDED ? BNE 20$ ; IF NE, NO (TRY FCS ERROR) ERRMSG TOOMNY,<%WHO-F-TOOMANY, maximum @ file depth exceeded.> JMP EXIT ; CONSIDER THIS FATAL ; Report an error message. 20$: MOV F.ERR(R0),R0 ; COPY THE ERROR CODE CALL WRTERR ; WRITE THE ERROR MESSAGE BR GETCMD ; AND GET THE NEXT COMMAND 30$: SERR: ERRMSG SYNERR,<%WHO-W-SYNERR, syntax error.> ERRMSG HLPINF,<%WHO-I-HLPINF, type HELP for help information.> BR GETCMD ; GET THE NEXT COMMAND .DSABL LSB ; Got a command line. GOTCMD::MOV G.CMLD(R0),R3 ; COPY THE BYTE COUNT BEQ DOIT ; IF EQ, USE DEFAULTS MOV G.CMLD+2(R0),R4 ; INPUT BUFFER ADDRESS MOV R4,R0 ; COPY THE BUFFER ADDRESS ADD R3,R0 ; POINT TO END OF LINE CLRB (R0) ; NOW, TERMINATE WITH NULL ; ; 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 #CLIBUF,CLIPTR ; SET CLI BUFFER POINTER MOV #DEVBUF,DEVPTR ; SET DEVICE BUFFER POINTER MOV #HLPBUF,HLPPTR ; SET THE HELP BUFFER POINTER MOV #USEBUF,USEPTR ; SET USER BUFFER POINTER MOV #WRKBUF,WRKPTR ; SET WORK BUFFER POINTER CLR DEVNUM ; DEFAULT UNIT NUMBER = 0 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 JMP SERR ; HAD A SYNTAX ERROR DOIT:: BIT #B.HELP,STATUS ; DID USER GET SOME HELP ? BNE 20$ ; IF NE, YES (NEXT COMMAND) CLR ENTCNT ; NUMBER OF ENTRYS SELECTED CALL OPEN ; OPEN THE ACCOUNT FILE BCS EXIT ; IF CS, FAILURE BIT #B.HDR,STATUS ; SHOULD WE WRITE HEADER ? BEQ 10$ ; IF EQ, NO (SKIP IT) CALL BLANK ; WRITE A BLANK RECORD MOV #HEADER,R0 ; YES, SET THE ADDRESS CALL WRITE ; AND GO WRITE IT CALL BLANK ; ANOTHER BLANK RECORD 10$: DIR$ #ATTACH ; ATTACH THE TERMINAL CALL CHKERR ; CHECK/DISPLAY ERRORS BCS 20$ ; IF CS, ERROR CALL READ ; DISPLAY THE ACCOUNT ENTRYS CLOSE$ #$ACTFL ; CLOSE THE ACCOUNT FILE CALL TOTALS ; WRITE TOTAL ENTRYS SELECTED DIR$ #DETACH ; DETACH THE TERMINAL 20$: JMP GETCMD ; NOW GET THE NEXT COMMAND 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 CHKCLI ; SEE IF THIS CLI IS VALID BCS 25$ ; IF NE, NO (DO NEXT ENTRY) CALL CHKDEV ; SEE IF THIS DEVICE IS VALID BCS 25$ ; IF CS, NO (DO NEXT ENTRY) CALL CHKGRP ; SEE IF THIS GROUP IS VALID BCS 25$ ; IF CS, NO (DO NEXT ENTRY) CALL CHKUIC ; SEE IF THIS UIC IS VALID BCS 25$ ; IF CS, NO (DO NEXT ENTRY) CALL CHKUSE ; SEE IF THIS USER IS VALID BCS 25$ ; IF CS, NO (DO NEXT ENTRY) INC ENTCNT ; COUNT THIS ENTRY FOR TOTALS CALL FORMAT ; GO FORMAT THIS ENTRY MOV #BUFF,R0 ; SET THE BUFFER ADDRESS CALL WRITE ; AND WRITE THIS ENTRY BCS 100$ ; IF CS, ERROR (RETURN) 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 = updated output buffer. ; ;- FORMAT::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.SYDV,(R1)+ ; ADD IN OFFSETS (SYSTEM_DISK) ADD #A.GRP,(R1)+ ; " " (GROUP) ADD #A.MBR,(R1)+ ; " " (MEMBER) ADD #A.LNM,(R1)+ ; " " (LASTNAME) ADD #A.FNM,(R1)+ ; " " (FIRSTNAME) MOV A.CLI(R3),(R1)+ ; COPY THE CLI NAME MOV A.CLI+2(R3),(R1)+ ; AND THE SECOND HALF 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 MOVB A.NLOG(R3),(R1)+ ; SAVE NUMBER OF LOGINS 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 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) ; DONE ? BNE 20$ ; BR IF NO BR 40$ ; CONTINUE... 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 ; Format the time of last logon. 40$: MOV #EDTIME,R1 ; SET UP TO MOV #ARGTIM,R2 ; CALL $EDMSG CALL $EDMSG ; FORMAT THE TIME / LOGINS ; 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 TOTALS - WRITE TOTAL NUMBER OF ENTRYS SELECTED ;+ ; ; TOTALS _ Write total number of entrys selected. ; ; Inputs: ; ENTCNT = the number of entrys selected. ; ; Outputs: ; All registers are preserved. ; ;- TOTALS: CALL $SAVAL ; SAVE ALL REGISTERS BIT #B.TRL,STATUS ; SHOULD WE WRITE TRAILER ? BEQ 100$ ; IF EQ, NO MOV ENTCNT,R1 ; COPY THE ENTRY COUNT BEQ 10$ ; IF EQ, NONE FOUND CALL BLANK ; WRITE A BLANK LINE 10$: MOV #SELCNT,R0 ; STORE ASCII NUMBER HERE CLR R2 ; SUPPRESS LEADING ZEROS CALL $CBDMG ; CONVERT TO DECIMAL ASCII CLRB (R0) ; TERMINATE WITH NULL MOV #TRAILR,R0 ; ADDRESS OF TRAILER MESSAGE CALL WRITE ; NOW WRITE IT CALL BLANK ; WRITE ANOTHER BLANK LINE 100$: RETURN .END WHO ; TRANSFER ADDRESS