1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
|
page 80,132
; SCCSID = @(#)tmisc1.asm 4.1 85/09/22
; SCCSID = @(#)tmisc1.asm 4.1 85/09/22
TITLE Part7 COMMAND Transient Routines
; More misc routines
.xlist
.xcref
INCLUDE comsw.asm
INCLUDE DOSSYM.INC
INCLUDE comseg.asm
INCLUDE comequ.asm
.list
.cref
CODERES SEGMENT PUBLIC BYTE ;AC000;
EXTRN RSTACK:BYTE
CodeRes ENDS
DATARES SEGMENT PUBLIC BYTE ;AC000;
EXTRN CALL_FLAG:BYTE
EXTRN EchoFlag:BYTE
EXTRN EXEC_BLOCK:BYTE
EXTRN EXTCOM:BYTE
EXTRN PIPEFLAG:BYTE
EXTRN PIPEPTR:WORD
EXTRN PIPESTR:BYTE
EXTRN RESTDIR:BYTE
EXTRN RE_OUT_APP:BYTE
EXTRN RE_OUTSTR:BYTE
DATARES ENDS
TRANDATA SEGMENT PUBLIC BYTE ;AC000;
EXTRN BADDRV_PTR:WORD
EXTRN BADNAM_PTR:WORD
EXTRN COMTAB:BYTE ;AC000;
EXTRN extend_buf_ptr:word ;AN000;
EXTRN msg_disp_class:byte ;AN000;
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN arg:byte ; the arg structure!
EXTRN APPEND_EXEC:BYTE ;AN041;
EXTRN CHKDRV:BYTE
EXTRN COMBUF:BYTE
EXTRN EXECPATH:BYTE
EXTRN EXEC_ADDR:DWORD
EXTRN FILTYP:BYTE
EXTRN IDLEN:BYTE
EXTRN KPARSE:BYTE ;AC000;
EXTRN PARM1:BYTE
EXTRN PARM2:BYTE
EXTRN PathPos:word
EXTRN RESSEG:WORD
EXTRN RE_INSTR:BYTE
EXTRN SPECDRV:BYTE
EXTRN SWITCHAR:BYTE
EXTRN switch_list:byte
EXTRN TRAN_TPA:WORD
IF IBM
EXTRN ROM_CALL:BYTE
EXTRN ROM_CS:WORD
EXTRN ROM_IP:WORD
ENDIF
TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC byte
ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
EXTRN APPEND_PARSE:NEAR ;AN010;
EXTRN BATCOM:NEAR
EXTRN DOCOM1:NEAR
EXTRN PIPEERRSYN:NEAR
EXTRN TCOMMAND:NEAR
IF IBM
EXTRN ROM_EXEC:NEAR
EXTRN ROM_SCAN:NEAR
ENDIF
PUBLIC CERROR
PUBLIC DRVBAD
PUBLIC EXTERNAL
PUBLIC FNDCOM
PUBLIC PRESCAN
PUBLIC SWITCH
ASSUME DS:TRANGROUP
;---------------------------
; We can get rid of this switch processing code if we can take
; care of the remaining two calls to switch, later in the file.
; However, I have not checked whether or not any other files use
; switch -- after all, it IS public!
;---------------------------
RETSW:
XCHG AX,BX ; Put switches in AX
return
SWITCH:
XOR BX,BX ; Initialize - no switches set
SWLOOP:
INVOKE SCANOFF ; Skip any delimiters
CMP AL,[SWITCHAR] ; Is it a switch specifier?
JNZ RETSW ; No -- we're finished
OR BX,fSwitch ; Indicate there is a switch specified
INC SI ; Skip over the switch character
INVOKE SCANOFF
CMP AL,0DH
JZ RETSW ; Oops
INC SI
; Convert lower case input to upper case
INVOKE UPCONV
MOV DI,OFFSET TRANGROUP:switch_list
MOV CX,SWCOUNT
REPNE SCASB ; Look for matching switch
JNZ BADSW
MOV AX,1
SHL AX,CL ; Set a bit for the switch
OR BX,AX
JMP SHORT SWLOOP
BADSW:
JMP SHORT SWLOOP
SWCOUNT EQU 5 ; Length of switch_list
DRVBAD:
MOV DX,OFFSET TRANGROUP:BADDRV_ptr
JMP CERROR
externalj:
jmp EXTERNAL
fndcom: ; search the internal command table
OR AL,AL ; Get real length of first arg
jz externalj ; If 0, it must begin with "\" so has
; to be external.
; barryf code starts here
IF IBM
call test_append ; see if APPEND installed
je contcom ; not loaded
append_internal:
mov cl,TRANGROUP:IDLEN
mov ch,0
mov pathpos,cx
inc append_exec ;AN041; set APPEND to ON
invoke ioset ; re-direct the o'l io
mov SI, offset TRANGROUP:IDLEN ; address command name, DS already set
mov DX,-1 ; set invoke function
mov di,offset TRANGROUP:APPEND_PARSE;AN010; Get the entry point for PARSE for APPEND
mov AX,0AE01H
int 2FH ; execute command
cmp TRANGROUP:IDLEN,0 ; execute requested
jne contcom
jmp Cmd_done
contcom: ; continue with internal scan
ENDIF
; barryf code ends here
mov DI, OFFSET TRANGROUP:COMTAB
XOR CX,CX
findcom:
mov SI, offset TRANGROUP:IDLEN+1 ; pointer to command argument
mov CL, [DI] ; load length of internal command
inc di ; advance past length
jcxz externalj ; if it's zero, we're out of internals
cmp CL, IDLEN ; that of the command argument
jnz abcd ; lengths not equal ==> strings not eq
MOV PathPos,CX ; store length of command
repz cmpsb
abcd:
lahf ; save the good ol' flags
add DI, CX ; skip over remaining internal, if any
mov AL, BYTE PTR [DI] ; load drive-check indicator byte (DCIB)
mov [CHKDRV], AL ; save command flag byte in chkdrv
inc DI ; increment DI (OK, OK, I'll stop)
mov BX, WORD PTR [DI] ; load internal command address
inc DI ; skip over the puppy
inc DI
sahf ; remember those flags?
jnz findcom ; well, if all the cmps worked...
;
; All messages get redirected.
;
cmp append_exec,0 ;AN041; APPEND just executed?
jnz dont_set_io ;AN041; Yes - this junk is already set
invoke ioset ; re-direct the ol' i/o
dont_set_io: ;AN041;
invoke SETSTDINON ;AN026; turn on critical error on STDIN
invoke SETSTDOUTOFF ;AN026; turn off critical error on STDOUT
test [CHKDRV], fCheckDrive ; did we wanna check those drives?
jz nocheck
mov AL, [PARM1] ; parse_file_descriptor results tell
or AL, [PARM2] ; us whether those drives were OK
cmp AL, -1
jnz nocheck
jmp drvbad
;
; The user may have omitted the space between the command and its arguments.
; We need to copy the remainder of the user's command line into the buffer.
; Note that thisdoes not screw up the arg structure; it points into COMBUF not
; into the command line at 80.
;
nocheck:
call cmd_copy
switcheck:
test [CHKDRV], fSwitchAllowed ; Does the command take switches
jnz realwork ; Yes, process the command
call noswit ; No, check to see if any switches
jnz realwork ; None, process the command
mov msg_disp_class,parse_msg_class ;AN000; set up parse error msg class
MOV DX,OFFSET TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer
mov Extend_Buf_ptr,BadSwt_ptr ;AN000; get "Invalid switch" message number
jmp CERROR ; Print error and chill out...
realwork:
call BX ; do some real work, at last
; See if we're in a batch CALL command. If we are, reprocess the command line,
; otherwise, go get another command.
Cmd_done:
push cs ; g restore data segment
pop ds ; g
push ds ; g save data segment
mov ds,[resseg] ; g get segment containing call flag
ASSUME ds:resgroup
cmp call_flag, call_in_progress ; G Is a call in progress?
mov call_flag, 0 ; G Either way, reset flag
pop ds ; g get data segment back
jz incall ; G
jmp tcommand ; chill out...
incall:
JMP DOCOM1
noswit:
push di ; Save di
mov di,81h ; di = ptr to command args
mov si,80h ; Get address of length of command args
lodsb ; Load length
mov cl,al ; Move length to cl
xor ch,ch ; Zero ch
mov al,[SWITCHAR] ; al = switch character
cmp al,0 ; Turn off ZF
repnz scasb ; Scan for a switch character and return
pop di ; with ZF set if one was found
ret
EXTERNAL:
IF IBM
call test_append ; check to see if append installed
je not_barryf ; no - truly external command
jmp append_internal ; yes - go to Barryf code
not_barryf:
ENDIF
MOV [FILTYP],0
MOV DL,[SPECDRV]
MOV [IDLEN],DL
IF IBM
MOV [ROM_CALL],0
PUSH DX
MOV DX,OFFSET TRANGROUP:IDLEN
CALL ROM_SCAN
POP DX
JNC DO_SCAN
INC [ROM_CALL]
JMP PostSave
DO_SCAN:
ENDIF
IF IBM
PostSave:
ENDIF
MOV DI,OFFSET TRANGROUP:EXECPATH
MOV BYTE PTR [DI],0 ; Initialize to current directory
IF IBM
CMP [ROM_CALL],0
JZ Research
JMP NeoExecute
ENDIF
RESEARCH:
invoke path_search ; find the mother (result in execpath)
or AX, AX ; did we find anything?
je badcomj45 ; null means no (sob)
cmp AX, 04H ; 04H and 08H are .exe and .com
jl rsrch_br1 ; fuckin' sixteen-bit machine ought
jmp execute ; to be able to handle a SIXTEEN-BIT
rsrch_br1: ; DISPLACEMENT!!
jmp batcom ; 02H is .bat
BADCOMJ45:
JMP BADCOM
ASSUME DS:TRANGROUP,ES:TRANGROUP
EXECUTE:
NeoExecute:
invoke IOSET
invoke SETSTDINOFF ;AN026; turn off critical error on STDIN
invoke SETSTDOUTOFF ;AN026; turn off critical error on STDOUT
MOV ES,[TRAN_TPA]
MOV AH,DEALLOC
INT int_command ; Now running in "free" space
MOV ES,[RESSEG]
ASSUME ES:RESGROUP
INC [EXTCOM] ; Indicate external command
MOV [RESTDIR],0 ; Since USERDIR1 is in transient, insure
; this flag value for re-entry to COMMAND
MOV DI,FCB
MOV SI,DI
MOV CX,052H ; moving (100h-5Ch)/2 = 80h-2Eh
REP MOVSW ; Transfer parameters to resident header
MOV DX,OFFSET TRANGROUP:EXECPATH
MOV BX,OFFSET RESGROUP:EXEC_BLOCK
MOV AX,EXEC SHL 8
IF IBM
TEST [ROM_CALL],-1
JZ OK_EXEC
JMP ROM_EXEC
OK_EXEC:
ENDIF
;
; we are now running in free space. anything we do from here on may get
; trashed. Move the stack (also in free space) to allocated space because
; since EXEC restores the stack, somebody may trash what is on the stack.
;
MOV CX,ES
MOV SS,CX
MOV SP,OFFSET RESGROUP:RSTACK
JMP [EXEC_ADDR] ; Jmp to the EXEC in the resident
BADCOM:
PUSH CS
POP DS
MOV DX,OFFSET TRANGROUP:BADNAM_ptr
CERROR:
INVOKE std_eprintf
JMP TCOMMAND
;
; Prescan converts the input buffer into a canonicalized form. All
; redirections and pipes are removed.
;
PRESCAN: ; Cook the input buffer
ASSUME DS:TRANGROUP,ES:TRANGROUP
XOR CX,CX
MOV ES,[RESSEG]
ASSUME ES:RESGROUP
MOV SI,OFFSET TRANGROUP:COMBUF+2
MOV DI,SI
CountQuotes:
LODSB ; get a byte
CMP AL,22h ; is it a quote?
JNZ CountEnd ; no, try for end of road
INC CH ; bump count
JMP CountQuotes ; go get next char
CountEnd:
CMP AL,13 ; end of road?
JNZ CountQuotes ; no, go back for next char
;;;; IF KANJI 3/3/KK
PUSH CX ; save count
MOV SI,DI ; get back beginning of buffer
KanjiScan:
LODSB ; get a byte
INVOKE TestKanj ; is it a leadin byte
JZ KanjiQuote ; no, check for quotes
MOV AH,AL ; save leadin
LODSB ; get trailing byte
CMP AX,8140h ; is it Kanji space
JNZ KanjiScan ; no, go get next
MOV [SI-2],2020h ; replace with spaces
JMP KanjiScan ; go get next char
KanjiQuote:
CMP AL,22h ; beginning of quoted string
JNZ KanjiEnd ; no, check for end
DEC CH ; drop count
JZ KanjiScan ; if count is zero, no quoting
KanjiQuoteLoop:
LODSB ; get next byte
CMP AL,22h ; is it another quote
JNZ KanjiQuoteLoop ; no, get another
DEC CH ; yes, drop count
JMP KanjiScan ; go get next char
KanjiEnd:
CMP AL,13 ; end of line character?
JNZ KanjiScan ; go back to beginning
POP CX ; get back original count
;;;; ENDIF 3/3/KK
MOV SI,DI ; restore pointer to begining
PRESCANLP:
LODSB
;;;; IF KANJI 3/3/KK
INVOKE TESTKANJ
JZ NOTKANJ6
MOV [DI],AL
INC DI ; fake STOSB into DS
LODSB ; grab second byte
MOV [DI],AL ; fake stosb into DS
INC DI
INC CL
INC CL
JMP PRESCANLP
NOTKANJ6:
;;;; ENDIF 3/3/KK
CMP AL,'"' ; " character
JNZ TRYGREATER
DEC CH
JZ TRYGREATER
QLOOP:
MOV [DI],AL
INC DI
INC CL
LODSB
CMP AL,'"' ; " character
JNZ QLOOP
DEC CH
TRYGREATER:
CMP AL,rabracket
JNZ NOOUT
;
; We have found a ">" char. We need to see if there is another ">"
; following it.
;
CMP BYTE PTR [SI],al
JNZ NOAPPND
LODSB
INC [RE_OUT_APP] ; Flag >>
NOAPPND:
;
; Now we attempt to find the file name. First, scan off all whitespace
;
INVOKE SCANOFF
CMP AL,labracket ;AN040; was there no filename?
JZ REOUT_ERRSET ;AN040; yes - set up error
CMP AL,0DH
JNZ GOTREOFIL
;
; There was no file present. Set us up at end-of-line.
;
REOUT_ERRSET: ;AN040; set up for an error
mov byte ptr [di], 0dh ; Clobber first ">"
MOV WORD PTR [RE_OUTSTR],09H ; Cause an error later
JMP PRESCANEND
GOTREOFIL:
PUSH DI
MOV DI,OFFSET RESGROUP:RE_OUTSTR
MOV BX,DI
PUSH ES
SETREOUTSTR: ; Get the output redirection name
LODSB
CMP AL,0DH
JZ GOTRESTR
INVOKE DELIM
JZ GOTRESTR
CMP AL,[SWITCHAR]
JZ GOTRESTR
CMP AL,'"' ;AN033; Is the character a quote?
JZ PIPEERRSYNJ5 ;AN033; Yes - get out quick - or system crashes
CMP AL,labracket ;AN002; Is char for input redirection
JZ ABRACKET_TERM ;AN002; yes - end of string
CMP AL,rabracket ;AN002; Is char for output redirection
JNZ NO_ABRACKET ;AN002; no - not end of string
abracket_term: ;AN002; have end of string by < or >
DEC SI ;AN002; back up over symbol
MOV AL,BLANK ;AN002; show delimiter as char
JMP SHORT GOTRESTR ;AN002; go process it
no_abracket: ;AN002; not at end of string
STOSB ; store it into resgroup
JMP SHORT SETREOUTSTR
NOOUT:
CMP AL,labracket
JNZ CHKPIPE
mov bx,si ; Save loc of "<"
INVOKE SCANOFF
CMP AL,rabracket ;AN040; was there no filename?
JZ REIN_ERRSET ;AN040; yes - set up error
CMP AL,0DH
JNZ GOTREIFIL
REIN_ERRSET: ;AN040; set up for error
mov byte ptr [di],0dh ; Clobber "<"
MOV WORD PTR [RE_INSTR],09H ; Cause an error later
JMP SHORT PRESCANEND
GOTREIFIL:
PUSH DI
MOV DI,OFFSET TranGROUP:RE_INSTR
MOV BX,DI
PUSH ES
PUSH CS
POP ES ; store in TRANGROUP
JMP SHORT SETREOUTSTR ; Get the input redirection name
CHKPIPE:
MOV AH,AL
CMP AH,AltPipeChr
JZ IsPipe3
CMP AH,vbar
JNZ CONTPRESCAN
IsPipe3:
;
; Only push the echo flag if we are entering the pipe for the first time.
;
CMP PipeFlag,0
JNZ NoEchoPush
SHL EchoFlag,1 ; push echo state and turn it off
NoEchoPush:
INC [PIPEFLAG]
INVOKE SCANOFF
CMP AL,0DH
JZ PIPEERRSYNJ5
CMP AL,AltPipeChr
JZ PIPEERRSYNJ5
CMP AL,vbar ; Double '|'?
JNZ CONTPRESCAN
PIPEERRSYNJ5:
PUSH ES
POP DS ; DS->RESGROUP
JMP PIPEERRSYN
;
; Trailing :s are allowed on devices. Check to be sure that there is more
; than just a : in the redir string.
;
GOTRESTR:
XCHG AH,AL
mov al,':'
SUB BX,DI ; compute negatinve of number of chars
CMP BX,-1 ; is there just a :?
JZ NotTrailCol ; yep, don't change
CMP BYTE PTR ES:[DI-1],al ; Trailing ':' OK on devices
JNZ NOTTRAILCOL
DEC DI ; Back up over trailing ':'
NOTTRAILCOL:
XOR AL,AL
STOSB ; NUL terminate the string
POP ES
POP DI ; Remember the start
CONTPRESCAN:
MOV [DI],AH ; "delete" the redirection string
INC DI
CMP AH,0DH
JZ PRESCANEND
INC CL
JMP PRESCANLP
PRESCANEND:
CMP [PIPEFLAG],0
JZ ISNOPIPE
MOV DI,OFFSET RESGROUP:PIPESTR
MOV [PIPEPTR],DI
MOV SI,OFFSET TRANGROUP:COMBUF+2
INVOKE SCANOFF
PIPESETLP: ; Transfer the pipe into the resident
LODSB ; pipe buffer
STOSB
CMP AL,0DH
JNZ PIPESETLP
ISNOPIPE:
MOV [COMBUF+1],CL
CMP [PIPEFLAG],0
PUSH CS
POP ES
return
cmd_copy proc near
MOV SI,OFFSET TRANGROUP:COMBUF+2
INVOKE Scanoff ; advance past separators...
add si,PathPos
mov di,81h
xor cx,cx
CmdCopy:
lodsb
stosb
cmp al,0dh
jz CopyDone
inc cx
jmp CmdCopy
CopyDone:
mov byte ptr ds:[80h],cl ; Store count
ret
cmd_copy endp
test_append proc near
mov BX,offset TRANGROUP:COMBUF ; barry can address
mov SI, offset TRANGROUP:IDLEN ; address command name, DS already set
mov DX,-1 ; set install check function
mov AX,0AE00H
int 2FH ; see if loaded
cmp AL,00H
ret
test_append endp
TRANCODE ENDS
END
|