home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.wwiv.com
/
ftp.wwiv.com.zip
/
ftp.wwiv.com
/
pub
/
MISC
/
ARTFIX09.ZIP
/
NETMGR
/
NETMGR.ASM
< prev
next >
Wrap
Assembly Source File
|
2000-01-01
|
16KB
|
518 lines
; Netmgr.Asm written 1999 by Tobias Ernst.
;
; This file installs interrupt service handlers that are needed by the
; patched NetMgr executable and then spawns the patched Netmgr executable,
; and afterwards deinstalls the interrupt service handlers. The patched
; Netmgr executable is expected to have the name "netmgr.ovl" and reside
; in the same directory as the netmgr.com file that is assembled from
; netmgr.asm.
;
; This file is written for Borland TASM, but should also work with
; microsoft MASM and compatible assemblers, though I didn't test it.
; Assemble as follows:
;
; tasm netmgr.asm
; tlink netmgr /t
;
; If you use another linker, assure that a .COM file is generated, or
; convert the EXE file with EXE2BIN. It is important that the file is
; a .COM file!
DGROUP group _TEXT, _DATA
_TEXT SEGMENT BYTE PUBLIC 'CODE'
ASSUME CS: DGROUP, DS:DGROUP, SS:DGROUP
org 0100h
start: jmp main
; Symbolic contants for the interrupt vectors to use
vector1 equ 08Bh
vector2 equ 08Ch
vector3 equ 08Dh
vector4 equ 08Eh
vector5 equ 08Fh
; Interrupt Service Routine #1
; Function: - Get a two digit year number from [bp-10h] to AX
; - Convert AX to a "tm.tm_year" compatible year number, that
; is, the number of years that have passed since 1900.
; Purpose: This routine is called when reading in a message from the
; Hudson Message Base. HMB only has a two digit year field,
; so we have to interpret a two digit year number somehow.
; Here, we assume that a year number of 00..79 is in 20xx,
; while a year number of 80..99 is in 19xx. This makes HMB
; save until 12/31/2079.
service1:
mov ax, word ptr [bp-10h]
cmp ax, 80d ; is ax >= 80
jae twc2 ; if so -> 19xx
add ax, 100d ; otherwise: 20xx, add 100 dec
twc2: iret
; Interrupt Service Routines #2
; Function: Get a year number in tm.tm_year format from [si+0a],
; and push the modulo of the division of this number by 100
; to the stack.
; Notes: As an interrupt normally does not leave anything on the
; stack, this code looks a bit unconventional
; Purpose: This routine is called when writing a FTSC date stamp into
; a PKT file, or when creating a textual header represenatation
; (in boundes, forwards, etc) and prevents the 2 digit date
; field from spilling (without the modulo 100 operation, "100"
; would be written there in the year 2000 instead of 00).
service2: mov cs:[tmpax],ax ;save AX
pop ax ;get the return address from stack
mov cs:[retadd1],ax
pop ax
mov cs:[retadd2],ax
pop ax
mov cs:[retadd3],ax
mov ax, word ptr[si+0ah]
push cx
mov cl, 064h ; only pass the modulo 100 value
idiv cl ; to sprintf
pop cx
mov al,ah
xor ah,ah
push ax
push cs:[retadd3] ;Now jump back
push cs:[retadd2]
push cs:[retadd1]
mov ax,cs:[tmpax]
iret
tmpax dw 0
retadd1 dw 0
retadd2 dw 0
retadd3 dw 0
; Interrupt Service Routines #3
; Function: Get a year number in tm.tm_year format from [bx+0a],
; and push the modulo of the division of this number by 100
; to the stack.
; Notes: As an interrupt normally does not leave anything on the
; stack, this code looks a bit unconventional
; Purpose: This routine is called when writing a FTSC date stamp
; into a *.squish or *.msg base, and when writing a hudson
; time stamp. It prevents the 2 digit date field from spilling
; (without the modulo 100 operation, "100" would be written
; there in the year 2000 instead of 00).
service3: mov cs:[tmp2ax],ax ;save AX
pop ax ;get the return address from stack
mov cs:[ret2add1],ax
pop ax
mov cs:[ret2add2],ax
pop ax
mov cs:[ret2add3],ax
mov ax, word ptr[bx+0ah]
push cx
mov cl, 064h ; only pass the modulo 100 value
idiv cl ; to sprintf
pop cx
mov al,ah
xor ah,ah
push ax
push cs:[ret2add3] ;Now jump back
push cs:[ret2add2]
push cs:[ret2add1]
mov ax,cs:[tmp2ax]
iret
tmp2ax dw 0
ret2add1 dw 0
ret2add2 dw 0
ret2add3 dw 0
; Interrupt Service Routines #4
; Function: Get a year number in tm.tm_year format from [bx+0a],
; and push the modulo of the division of this number by 100
; to the stack.
; Notes: As an interrupt normally does not leave anything on the
; stack, this code looks a bit unconventional
; Purpose: This routine is called when writing a FTSC date stamp
; into a *.squish or *.msg base, and when writing a hudson
; time stamp. It prevents the 2 digit date field from spilling
; (without the modulo 100 operation, "100" would be written
; there in the year 2000 instead of 00).
service4: mov cs:[tmp3ax],ax ;save AX
pop ax ;get the return address from stack
mov cs:[ret3add1],ax
pop ax
mov cs:[ret3add2],ax
pop ax
mov cs:[ret3add3],ax
mov ax, word ptr[bx+0ah] ;get tm->tm_year
add ax, 1900d ;convert to 4 digit year
push ax
push cs:[ret3add3] ;Now jump back
push cs:[ret3add2]
push cs:[ret3add1]
mov ax,cs:[tmp3ax]
iret
tmp3ax dw 0
ret3add1 dw 0
ret3add2 dw 0
ret3add3 dw 0
; Interrupt Service Routines #5
; Function: Get a two digit year number from ax and convert it to a
; FAT-style timestamp (years since 1980). Works until 2080.
; Purpose: This routine is called when Netmgr reads a message from a
; *.MSG area and the Opus Written or Opus Arrived date are
; not set (this is allowed behaviour, only the FTSC date
; field is mandatory). In this case, Netmgr wants to derive
; valid dates for the Opus date stamps from the FTSC date,
; which only has the date in two digits. This previously failed
; in 2000, because 00 - 80 < 0.
service5: cmp ax, 80d
jae rudolph
add ax,20d
iret
rudolph: sub ax, 80d ; the red nosed reindeer
iret
; The main program. These routines install the correct interrupt handlers,
; execute timed.ovl, and restore the original interrupt handlers. This code
; is fairly uninteresting.
main:
mov ax, cs ; set up the segment registers and stack
mov ds, ax
mov ss, ax
mov es, ax
mov ax, offset DGROUP:stack_high
mov sp, ax
; free unneeded memory
mov bx, offset DGROUP:highwater
shr bx, 4
inc bx
mov ah, 4Ah
int 21h
; store the old interrupt vectors
mov ah, 35h
mov al, vector1
int 21h
mov [oldofs1],bx
mov [oldseg1],es
mov ah, 35h
mov al, vector2
int 21h
mov [oldofs2],bx
mov [oldseg2],es
mov ah, 35h
mov al, vector3
int 21h
mov [oldofs3],bx
mov [oldseg3],es
mov ah, 35h
mov al, vector4
int 21h
mov [oldofs4],bx
mov [oldseg4],es
mov ah, 35h
mov al, vector5
int 21h
mov [oldofs5],bx
mov [oldseg5],es
; set the new interrupt vectors
mov ah,25h
mov al, vector1
mov dx, offset DGROUP:service1
int 21h
mov ah,25h
mov al, vector2
mov dx, offset DGROUP:service2
int 21h
mov ah,25h
mov al, vector3
mov dx, offset DGROUP:service3
int 21h
mov ah,25h
mov al, vector4
mov dx, offset DGROUP:service4
int 21h
mov ah,25h
mov al, vector5
mov dx, offset DGROUP:service5
int 21h
; prepare the call to stringops
push ds
mov ax, offset DGROUP:paramoff
push ax
push ds
mov ax, offset DGROUP:paramseg
push ax
push ds
mov ax, offset DGROUP:prognameoff
push ax
push ds
mov ax, offset DGROUP:prognameseg
push ax
mov ah,062h ; get PSP
int 21h
push bx
xor ax,ax
push ax
call _stringops ; fill in the various structures
add sp, 014h
mov ax, [paramseg] ; call the DOS EXEC function
mov es, ax
mov bx, [paramoff]
mov dx, [prognameoff]
mov ax, [prognameseg]
mov ds, ax
mov ax, 04B00h
int 21h
mov ax, cs ; restore the registers
mov ds, ax
mov ss, ax
mov ax, offset DGROUP:stack_high
mov sp, ax
; restore the interrupt vectors
mov bx, ds
mov ah, 25h
mov al, vector1
mov dx, [oldofs1]
mov cx, [oldseg1]
mov ds, cx
int 21h
mov ds, bx
mov bx, ds
mov ah, 25h
mov al, vector2
mov dx, [oldofs2]
mov cx, [oldseg2]
mov ds, cx
int 21h
mov ds, bx
mov bx, ds
mov ah, 25h
mov al, vector3
mov dx, [oldofs3]
mov cx, [oldseg3]
mov ds, cx
int 21h
mov ds, bx
mov bx, ds
mov ah, 25h
mov al, vector4
mov dx, [oldofs4]
mov cx, [oldseg4]
mov ds, cx
int 21h
mov ds, bx
mov bx, ds
mov ah, 25h
mov al, vector5
mov dx, [oldofs5]
mov cx, [oldseg5]
mov ds, cx
int 21h
mov ds, bx
mov ah, 04dh ; query return code of the .OVL module
int 21h
mov ah, 04ch ; terminate program
int 21h
; _stringops
; This function fills in the huge bunch of tables that is required for the
; DOS exec function. It looks a bit weired, because it has originally been
; created by a C compiler.
_stringops proc near
push bp
mov bp,sp
sub sp,12
push si
push di
; /* pass the command line on as is */
les bx,dword ptr [bp+4]
mov al,byte ptr es:[bx+128]
mov byte ptr DGROUP:_cmdlin,al
cmp byte ptr DGROUP:_cmdlin,126
jle short @1@534
mov byte ptr DGROUP:_cmdlin,126
@1@534:
xor si,si
jmp short @1@618
@1@562:
les bx,dword ptr [bp+4]
add bx,si
mov al,byte ptr es:[bx+129]
mov byte ptr DGROUP:_cmdlin[si+1],al
inc si
@1@618:
mov al,byte ptr DGROUP:_cmdlin
cbw
cmp ax,si
jg short @1@562
mov byte ptr DGROUP:_cmdlin[si+1],13
; /* adjust the name of the file to be spawned in the env_block */
les bx,dword ptr [bp+4]
mov ax,word ptr es:[bx+44]
mov word ptr [bp-2],ax
mov word ptr [bp-4],0
mov ax,word ptr [bp-2]
mov dx,word ptr [bp-4]
mov word ptr [bp-6],ax
mov word ptr [bp-8],dx
jmp short @1@702
@1@674:
inc word ptr [bp-8]
@1@702:
les bx,dword ptr [bp-8]
cmp byte ptr es:[bx],1
jne short @1@674
les bx,dword ptr [bp-8]
cmp byte ptr es:[bx+1],0
jne short @1@674
mov ax,word ptr [bp-6]
mov dx,word ptr [bp-8]
add dx,2
mov word ptr [bp-10],ax
mov word ptr [bp-12],dx
mov word ptr [bp-6],ax
mov word ptr [bp-8],dx
jmp short @1@814
@1@786:
inc word ptr [bp-8]
@1@814:
les bx,dword ptr [bp-8]
cmp byte ptr es:[bx],0
jne short @1@786
les bx,dword ptr [bp-8]
mov byte ptr es:[bx-3],79
les bx,dword ptr [bp-8]
mov byte ptr es:[bx-2],86
les bx,dword ptr [bp-8]
mov byte ptr es:[bx-1],76
; /* fill in the parameter block */
mov ax,word ptr [bp-2]
mov word ptr DGROUP:_paramblock,ax
mov word ptr DGROUP:_paramblock+2,offset DGROUP:_cmdlin
mov word ptr DGROUP:_paramblock+4,ds
mov word ptr DGROUP:_paramblock+6,offset DGROUP:_fcb2
mov word ptr DGROUP:_paramblock+8,ds
mov word ptr DGROUP:_paramblock+10,offset DGROUP:_fcb2
mov word ptr DGROUP:_paramblock+12,ds
les bx,dword ptr [bp+16]
mov word ptr es:[bx],ds
les bx,dword ptr [bp+20]
mov word ptr es:[bx],offset DGROUP:_paramblock
les bx,dword ptr [bp+8]
mov ax,word ptr [bp-10]
mov word ptr es:[bx],ax
les bx,dword ptr [bp+12]
mov ax,word ptr [bp-12]
mov word ptr es:[bx],ax
pop di
pop si
mov sp,bp
pop bp
ret
_stringops endp
_TEXT ENDS
_DATA SEGMENT WORD PUBLIC 'DATA'
; These variables store the old interrupt vectors
oldseg1 dw ?
oldofs1 dw ?
oldseg2 dw ?
oldofs2 dw ?
oldseg3 dw ?
oldofs3 dw ?
oldseg4 dw ?
oldofs4 dw ?
oldseg5 dw ?
oldofs5 dw ?
; These variables are used to exchange data between the main program
; and the _stringops subroutine
paramoff dw 1
paramseg dw 2
prognameoff dw 3
prognameseg dw 4
; We do need a little bit of stack for our own ...
stack_low dw 128 dup (10)
stack_high dw 0
; These structures are filled in and passed to the DOS EXEC function
_cmdlin label byte
db 128 dup (0)
_paramblock label word
db 16 dup (0)
_fcb2 label word
db 35 dup (0)
_fcb1 label word
db 35 dup (0)
; This variable marks the last address in the file, so that the rest
; of the memory can be freed.
highwater db 0
_DATA ENDS
END start