Subversion Repositories SvarDOS

Rev

Rev 580 | Rev 987 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 580 Rev 983
1
;
1
;
2
; rmod - resident module of the SvarCOM command interpreter (NASM code)
2
; rmod - resident module of the SvarCOM command interpreter (NASM code)
3
;
3
;
4
; Copyright (C) 2021-2022 Mateusz Viste
4
; Copyright (C) 2021-2022 Mateusz Viste
5
; MIT license
5
; MIT license
6
;
6
;
7
; this is installed in memory by the transient part of SvarCOM. it has only
7
; this is installed in memory by the transient part of SvarCOM. it has only
8
; two jobs: providing a resident buffer for command history, environment, etc
8
; two jobs: providing a resident buffer for command history, environment, etc
9
; and respawning COMMAND.COM whenever necessary.
9
; and respawning COMMAND.COM whenever necessary.
10
 
10
 
11
CPU 8086
11
CPU 8086
12
org 0x100
12
org 0x100
13
 
13
 
14
PSP_ENVSEG equ 0x2C
14
PSP_ENVSEG equ 0x2C
15
 
15
 
16
section .text    ; all goes into code segment
16
section .text    ; all goes into code segment
17
 
17
 
18
                 ; offset
18
                 ; offset
19
SIG1 dw 0x1983   ;  +0
19
SIG1 dw 0x1983   ;  +0
20
SIG2 dw 0x1985   ;  +2
20
SIG2 dw 0x1985   ;  +2
21
SIG3 dw 0x2017   ;  +4
21
SIG3 dw 0x2017   ;  +4
22
SIG4 dw 0x2019   ;  +6  this acts also as a guardval to detect stack overflows
22
SIG4 dw 0x2019   ;  +6  acts also as a guardval to detect severe stack overflows
-
 
23
 
-
 
24
; Buffer used to remember previous command, when SvarCOM calls the buffered
-
 
25
; input service at INT 21h,AH=0x0A.
-
 
26
; This buffer is right before the stack, so in case of a stack overflow event
-
 
27
; (for example because of a "too ambitious" TSR) only this buffer is damaged,
-
 
28
; and can be invalidated without much harm.
-
 
29
INPUTBUF: times 130 db 0
-
 
30
 
-
 
31
; This stack sig is a guardian value that is checked by the transient part of
-
 
32
; SvarCOM to detect possible stack overflows. If a stack overflow occurs, then
-
 
33
; the INPUTBUFF area above is invalidated and stack signature reverted.
-
 
34
STACKSIG dw 0xCAFE
23
 
35
 
24
; DOS int 21h functions that I use require at least 40 bytes of stack under
36
; DOS int 21h functions that I use require at least 40 bytes of stack under
25
; DOS-C (FreeDOS) kernel, so here I reserve 64 bytes juste to be sure
37
; DOS-C (FreeDOS) kernel, so here I reserve 64 bytes juste to be sure
26
STACKBUF db "XXX  SVARCOM RMOD BY MATEUSZ VISTE  XXXXXXXXXXXXXXXXXXXXXXXXXXXX"
38
STACKBUF db "XXX  SVARCOM RMOD BY MATEUSZ VISTE  XXXXXXXXXXXXXXXXXXXXXXXXXXXX"
27
STACKPTR dw 0
39
STACKPTR dw 0
28
 
40
 
29
; offset of the COMSPEC variable in the environment block, 0 means "use
41
; offset of the COMSPEC variable in the environment block, 0 means "use
30
; boot drive". this value is patched by the transient part of COMMAND.COM
42
; boot drive". this value is patched by the transient part of COMMAND.COM
31
COMSPECPTR dw 0  ; +4Ah
43
COMSPECPTR dw 0  ; +4Ah
32
 
44
 
