title PUSER Written by Terry Pinto ;------------------------------------------------------------------- ; PUSER Version 1.72 - 04/18/87 ; ; Written by Terry Pinto ; Access Programming RAS ; (503) 644-0900 (300/1200 Baud) 24 hour/day ; (503) 646-4937 Voice - 6:00pm to 10:00pm ; ; This is a stand alone program designed to print the entire ; user list on the console or the list device. This program ; can be assembled using either M80 or SLR180 by using the ; following commands: ; ; M80 =PUSER/N SLR180P PUSER/6 ; ; You will have to link the program with the subroutine file ; supplied with PBBS, PBBSUBS.REL, and SYSLIB36.REL supplied ; with this library. Use the following command. ; ; For M80/L80: ; L80 /P:100,PUSER,PBBSUBS,SYSLIB36/S,PUSERxx/N/E ; ; For SLR180P ; SLRNKP PUSER/N,/A:100,PUSERxx,PBBSUBS/S,SYSLIB36/S,/E ; ; NOTE: In both cases, the 'xx' refers to the version number used ; ; Information and other assembly options are obtained from ; PBBSHDR.MAC and BDOSHDR.MAC. These files are included in the ; assembly process with the INCLUDE statement. ; ; This program may reside anywhere on the system in the current ; path. If you wish to use the non-wheel ability to allow your ; users to display the file, you will want to place it in the ; remote users path. The user file will be read from the currently ; defined SYSDRV and SYSUSR areas in PBBSHDR.MAC. ; ; HISTORY - ; Ver 1.80 01/19/88 Minor revision to link with the ; newer PBBSUBZ.REL file from PBBS ; version 4.0 and included code to ; optionally list either the folder ; numbers the user has access to, or ; the number of times on the system and ; the high message read. ; Ver 1.71 11/20/87 Included the new PBBSUBS.REL file ; from PBBS-04. Changed linker compat. ; by removing ORG statement. ; Ver 1.7 08/23/87 Corrected failure to pick up User ; at Record 0. Added new feature: ; printer initialization and de- ; initialization. Added ^C abort. ; (implemented PUSER16.MOD) Jerry Levy ; Ver 1.6 06/06/87 Corrected problems associated with ; the use of M80 when assembling. Colons ; were eliminated. ; Ver 1.5 04/18/87 Added specific access level request ; for display or printout for wheel user ; and fixed problem with no reset of ; total users selected ; Ver 1.4 03/31/87 Allowed for hardcopy output if ; wheel is set ; Ver 1.3 03/22/87 Allow for placement of file in ; any drive/user area on path and ; read the USER file in the SYSDRV ; and SYSUSR areas. ; Ver 1.2 03/19/87 Allow for recognition of wheel ; for printing of telephone number ; and record number ; Ver 1.1 03/16/87 Fix improper exit causing ccp ; crash ; Ver 1.0 03/15/87 Original release ; ;-------------------------------------------------------------------- ; .z80 ; needed for M80 ; aseg ; needed for M80 ; org 100h ; needed for M80 ; jp start ; ;true equ 0 ;false equ not true ;yes equ true ;no equ false ver equ 1 ; version vers equ 8 ; revision rev equ 0 ; minor revision ; ff equ 12 ; form feed character ; lines equ 22 ; maximum print lines on CRT minus two mxpln equ 66 ; maximum lines per page ; ; Set the following EQUate to indicate if you would like the hardcopy ; printout to include the folder numbers the user has access to or the ; number of times the user has been on the system and the high message ; read. Space limits us to having to choose one of the above two choices. ; If you want the folders listed, set FOLDER EQU 0FFh ; folder equ 0ffh ; 0 = tos/msg 0FFH = folders ; ; You may vary the constant in the following equate to adjust ; the number of printed lines per page. ; plines equ mxpln-14 ; print lines per page minus fourteen ; lstout equ 5 ; BDOS list output character ; ext lpstr, lafdc, lhldc, ladc, lhlfdc, la2hc ext phlfdc, pafdc ext lout INCLUDE PBBSHDR.z80 INCLUDE BDOSHDR.z80 ; ; Printer setup and exit strings. SUTPTR is for initializing ; the printer to compressed print mode, and EXPTR is for ; de-initialize it to return to normal print. ; ; These strings can be as long as you need them to be, but make ; certain that that the last byte is a null (0) which is needed ; as the string terminator. ; ; You could leave them as all-nulls and set your printer by ; means of an external program, if you wish. ; suptr: ; printer initialization db 0dh,1bh,14h,1bh,36h,0 ; edit for your printer ; for compressed type ; exptr: ; printer de-init. db 0dh,1bh,1dh,1bh,36h,0 ; ...for normal type ; ; Print all users subroutine ; start: ld (system),sp ; save stack ld sp,system ; point to stack call getdrv ; get current drive call getusr ; get current user ld a,sysdrv ld (tmpdrv),a call setdrv ; set drive ld a,sysusr ld (tmpusr),a call setusr ; set user area ; ; signon: call print ; print sign-on db cr,lf,'PUSER - Print PBBS Users',cr,lf if version db 'Version ',ver+'0','.',vers+'0',rev+'0' db ' - 01/19/88',cr,lf endif if credits db 'Written by Terry Pinto',cr,lf endif db cr,lf,0 ; pusers: ld hl,0 ; starting count of selected users ld (tusers),hl ; save in buffer ld a,(wheel) ; get wheel byte cp 0ffh ; is it set jp nz,puser1 ; if no, skip display call print ; print following message db cr,lf,'Send Output to [D]isplay - [P]rinter ' db 'or [X] to Exit ',0 call eatchr ; eat extra character call getch ; get user input call caps ; capitalize cp 'P' ; is it P jp z,slflg ; if yes, print users cp 'D' ; is it D jr z,dsply ; if yes, display users cp 'X' ; is it X jp z,exit ; exit program call print ; print following message db cr,lf,lf,0 ; spaceing jp pusers ; go back and start again dsply: call getacc ; get access level request call print ; print following message db cr,lf,lf,0 puser1: ld hl,0 ; starting record ld (currec),hl ; put starting record in buffer call uopen ; open user file ld hl,(currec) ; point to record counter jr user0 uslp: ld hl,(currec) ; point to first record inc hl ; increment record counter user0: ld (currec),hl ; put in buffer call get ; get record ld a,(availf) ; get available record field or a ; set flags jp z,uslp0 ; if unavailable, get next record ld a,(pacc) ; get access print level cp 0ffh ; does it say to print all levels? jp z,pall ; if so, print all levels ld a,(acessf) ; get access level field ld hl,pacc cp (hl) ; compare access field to access flag jp nz,uslp0 ; if not good - get the next record jr pnm ; continue processing pall: cp 2 ; is he a good user - 2 or above jp c,uslp0 ; if not good - get the next record pnm: ld hl,unamef ; point to user name field usnxt: ld a,(hl) ; look at first character of user name cp ' ' ; is it a blank record jr z,uslp ; if yes - goto next record gotus: ld hl,(tusers) ; get total users selected inc hl ; increment counter ld (tusers),hl ; save in buffer ld hl,(lncnt) ; get line count inc hl ; add one line ld (lncnt),hl ; save new count ld a,(lstflg) ; get list flag cp 0ffh ; is it set? jr nz,dspl1 ; if not, work with display ld de,plines ; get maximum printer line count jr lprnt ; continue dspl1: ld de,lines ; get maximum line count lprnt: sbc hl,de ; subtract jr c,gotnm ; skip more message ld hl,0 ; zero line count ld (lncnt),hl ; store in buffer ld a,(lstflg) ; get list flag cp 0ffh ; is it set? jr nz,more ; no, continue call ffd ; do a form feed jr gotnm ; skip [more] more: call print ; print [more] message db '[more]',0 call getch ; pause call eatchr ; eat extra characters call print ; new line db cr,0 ; start at beginning of line again gotnm: ld a,(lstflg) ; get list enable flag cp 0ffh ; is it set? jp z,ulist ; if so, goto print routine ld a,(wheel) ; load wheel byte cp 0ffh ; is it set jr nz,pname ; if no, don't print record number ld hl,(rrno) ; get record number ld a,1 ; length of field ld (trecno),a ; record number in buffer call pb2asc ; print record number in ascii ld hl,(currec) ; point to current record ld de,100 ; set up compare sbc hl,de ; subrtact 100 from current record jr nc,nopad ; if not, we don't need extra space call pad ; pad string nopad: call pad ; pad string pname: ld b,30 ; length of user name field ld hl,unamef ; point to user name field call printn ; print field ld hl,padstr ; pad string call printl ; print line ld b,20 ; length of city/state field ld hl,citstf ; point to city/state field call printn ; print field ld a,b ; put length of field in A or a ; set flags jr z,gotus1 ; bypass pad string - city/state filled field ld hl,padstr ; pad string call printl ; print line gotus1: ld a,(wheel) ; load wheel byte cp 0ffh ; is it set? jr nz,ldate ; if not, skip phone number ld b,12 ; length of field ld hl,phonef ; point to telephone number field call printl ; print field call pad ; pad string ldate: ld a,(wheel) ; load wheel byte cp 0ffh ; is it set jr z,date1 ; if yes, skip last on message call print ; print following messgae db ' last logon: ',0 date1: ld ix,lstonf ; point to last on field call pdate ; print date call pcrlf ; new line uslp0: call abort ; see if user wants to abort jr z,usdone ; if yes - exit xor a ; clear flags ld hl,maxu ; put maximum users in HL ex de,hl ; swap DE and HL ld hl,(currec) ; put current record in DE inc hl ; add 1 to record count sbc hl,de ; subtract HL-DE jp c,uslp ; get next record usdone: call close ; close user file call print ; print following message db cr,lf db 'Total number of selected users: ',0 ld hl,(tusers) ; get total number of users selected call phlfdc ; print results call print ; print following message db cr,lf,lf,'End of list...',0 done: ld hl,0 ; reset line counter ld (lncnt),hl ; save in buffer ld a,(lstflg) ; get list flag cp 0ffh ; is it set? call z,rslflg ; reset list flag ld a,(wheel) ; get wheel byte cp 0ffh ; is it set? jp z,pusers ; yes, get prompt line exit: ld sp,(system) ; restore stack pointer ld a,(curdrv) ; get entry drive in A ld (tmpdrv),a ; set up for SETDRV call setdrv ; call to set drive ld a,(curusr) ; get entry user area in A ld (tmpusr),a ; set up for SETUSR call setusr ; call to set user area ret ; exit ; ; Subroutines ; uopen: ld hl,users ; point to file call open ; open file ld hl,usrlen ; get length of record ld (rrsz),hl ; set into buffer ld hl,0 ; set record number ret pcrlf: call print ; call print routine db cr,lf,0 ret ; abort: push hl ; save the TBUF address push de push bc ld e,0ffh ld c,6 call spbdos ; see if we got a character or a jr z,abort3 ; if no key pressed, then continue cp 'S'-'@' ; ^S to pause jr z,abrtwt ; wait for next character cp 'K'-'@' ; ^K to abort jr z,abort2 cp 'C'-'@' ; ^C to abort jr z,abort2 call caps cp 'S' ; S to pause jr nz,abort1 ; if not, then exit abrtwt: call getch ; otherwise wait for another character cp 'K'-'@' ; does he want to quit? jr z,abort2 ; yup... cp 'C'-'@' ; ^C to abort jr z,abort2 call caps ; check a Q too... abort1: cp 'Q' ; is it 'Q' to quit? jr z,abort2 cp 'K' ; is it 'K' to quit? jr z,abort2 jr abort3 abort2: call print ; if yes, then print abort message db cr,lf,'++ ABORTED ++',cr,lf,0 ld hl,exptr ; point to printer exit string ld a,(lstflg) ; get print enable flag cp 0ffh ; is it set? call z,setlst ; if so, de-initialize printer pop bc ; restore all registers pop de pop hl xor a ld a,(wheel) ; get wheel byte cp 0ffh ; is it set? jp nz,exit ; get prompt line ld hl,0 ; set line count to zero ld (lncnt),hl ; store in buffer ld (tusers),hl ; set total users to zero jp pusers ; exit abort3: ld a,1 or a pop bc pop de pop hl ret ; pad: call print ; print following message db ' ',0 ; print a space for appearance ret ; getdu: getdrv: ld c,25 ; get current disk call bdos ld (curdrv),a ; save in buffer getusr: ld c,32 ; get current user area ld e,-1 ; get user call bdos ld (curusr),a ; save in buffer ret ; setdu: setdrv: ld a,(tmpdrv) ; put system drive in A ld e,a ; transfer to E ld c,14 ; call to set drive call spbdos setusr: ld a,(tmpusr) ; put system user area in A ld e,a ; transfer to E ld c,32 ; call to set user area call spbdos ret ; eatchr: ld e,0ffh ld c,6 call spbdos or a jr nz,eatchr ret ; slflg: call getacc ; get access level request ld hl,suptr ; point to setup string call setlst ; initialize printer ld hl,0 ; get starting page ld (pg),hl ; save in buffer call header ; print page header ld a,0ffh ; set list enable flag ld (lstflg),a ; save in buffer jp puser1 ; start print ; ; send string to printer with no interpretation of non- ; printable characters. First null is the string terminator ; setlst: ld a,(hl) ; point to first/next byte cp 0 ; ret z ; done if it's a null call lout ; defined in SYSLIB36 inc hl ; advance pointer jr setlst ; loop rslflg: ld a,0 ; set disable list flag ld (lstflg),a ; save in buffer ld hl,foot ; point to ending message call lpstr ; send to printer ld hl,(tusers) ; get total number of users on system call lhlfdc ; send to printer ld hl,lcrlf ; point to carriage return/line feed call lpstr ; send to printer call fmfd ; send form feed to printer ld hl,exptr ; point to printer exit string call setlst ; de-initialize the printer ret getacc: ld a,(lstflg) ; get print enable flag cp 0ffh ; is it set? jr z,pracc ; if so, show print message call print ; print following message db cr,'Enter Access Level to Display or to Display ' db 'ALL Access Levels ',0 jr gtch ; jump around next message pracc: call print ; print following message db cr,'Enter Access Level to Print or to Print' db 'ALL Access Levels ',0 gtch: call eatchr ; eat extra character call getch ; get user input call caps ; capitalize input cp cr ; is it a CR jr nz,pac ; if not, skip ld a,0ffh ; put FF in A ld (pacc),a ; if CR, store FF jr pa2 ; skip over pac: sub 30h ; convert input to hex ld (pacc),a ; put response in buffer pa2: call print ; print following message db cr,lf,lf,'PBBS User List - Access levels selected: ',0 ld hl,(lncnt) ; get line count inc hl ; increment line count inc hl ; by two to accomidate heading ld (lncnt),hl ; save in buffer ld a,(pacc) ; get requested access level cp 10h ; is it all levels? jr nc,pzro ; if so, skip call pafdc ; print level ret pzro: call print ; print following messgae db 'ALL ',0 ; print ALL message ret ; ; The following subroutine utilizes routines defined in SYSLIB36. ; ulist: push hl ; save register ld hl,(currec) ; get current record number call lhldc ; send to printer call pad2 ; space out listing call pad2 ; space some more ld hl,unamef ; point to name field ld de,lname ; point to temporary buffer ld bc,30 ; length of field ldir ; move into buffer ld hl,lname ; point to buffer ld (stad),hl ; save starting address call lpstr ; send to printer call lpad ; pad string call pad2 ld hl,citstf ; point to city/state field ld de,lcitst ; point to temporary buffer ld bc,20 ; length of field ldir ; move into buffer ld hl,lcitst ; point to buffer ld (stad),hl ; save starting address call lpstr ; send to printer ld de,4 ; offset for padstring add hl,de ; add offset for padding call lpad ; pad string ld hl,phonef ; point to telephone number ld de,lphone ; point to temporary buffer ld bc,12 ; length of field ldir ; move into buffer ld hl,lphone ; point to buffer ld (stad),hl ; save starting address call lpstr ; send to printer ld de,14 ; offset for padstring add hl,de ; add offset for padding call lpad ; pad string ld a,(acessf) ; get access field cp 8 ; is access above 7? jr c,pswd ; if not, display regular ld hl,hdpswd ; point to hidden password call lpstr ; send to printer call pad3 jp psw2 ; skip normal password pswd: ld hl,pswrdf ; point to password field ld de,lpswrd ; point to temporary buffer ld bc,10 ; length of field ldir ; move into buffer ld hl,lpswrd ; point to buffer ld (stad),hl ; save starting address call lpstr ; send to printer ld de,15 ; offset for padstring add hl,de ; add offset for padding call lpad ; pad string psw2: ld a,(acessf) ; point to access level field call lafdc ; send to printer call pad2 ; space out listing ld hl,(tmsonf) ; point to times on system call lhldc ; send to printer call pad3 ; space out listing ld hl,lstonf ; point to date call lpdate call pad2 ; space out listing if folder ld hl,(ufaccf) ; get user folder access bitmap call bits ; process first 4 bits ld a,' ' ; space out call lout ; send space to LST: call bits ; process next 4 bits jr upl ; Subroutine to test the User Folder ACCess Flag (UFACCF). Testing is ; done using the following bitmap structure: ; ; Folder # 9 8 7 6 5 4 3 2 ; PMNT N N Y B Y Y Y Y ; ------------------------------ ; Register H 0 0 1 1 1 1 1 1 'grant' bits 1=granted ; Register L 0 0 0 1 0 0 0 0 'blocked' bits 1=blocked ; ------------------------------ ; Bit # 7 6 5 4 3 2 1 0 ; ; bits in H can be set manually by the sysop using PMNT or by allowing ; the system to set automatically by access level. If access to a specific ; folder is denied, then the sysop can 'block' access by using the BLOCK ; function in PMNT. In the example above, the user has been automatically ; given access to folders 2 thru 7 and the sysop has specifically blocked ; access to folder 6 for this user. The line labeled PMNT above is the way ; the display would appear using PMNT (read from right to left). bits: ld b,4 ; set number of bits to display per round bit: bit 0,h ; test bit 7 of register H jr nz,grant ; if set, access is granted bit 0,l ; test bit 7 of register L jr nz,block ; if set, access is blocked ld a,'N' ; otherwise access is denied jr prbit block: ld a,'B' ; show blocked access jr prbit grant: ld a,'Y' ; load a 'Y' prbit: call lout ; send to printer sra h ; shift H register left sra l ; shift L register left djnz bit ; repeat until done ret else ld a,(totmef) ; point to total time on system call ladc ; send to printer call pad3 ; space out listing ld a,(himsgf) ; point to high message read call ladc ; send to printer call pad2 ; space out listing endif ; folder upl: ld a,(upldsf) ; point to total uploads call ladc ; send to printer call pad2 ; space out listing ld a,(dnldsf) ; point to total downloads call ladc ; send to printer ld hl,lcrlf ; point to list cr,lf call lpstr ; send cr,lf pop hl ; restore register jp uslp ; return for next record ; padc: ld hl,lspc ; point to comma and space call lpstr ; send to printer ret pad1: ld hl,lsp1 ; point to 1 space call lpstr ; send to printer ret pad2: ld hl,lsp2 ; point to 2 spaces call lpstr ; send to printer ret pad3: ld hl,lsp3 ; point to 3 spaces call lpstr ; send to printer ret ; lpad: ld de,(stad) ; put starting address in DE sbc hl,de ; subtract starting address ; from ending address ex de,hl ; put difference in DE ld hl,padstr ; point to padstring add hl,de ; add difference as offset ; into padstring call lpstr ; print remainder of padstring ret ffd: call fmfd header: ld hl,(pg) ; point to page number inc hl ; add 1 to page ld (pg),hl ; save in buffer ld hl,lphdr ; point to header call lpstr ; send to printer ld hl,lphdr2 ; point to second part of header call lpstr ; send to printer ld hl,(pg) ; point to page number call lhlfdc ; send to printer if folder ld hl,lphdr4 ; point to folder header else ld hl,lphdr3 ; point to third part of header endif call lpstr ; send to printer ret lpdate: ld a,(hl) ; point to month push hl ; save month address on stack add a,a ; multiply month by 2 add a,a ; multiply month by 2 again ld e,a ; put in LSB of DE pair ld d,0 ; zero MSB of DE ld hl,montbl ; point to month table add hl,de ; add in offset (HL now points to month) dec hl ; subtract 1 dec hl ; subtract 1 more dec hl ; subtract another 1 dec hl ; subtract yet another for 4 call lpstr ; send to printer pop hl ; restore stack inc hl ; add 1 to HL ld a,(hl) ; point to day push hl ; save day address on stack call ladc ; send to printer ld hl,slash ; point to / call lpstr ; send to printer pop hl ; restore stack inc hl ; add 1 to HL ld a,(hl) ; point to year call lafdc ; send to printer ret ; fmfd: ld c,lstout ; BDOS list character output ld e,ff ; character to send to list device call bdos ; send character ret ; montbl: db 'Jan',0 db 'Feb',0 db 'Mar',0 db 'Apr',0 db 'May',0 db 'Jun',0 db 'Jul',0 db 'Aug',0 db 'Sep',0 db 'Oct',0 db 'Nov',0 db 'Dec',0 ; ; messages ; lphdr: db cr,lf db '==================================================' db '==================================================' db '===============================',cr,lf db 'PUSER - Version ',ver+'0','.',vers+'0',' - 03/24/87' db ' ' db ' PBBS USER FILE LISTING',0 lphdr2: db cr,lf db 'Written by: Terry Pinto - Access Programming RAS ' db ' ' db ' Page ',0 lphdr3: db cr,lf db '--------------------------------------------------' db '--------------------------------------------------' db '-------------------------------',cr,lf db 'Rec # User name Location (city st) ' db ' Phone # Password Lvl Log # Last on TOS ' db ' Msg ULD DLD',cr,lf db '----- ------------------------------ -------------------- ' db ' ------------ ---------- --- ----- --------- --- ' db '---- --- ---',cr,lf,0 ; lphdr4: db cr,lf db '--------------------------------------------------' db '--------------------------------------------------' db '-------------------------------',cr,lf db 'Rec # User name Location (city st) ' db ' Phone # Password Lvl Log # Last on Fold' db 'ers ULD DLD',cr,lf db '----- ------------------------------ -------------------- ' db ' ------------ ---------- --- ----- --------- 2345-' db '6789 --- ---',cr,lf,0 foot: db cr,lf,'Total number of selected users on system: ',0 ; lname: db ' ',0 lcitst: db ' ',0 lphone: db ' ',0 lpswrd: db ' ',0 hdpswd: db '----------',0 stad: dw 0 ; temporary storage lspc: db ', ',0 ; coma and single space for print lsp1: db ' ',0 ; single space for print lsp2: db ' ',0 ; double space for print lsp3: db ' ',0 ; triple space for print slash: db '/',0 ; slash for date lcrlf: db cr,lf,0 ; list crlf ; ; buffer area ; pacc: db 0ffh ; display access level pg: dw 0 ; page number tusers: dw 0 ; total users on system lstflg: db 0 ; list enable flag lncnt: dw 0 ; line counter tmpdrv: db 0 ; temporary drive tmpusr: db 0 ; temporary user area curdrv: db 0 ; current drive curusr: db 0 ; current user area ccpstk: dw 0 ; pbbs stack pointer currec: dw 0 ; current record number trecno: dw 0 ; temporary record number acctmp: db 0 ; temporary access level ds 64 ; define stack area system: dw 0 ; end