home *** CD-ROM | disk | FTP | other *** search
- name int21
- _text segment byte public 'code'
- dgroup group _data,_bss
- assume cs:_text,ds:dgroup
- _text ends
- _data segment word public 'data'
- _d@ label byte
- _data ends
- _bss segment word public 'bss'
- _b@ label byte
- _bss ends
-
- ;
- ; I switch to my own stack when handling an int 21 request on behalf
- ; of a process. This is done because the amount of stack available to
- ; the calling process is not known. The flag "onintstack" indicates
- ; whether this special stack is currently in use so that we do not
- ; inadvertantly try to use it again. If an int 21 call is made while
- ; this stack is in use (as can occur for instance when we are flushing
- ; a buffer to disk, or calling ioctl to find out whether the current
- ; handle refers to the console), we do not call the C function
- ; "int21handler", but rather chain to DOS immediately.
- ;
- _bss segment word public 'bss'
- db 512 dup (?)
- intstack label byte
- _bss ends
-
- _text segment byte public 'code'
- public _grab21, _rstr21, _getpsp, _setpsp, _getdosflag, _callDOS
- extrn _int21handler:near
-
- savesp dw ? ; saved ss:sp of calling process
- savess dw ?
- onintstack dw ?
-
- ;
- ; psp = getpsp(void)
- ;
- _getpsp proc near
- mov ah, 51h
- int 21h
- mov ax, bx
- ret
- _getpsp endp
-
- ;
- ; void setpsp(psp)
- ;
- ; This function uses undocumented DOS function 50h
- ;
- _setpsp proc near
- push bp
- mov bp, sp
- mov bx, [bp+4]
- mov ah, 50h
- int 21h
- pop bp
- ret
- _setpsp endp
-
- ;
- ; char far *dosflag = getdosflag(void);
- ;
- ; Returns a pointer to the "indos" flag. This is used to prevent
- ; any attempt to re-enter DOS.
- ;
- _getdosflag proc near
- mov ah,34h
- int 21h
- mov ax, bx
- mov dx, es
- ret
- _getdosflag endp
-
- ;
- ; int grab21(void)
- ;
- ; Intercept DOS function calls by installing our own
- ; int 21 handler. Zero is returned if the current int 21
- ; handler has the same offset as the one being installed.
- ; This is used as a quick check to see if script
- ; is already active. It is far from a foolproof check,
- ; for instance it is possible that the DOS interrupt
- ; handler has the same offset as our own handler in which
- ; case this function would indicate that script was already
- ; active when in fact it was not. The probability is reasonably
- ; small that this won't occur.
- ;
- _grab21 proc near
- mov ax, 3521h ; save current int 21 handler
- int 21h
- mov word ptr cs:oldvct21, bx
- mov word ptr cs:oldvct21+2, es
- mov dx, offset int21 ; set up our int 21 handler
- cmp bx, dx
- je nogo
- mov ax, 2521h
- int 21h
- mov cs:onintstack,0
- mov ax,1
- ret
- nogo:
- mov ax,0
- ret
- _grab21 endp
-
- ;
- ; rstr21()
- ;
- ; Repair the damage done above before exiting.
- ;
- _rstr21 proc near
- mov cs:onintstack,1
- push ds
- lds dx, dword ptr cs:oldvct21
- mov ax, 2521h
- int 21h
- pop ds
- ret
- _rstr21 endp
-
- ;
- ; The int 21 first level handler.
- ; This function sets up a stack, pushes the processor registers
- ; on this stack, and then calls C. In order that the C handler
- ; can make DOS calls without recursing, the flag "onintstack"
- ; is set. If the following ISR is called when this flag is set,
- ; it will not call the C handler again, but instead will chain
- ; immediately to DOS
- ;
- int21 proc far
- cmp cs:onintstack, 0
- jne chain
- mov cs:onintstack, 1
- mov word ptr cs:savesp, sp ; switch stacks
- mov word ptr cs:savess, ss
- push cs
- pop ss
- mov sp, offset dgroup:intstack
- sti
- cld
- ;
- push es ; Save regs on the new stack.
- push ds ; The C function "int21hander"
- push dx ; expects the registers
- push cx ; in this order.
- push bx ; They must look like a
- push ax ; "union MYFRAME"
-
- push cs
- pop ds
-
- call near ptr _int21handler
- mov ah,al
- sahf
- pop ax
- pop bx
- pop cx
- pop dx
- pop ds
- pop es
- ;
- mov cs:onintstack, 0
- mov ss, word ptr cs:savess ; Restore the original stack
- mov sp, word ptr cs:savesp
-
- je chain ; Nothing between the sahf above, and here
- ; is allowed to affect the flags.
- ret 2 ; Carry flag still set from sahf above.
- chain:
- db 0EAh ; opcode for FAR JUMP
- oldvct21 dd ?
- int21 endp
-
- ;
- ; flags = callDOS(regp)
- ; union MYFRAME *regp;
- ;
- ; This function loads the registers from "regp", executes an int 21
- ; and then copies the modified registers back into "regp"
- ; The processor flags are returned as the value of the function
- ;
- ; This function is currently used to read console input on behalf
- ; of a process and is called while the special stack is in use.
- ; This means that "onintstack" is set. A problem arises if the
- ; user types ^C in response to this input request. In this case,
- ; the calling process is aborted by DOS and never returns to this
- ; procedure. This means that we never get a chance to clear
- ; "onintstack". The effects of this are that no further output
- ; will be written to the output file. A possible solution may
- ; be to chain to the termination vector (int 22h), but this would
- ; have to done every time "callDOS" is called and not just once
- ; when script starts up, because DOS fiddles with this vector
- ; whenever a new process is created, or an old one destroyed.
- ;
- _callDOS proc near
- push bp
- mov bp,sp
- mov bx,[bp+4]
-
- mov es, [bx+10]
- mov ax,[bx+8]
- push ax
- mov dx, [bx+6]
- mov cx, [bx+4]
- mov ax, [bx+0]
- mov bx, [bx+2]
- pop ds
-
- pushf ; Fake interrupt
- call oldvct21
- pushf ; Preserve flags from DOS
-
- push ds
- push cs
- pop ds
- push bx
- mov bx,[bp+4]
- mov [bx+0],ax
- pop [bx+2]
- mov [bx+4],cx
- mov [bx+6],dx
- pop [bx+8]
- mov [bx+10],es
-
- pop ax ; Return the flags from the DOS call
- pop bp
- ret
- _callDOS endp
-
- ;
- ; void _Getdate(struct date *)
- ;
- public _Getdate
- _Getdate proc near
- push bp
- mov bp,sp
- mov ah, 2Ah
- int 21h
- mov bx,[bp+4]
- mov [bx],cx
- mov [bx+2],dx
- mov [bx+4],al
- pop bp
- ret
- _Getdate endp
-
- ;
- ; void _Gettime(struct time *)
- ;
- public _Gettime
- _Gettime proc near
- push bp
- mov bp,sp
- mov ah, 2Ch
- int 21h
- mov bx,[bp+4]
- mov [bx],dx
- mov [bx+2],cx
- pop bp
- ret
- _Gettime endp
-
- _text ends
-
-
- _data segment word public 'data'
- _s@ label byte
- _data ends
-
- end
-