33
; fallback COMSPEC string used if no COMPSEC is present in the environment
45
; fallback COMSPEC string used if no COMPSEC is present in the environment
34
; drive. drive is patched by the transient part of COMMAND.COM
46
; drive. drive is patched by the transient part of COMMAND.COM
35
COMSPECBOOT db "@:\COMMAND.COM", 0 ; +4Ch
47
COMSPECBOOT db "@:\COMMAND.COM", 0 ; +4Ch
36
 
48
 
37
; exit code of last application
49
; exit code of last application
38
LEXCODE  db 0    ; +5Bh
50
LEXCODE  db 0    ; +5Bh
39
 
51
 
40
; ExecParamRec used by INT 21h, AX=4b00 (load and execute program), 14 bytes:
52
; ExecParamRec used by INT 21h, AX=4b00 (load and execute program), 14 bytes:
41
;  offset  size  content
53
;  offset  size  content
42
;     +0     2   segment of environment for child (0 = current)
54
;     +0     2   segment of environment for child (0 = current)
43
;     +2     4   address of command line to place at PSP:0080
55
;     +2     4   address of command line to place at PSP:0080
44
;     +6     4   address of an FCB to be placed at PSP:005c
56
;     +6     4   address of an FCB to be placed at PSP:005c
45
;    +0Ah    4   address of an FCB to be placed at PSP:006c
57
;    +0Ah    4   address of an FCB to be placed at PSP:006c
46
EXEC_PARAM_REC db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0   ; +5Ch
58
EXEC_PARAM_REC db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0   ; +5Ch
47
 
59
 
48
; Program to execute, preset by SvarCOM (128 bytes, ASCIIZ)
60
; Program to execute, preset by SvarCOM (128 bytes, ASCIIZ)
49
EXECPROG: times 128 db 0                                     ; +6Ah
61
EXECPROG: times 128 db 0                                     ; +6Ah
50
 
62
 
51
; File where stdin and stdout should be redirected (0 = no redirection)
63
; File where stdin and stdout should be redirected (0 = no redirection)
52
REDIR_INFIL:     times 128 db 0     ; +EAh
64
REDIR_INFIL:     times 128 db 0     ; +EAh
53
REDIR_OUTFIL:    times 128 db 0     ; +16Ah
65
REDIR_OUTFIL:    times 128 db 0     ; +16Ah
54
REDIR_OUTAPPEND: dw 0               ; +1EAh
66
REDIR_OUTAPPEND: dw 0               ; +1EAh
55
REDIR_DEL_STDIN: db 0               ; +1ECh  indicates that the stdin file
67
REDIR_DEL_STDIN: db 0               ; +1ECh  indicates that the stdin file
56
                                    ;        should be deleted (pipes). This
68
                                    ;        should be deleted (pipes). This
57
                                    ;        MUST contain the 1st char of
69
                                    ;        MUST contain the 1st char of
58
                                    ;        REDIR_INFIL!
70
                                    ;        REDIR_INFIL!
59
 
71
 
60
; CTRL+BREAK (int 23h) handler
72
; CTRL+BREAK (int 23h) handler
61
; According to the TechHelp! Manual: "If you want to abort (exit to the parent
73
; According to the TechHelp! Manual: "If you want to abort (exit to the parent
62
; process), then set the carry flag and return via a FAR RET. This causes DOS
74
; process), then set the carry flag and return via a FAR RET. This causes DOS
63
; to perform normal cleanup and exit to the parent." (otherwise use iret)
75
; to perform normal cleanup and exit to the parent." (otherwise use iret)
64
BREAK_HANDLER:            ; +1EDh
76
BREAK_HANDLER:            ; +1EDh
65
stc
77
stc
66
retf
78
retf
67
 
79
 
68
 
80
 
69
skipsig:                  ; +1EFh
81
skipsig:                  ; +1EFh
70
 
82
 
