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
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
|
page 80,132
; SCCSID = @(#)copy.asm 1.1 85/05/14
; SCCSID = @(#)copy.asm 1.1 85/05/14
TITLE COMMAND COPY routines.
; MODIFICATION HISTORY
;
; 11/01/83 EE Added a few lines at the end of SCANSRC2 to get multiple
; file concatenations (eg copy a.*+b.*+c.*) to work properly.
; 11/02/83 EE Commented out the code in CPARSE which added drive designators
; to tokens which begin with path characters so that PARSELINE
; will work correctly.
; 11/04/83 EE Commented out the code in CPARSE that considered paren's to be
; individual tokens. That distinction is no longer needed for
; FOR loop processing.
; 11/17/83 EE CPARSE upper case conversion is now flag dependent. Flag is
; 1 when Cparse is called from COPY.
; 11/17/83 EE Took out the comment chars around code described in 11/04/83
; mod. It now is conditional on flag like previous mod.
; 11/21/83 NP Added printf
; 12/09/83 EE CPARSE changed to use CPYFLAG to determine when a colon should
; be added to a token.
; 05/30/84 MZ Initialize all copy variables. Fix confusion with destclosed
; NOTE: DestHand is the destination handle. There are two
; special values: -1 meaning destination was never opened and
; 0 which means that the destination has been openned and
; closed.
; 06/01/84 MZ Above reasoning totally specious. Returned things to normal
; 06/06/86 EG Change to fix problem of source switches /a and /b getting
; lost on large and multiple file (wildcard) copies.
; 06/09/86 EG Change to use xnametrans call to verify that source and
; destination are not equal.
.xlist
.xcref
INCLUDE comsw.asm
INCLUDE DOSSYM.INC
INCLUDE comseg.asm
INCLUDE comequ.asm
.list
.cref
DATARES SEGMENT PUBLIC BYTE ;AC000;
EXTRN VERVAL:WORD
EXTRN RSRC_XA_SEG:WORD ;AN030;
DATARES ENDS
TRANDATA SEGMENT PUBLIC BYTE ;AC000;
EXTRN BADCD_ptr:word
EXTRN COPIED_ptr:word
EXTRN Extend_buf_ptr:word ;AN000;
EXTRN Extend_buf_sub:byte ;AN000;
EXTRN file_name_ptr:word
EXTRN INBDEV_ptr:word ;AC000;
EXTRN msg_disp_class:byte ;AN000;
EXTRN overwr_ptr:word
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN ALLSWITCH:WORD
EXTRN ARGC:BYTE
EXTRN ASCII:BYTE
EXTRN BINARY:BYTE
EXTRN BYTCNT:WORD
EXTRN CFLAG:BYTE
EXTRN comma:byte
EXTRN CONCAT:BYTE
EXTRN concat_xa:byte ;AN000;
EXTRN copy_num:word ;AC000;
EXTRN CPDATE:WORD
EXTRN CPTIME:WORD
EXTRN cpyflag:byte ;AC000;
EXTRN CURDRV:BYTE
EXTRN DESTBUF:BYTE
EXTRN DestClosed:BYTE
EXTRN DESTFCB:BYTE
EXTRN DESTFCB2:BYTE
EXTRN DESTHAND:WORD
EXTRN DESTINFO:BYTE
EXTRN DESTISDIR:BYTE
EXTRN DESTSIZ:BYTE
EXTRN DESTSWITCH:WORD
EXTRN DESTTAIL:WORD
EXTRN DESTVARS:BYTE
EXTRN DIRBUF:BYTE
EXTRN expand_star:byte
EXTRN FILECNT:WORD
EXTRN FIRSTDEST:BYTE
EXTRN FRSTSRCH:BYTE
EXTRN INEXACT:BYTE
EXTRN MELCOPY:BYTE
EXTRN MELSTART:WORD
EXTRN msg_flag:byte ;AN022;
EXTRN NOWRITE:BYTE
EXTRN NXTADD:WORD
EXTRN objcnt:byte
EXTRN one_char_val:byte ;AN000;
EXTRN parse_last:word ;AN018;
EXTRN PLUS:BYTE
EXTRN plus_comma:byte
EXTRN RDEOF:BYTE
EXTRN RESSEG:WORD
EXTRN SCANBUF:BYTE
EXTRN SDIRBUF:BYTE
EXTRN src_xa_size:word ;AN000;
EXTRN src_xa_seg:word ;AN000;
EXTRN SRCBUF:BYTE
EXTRN SRCHAND:WORD
EXTRN SRCINFO:BYTE
EXTRN SRCISDEV:BYTE
EXTRN SRCPT:WORD
EXTRN SRCSIZ:BYTE
EXTRN SRCTAIL:WORD
EXTRN SRCVARS:BYTE
EXTRN srcxname:byte
EXTRN STARTEL:WORD
EXTRN string_ptr_2:word
EXTRN TERMREAD:BYTE
EXTRN TPA:WORD
EXTRN USERDIR1:BYTE
EXTRN WRITTEN:WORD
EXTRN xa_cp_out:byte ;AN030;
EXTRN xa_list_attr:word ;AC030;
TRANSPACE ENDS
; ******************************************
; COPY CODE
;
TRANCODE SEGMENT PUBLIC BYTE
EXTRN CERROR:NEAR
EXTRN COPERR:NEAR
EXTRN TCOMMAND:NEAR
PUBLIC COPY
ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:NOTHING
break Copy
assume ds:trangroup,es:trangroup
COPY:
; First order of buisness is to find out about the destination
;
; initialize all internal variables
;
xor ax,ax
mov copy_num,ax
mov SrcPt,AX
mov SrcTail,AX
mov CFlag,AL
mov NxtAdd,AX
mov DestSwitch,AX
mov StartEl,AX
mov DestTail,AX
mov DestClosed,AL
mov DestSiz,AL
mov SrcSiz,AL
mov DestInfo,AL
mov SrcInfo,AL
mov InExact,AL
mov DestVars,AL
mov SrcVars,AL
mov UserDir1,AL
mov NoWrite,AL
mov RdEOF,AL
mov SrcHand,AX
mov CpDate,AX
mov CpTime,AX
mov xa_list_attr,ax ;AN030; initialize code page to none
mov SrcIsDev,AL
mov TermRead,AL
mov comma,al ;g
mov plus_comma,al ;g
mov msg_flag,al ;AN022;
mov [ALLSWITCH],AX ; no switches
mov [ARGC],al ; no arguments
mov [PLUS],al ; no concatenation
mov [BINARY],al ; Binary not specifically specified
mov [ASCII],al ; ASCII not specifically specified
mov [FILECNT],ax ; No files yet
mov [WRITTEN],ax ; Nothing written yet
mov [CONCAT],al ; No concatenation
mov [MELCOPY],al ; Not a Mel Hallerman copy
mov [concat_xa],al ;AN000; initialize flag for concatenation XA
mov MelStart,ax ; Not a Mel Hallerman copy
mov word ptr [SCANBUF],ax ; Init buffer
mov word ptr [DESTBUF],ax ; Init buffer
mov word ptr [SRCBUF],ax ; Init buffer
mov word ptr [SDIRBUF],ax ; Init buffer
mov word ptr [DIRBUF],ax ; Init buffer
mov word ptr [DESTFCB],ax ; Init buffer
mov objcnt,al ; Init command line object count
dec ax
mov DestHand,AX ; destination has never been opened
mov [FRSTSRCH],al ; First search call
mov [FIRSTDEST],al ; First time
mov [DESTISDIR],al ; Don't know about dest
mov src_xa_seg,ax ;AN000; initialize attribute segment to -1
mov si,81H
mov bl,plus_chr ; include '+' as a delimiter
inc byte ptr [expand_star] ; want to include * expansion in cparse
mov cpyflag,1 ; Turn "CPARSE called from COPY flag" on
DESTSCAN:
xor bp,bp ; no switches
mov di,offset trangroup:SCANBUF
mov parse_last,si ;AN018; save start of parsed string
invoke CPARSE
PUSHF ; save flags
inc objcnt
test bh,80H ; A '+' argument?
jz NOPLUS ; no
mov [PLUS],1 ; yes
NOPLUS:
test bh,1 ; Switch?
jz TESTP2 ; no
test bp,SwitchV ;AN038; Verify requested?
jz not_slashv ;AN038; No - set the switch
test [allswitch],SwitchV ;AN038; Verify already entered?
jz not_slashv ;AN038; No - set the switch
;AD018; or [allswitch],FBadSwitch ;AN038; Set up bad switch
or BP,FBadSwitch ;AN018; Set up bad switch
not_slashv: ;AN038;
or [DESTSWITCH],BP ; Yes, assume destination
or [ALLSWITCH],BP ; keep tabs on all switches
test BP,NOT SwitchCopy ;AN018; Bad switch?
jz NOT_BAD_SWITCH ;AN018; Switches are okay
popf ;AN018; fix up stack
mov ax,BadSwt_ptr ;AN018; get "Invalid switch" message number
invoke Setup_parse_error_msg ;AN018; setup to print the message
jmp CERROR ;AC018; exit
NOT_BAD_SWITCH: ;AN018; switch okay
POPF ; get flags back
jc CHECKDONE ; Hit CR?
jmp short DESTSCAN
TESTP2:
POPF ; get flags back
jc CHECKDONE ; Hit CR?
test bh,80H ; Plus?
jnz GOTPLUS ; Yes, not a separate arg
inc [ARGC] ; found a real arg
GOTPLUS:
push SI
mov ax,[STARTEL]
mov SI,offset trangroup:SCANBUF ; Adjust to copy
sub ax,SI
mov DI,offset trangroup:DESTBUF
add ax,DI
mov [DESTTAIL],AX
mov [DESTSIZ],cl ; Save its size
inc cx ; Include the nul
rep movsb ; Save potential destination
mov [DESTINFO],bh ; Save info about it
mov [DESTSWITCH],0 ; reset switches
pop SI
jmp DESTSCAN ;AC018; keep going
CHECKDONE:
cmp plus,1 ; If a statement like "copy file+" is
jnz cdcont ; entered, complain about it.
cmp argc,1
jnz cdcont
cmp objcnt,2
jnz cdcont
mov dx,offset trangroup:overwr_ptr
jmp coperr
cdcont:
mov al,[PLUS]
mov [CONCAT],al ; PLUS -> Concatination
shl al,1
shl al,1
mov [INEXACT],al ; CONCAT -> inexact copy
mov al,[ARGC]
or al,al ; Good number of args?
jnz TRY_TOO_MANY ;AC000; there are args, see if too many
MOV DX,OFFSET TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer
mov Extend_Buf_ptr,LessArgs_ptr ;AN000; get "Required parameters missing" message number
jmp short cerror_parsej ;AN000; exit
TRY_TOO_MANY:
cmp al,2
jbe ACOUNTOK
MOV DX,OFFSET TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer
mov Extend_Buf_ptr,MoreArgs_ptr ;AN000; get "Too many parameters" message number
CERROR_PARSEJ:
mov msg_disp_class,parse_msg_class ;AN000; set up parse error msg class
CERROR4J:
jmp CERROR ; no, too many
ACOUNTOK:
mov bp,offset trangroup:DESTVARS
cmp al,1
jnz GOT2ARGS
mov al,[CURDRV] ; Dest is default drive:*.*
add al,capital_A
mov ah,':'
mov [bp.SIZ],2
mov di,offset trangroup:DESTBUF
stosw
mov [DESTSWITCH],0 ; no switches on dest
mov [bp.INFO],2 ; Flag dest is ambig
mov [bp.ISDIR],0 ; Know destination specs file
invoke SETSTARS
GOT2ARGS:
cmp [bp.SIZ],2
jnz NOTSHORTDEST
mov al,':'
cmp [DESTBUF+1],al
jnz NOTSHORTDEST ; Two char file name
or [bp.INFO],2 ; Know dest is d:
mov di,offset trangroup:DESTBUF + 2
mov [bp.ISDIR],0 ; Know destination specs file
invoke SETSTARS
NOTSHORTDEST:
mov di,[bp.TTAIL]
cmp byte ptr [DI],0
jnz CHKSWTCHES
mov dx,offset trangroup:BADCD_ptr
mov al,':'
cmp byte ptr [DI-2],al
jnz CERROR4J ; Trailing '/' error
mov [bp.ISDIR],2 ; Know destination is d:/
or [bp.INFO],6
invoke SETSTARS
CHKSWTCHES:
;AD018; mov ax,[ALLSWITCH]
;AD018; test ax,NOT SwitchCopy
;AD018; jz NOT_BAD_SWITCH ;AN000; Switches are okay
;AD018; MOV DX,OFFSET TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer
;AD018; mov Extend_Buf_ptr,BadSwt_ptr ;AN000; get "Invalid switch" message number
;AD018; jmp short CERROR_PARSEJ ;AC000; Switch specified which is not known
; Now know most of the information needed about the destination
;AD018; NOT_BAD_SWITCH:
if not ibmcopyright
mov ax, [allswitch] ; Which switches were requested? Hmmm?
endif
TEST AX,SwitchV ; Verify requested?
JZ NOVERIF ; No
MOV AH,GET_VERIFY_ON_WRITE
INT int_command ; Get current setting
PUSH DS
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
XOR AH,AH
MOV [VERVAL],AX ; Save current setting
POP DS
ASSUME DS:TRANGROUP
MOV AX,(SET_VERIFY_ON_WRITE SHL 8) OR 1 ; Set verify
INT int_command
NOVERIF:
xor bp,bp ; no switches
mov si,81H
mov bl,plus_chr ; include '+' as a delimiter
SCANFSRC:
mov di,offset trangroup:SCANBUF
invoke CPARSE ; Parse first source name
test bh,1 ; Switch?
jnz SCANFSRC ; Yes, try again
or [DESTSWITCH],bp ; Include copy wide switches on dest
test bp,SwitchB
jnz NOSETCASC ; Binary explicit
cmp [CONCAT],0
JZ NOSETCASC ; Not Concat
mov [ASCII],SwitchA ; Concat -> ASCII copy if no B switch
mov [concat_xa],do_xa ;AN000; set up to do XA only on first file
NOSETCASC:
call source_set
call FRSTSRC
jmp FIRSTENT
PUBLIC EndCopy
ENDCOPY:
CALL CLOSEDEST
ENDCOPY2:
call deallocate_src_xa ;AN030; deallocate xa segment
invoke free_tpa ;AN000; Make sure work area
invoke alloc_tpa ;AN000; is reset properly
MOV DX,OFFSET TRANGROUP:COPIED_ptr
MOV SI,[FILECNT]
mov copy_num,si
invoke std_printf
JMP TCOMMAND ; Stack could be messed up
SRCNONEXIST:
cmp [CONCAT],0
jnz NEXTSRC ; If in concat mode, ignore error
mov msg_disp_class,ext_msg_class ;AN000; set up extended error msg class
mov dx,offset TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer
mov Extend_Buf_ptr,error_file_not_found ;AN000; get message number in control block
mov string_ptr_2,offset trangroup:srcbuf ;AC046; get address of failed string
mov Extend_buf_sub,one_subst ;AC046; put number of subst in control block
jmp COPERR
SOURCEPROC:
call source_set
cmp [CONCAT],0
jnz LEAVECFLAG ; Leave CFLAG if concatination
FRSTSRC:
xor ax,ax
mov [CFLAG],al ; Flag destination not created
mov [NXTADD],ax ; Zero out buffer
mov DestClosed,AL
LEAVECFLAG:
mov [SRCPT],SI ; remember where we are
mov di,offset trangroup:USERDIR1
mov bp,offset trangroup:SRCVARS
invoke BUILDPATH ; Figure out everything about the source
mov si,[SRCTAIL] ; Create the search FCB
return
NEXTSRC:
cmp [PLUS],0
jnz MORECP
ENDCOPYJ2:
jmp ENDCOPY ; Done
MORECP:
xor bp,bp ; no switches
mov si,[SRCPT]
mov bl,plus_chr ; include '+' as a delimiter
SCANSRC:
mov di,offset trangroup:SCANBUF
invoke CPARSE ; Parse first source name
JC EndCopyJ2 ; if error, then end (trailing + case)
test bh,80H
jz ENDCOPYJ2 ; If no '+' we're done
test bh,1 ; Switch?
jnz SCANSRC ; Yes, try again
call SOURCEPROC
cmp comma,1 ;g was +,, found last time?
jnz nostamp ;g no - try for a file
mov plus_comma,1 ;g yes - set flag
jmp srcnonexist ;g we know we won't find it
nostamp: ;g
mov plus_comma,0 ;g reset +,, flag
FIRSTENT:
mov di,FCB
mov ax,PARSE_FILE_DESCRIPTOR SHL 8
INT int_command
CMP BYTE PTR [SI],0 ; parse everything?
JNZ SrchDone ; no, error, simulate no more search
mov ax,word ptr [SRCBUF] ; Get drive
cmp ah,':'
jz DRVSPEC1
mov al,'@'
DRVSPEC1:
or al,20h
sub al,60h
mov ds:[FCB],al
mov ah,DIR_SEARCH_FIRST
call SEARCH
SrchDone:
pushf ; Save result of search
invoke RESTUDIR1 ; Restore users dir
popf
jz NEXTAMBIG0
jmp SRCNONEXIST ; Failed
NEXTAMBIG0:
xor al,al
xchg al,[FRSTSRCH]
or al,al
jz NEXTAMBIG
SETNMEL:
mov cx,12
mov di,OFFSET TRANGROUP:SDIRBUF
mov si,OFFSET TRANGROUP:DIRBUF
rep movsb ; Save very first source name
NEXTAMBIG:
xor al,al
mov [NOWRITE],al ; Turn off NOWRITE
mov di,[SRCTAIL]
mov si,offset trangroup:DIRBUF + 1
invoke FCB_TO_ASCZ ; SRCBUF has complete name
MELDO:
cmp [CONCAT],0
jnz SHOWCPNAM ; Show name if concat
test [SRCINFO],2 ; Show name if multi
jz DOREAD
SHOWCPNAM:
mov dx,offset trangroup:file_name_ptr
invoke std_printf
invoke CRLF2
DOREAD:
call DOCOPY
cmp [CONCAT],0
jnz NODCLOSE ; If concat, do not close
call CLOSEDEST ; else close current destination
jc NODCLOSE ; Concat flag got set, close didn't really happen
mov [CFLAG],0 ; Flag destination not created
NODCLOSE:
cmp [CONCAT],0 ; Check CONCAT again
jz NOFLUSH
invoke FLSHFIL ; Flush output between source files on
; CONCAT so LOSTERR stuff works
; correctly
TEST [MELCOPY],0FFH
jz NOFLUSH
jmp SHORT DOMELCOPY
NOFLUSH:
call SEARCHNEXT ; Try next match
jnz NEXTSRCJ ; Finished with this source spec
mov [DESTCLOSED],0 ; Not created or concat ->...
jmp NEXTAMBIG ; Do next ambig
DOMELCOPY:
cmp [MELCOPY],0FFH
jz CONTMEL
mov SI,[SRCPT]
mov [MELSTART],si
mov [MELCOPY],0FFH
CONTMEL:
xor BP,BP
mov si,[SRCPT]
mov bl,plus_chr
SCANSRC2:
mov di,OFFSET TRANGROUP:SCANBUF
invoke CPARSE
test bh,80H
jz NEXTMEL ; Go back to start
test bh,1 ; Switch ?
jnz SCANSRC2 ; Yes
call SOURCEPROC
invoke RESTUDIR1
mov di,OFFSET TRANGROUP:DESTFCB2
mov ax,PARSE_FILE_DESCRIPTOR SHL 8
INT int_command
mov bx,OFFSET TRANGROUP:SDIRBUF + 1
mov si,OFFSET TRANGROUP:DESTFCB2 + 1
mov di,[SRCTAIL]
invoke BUILDNAME
cmp [CONCAT],0 ; Are we concatenating?
jz meldoj ; No, continue.
;
; Yes, turn off nowrite because this part of the code is only reached after
; the first file has been dealt with.
;
mov [NOWRITE],0
meldoj:
jmp MELDO
NEXTSRCJ:
jmp NEXTSRC
NEXTMEL:
call CLOSEDEST
xor ax,ax
mov [CFLAG],al
mov [NXTADD],ax
mov [DESTCLOSED],al
mov si,[MELSTART]
mov [SRCPT],si
call SEARCHNEXT
jz SETNMELJ
jmp ENDCOPY2
SETNMELJ:
jmp SETNMEL
SEARCHNEXT:
MOV AH,DIR_SEARCH_NEXT
TEST [SRCINFO],2
JNZ SEARCH ; Do search-next if ambig
OR AH,AH ; Reset zero flag
return
SEARCH:
PUSH AX
MOV AH,SET_DMA
MOV DX,OFFSET TRANGROUP:DIRBUF
INT int_command ; Put result of search in DIRBUF
POP AX ; Restore search first/next command
MOV DX,FCB
INT int_command ; Do the search
OR AL,AL
return
DOCOPY:
mov si,offset trangroup:SRCBUF ;g do name translate of source
mov di,offset trangroup:SRCXNAME ;g save for name comparison
mov ah,xnametrans ;g
int int_command ;g
mov [RDEOF],0 ; No EOF yet
MOV AX,EXTOPEN SHL 8 ;AC000; open the file
mov bx,read_open_mode ;AN000; get open mode for COPY
xor cx,cx ;AN000; no special files
mov dx,read_open_flag ;AN000; set up open flags
mov di,-1 ;AN030; no parameter list
INT int_command
jnc OpenOK
;
; Bogosity: IBM wants us to issue Access denied in this case. THey asked
; for it...
;
jmp error_on_source ;AC022; clean up and exit
OpenOK:
mov bx,ax ; Save handle
mov [SRCHAND],bx ; Save handle
mov ax,(FILE_TIMES SHL 8)
INT int_command
jc src_cp_error ;AN022; If error, exit
mov [CPDATE],dx ; Save DATE
mov [CPTIME],cx ; Save TIME
mov cx,xa_list_attr ;AN000; get old code page in cx
push cx ;AN000; save old attribute
mov xa_list_attr,0 ;AN000; initialize code page
mov ax,(file_times SHL 8)+get_XA ;AC030; get extended attribute size
mov si,-1 ;AN030; no querylist
xor cx,cx ;AN030; indicate we want size
int int_command ;AC000;
jc src_cp_error ;AN022; If error, exit
mov src_xa_size,cx ;AN000; save size
cmp cx,0 ;AN000; are there any?
pop cx ;AN000; get old attribute
jz no_cp_get ;AN030; no - don't get attributes
push cx ;AN030; save old code page
invoke get_file_code_page_tag ;AN000; get file's code page
pop cx ;AN030 retrieve old code page
jnc no_cp_get ;AN000; no error - continue
src_cp_error: ;AN022;
jmp error_on_source ;AC022; and exit
no_cp_get:
cmp [concat],0 ;AN000; are we doing concatenation
jz get_src_xa ;AN000; no get source extended attrib
cmp [concat_xa],do_xa ;AN000; is this the first file?
jz get_src_xa ;AN000; yes - get extended attributes
cmp cx,xa_list_attr ;AN000; no - see if code pages match
jz no_copy_xa_jmp ;AN000; code pages match - continue
mov xa_list_attr,inv_cp_tag ;AN000; set invalid code page tag
no_copy_xa_jmp: ;AC022;
jmp no_copy_xa ;AN000; don't get extended attributes
get_src_xa:
call deallocate_src_xa ;AN030; deallocate any existing XA segment
cmp src_xa_size,0 ;AN000; are there any extended attributes?
jz no_copy_xa_jmp ;AC022; nothing there - don't allocate memory
push bx ;AN000; save handle
invoke free_tpa ;AN000; need to make free memory, first
mov bx,src_xa_size ;AN000; get bytes (size of XA) into bx
mov cl,4 ;AN000; divide bytes by 16 to convert
shr bx,cl ;AN000; to paragraphs
inc bx ;AN000; round up
mov ax,(alloc SHL 8) ;AN000; allocate memory for XA
int int_command ;AN000;
pushf ;AN000; save flags
mov [src_xa_seg], AX ;AN000; save new segment
push ds ;AN030; get resident segment
mov ds,[resseg] ;AN030; and save copy of xa
assume ds:resgroup ;AN030; segment in resident
mov [rsrc_xa_seg],ax ;AN030; in case user breaks
pop ds ;AN030; out or has critical
assume ds:trangroup ;AN030; error
invoke alloc_tpa ;AN000; reallocate the work area
popf ;AN000; restore flags
pop bx ;AN000; restore handle
jnc Alloc_for_xa_okay ;AN000; no carry - everything okay
call closesrc ;AN000; close the source file
mov msg_disp_class,ext_msg_class ;AN000; set up extended error msg class
mov dx,offset TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer
mov Extend_Buf_ptr,error_not_enough_memory ;AN000; get message number in control block
jmp cerror ;AN000; exit
Alloc_for_xa_okay:
mov ax,(file_times SHL 8)+get_XA ;AN000; get extended attributes
push es ;AN000; save es
mov es,[src_xa_seg] ;AN000; get segment for XA list
xor di,di ;AN000; offset of return list
mov si,-1 ;AN030; get all attributes
mov cx,[src_xa_size] ;AN000; get size of list
int int_command ;AN000; get all the attributes
pop es ;AN000; restore es
jnc no_copy_xa ;AC022; no error - continue
error_on_source: ;AN022; we have a BAD error
invoke set_ext_error_msg ;AN022; set up the error message
mov string_ptr_2,offset trangroup:srcbuf ;AN022; get address of failed string
mov Extend_buf_sub,one_subst ;AN022; put number of subst in control block
invoke std_Eprintf ;AN022; print it
cmp [srchand],0 ;AN022; did we open the file?
jz no_close_src ;AN022; no - don't close
call closesrc ;AN022; clean up
no_close_src: ;AN022;
cmp [cflag],0 ;AN022; was destination created?
jz endcopyj3 ;AN022; no - just cleanup and exit
jmp endcopy ;AN022; clean up concatenation and exit
endcopyj3: ;AN022;
jmp endcopy2 ;AN022;
no_copy_xa:
mov bx,[srchand] ;AN022; get handle back
mov ax,(IOCTL SHL 8)
INT int_command ; Get device stuff
and dl,devid_ISDEV
mov [SRCISDEV],dl ; Set source info
jz COPYLP ; Source not a device
cmp [BINARY],0
jz COPYLP ; ASCII device OK
mov dx,offset trangroup:INBDEV_ptr ; Cannot do binary input
jmp COPERR
COPYLP:
mov bx,[SRCHAND]
mov cx,[BYTCNT]
mov dx,[NXTADD]
sub cx,dx ; Compute available space
jnz GOTROOM
invoke FLSHFIL
CMP [TERMREAD],0
JNZ CLOSESRC ; Give up
mov cx,[BYTCNT]
GOTROOM:
push ds
mov ds,[TPA]
ASSUME DS:NOTHING
mov ah,READ
INT int_command
pop ds
ASSUME DS:TRANGROUP
jc error_on_source ;AC022; Give up if error
mov cx,ax ; Get count
jcxz CLOSESRC ; No more to read
cmp [SRCISDEV],0
jnz NOTESTA ; Is a device, ASCII mode
cmp [ASCII],0
jz BINREAD
NOTESTA:
MOV DX,CX
MOV DI,[NXTADD]
MOV AL,1AH
PUSH ES
MOV ES,[TPA]
REPNE SCASB ; Scan for EOF
POP ES
JNZ USEALL
INC [RDEOF]
INC CX
USEALL:
SUB DX,CX
MOV CX,DX
BINREAD:
ADD CX,[NXTADD]
MOV [NXTADD],CX
CMP CX,[BYTCNT] ; Is buffer full?
JB TESTDEV ; If not, we may have found EOF
invoke FLSHFIL
CMP [TERMREAD],0
JNZ CLOSESRC ; Give up
JMP SHORT COPYLP
TESTDEV:
cmp [SRCISDEV],0
JZ CLOSESRC ; If file then EOF
CMP [RDEOF],0
JZ COPYLP ; On device, go till ^Z
CLOSESRC:
mov bx,[SRCHAND]
mov ah,CLOSE
INT int_command
return
;
; We are called to close the destination. We need to note whether or not
; there is any internal data left to be flushed out.
;
CLOSEDEST:
cmp [DESTCLOSED],0
retnz ; Don't double close
MOV AL,BYTE PTR [DESTSWITCH]
invoke SETASC ; Check for B or A switch on destination
JZ BINCLOS
MOV BX,[NXTADD]
CMP BX,[BYTCNT] ; Is memory full?
JNZ PUTZ
invoke TRYFLUSH ; Make room for one lousy byte
jz NOCONC
CONCHNG: ; Concat flag changed on us
stc
return
NOCONC:
XOR BX,BX
PUTZ:
PUSH DS
MOV DS,[TPA]
MOV WORD PTR [BX],1AH ; Add End-of-file mark (Ctrl-Z)
POP DS
INC [NXTADD]
MOV [NOWRITE],0 ; Make sure our ^Z gets written
MOV AX,[WRITTEN]
ADD AX,[NXTADD]
JC BINCLOS ; > 1
CMP AX,1
JZ FORGETITJ ; WRITTEN = 0 NXTADD = 1 (the ^Z)
BINCLOS:
invoke TRYFLUSH
jnz CONCHNG
cmp [WRITTEN],0
ForgetItJ:
jnz no_forget ;AC000; Wrote something
jmp FORGETIT ;AC000; Never wrote nothing
no_forget:
MOV BX,[DESTHAND]
MOV CX,[CPTIME]
MOV DX,[CPDATE]
CMP [INEXACT],0 ; Copy not exact?
JZ DODCLOSE ; If no, copy date & time
MOV AH,GET_TIME
INT int_command
SHL CL,1
SHL CL,1 ; Left justify min in CL
SHL CX,1
SHL CX,1
SHL CX,1 ; hours to high 5 bits, min to 5-10
SHR DH,1 ; Divide seconds by 2 (now 5 bits)
OR CL,DH ; And stick into low 5 bits of CX
PUSH CX ; Save packed time
MOV AH,GET_DATE
INT int_command
SUB CX,1980
XCHG CH,CL
SHL CX,1 ; Year to high 7 bits
SHL DH,1 ; Month to high 3 bits
SHL DH,1
SHL DH,1
SHL DH,1
SHL DH,1 ; Most sig bit of month in carry
ADC CH,0 ; Put that bit next to year
OR DL,DH ; Or low three of month into day
MOV DH,CH ; Get year and high bit of month
POP CX ; Get time back
DODCLOSE:
CMP BX,0
JLE CloseDone
MOV AX,(FILE_TIMES SHL 8) OR 1
INT int_command ; Set date and time
jc xa_cleanup_err ;AN022; handle error
mov ax,(file_times SHL 8)+set_XA ;AN000; set code page
mov di,offset trangroup:xa_cp_out ;AC030; offset of attr list
int int_command ;AN000;
jc xa_cleanup_err ;AN030; exit if error
;
; See if the destination has *anything* in it. If not, just close and delete
; it.
;
no_xa_cleanup_err:
mov ax,(lseek shl 8) + 2 ; seek to EOF
xor dx,dx
mov cx,dx
int 21h
;
; DX:AX is file size
;
or dx,ax
pushf
mov ax,(IOCTL SHL 8) + 0 ; get the destination attributes
int 21h
push dx ; save them away
MOV AH,CLOSE
INT int_command
pop dx
jnc close_cont ;AN022; handle error on close
popf ;AN022; get the flags back
xa_cleanup_err: ;AN022;
call cleanuperr ;AN022; attempt to delete the target
call DestDelete ;AN022; attempt to delete the target
jmp short fileclosed ;AN022; close the file
close_cont: ;AN022; no error - continue
popf
jnz CloseDone
test dx,80h ; is the destination a device?
jnz CloseDone ; yes, copy succeeded
call DestDelete
jmp short FileClosed
CloseDone:
INC [FILECNT]
FileClosed:
INC [DESTCLOSED]
RET50:
CLC
return
FORGETIT:
MOV BX,[DESTHAND]
CALL DODCLOSE ; Close the dest
call DestDelete
MOV [FILECNT],0 ; No files transferred
JMP RET50
DestDelete:
MOV DX,OFFSET TRANGROUP:DESTBUF
MOV AH,UNLINK
INT int_command ; And delete it
return
source_set proc near
push SI
mov ax,[STARTEL]
mov SI,offset trangroup:SCANBUF ; Adjust to copy
sub ax,SI
mov DI,offset trangroup:SRCBUF
add ax,DI
mov [SRCTAIL],AX
mov [SRCSIZ],cl ; Save its size
inc cx ; Include the nul
rep movsb ; Save this source
mov [SRCINFO],bh ; Save info about it
pop SI
mov ax,bp ; Switches so far
invoke SETASC ; Set A,B switches accordingly
invoke SWITCH ; Get any more switches on this arg
invoke SETASC ; Set
return
source_set endp
;****************************************************************
;*
;* ROUTINE: Cleanuperr
;*
;* FUNCTION: Issues extended error message for destination
;* if not alreay issued
;*
;* INPUT: return from INT 21
;*
;* OUTPUT: none
;*
;****************************************************************
cleanuperr proc near ;AN022;
cmp msg_flag,0 ;AN022; have we already issued a message?
jnz cleanuperr_cont ;AN022; yes - don't issue duplicate error
invoke set_ext_error_msg ;AN022; set up error message
mov string_ptr_2,offset trangroup:destbuf ;AN022; get address of failed string
mov Extend_buf_sub,one_subst ;AN022; put number of subst in control block
invoke std_eprintf ;AN022; issue the error message
cleanuperr_cont: ;AN022;
ret ;AN022; return to caller
cleanuperr endp ;AN022;
;****************************************************************
;*
;* ROUTINE: Deallocate_Src_XA
;*
;* FUNCTION: Deallocates source extended attribute segment
;* and resets both resident and transient variables.
;*
;*
;* INPUT: none
;*
;* OUTPUT: none
;*
;****************************************************************
Deallocate_Src_XA proc near ;AN030;
cmp [src_xa_seg],no_xa_seg ;AN030; has any XA segment been allocated
jz no_src_xa ;AN030; no - continue
push es ;AN030;
mov es,src_xa_seg ;AN030; yes - free it
mov ax,(Dealloc SHL 8) ;AN030; Deallocate memory call
int int_command ;AN030;
pop es ;AN030;
mov [src_xa_seg],no_xa_seg ;AN030; reset to no segment
push ds ;AN030; reinitialize resident
mov ds,[resseg] ;AN030; copy of xa segment
assume ds:resgroup ;AN030;
mov [rsrc_xa_seg],no_xa_seg ;AN030; reset to no segment
pop ds ;AN030;
assume ds:trangroup ;AN030;
no_src_xa: ;AN030;
ret ;AN030; return to caller
Deallocate_Src_XA endp ;AN030;
TRANCODE ENDS
END
|