home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of Shareware - Software Farm 2
/
wosw_2.zip
/
wosw_2
/
CPROG
/
CLPRNT24.ZIP
/
CL-PRINT.ASM
next >
Wrap
Assembly Source File
|
1992-05-03
|
54KB
|
1,023 lines
; CL-Print.asm;
CR Equ 13
LF Equ 10
BELL Equ 7
TAB Equ 9
SWITCH Equ '/'
CODE SEGMENT ;*************************
ASSUME CS:CODE,DS:CODE ;* *
Org 100H ;* REMEMBER TO EXE2BIN *
;* *
Start: Jmp Beginning ;*************************
; Data Area
; ---------
Copyright$ DB CR,LF,'CL-Print Ver 2.40 - '
DB 'Copyright 1991,1992 Gary Meeker',CR,LF,'"'
Comment$ DB 62 DUP (' '), CR, LF, 1AH
Quote2$ DB '"=>$'
File_Start DW ? ;Points to Asciiz Filename
Commands DB 'BQN*Z'
BiosDos DB 0FFH ;0=Bios, -1=DOS Time/Date
Quiet DB 0FFH ;0=Quiet, -1=Copyright Display
NoAppend DB 0FFH ;0=No Append, -1=Append
Close_It DB 0FFH ;0=write 62 *'s
ASCIIZ$ DB ' ' ;0=ASCIIZ, Space
Usage_Msg DB BELL,CR,LF
DB 'Usage: CL-PRINT filespec "logstring"',CR,LF,LF
DB ' String must be in quotes or decimal ASCII - '
DB 'Seperate multiple codes by commas.',CR,LF,LF
; DB ' e.g. CL-PRINT C:\PCB\CALLER /S,"Scheduled Event Ended /A"',CR,LF,LF
DB TAB,'/A = " at MM-DD-YY HH:MM:SS"',CR,LF
DB TAB,'/D = "MM-DD-YY"',CR,LF
DB TAB,'/L = "MM-DD-YY (HH:MM)"',CR,LF
DB TAB,'/S = 6 spaces',CR,LF
DB TAB,'/T = "HH:MM"',CR,LF
DB TAB,'/* = row of *',CR,LF
DB TAB,'/Q = No console output',CR,LF
DB TAB,'/N = Create NEW file'
DB TAB,'/B = use BIOS Date/Time Services '
CrLf$ DB CR,LF,'$'
NoUser$ DB BELL,CR,LF,'No User Online!',CR,LF,'$'
PCBDrive DB 'PCBDRIVE='
LenPCBDrive EQU $ - PCBDrive
PCBDir DB 'PCBDIR='
LenPCBDir EQU $ - PCBDir
PCBoardSys$ DB 'PCBOARD.SYS',0
PCBoardDat$ DB 'PCBOARD.DAT',0
Not_Found2 DB ' - File not found! ',CR,LF,'$'
Not_Found3 DB ' - Path not found! ',CR,LF,'$'
No_Handle DB ' - No handles left!',CR,LF,'$'
No_Access DB ' - Access Denied!',CR,LF,'$'
Unknown DB ' - Unknown Error!',CR,LF,'$'
ReadError$ DB ' - Error reading file!',CR,LF,'$'
; Code Area
; ---------
;-------------------------------------------------------;
; First we will parse the filename and the string. ;
;-------------------------------------------------------;
Beginning: Mov DX,OFFSET Usage_Msg ;Point to syntax message.
Cld ;Move in forward direction.
Mov AX,DS ;Point ES to DS
Mov ES,AX
Mov SI,80H ;Point to parameters.
Mov DI,81H ;Point DI for SCASB
Mov AL,'@' ;See if any @ Variables exist
Xor CH,CH ;Get Command Line
Mov CL,[SI] ; Length in CX
Jcxz ErrorExit ;Nevermind if no parameters
Repne Scasb ;Do we have any @ variables
Jne No_Read ;Nope, None found
Call ReadFile ;Yep, Read PCBoard files into
Jc ErrorExit ; buffers, oops Error occured
No_Read: Mov DI,OFFSET Comment$ ;Point to comment string storage.
Xor CX,CX ;Set string counter to zero.
Call Space ;Parse leading spaces.
Mov File_Start,SI ;We now point to filename.
File_Byte: Cmp BYTE PTR [SI],CR ;Is it a carriage return?
Jz ErrorExit ;If yes, exit with syntax error.
Cmp BYTE PTR [SI],' ' ;Is it a space?
Jz Asciiz ;If yes, end of filename
Inc SI ; else, point to next byte
Jmp File_Byte ; and check it.
OpenError: Call File_Error ;Show what type of Error
ErrorExit: Call Display
Mov AX,4C01H
Int 21H ; and terminate.
Asciiz: Mov BYTE PTR [SI],0 ;Make filename into ASCIIZ.
Call Space ;Parse the spaces.
String_Byte: Call String ;Get string.
Cmp BYTE PTR [SI],CR ;Are we now pointing to CR?
Jz Open_File ;If yes, we are done here
Inc SI ; else point to next byte
Cmp CX,62 ;Maximum Length?
Jl String_Byte ; No, get rest of string.
;------------------------------------------;
; OK, Open file and seek to the end of it. ;
;------------------------------------------;
Open_File: Push CX ;Save length
Mov DX,File_Start ;Point to ASCIIZ filename
Cmp NoAppend, 0 ;Is it NoAppend mode?
Je Create_File ;Yes, Just create it!
Mov AX,3D41H ; Open file for writing.
Int 21H
Jnc Open2 ;OK if no error
Cmp AX,2 ;Was it NOT FOUND?
Jne OpenError ; No, Report the error
Create_File: Mov AH,3CH ; Yes, Create File
Xor CX,CX ; Normal Attribute
Int 21H
Jc OpenError ;Report the error
Open2: Mov BX,AX ;File Handle to BX
Mov AX,4202H ;No, Move File Pointer
Xor CX,CX ; Zero offset
Xor DX,DX ; from end of file (CX:DX = 0)
Int 21H
Pop CX
;------------------------------------------------;
; We are ready to write the comment to the file. ;
;------------------------------------------------;
Write: Jcxz Skip_Write
Mov DX,OFFSET Comment$ ;Point to COMMENT$
Jmp SHORT Write_Close ;Write the comment
Make_Close: Call Do_Close ;Fill the Buffer
Write_Close: Mov CX,64 ;64 Bytes to write
Mov AH,40H ; and write comment.
Int 21H
Skip_Write: Cmp Close_It,0FFH ;Do we need a row of *,s
Jne Make_Close ;yes
Mov AH,3EH ;No,close file.
Int 21H
Cmp Quiet,0FFh ;Quiet Mode
Jne QExit ;Yes, So Exit
Mov Comment$+62,'$' ;No, prepare the Comment
Mov DX,OFFSET Copyright$ ;Point to Copyright message
Call Display
Mov DX,OFFSET Quote2$ ;Print trailing Quote & Arrow
Call Display
Mov SI,File_Start ;Point to File Name
Call DisplayText
;------------------------------------------;
; The exit is placed in the middle of code ;
; so it can be reached by short jumps. ;
;------------------------------------------;
Exit2: Mov DX,OFFSET CrLf$
Exit: Call Display
QExit: Mov AX,4C00H
Int 21H ; and terminate.
File_Error: Mov DX,OFFSET Not_Found2
Cmp AX,2
Je Error_Ret
Mov DX,OFFSET Not_Found3
Cmp AX,3
Je Error_Ret
Mov DX,OFFSET No_Handle
Cmp AX,4
Je Error_Ret
Mov DX,OFFSET No_Access
Cmp AX,5
Je Error_Ret
Mov DX,OFFSET Unknown
Error_Ret: Ret
;---------------------------------------;
; This subroutine will use DOS function ;
; to print string terminated by '$' ;
;---------------------------------------;
Display: Mov AH,9 ;Display message
Int 21H ;
Ret ;
;---------------------------------------------;
; This subroutine will get the quoted string ;
; or convert the decimal ASCII to hexadecimal ;
; and store in the appropriate storage area. ;
;---------------------------------------------;
String: Mov AH,[SI] ;Get a character
Cmp AH,'"' ;Is it double quotes?
Jz Got_Quote ;Yes -
Cmp AH,"'" ;No - Is it single quotes?
Jnz Number ;If no, must be number
Got_Quote: Inc SI ; else, point to first string
Next_String: Lodsb ; byte and retrieve.
Cmp AL,CR ;Is it carriage return?
Jz Exit ;If yes, syntax error; exit.
Cmp AL,SWITCH ;Is it a Switch character
Jz Is_Switch ;Yes
Cmp AL,'@' ;No, Is it a Var Subst Char?
Jnz Not_switch ;No,
Is_Switch: Call Substitute ;Yes, Substitute
Jnc Next_2 ; If Not carry then continue
Ret ; else done
Not_Switch: Cmp AL,AH ;Is it a matching quotes?
Jnz Store ;If no, store the byte
Call Delimiter ; else, see if delimiter
Jnc Store ; and store the quote if part
Ret ; of string else, we are done.
Store: Stosb ;Store the byte
Inc CX ; increment byte count
Next_2: Cmp CX,62 ;Maximum length?
Jl Next_String ; no, get next string byte
Ret ; yes, then return
;-------------------------------;
; This routine converts Decimal ;
; Ascii number to charcater and ;
; places it in Comment$ ;
;-------------------------------;
Number: Xor BL,BL ;Zero into hex counter.
Cmp AH,Switch ;Was it a Switch character?
Jz Is_Switch2 ;Yes
Cmp AH,'@' ;No, Is it a Var Subst char?
Jnz Get_Number ;No, must be a number
Is_Switch2: Inc SI ;Yes, Skip the Switch Char
Mov AL,AH ;Copy Switch to AL
Jmp SHORT Substitute ;Do the substitute
Get_Number: Call Delimiter ;Is it a delimiter?
Jnc Load_Number ;If no, get next decimal number
Mov AL,BL ; get hex byte
Stosb ; and store
Inc CX ; increment byte count
Ret ; yes, then return
Jump2Exit: Jmp Exit
Load_Number: Lodsb ;Get the decimal number
Cmp AL,'0' ;Is it between 0 and 9?
Jb Jump2Exit ;If no, syntax error
Cmp AL,'9'
Ja Jump2Exit
Sub AL,30H ; else, convert to hex
Mov BH,AL ; and save
Mov AL,10 ; multiply by ten
Mul BL ; to shift place left
Mov BL,AL
Add BL,BH ; add new number
Jmp Get_Number ; and get next decimal number.
;------------------------------------------------;
; This subroutine converts '/' variables to ;
; their values and stuffs Comment$ ;
;------------------------------------------------;
Substitute: Push AX ;Save Quote
Mov AH,AL ;Save the switch
Lodsb ;Get the next Character
Cmp AL,'a' ;Lower Case?
Jb S1 ;No,
Cmp AL,'z' ;Maybe, let's see
Ja S1 ;No,
Sub AL,20h ;Yes, convert to Upper Case
S1: Cmp AH,Switch ;Is it a switch or Var Subst?
Je Do_Switch ;It was a Switch?
Jmp VarSub ;No, It was a Var Subst?
Do_Switch: Mov BX,5 ;5 commands to check
Next_Cmp: Cmp AL,Commands-1[BX] ;Is this the one?
Je Set_Mode ;Yes
Dec BX ;No, Decrement BX
Jnz Next_Cmp ;Loop until Done
;---------------------------------------------------------------------------
; Cmp AL,'Q' ;Is it QUIET Switch?
; code Je Set_Quiet ;Yes (Carry is Cleared)
; replaced Cmp AL,'N' ;Is it NoAppend mode?
; by 5 Je Set_NoAppend ;Yes, (Carry is Cleared)
; lines Cmp AL,'B' ;Is it BIOS services mode?
; above Je Set_TimeDate ;Yes, (Carry is Cleared)
; Cmp AL,'*' ;No, Is it CLOSED Var?
; Je Set_Closed ;Yes (Carry is Cleared)
; Cmp AL,'Z' ;Is it a ASCIIZ var?
; Je Set_ASCIIZ ;Yes, Carry is Cleared
;---------------------------------------------------------------------------
Cmp AL,CR ;Is it CR?
Je Jump2Exit ;If yes, syntax error; exit.
Mov BX,DI ;Save COMMENT$ Pointer
Mov DI,OFFSET DatBuffer ;Point to Buffer
Cmp AL,'T' ;Is it TIME var?
Je Stuff_Time ;Yes, and Carry is Clear
Cmp AL,'D' ;Is it DATE Var?
Je Stuff_Date ;No,
Cmp AL,'A' ;Maybe, let's see
Jnz S2 ;No,
Mov AX,'a ' ;Yes, Set ' at ' in Buffer
Stosw ;
Mov AX,' t' ;
Stosw ;
Call Do_Date ;add Date to Buffer
Mov AL,' ' ;add ' '
Stosb ;
Stc ;We want seconds too
Stuff_Time: Call DO_Time ;add Time to Buffer
Jmp SHORT Stuff_It
S2: Cmp AL,'L' ;Is it LOGON Var?
Jne S3 ;No,
Call Do_Date ;Yes, Set Date in Buffer
Mov AX,'( ' ; add ' ('
Stosw ;
Clc ;We don't want seconds
Call Do_Time ;add Time to Buffer
Mov AL,')' ; add ')'
Stosb ;
Jmp SHORT Stuff_It
S3: Cmp AL,'S' ;Is it SPACES var?
Jne S4 ;No,
Mov AX,' ' ;Yes, Set six spaces in Buffer
Stosw ;
Stosw ;
Stosw ;
Jmp SHORT Stuff_It
S4: Mov DI,BX ;restore Comment$ pointer
Stosb ;just store it
Inc CX ;count it
Clc ;
Pop AX ;Restore Quote
Ret
Set_Mode: Mov BiosDOS-1[BX],BH ;Handles all 5 Set variables, BH=0
Pop AX ;Restore Quote
Ret ;Done - Carry Clear
;---------------------------------------------------------------------------
;Set_ASCIIZ: Mov BYTE PTR ASCIIZ$,0 ;Set 0 in ASCIIZ$
; Pop AX ;Restore Quote
; Ret ;Done - Carry Clear
;Set_Quiet: Mov BYTE PTR Quiet,0 ;Show Quiet mode
; Pop AX ;Restore Quote
; Ret ;Done - Carry Clear
;Set_NoAppend: Mov BYTE PTR NoAppend,0 ;Show NoAppend mode
; Pop AX ;Restore Quote
; Ret ;Done - Carry Clear
;Set_TimeDate: Mov BYTE PTR BiosDos,0 ;Show BIOS Services used
; Pop AX ;Restore Quote
; Ret ;Done - Carry Clear
;Set_Closed: Mov BYTE PTR Close_It,0 ;Show Closed mode
; Pop AX ;Restore Quote
; Ret ;Done - Carry Clear
;---------------------------------------------------------------------------
Stuff_Date: Call Do_Date ;Yes, Set Date in Buffer
Stuff_It: Xor AL,AL ;Zero marks end of data
Stosb ;
Mov DI,BX ;resore Comment$ pointer
Mov BX,SI ;Save Command Line pointer
Mov SI,OFFSET DatBuffer ;Point to Buffer
Stuff_More: Lodsb ;Get character from Buffer
Or AL,AL ;End of data
Jz Done_Stuff ;Yes,
Stosb ;Copy to Comment$
Inc CX ;Count it
Cmp CX,62 ;Maximum Length?
Jl Stuff_More ;No - Continue
Stc ;Yes - Indicate that
Done_Stuff: Mov SI,BX ;Restore Command Line pointer
Pop AX ;Restore Quote
Ret ;All done
;------------------------------------------;
; This subroutine Reads Date and stuffs ;
; buffer with information (uses part of ;
; Do_Time routine) ;
;------------------------------------------;
Do_Date: Push BX ;Save BX
Push CX ;Save Length
Push DX ;Save Message Pointer
Test BiosDOS,0 ;Get flag
Jne DosDate ;We use DOS
Mov AH,04H ;Get date service
Int 1AH ;Call BIOS - return codes as follows:
;CH = Century (19-20) CL = Year (00-99)
;DH = Month (1-12) DL = Day (00-31)
Jmp SHORT Do_Date1
DosDate: Mov AH,2AH ;Get System Date
Int 21H ;DOS Call
Sub CX,1900 ;Remove Century
Do_Date1: Mov AL,DH ;Month
Call ASCII ;Convert byte to ASCII digits
Mov AL,'-' ;
Stosb ;
Mov AL,DL ;Day
Call ASCII ;Convert byte to ASCII digits
Mov AL,'-' ;
Stosb ;
Mov AL,CL ;Year
Jmp SHORT Skip_Seconds
;------------------------------------------;
; This subroutine Reads Time and stuffs ;
; buffer with information ;
;------------------------------------------;
Do_Time: Push BX ;Save BX
Push CX ;Save Length
Push DX ;Save Message Pointer
PushF ;Save Flags
Test BiosDOS,0 ;Get flag
Jne DosTime ;We use DOS
Mov AH,02H ;Get time service
Int 1AH ;Call BIOS - return codes as follows:
;CH = Hours (0-23) CL = Minutes (0-59)
;DH = Seconds (0-59)
Jmp SHORT Do_Time1
DosTime: Mov AH,2CH ;Get System Time
Int 21H ;DOS Call
Do_Time1: Mov AL,CH ;Hours
Call ASCII ;Convert byte to ASCII digits
Mov AL,':' ;
Stosb ;
Mov AL,CL ;Minutes
PopF ;Restore Flags
Jnc Skip_Seconds ;Skip the Seconds if No Carry
Call ASCII ;Convert byte to ASCII digits
Mov AL,':' ;
Stosb ;
Mov AL,DH ;Seconds
Skip_Seconds: Pop DX ;Restore Message Pointer
Pop CX ;Restore Length
Pop BX ;Restore BX
ASCII: Test BiosDos,0 ;Do we use DOS or BIOS
Jne DosASCII ;We use DOS
Mov AH,AL ;Need to get BCD Digits
Shr AL,1 ; MSD in AL
Shr AL,1 ; lower
Shr AL,1 ; 4
Shr AL,1 ; Bits
And AH,0FH ;And LSD in AH cleanly
PutAscii: Or AX,3030H ;Convert to ASCII
Stosw ;Stuff Digits into Buffer (in reverse)
Ret ;SI Points to String Data
DosASCII: Mov BL,10 ;Divide by 10
Xor AH,AH ;Change AL to AX
Div BL ;Do the Division
Jmp PutAscii ;and write the digits
;--------------------------------------------;
; This subroutine will translate @ variables ;
; to data read from PCBOARD.SYS & USERS file ;
;--------------------------------------------;
VarSub: Push DI ;Save Comment$ pointer
Mov BX,OFFSET SUB_TABLE ;Point to Variable List
Mov DI,OFFSET DatBuffer ;Point to Buffer
NextVar: Mov AH,[BX] ;Get a letter from table
Or AH,AH ;End of table?
Jz NoSub ;Yes, no match then
Cmp AH,AL ;No, Is this our Letter?
Jz GotIt ; Yes,
Add BX,4 ; No, Bump the pointer
Jmp NextVar ; Next Variable
GotIt: Mov AX,[BX][1] ;Get Offset value from table
Mov CL,[BX][3] ;Get Length value from table
Xor CH,CH ;Convert to word
Mov BX,SI ;Save Command line pointer
Mov SI,OFFSET SysBuffer ;Point to PCBOARD.SYS Buffer
Add SI,AX ;Add Offset
VarCopy: Lodsb ;Get Character
Or AL,AL ;Is it a Zero
Jnz CopyIt ;No,
Or AL,ASCIIZ$ ;Yes, Is ASCIIZ$ = 0
Jz CopyDone ; Yes, Done
CopyIt: Stosb ; No, Copy it
Loop VarCopy ;Loop till Done
; Rep Movsb ;Copy Variable to Buffer
CopyDone: Mov SI,BX ;Restore Command line pointer
Pop BX ;Restore Comment$ Pointer to BX
Jmp Stuff_It ; Now stuff the data in Comment$
NoSub: Pop BX ;Restore Comment$ Pointer to BX
Jmp S4 ;Just store the character
;--------------------------------;
; This subroutine will parse ;
; leading and delimiting spaces. ;
;--------------------------------;
Space: Inc SI ;Point to next byte
Cmp BYTE PTR [SI],' ' ;Is it space?
Jz Space ;If no, get next byte
Ret ; else, return.
;----------------------------;
; This subroutine will check ;
; for delimiter characters. ;
;----------------------------;
Delimiter: Push AX
Mov AL,[SI]
Clc ;Assume not delimiter.
Cmp AL,' ' ;Is it space
Jz Set_Carry
Cmp AL,CR ; or carriage return
Jz Set_Carry
Cmp AL,',' ; or comma?
Jz Set_Carry
Cmp AL,';' ; or semi-colon?
Jz Set_Carry
Cmp AL,Switch ; or Switch?
Jnz Return ;If no, return else, indicate
Set_Carry: Stc ; by setting carry flag
Return: Pop AX
Ret ; and return.
;----------------------------;
; This subroutine will fill ;
; the buffer with *'s. ;
;----------------------------;
Do_Close: Mov DI,Offset DatBuffer ;Point to Buffer for this
Mov DX,DI ;DX also for Write
Mov AL,'*' ;Make a line of *'s
Mov CX,62 ;Need 62 of them
Rep Stosb ;
Mov AL,CR ;Add a Carriage Return
Mov AH,LF ; and Line Feed
Stosw
Mov Close_It,0FFh ;Turn Off flag or we will be here
Ret ; forever - and Return
;---------------------------------------;
; This subroutine will use DOS function ;
; to print string terminated by Zero. ;
;---------------------------------------;
DisplayText: Lodsb ;get a character
Or AL,AL ;End of name
Jz DisplayDone ;Yes, Done
Mov DL,AL ;No,Print it
Mov AH,2 ;Character Output
Int 21H
Jmp DisplayText ;Loop until done
DisplayDone: Ret
;---------------------------------------;
; This subroutine will read PCBOARD.SYS ;
; file into a buffer area. ;
;---------------------------------------;
ReadFile: Push DI ;
Push SI ;
Push DX ;Save message pointer
Xor CX,CX ;Zero Counter for test purposes
NextFlush: Mov BX,CX ;Let's dup the Stdin handle
Mov AH,45h ;service to duplicate a file handle
Int 21h ;call DOS to do it
Jcxz StartFlush ;First Time thru
Jmp SHORT CloseIt
StartFlush: Mov CX,AX ;copy to CX for counter
CloseIt: Mov BX,AX ;put the new handle into BX
; Mov DX,AX ;Copy Handle number
; Add DX,3030h ;Make it Ascii
; Mov AH,2 ;Display Character
; Int 21h ;Let's display the number for testing
Mov AH,3Eh ;and close the "alias" file
Int 21h ;call DOS to do it
Dec CX ;Next Handle
Cmp CX,4 ;Did we inherit any files?
Ja NextFlush ;Yes, lets Flush them
;No, or we went thru them all!
DoneFlushing: Mov DI,OFFSET SysBuffer ;Point to PCBoard.Sys Buffer area
Push DI
Mov CX,1024 ;Let's fill the whole buffer area
Mov AL,'.' ; with '.' characters
Rep Stosb ; and do it
Mov DX,OFFSET PCBoardSys$ ;Point to Asciiz filename
Call CheckFile ;See if it's present
Pop DI
Mov CX,128 ;128 bytes is all we need
Xor AX,AX ;No Record Seek
Call ReadBuffer ;
Jc ReadErr_Hop ;
Mov AL,SysBuffer + 84 ;Get the first character (UserName)
Cmp AL, ' ' ;Is it a space?
Je NoUser ;Yes
Mov DX,OFFSET PCBoardDat$ ;Point to Asciiz filename
Call CheckFile ;See if it's present
Mov DI,OFFSET DatBuffer ;Point to PCBoard.Dat Buffer area
Mov CX,8000 ;8000 bytes is more than enough
Xor AX,AX ;No Record Seek
Call ReadBuffer
ReadErr_Hop: Jc ReadError
Mov DI,OFFSET DatBuffer ;Point to PCBoard.Dat Buffer area
Mov CX,8000
Mov BX,28 ;Scan past 28 Lines
Mov AL,LF
NextLine: Repne Scasb
Dec BX
Jnz NextLine
Mov DX,DI ;DX points to filename
Repne Scasb ;Find End of line
Dec DI ;back up
Dec DI ;back up
Mov Byte Ptr [DI],0 ;Make ASCIIZ
; Push DX
; Mov SI,DX
; Call DisplayText ;Lets see that name
; Pop DX
Mov DI,OFFSET UserBuffer ;Point to User File Buffer
Mov CX,400 ;400 Bytes in User Record
Mov AX,Word Ptr SYSBuffer+23 ;Get User Record Number
Or AX,AX ;Test the Record Number
Jz NoUser ;None present, error
Push AX ;Save the record Number
Call ReadBuffer
Pop CX
Jc ReadError
Mov AH,3EH ;Close file
Int 21H
Mov DI,OFFSET UserBuffer+229 ;Point to LastMsgConf
Mov SI,OFFSET UserBuffer+87 ;Point SI to Last Date On
Mov AX,CX ;Get Record Number
Call TransferInt2 ;Copy Integer
Call TransferDate ;Copy Date (DI=DI+8, SI=SI+6)
Add SI,8 ;Point to Last Scan Date
Call TransferDate ;Copy Date (DI=DI+8, SI=SI+6)
Call TransferChr ;Copy Chr$(Seclevel)
Call TransferInt ;Copy Integer (TimesOn)
Add SI,73 ;Point to Minutes On
Call TransferInt ;Copy Integer (Minutes On)
Call TransferDate ;Copy Date (DI=DI+8, SI=SI+6)
Call TransferChr ;Copy Chr$(ExpSecLevel)
Mov AX,Word Ptr SYSBuffer+109 ;Get Time Remaining
Call TransferInt2 ;Copy Integer
Mov SI,OFFSET UserBuffer ;Point SI to UserName
Call TransferFile ;Make it a FileName
Pop DX ;Restore message pointer
Clc ;Indicate No Error
Jmp SHORT ReadError2 ;
NoUser: Mov DX, OFFSET NoUser$ ;No user Online!
Stc
ReadError: Pop AX ;Forget message pointer
ReadError2: Pop SI
Pop DI
Ret
;---------------------------------------;
; Transfer UserName to FileName ;
;---------------------------------------;
TransferFile: Mov BL,'.' ; We need a '.', then a 0h
Mov BH,' ' ; First we need to find space
Mov AH,254 ; Flag shows we are in FileName, then Ext.
Mov CX,8 ; Eight Characters Max
Mov DX,25 ; UserName is 25 characters long
Next_Char: Lodsb ; Read a Char
Dec DX ; Count it
Call CheckChar ; Check for bad characters
Cmp AL,BH ; Is it a Space?
Jne Not_Space ; No, continue then
Inc AH ; Yes, Show we found a Space
Do_Dot: Mov AL,BL ; Yes, Time for the '.' or 0h
Not_Space: Stosb ; Store the character
Cmp AL,BL ; Was it a '.'?
Je Extension ; Yes
Loop Next_Char ; No, then loop till all 8
Jmp Do_Dot ; And now we need a Dot
Extension: Or BL,BL ; Are we Done (BL = 0)?
Jz FileDone ; Yes, Bye-bye
Xor BL,BL ; Zero to BL
Inc AH ; No, Did we find a Space already?
Jz Skip_Scan ; Yes, then No need for scan!
Mov CX,DX ; No, Get Characters remaining in UserName
Xchg SI,DI ; Scasb needs ES:DI (but we want to scan SI)
Mov AL,BH ; Scan for a Space
Repne Scasb ; Do the scan
Xchg SI,DI ; Restore SI & DI (SI past the SPACE!)
Jne End_File ; Sorry, no Space found, end the name
Inc AH ; AH = 0 (else we exit!)
Skip_Scan: Mov CX,3 ; Three characters MAX for extension
Jz Next_Char ; Back we go for the extension
End_File: Mov [DI],BL ; There isn't one, end the FileName here
FileDone: Ret
CheckChar: Cmp AL,BH ; Space is OK
Je Char_Ok
Cmp AL,BH ; '.' or 0h is OK
Je Char_Ok
Cmp AL,'0' ; Ctrl-Chars !"#$%'&()*+,-./ are no good
Jb Bad_Char
Cmp AL,'9' ; 0-9 are OK
Jbe Char_Ok
Cmp AL,'A' ; ;:<=>? are no good
Jb Bad_Char
Cmp AL,'Z' ; A-Z are OK
Jbe Char_Ok ; Anything else is no good
Bad_Char: Mov AL,'$' ; Replace all bad characters with '$'
Char_Ok: Ret
;---------------------------------------;
; Transfer Date from yymmdd to mm-dd-yy ;
;---------------------------------------;
TransferDate: Mov BL,'-'
Lodsw ; Read Year
Movsw ; Copy Month
Mov [DI],BL ; Write '-'
Inc DI
Movsw ; Copy Day
Mov [DI],BL ; Write '-'
Inc DI
Stosw ; Write year
Ret
;------------------------------------------;
; This subroutine will converts a byte ;
; into ascii text ;
;------------------------------------------;
TransferChr: Lodsb ;Read the Chr
Xor AH,AH ;force upper byte to zero
Mov DX,3 ;We want 3 characters
Jmp SHORT TI2
;------------------------------------------;
; This subroutine will converts an integer ;
; into ascii text ;
;------------------------------------------;
TransferInt: Lodsw ;Read the integer
TransferInt2: Mov DX,5 ;We want 5 characters
TI2: Push BX ;Save register
Mov BL,10 ;for division by 10
Xor CX,CX ;set count to zero
Divide: Push DX ;save register
Xor DX,DX ;perform word divide
Xor BH,BH ; to avoid divide overflow
Div BX ;return quotient in AX
Mov BH,DL ;return remainder in BH
Pop DX
Push BX ;build our number on the stack
Inc CX ;keep count of them
Or AX,AX ;All done? (remainder = 0)
Jnz Divide ;No, Keep dividing
Mov AH,"0" ;prepare for ASCII translation
Write_it: Pop BX ;get a remainder off the stack
Mov AL,BH ;put remainder in AL
Add AL,AH ;convert to ASCII
Stosb ;write digit to end of string
Dec DX ;decrement desired count
Loop Write_it ;pop all of them off of stack
Mov CX,DX ;Remaining Count to CX
Pop BX ;Retore register
Jcxz PadDone ;No padding needed
Xor AL,AL ;Load Zero
Rep Stosb ;Pad remainder
PadDone: Ret ;All Done!
;-------------------------------------------;
; DX Points to ASCIIZ Filename ;
; ;
; Check to see if file in current directory ;
; or at %PCBDRIVE%%PCBDIR% from environment ;
;-------------------------------------------;
CheckFile: Push DX ;Save filename pointer
Mov AX,3D40H ;Open file for reading.
Int 21H
Jc CheckError ;Error if Carry Set
Mov AX,BX ;Copy handle of open file
Mov AH,3Eh ;and close it.
Int 21H
Jnc CheckDone ;OK, File exists
CheckError: Cmp AX,2 ;File Not Found?
Jne CheckDone ;Exit if anything else
Mov BX,OFFSET UserBuffer
Pop SI ;Get filename pointer
Push BX ;Save Buffer Address instead
Push SI ;Now save filename pointer
Mov DX,OFFSET PCBDrive
Mov BP,LenPCBDrive
Call Copy_Env ;Findit & Copy it
Mov DX,OFFSET PCBDir
Mov BP,LenPCBDir
Call Copy_Env ;Findit & Copy it
Pop SI ;Get back filename pointer
Mov AL,'\' ;Append a '\' (if needed)
Cmp [DI-1],AL ;Is there one already?
Je No_Slash ;Yes,
Stosb ;No, so add one.
No_Slash: Call Copy_ASCIIZ ;And Copy it
Stosb ; And terminate it with a Zero
; Pop SI ;Get the buffer address
; Push SI ; put it back on the stack
; Call DisplayText ; Now, Lets see that name!
CheckDone: Pop DX ;Get Filename pointer or buffer address.
Ret
;------------------------------------------------------;
; On Entry: ;
; BX Points to Destination Buffer ;
; DX points to Target String to find in Environment ;
; BP Contains length of Target String ;
; On Exit: ;
; BX adjusted to next character to write in Buffer ;
; DI is same as BX (All other Regs altered) ;
;------------------------------------------------------;
Copy_Env: Mov AX,CS:[2Ch] ;Point ES to Environment
Mov ES,AX ;
Xor DI,DI ;Start of Environment (ES:DI)
Xor AX,AX ;
Next_Env: Mov CX,BP ;Get length.
Mov SI,DX ;Get Target pointer
Rep Cmpsb ;Do we have a match? (DS:SI) = (ES:DI)
Je FoundMatch ;Yes, Found it
Dec DI ;No, It didn't match, back up one
Mov CX,-1 ;
Repne Scasb ;Find the end of this one (ES:DI)
Cmp ES:[DI],AL ;Is this the last one?
Jne Next_Env ;No, Do the next one.
Mov DI,BX ;Point DI to Buffer also
Je Copy_Exit ;Yes, No Copy
FoundMatch: Mov AX,ES ;Point DS to Env Segment
Mov DS,AX ;
Mov AX,CS ; and ES back to Program Data Segment
Mov ES,AX ;
Mov SI,DI ;Point SI to variable value
Mov DI,BX ;Point DI to Buffer
Copy_ASCIIZ: Xor AL,AL ;We need to copy up to the 0h
Copy_Next: Cmp [SI],AL ;Is this the end?
Je Copy_Done ;Yes,
Movsb ;No, Copy it (ES:DI) <= (DS:SI)
Jne Copy_Next ;Keep going
Copy_Done: Mov BX,DI ;Update BX
Copy_Exit: Mov DX,CS ;Make sure DS points to
Mov DS,DX ; Code Segment again.
Mov ES,DX ; and ES too!
Ret ;
;--------------------------------;
; DX Points to ASCIIZ Filename ;
; DI Points to Buffer Area ;
; CX Contains Length to read ;
; AX Contains Record Number or 0 ;
; Carry set if error ;
;--------------------------------;
ReadBuffer: Mov SI,DX ;Save filename pointer (for disp)
Push AX ;Save Record Number (if any)
Mov AX,3D40H ;Open file for reading.
Int 21H
Pop BX ;Restore Record Number (to BX)
Jc FileError ;Error if Carry Set
Xchg AX,BX ;Copy handle of open file
Or AX,AX ;Random Record Seek?
Jz No_Seek ;No,
Push CX
Dec AX
Mul CX ;Yes, CX=Length, AX=Record Number
;Now DX:AX = Seek (Save Length)
Mov CX,AX ;Now DX:CX
Xchg CX,DX ;Now CX:DX
Mov AX,4200H ;Seek
Int 21H
Pop CX ;Restore Length
Jc FileError ;Error if Carry Set
No_Seek: Mov DX,DI ;Point to buffer
Mov AH,3FH ;Read from handle
Int 21H
Jc FileError ;Error if Carry Set
Mov AH,3EH ;Close file
Int 21H
Jc FileError
Ret ;All done
FileError: Push AX ;Save error code
Call DisplayText ;Display the filename
;For trouble shooting error codes use the following
; Mov DL,' '
; Mov AH,2 ;Character Output
; Int 21H
; Mov DL,'('
; Mov AH,2 ;Character Output
; Int 21H
; Mov DL,BL
; Add DL,30h
; Mov AH,2 ;Character Output
; Int 21H
; Mov DL,')'
; Mov AH,2 ;Character Output
; Int 21H
Pop AX ;Get error code
Call File_Error ;Translate it
Stc ;Indicate the error
Ret
SUB_TABLE LABEL BYTE
DB 'F', 25, 0, 15 ; First Name (Proper Case)
DB '?', 40, 0, 12 ; Password
DB 'G', 56, 0, 5 ; Time User logged On
DB 'Z', 80, 0, 4 ; Language Extension
DB 'N', 84, 0, 25 ; User Full Name
DB '*', 146, 1, 5 ; Time Remaining (from 109)
DB 'V', 112, 0, 5 ; Event Time
DB 'C', 153, 0, 24 ; City, State
DB 'B', 189, 0, 13 ; Bus/Data Phone
DB 'H', 202, 0, 13 ; Home/Voice Phone
DB 'D', 106, 1, 8 ; Last Date On (from 215)
DB 'T', 221, 0, 5 ; Last Time On
DB '!', 226, 0, 1 ; Expert Mode (Y or N)
DB 'P', 227, 0, 1 ; Default Protocol
DB 'L', 114, 1, 8 ; Last Dir Scan (from 229)
DB 'A', 122, 1, 3 ; Sec Level Access (from 235)
DB '#', 125, 1, 5 ; Number of Times On (from 236)
DB 'M', 130, 1, 5 ; TimeSpent last call (from 311)
DB 'E', 135, 1, 8 ; Expiration Date (from 313)
DB 'X', 143, 1, 3 ; Expiration Sec Level (from 319)
DB 'U', 251, 0, 30 ; User Maintained Comment
DB 'S', 25, 1, 30 ; Sysop Maintained Comment
DB 'R', 101, 1, 5 ; Record Number
DB '=', 151, 1, 13 ; First.Last
DB '$', 101, 1, 63 ; Translated Data
Table_End DB 0 ; 528 DUP ('.') ;PCBoard.Sys reads in here
SysBuffer EQU Table_End + 1
; 0 Display AS STRING * 2 'Display On/Off ("-1" = On, " 0" = Off)
; 2 Printer AS STRING * 2 'Printer On/Off ("-1" = On, " 0" = Off)
; 4 PageBell AS STRING * 2 'Page Bell On/Off ("-1" = On, " 0" = Off)
; 6 CallAlarm AS STRING * 2 'Caller Alarm On/Off ("-1" = On, " 0" = Off)
; 8 SysopFlag AS STRING * 1 'Sysop Flag (" ", "N"=sysop next, "X"=exit dos)
; 9 ErrCorr AS STRING * 2 'Error Corrected ("-1" = On, " 0" = Off)
; 11 Graphics AS STRING * 1 'Graphics Mode ('Y'=yes, 'N'=no, '7'=7E1)
; 12 NodeChat AS STRING * 1 'Node Chat Status ('A'=available, 'U'=unavailable)
; 13 DTEPort AS STRING * 5 'DTE Port Speed (PC to Modem speed)
; 18 Connect AS STRING * 5 'Connect Speed shown to caller or "Local"
;| 23 RecNum AS INTEGER 'User's Record Number in the USERS file
;| 25 FirstName AS STRING * 15 'User's First Name (padded to 15 characters)
;| 40 Password AS STRING * 12 'User's Password (padded to 12 characters)
; 52 TimeOn AS INTEGER 'Time User Logged On (in minutes since midnight)
; 54 TimeUsed AS INTEGER 'Time used so far today (negative number of minutes)
;| 56 TimeOnF AS STRING * 5 'Time User Logged On (in "HH:MM" format)
; 61 DayTime AS INTEGER 'Time Allowed On (from PWRD file)
; 63 DLKbytes AS INTEGER 'Allowed K-Bytes for Download
; 65 ConfArea AS STRING * 1 'Conference Area user was in (if <= 255)
; 66 ConfJoined AS STRING * 5 'Conference Areas the user has joined this session
; 71 ConfScaned AS STRING * 5 'Conference Areas the user has scanned this session
; 76 ConfAddTime AS INTEGER 'Conference Add Time in minutes
; 78 CreditTime AS INTEGER 'Upload/Sysop CHAT Credit Minutes
;| 80 LangExt AS STRING * 4 'Language Extension
;| 84 UserName AS STRING * 25 'User's Full Name (padded to 25 characters)
;| 109 MinRemain AS INTEGER 'Calculated Minutes Remaining
; 111 NodeNum AS STRING * 1 'Node Number (or ' ' if no network) CHR$()
;| 112 EventTime AS STRING * 5 'Scheduled Event Time (in "HH:MM" format)
; 117 EventOn AS STRING * 2 'Is Event Active ("-1" = On, " 0" = Off)
; 119 EventSlide AS STRING * 2 'Slide Event ("-1" = On, " 0" = Off)
; 121 MemMesg AS STRING * 4 'Memorized Message Number MKSMBF$()
; 125 ComPort AS STRING * 1 'Comm Port Number (0=none, 1-8)
; 126 Reserved1 AS STRING * 1 'Reserved for PCBoard
; 127 Reserved2 AS STRING * 1 'Reserved for PCBoard
UserBuffer EQU SysBuffer+128 ;Users record reads in here
;| 128 UserName AS STRING * 25 'First name and Last name
;| 153 CityState AS STRING * 24 'City and State
; 177 Password AS STRING * 12 'Password
;| 189 BusPhone AS STRING * 13 'Business Phone Number
;| 202 HomePhone AS STRING * 13 'Home Phone Number
;| 215 LastOnDate AS STRING * 6 'Last Date on system (in yymmdd format)
;| 221 LastOnTime AS STRING * 5 'Last Time on system (in hh:mm format)
;| 226 Expert AS STRING * 1 'Expert Mode - "Y" or "N"
;| 227 Protocol AS STRING * 1 'Protocol
; 228 PackedFlags AS STRING * 1 'Dirty, ClrScrn, HasMail, DontAsk, Editor
;| 229 LastDirScan AS STRING * 6 'Last date looked at directory (in yymmdd format)
;| 235 SecLevel AS STRING * 1 'Security Level CHR$(X)
;| 236 TimesOn AS INTEGER 'Number of times on the system
; 238 PageLength AS STRING * 1 'Page Length CHR$(X)
; 239 Uploads AS INTEGER 'Number of Uploads
; 241 Downloads AS INTEGER 'Number of Downloads
; 243 DailyDlBytes AS STRING * 8 'Daily Download Bytes so far
;| 251 UserComment AS STRING * 30 'User Maintained Comment
;| 281 SysopComment AS STRING * 30 'Sysop Maintained Comment
;| 311 TimeSpent AS INTEGER 'Elapsed Time on system on last date called
;| 313 SubDate AS STRING * 6 'Subscription Registration Date (yymmdd format)
;| 319 ExpSecLevel AS STRING * 1 'Subscription Expired Security Level CHR$(X)
; 320 LastConference AS STRING * 1 'Last Conference left - CHR$(X) - 255 = Ext.
; 321 AreaReg AS STRING * 5 'Area Registration Info (1-39) BitMap
; 326 ExpAreaReg AS STRING * 5 'Expired Area Registration Info (1-39) BitMap
; 331 UserScanArea AS STRING * 5 'User Message Scan Areas (1-39) BitMap
; 336 TotalDownloads AS STRING * 8 'Total Bytes Download - all calls
; 344 TotalUploads AS STRING * 8 'Total Bytes Upload - all calls
; 352 Delete AS STRING * 1 'Positive Delete Flag to Delete User (Repack)
; 353 LastMsgMain AS STRING * 4 'Last message read in Main Board MKSMBF$()
; 357 LastMsgConf AS STRING * 156 'Last message read in Conferences 39 * 4 "
; ' (Gets overwritten by 3 date conversions)
; ' ( & numeric conversions)
; 513 InfPointer AS LONG 'Pointer into USERS.INF record
; 517 Space2 AS STRING * 9 'Reserved
; 526 ExtLastConference AS INTEGER 'Last Conference Left (If LastConf.$ = 255)
DatBuffer EQU UserBuffer+400 ;PCBoard.Dat read in here
;and we buffer or conversions.
CODE ENDS
END Start