71
; set up CS=DS=SS and point SP to my private stack buffer
83
; set up CS=DS=SS and point SP to my private stack buffer
72
mov ax, cs
84
mov ax, cs
73
mov ds, ax
85
mov ds, ax
74
mov es, ax
86
mov es, ax
75
mov ss, ax
87
mov ss, ax
76
mov sp, STACKPTR
88
mov sp, STACKPTR
77
 
89
 
78
; set up myself as break handler
90
; set up myself as break handler
79
mov ax, 0x2523  ; set int vector 23h
91
mov ax, 0x2523  ; set int vector 23h
80
mov dx, BREAK_HANDLER
92
mov dx, BREAK_HANDLER
81
int 0x21
93
int 0x21
82
 
94
 
83
; revert stdin/stdout redirections (if any) to their initial state
95
; revert stdin/stdout redirections (if any) to their initial state
84
call REVERT_REDIR_IF_ANY
96
call REVERT_REDIR_IF_ANY
85
 
97
 
86
; redirect stdin and/or stdout if required
98
; redirect stdin and/or stdout if required
87
call REDIR_INOUTFILE_IF_REQUIRED
99
call REDIR_INOUTFILE_IF_REQUIRED
88
 
100
 
89
; should I executed command.com or a pre-set application?
101
; should I executed command.com or a pre-set application?
90
or [EXECPROG], byte 0
102
or [EXECPROG], byte 0
91
jz EXEC_COMMAND_COM
103
jz EXEC_COMMAND_COM
92
 
104
 
93
; TODO: perhaps I should call the DOS SetPSP function here? But if I do, the
105
; TODO: perhaps I should call the DOS SetPSP function here? But if I do, the
94
;       int 21h, ah=50h call freezes...
106
;       int 21h, ah=50h call freezes...
95
;mov ah, 0x50           ; DOS 2+ -- Set PSP
107
;mov ah, 0x50           ; DOS 2+ -- Set PSP
96
;mov bx, cs
108
;mov bx, cs
97
;int 0x21
109
;int 0x21
98
 
110
 
99
; exec an application preset (by SvarCOM) in the ExecParamRec
111
; exec an application preset (by SvarCOM) in the ExecParamRec
100
mov ax, 0x4B00         ; DOS 2+ - load & execute program
112
mov ax, 0x4B00         ; DOS 2+ - load & execute program
101
mov dx, EXECPROG       ; DS:DX  - ASCIZ program name (preset at PSP[already)
113
mov dx, EXECPROG       ; DS:DX  - ASCIZ program name (preset at PSP[already)
102
mov bx, EXEC_PARAM_REC ; ES:BX  - parameter block pointer
114
mov bx, EXEC_PARAM_REC ; ES:BX  - parameter block pointer
103
int 0x21
115
int 0x21
104
mov [cs:EXECPROG], byte 0 ; do not run app again (+DS might have been changed)
116
mov [cs:EXECPROG], byte 0 ; do not run app again (+DS might have been changed)
105
 
117
 
106
jmp short skipsig      ; enforce valid ds/ss/etc (can be lost after int 21,4b)
118
jmp short skipsig      ; enforce valid ds/ss/etc (can be lost after int 21,4b)
107
 
119
 
108
EXEC_COMMAND_COM:
120
EXEC_COMMAND_COM:
109
 
121
 
110
; collect the exit code of previous application
122
; collect the exit code of previous application
111
mov ah, 0x4D
123
mov ah, 0x4D
112
int 0x21
124
int 0x21
113
mov [LEXCODE], al
125
mov [LEXCODE], al
114
 
126
 
115
; zero out the exec param block (14 bytes)
127
; zero out the exec param block (14 bytes)
116
mov al, 0              ; byte to write
128
mov al, 0              ; byte to write
117
mov cx, 14             ; how many times
129
mov cx, 14             ; how many times
118
mov di, EXEC_PARAM_REC ; ES:DI = destination
130
mov di, EXEC_PARAM_REC ; ES:DI = destination
119
cld                    ; stosb must move forward
131
cld                    ; stosb must move forward
120
rep stosb              ; repeat cx times
132
rep stosb              ; repeat cx times
121
 
133
 
122
; preset the default COMSPEC pointer to ES:DX (ES is already set to DS)
134
; preset the default COMSPEC pointer to ES:DX (ES is already set to DS)
123
mov dx, COMSPECBOOT
135
mov dx, COMSPECBOOT
124
 
136
 
125
; do I have a valid COMSPEC?
137
; do I have a valid COMSPEC?
126
or [COMSPECPTR], word 0
138
or [COMSPECPTR], word 0
127
jz USEDEFAULTCOMSPEC
139
jz USEDEFAULTCOMSPEC
128
; set ES:DX to actual COMSPEC (in env segment)
140
; set ES:DX to actual COMSPEC (in env segment)
129
mov es, [PSP_ENVSEG]
141
mov es, [PSP_ENVSEG]
130
mov dx, [COMSPECPTR]
142
mov dx, [COMSPECPTR]
131
USEDEFAULTCOMSPEC:
143
USEDEFAULTCOMSPEC:
132
 
144
 
133
; prepare the exec param block
145
; prepare the exec param block
134
mov ax, [PSP_ENVSEG]
146
mov ax, [PSP_ENVSEG]
135
mov [EXEC_PARAM_REC], ax
147
mov [EXEC_PARAM_REC], ax
136
mov [EXEC_PARAM_REC+2], word CMDTAIL
148
mov [EXEC_PARAM_REC+2], word CMDTAIL
137
mov [EXEC_PARAM_REC+4], cs
149
mov [EXEC_PARAM_REC+4], cs
138
 
150
 
139
; execute command.com
151
; execute command.com
140
mov ax, 0x4B00         ; DOS 2+ - load & execute program
152
mov ax, 0x4B00         ; DOS 2+ - load & execute program
141
push es                ;
153
push es                ;
142
pop ds                 ;
154
pop ds                 ;
143
;mov dx, COMSPEC       ; DS:DX  - ASCIZ program name (preset already)
155
;mov dx, COMSPEC       ; DS:DX  - ASCIZ program name (preset already)
144
push cs
156
push cs
145
pop es
157
pop es
146
mov bx, EXEC_PARAM_REC ; ES:BX  - parameter block pointer
158
mov bx, EXEC_PARAM_REC ; ES:BX  - parameter block pointer
147
int 0x21
159
int 0x21
148
 
160
 
149
; if all went well, jump back to start
161
; if all went well, jump back to start
150
jnc skipsig
162
jnc skipsig
151
 
163
 
152
; restore DS=CS
164
; restore DS=CS
153
mov bx, cs
165
mov bx, cs
154
mov ds, bx
166
mov ds, bx
155
 
167
 
156
; update error string so it contains the error number
168
; update error string so it contains the error number
157
add al, '0'
169
add al, '0'
158
mov [ERRLOAD + 4], al
170
mov [ERRLOAD + 4], al
159
 
171
 
160
; display error message
172
; display error message
161
mov ah, 0x09
173
mov ah, 0x09
162
mov dx, ERRLOAD
174
mov dx, ERRLOAD
163
int 0x21
175
int 0x21
164
 
176
 
165
; wait for keypress
177
; wait for keypress
166
mov ah, 0x08
178
mov ah, 0x08
167
int 0x21
179
int 0x21
168
 
180
 
169
; back to program start
181
; back to program start
170
jmp skipsig
182
jmp skipsig
171
 
183
 
172
; command.com tail arguments, in PSP format: length byte followed by args and
184
; command.com tail arguments, in PSP format: length byte followed by args and
173
; terminated with \r) - a single 0x0A byte is passed so SvarCOM knows it is
185
; terminated with \r) - a single 0x0A byte is passed so SvarCOM knows it is
174
; called as respawn (as opposed to being invoked as a normal application)
186
; called as respawn (as opposed to being invoked as a normal application)
175
; this allows multiple copies of SvarCOM to stack upon each other.
187
; this allows multiple copies of SvarCOM to stack upon each other.
176
CMDTAIL db 0x01, 0x0A, 0x0D
188
CMDTAIL db 0x01, 0x0A, 0x0D
177
 
189
 
178
ERRLOAD db "ERR x, FAILED TO LOAD COMMAND.COM", 13, 10, '$'
190
ERRLOAD db "ERR x, FAILED TO LOAD COMMAND.COM", 13, 10, '$'
179
 
191
 
180
; variables used to revert stdin/stdout to their initial state
192
; variables used to revert stdin/stdout to their initial state
181
OLD_STDOUT dw 0xffff
193
OLD_STDOUT dw 0xffff
182
OLD_STDIN  dw 0xffff
194
OLD_STDIN  dw 0xffff
183
 
195
 
184
 
196
 
185
; ****************************************************************************
197
; ****************************************************************************
186
; *** ROUTINES ***************************************************************
198
; *** ROUTINES ***************************************************************
187
; ****************************************************************************
199
; ****************************************************************************
188
 
200
 
189
; ----------------------------------------------------------------------------
201
; ----------------------------------------------------------------------------
190
; revert stdin/stdout redirections (if any) to their initial state
202
; revert stdin/stdout redirections (if any) to their initial state
191
REVERT_REDIR_IF_ANY:
203
REVERT_REDIR_IF_ANY:
192
; is stdout redirected?
204
; is stdout redirected?
193
mov bx, [OLD_STDOUT]
205
mov bx, [OLD_STDOUT]
194
cmp bx, 0xffff
206
cmp bx, 0xffff
195
je STDOUT_DONE
207
je STDOUT_DONE
196
; revert the stdout handle (dst in BX already)
208
; revert the stdout handle (dst in BX already)
197
mov cx, 1        ; src handle (1=stdout)
209
mov cx, 1        ; src handle (1=stdout)
198
mov ah, 0x46     ; redirect a handle
210
mov ah, 0x46     ; redirect a handle
199
int 0x21
211
int 0x21
200
; close the old handle (still in bx)
212
; close the old handle (still in bx)
201
mov ah, 0x3e
213
mov ah, 0x3e
202
int 0x21
214
int 0x21
203
mov [OLD_STDOUT], word 0xffff ; mark stdout as "not redirected"
215
mov [OLD_STDOUT], word 0xffff ; mark stdout as "not redirected"
204
STDOUT_DONE:
216
STDOUT_DONE:
205
 
217
 
206
; is stdin redirected?
218
; is stdin redirected?
207
mov bx, [OLD_STDIN]
219
mov bx, [OLD_STDIN]
208
cmp bx, 0xffff
220
cmp bx, 0xffff
209
je STDIN_DONE
221
je STDIN_DONE
210
; revert the stdin handle (dst in BX already)
222
; revert the stdin handle (dst in BX already)
211
xor cx, cx       ; src handle (0=stdin)
223
xor cx, cx       ; src handle (0=stdin)
212
mov ah, 0x46     ; redirect a handle
224
mov ah, 0x46     ; redirect a handle
213
int 0x21
225
int 0x21
214
; close the old handle (still in bx)
226
; close the old handle (still in bx)
215
mov ah, 0x3e
227
mov ah, 0x3e
216
int 0x21
228
int 0x21
217
mov [OLD_STDIN], word 0xffff ; mark stdin as "not redirected"
229
mov [OLD_STDIN], word 0xffff ; mark stdin as "not redirected"
218
 
230
 
219
; delete stdin file if required
231
; delete stdin file if required
220
cmp [REDIR_DEL_STDIN], byte 0
232
cmp [REDIR_DEL_STDIN], byte 0
221
je STDIN_DONE
233
je STDIN_DONE
222
; revert the original file and delete it
234
; revert the original file and delete it
223
mov ah, [REDIR_DEL_STDIN]
235
mov ah, [REDIR_DEL_STDIN]
224
mov [REDIR_INFIL], ah
236
mov [REDIR_INFIL], ah
225
mov ah, 0x41     ; DOS 2+ - delete file pointed at by DS:DX
237
mov ah, 0x41     ; DOS 2+ - delete file pointed at by DS:DX
226
mov dx, REDIR_INFIL
238
mov dx, REDIR_INFIL
227
int 0x21
239
int 0x21
228
mov [REDIR_INFIL], byte 0
240
mov [REDIR_INFIL], byte 0
229
mov [REDIR_DEL_STDIN], byte 0
241
mov [REDIR_DEL_STDIN], byte 0
230
 
242
 
231
STDIN_DONE:
243
STDIN_DONE:
232
 
244
 
233
ret
245
ret
234
; ----------------------------------------------------------------------------
246
; ----------------------------------------------------------------------------
235
 
247
 
236
 
248
 
237
; ----------------------------------------------------------------------------
249
; ----------------------------------------------------------------------------
238
; redirect stdout if REDIR_OUTFIL points to something
250
; redirect stdout if REDIR_OUTFIL points to something
239
REDIR_INOUTFILE_IF_REQUIRED:
251
REDIR_INOUTFILE_IF_REQUIRED:
240
cmp [REDIR_OUTFIL], byte 0
252
cmp [REDIR_OUTFIL], byte 0
241
je NO_STDOUT_REDIR
253
je NO_STDOUT_REDIR
242
mov si, REDIR_OUTFIL   ; si = output file
254
mov si, REDIR_OUTFIL   ; si = output file
243
mov ax, 0x6c00         ; Extended Open/Create
255
mov ax, 0x6c00         ; Extended Open/Create
244
mov bx, 1              ; access mode (0=read, 1=write, 2=r+w)
256
mov bx, 1              ; access mode (0=read, 1=write, 2=r+w)
245
xor cx, cx             ; file attribs when(if) file is created (0=normal)
257
xor cx, cx             ; file attribs when(if) file is created (0=normal)
246
mov dx, [REDIR_OUTAPPEND] ; action if file exist (0x11=open, 0x12=truncate)
258
mov dx, [REDIR_OUTAPPEND] ; action if file exist (0x11=open, 0x12=truncate)
247
int 0x21               ; ax=handle on success (CF clear)
259
int 0x21               ; ax=handle on success (CF clear)
248
mov [REDIR_OUTFIL], byte 0
260
mov [REDIR_OUTFIL], byte 0
249
jc NO_STDOUT_REDIR     ; TODO: abort with an error message instead
261
jc NO_STDOUT_REDIR     ; TODO: abort with an error message instead
250
 
262
 
251
; jump to end of file if flag was 0x11 (required for >> redirections)
263
; jump to end of file if flag was 0x11 (required for >> redirections)
252
cmp [REDIR_OUTAPPEND], word 0x11
264
cmp [REDIR_OUTAPPEND], word 0x11
253
jne SKIP_JMPEOF
265
jne SKIP_JMPEOF
254
mov bx, ax
266
mov bx, ax
255
mov ax, 0x4202         ; jump to position EOF - CX:DX in handle BX
267
mov ax, 0x4202         ; jump to position EOF - CX:DX in handle BX
256
xor cx, cx
268
xor cx, cx
257
xor dx, dx
269
xor dx, dx
258
int 0x21
270
int 0x21
259
mov ax, bx             ; put my handle back in ax, as expected by later code
271
mov ax, bx             ; put my handle back in ax, as expected by later code
260
SKIP_JMPEOF:
272
SKIP_JMPEOF:
261
 
273
 
262
; duplicate current stdout so I can revert it later
274
; duplicate current stdout so I can revert it later
263
push ax                ; save my file handle in stack
275
push ax                ; save my file handle in stack
264
mov ah, 0x45           ; duplicate file handle BX
276
mov ah, 0x45           ; duplicate file handle BX
265
mov bx, 1              ; 1 = stdout
277
mov bx, 1              ; 1 = stdout
266
int 0x21               ; ax=new (duplicated) file handle
278
int 0x21               ; ax=new (duplicated) file handle
267
mov [OLD_STDOUT], ax   ; save the old handle in memory
279
mov [OLD_STDOUT], ax   ; save the old handle in memory
268
 
280
 
269
; redirect stdout to my file
281
; redirect stdout to my file
270
pop bx                 ; dst handle
282
pop bx                 ; dst handle
271
mov cx, 1              ; src handle (1=stdout)
283
mov cx, 1              ; src handle (1=stdout)
272
mov ah, 0x46           ; "redirect a handle"
284
mov ah, 0x46           ; "redirect a handle"
273
int 0x21
285
int 0x21
274
 
286
 
275
; close the original file handle, I no longer need it
287
; close the original file handle, I no longer need it
276
mov ah, 0x3e           ; close a file handle (handle in BX)
288
mov ah, 0x3e           ; close a file handle (handle in BX)
277
int 0x21
289
int 0x21
278
NO_STDOUT_REDIR:
290
NO_STDOUT_REDIR:
279
 
291
 
280
; *** redirect stdin if REDIR_INFIL points to something ***
292
; *** redirect stdin if REDIR_INFIL points to something ***
281
cmp [REDIR_INFIL], byte 0
293
cmp [REDIR_INFIL], byte 0
282
je NO_STDIN_REDIR
294
je NO_STDIN_REDIR
283
mov dx, REDIR_INFIL    ; dx:dx = file
295
mov dx, REDIR_INFIL    ; dx:dx = file
284
mov ax, 0x3d00         ; open file for read
296
mov ax, 0x3d00         ; open file for read
285
int 0x21               ; ax=handle on success (CF clear)
297
int 0x21               ; ax=handle on success (CF clear)
286
mov [REDIR_INFIL], byte 0
298
mov [REDIR_INFIL], byte 0
287
jc NO_STDIN_REDIR      ; TODO: abort with an error message instead
299
jc NO_STDIN_REDIR      ; TODO: abort with an error message instead
288
 
300
 
289
; duplicate current stdin so I can revert it later
301
; duplicate current stdin so I can revert it later
290
push ax                ; save my file handle in stack
302
push ax                ; save my file handle in stack
291
mov ah, 0x45           ; duplicate file handle BX
303
mov ah, 0x45           ; duplicate file handle BX
292
xor bx, bx             ; 0=stdin
304
xor bx, bx             ; 0=stdin
293
int 0x21               ; ax=new (duplicated) file handle
305
int 0x21               ; ax=new (duplicated) file handle
294
mov [OLD_STDIN], ax    ; save the old handle in memory
306
mov [OLD_STDIN], ax    ; save the old handle in memory
295
 
307
 
296
; redirect stdout to my file
308
; redirect stdout to my file
297
pop bx                 ; dst handle
309
pop bx                 ; dst handle
298
xor cx, cx             ; src handle (0=stdin)
310
xor cx, cx             ; src handle (0=stdin)
299
mov ah, 0x46           ; "redirect a handle"
311
mov ah, 0x46           ; "redirect a handle"
300
int 0x21
312
int 0x21
301
 
313
 
302
; close the original file handle, I no longer need it
314
; close the original file handle, I no longer need it
303
mov ah, 0x3e           ; close a file handle (handle in BX)
315
mov ah, 0x3e           ; close a file handle (handle in BX)
304
int 0x21
316
int 0x21
305
NO_STDIN_REDIR:
317
NO_STDIN_REDIR:
306
ret
318
ret
307
; ----------------------------------------------------------------------------
319
; ----------------------------------------------------------------------------
308
 
320