From 2d04cacc5322951f187bb17e017c12920ac8ebe2 Mon Sep 17 00:00:00 2001 From: Mark Zbikowski Date: Thu, 25 Apr 2024 21:24:10 +0100 Subject: MZ is back! --- v4.0/src/CMD/COMMAND/COMEQU.ASM | 241 ++++++ v4.0/src/CMD/COMMAND/COMMAND.LNK | 6 + v4.0/src/CMD/COMMAND/COMMAND.SKL | 213 +++++ v4.0/src/CMD/COMMAND/COMMAND1.ASM | 638 ++++++++++++++ v4.0/src/CMD/COMMAND/COMMAND2.ASM | 619 ++++++++++++++ v4.0/src/CMD/COMMAND/COMSEG.ASM | 43 + v4.0/src/CMD/COMMAND/COMSW.ASM | 6 + v4.0/src/CMD/COMMAND/COPY.ASM | 1001 ++++++++++++++++++++++ v4.0/src/CMD/COMMAND/COPYPR1.ASM | 276 ++++++ v4.0/src/CMD/COMMAND/COPYPR2.ASM | 450 ++++++++++ v4.0/src/CMD/COMMAND/CPARSE.ASM | 417 +++++++++ v4.0/src/CMD/COMMAND/ENVDATA.ASM | 28 + v4.0/src/CMD/COMMAND/FORDATA.ASM | 19 + v4.0/src/CMD/COMMAND/IFEQU.ASM | 18 + v4.0/src/CMD/COMMAND/INIT.ASM | 1685 +++++++++++++++++++++++++++++++++++++ v4.0/src/CMD/COMMAND/IPARSE.ASM | 38 + v4.0/src/CMD/COMMAND/MAKEFILE | 134 +++ v4.0/src/CMD/COMMAND/PARSE2.ASM | 422 ++++++++++ v4.0/src/CMD/COMMAND/PATH1.ASM | 507 +++++++++++ v4.0/src/CMD/COMMAND/PATH2.ASM | 458 ++++++++++ v4.0/src/CMD/COMMAND/RDATA.ASM | 611 ++++++++++++++ v4.0/src/CMD/COMMAND/RESMSG.EQU | 43 + v4.0/src/CMD/COMMAND/RUCODE.ASM | 739 ++++++++++++++++ v4.0/src/CMD/COMMAND/TBATCH.ASM | 1045 +++++++++++++++++++++++ v4.0/src/CMD/COMMAND/TBATCH2.ASM | 753 +++++++++++++++++ v4.0/src/CMD/COMMAND/TCMD1A.ASM | 598 +++++++++++++ v4.0/src/CMD/COMMAND/TCMD1B.ASM | 730 ++++++++++++++++ v4.0/src/CMD/COMMAND/TCMD2A.ASM | 552 ++++++++++++ v4.0/src/CMD/COMMAND/TCMD2B.ASM | 597 +++++++++++++ v4.0/src/CMD/COMMAND/TCODE.ASM | 540 ++++++++++++ v4.0/src/CMD/COMMAND/TDATA.ASM | 777 +++++++++++++++++ v4.0/src/CMD/COMMAND/TENV.ASM | 633 ++++++++++++++ v4.0/src/CMD/COMMAND/TENV2.ASM | 663 +++++++++++++++ v4.0/src/CMD/COMMAND/TFOR.ASM | 551 ++++++++++++ v4.0/src/CMD/COMMAND/TMISC1.ASM | 655 ++++++++++++++ v4.0/src/CMD/COMMAND/TMISC2.ASM | 487 +++++++++++ v4.0/src/CMD/COMMAND/TPARSE.ASM | 76 ++ v4.0/src/CMD/COMMAND/TPIPE.ASM | 660 +++++++++++++++ v4.0/src/CMD/COMMAND/TPRINTF.ASM | 365 ++++++++ v4.0/src/CMD/COMMAND/TRANMSG.ASM | 671 +++++++++++++++ v4.0/src/CMD/COMMAND/TSPC.ASM | 488 +++++++++++ v4.0/src/CMD/COMMAND/TUCODE.ASM | 520 ++++++++++++ v4.0/src/CMD/COMMAND/UINIT.ASM | 270 ++++++ 43 files changed, 20243 insertions(+) create mode 100644 v4.0/src/CMD/COMMAND/COMEQU.ASM create mode 100644 v4.0/src/CMD/COMMAND/COMMAND.LNK create mode 100644 v4.0/src/CMD/COMMAND/COMMAND.SKL create mode 100644 v4.0/src/CMD/COMMAND/COMMAND1.ASM create mode 100644 v4.0/src/CMD/COMMAND/COMMAND2.ASM create mode 100644 v4.0/src/CMD/COMMAND/COMSEG.ASM create mode 100644 v4.0/src/CMD/COMMAND/COMSW.ASM create mode 100644 v4.0/src/CMD/COMMAND/COPY.ASM create mode 100644 v4.0/src/CMD/COMMAND/COPYPR1.ASM create mode 100644 v4.0/src/CMD/COMMAND/COPYPR2.ASM create mode 100644 v4.0/src/CMD/COMMAND/CPARSE.ASM create mode 100644 v4.0/src/CMD/COMMAND/ENVDATA.ASM create mode 100644 v4.0/src/CMD/COMMAND/FORDATA.ASM create mode 100644 v4.0/src/CMD/COMMAND/IFEQU.ASM create mode 100644 v4.0/src/CMD/COMMAND/INIT.ASM create mode 100644 v4.0/src/CMD/COMMAND/IPARSE.ASM create mode 100644 v4.0/src/CMD/COMMAND/MAKEFILE create mode 100644 v4.0/src/CMD/COMMAND/PARSE2.ASM create mode 100644 v4.0/src/CMD/COMMAND/PATH1.ASM create mode 100644 v4.0/src/CMD/COMMAND/PATH2.ASM create mode 100644 v4.0/src/CMD/COMMAND/RDATA.ASM create mode 100644 v4.0/src/CMD/COMMAND/RESMSG.EQU create mode 100644 v4.0/src/CMD/COMMAND/RUCODE.ASM create mode 100644 v4.0/src/CMD/COMMAND/TBATCH.ASM create mode 100644 v4.0/src/CMD/COMMAND/TBATCH2.ASM create mode 100644 v4.0/src/CMD/COMMAND/TCMD1A.ASM create mode 100644 v4.0/src/CMD/COMMAND/TCMD1B.ASM create mode 100644 v4.0/src/CMD/COMMAND/TCMD2A.ASM create mode 100644 v4.0/src/CMD/COMMAND/TCMD2B.ASM create mode 100644 v4.0/src/CMD/COMMAND/TCODE.ASM create mode 100644 v4.0/src/CMD/COMMAND/TDATA.ASM create mode 100644 v4.0/src/CMD/COMMAND/TENV.ASM create mode 100644 v4.0/src/CMD/COMMAND/TENV2.ASM create mode 100644 v4.0/src/CMD/COMMAND/TFOR.ASM create mode 100644 v4.0/src/CMD/COMMAND/TMISC1.ASM create mode 100644 v4.0/src/CMD/COMMAND/TMISC2.ASM create mode 100644 v4.0/src/CMD/COMMAND/TPARSE.ASM create mode 100644 v4.0/src/CMD/COMMAND/TPIPE.ASM create mode 100644 v4.0/src/CMD/COMMAND/TPRINTF.ASM create mode 100644 v4.0/src/CMD/COMMAND/TRANMSG.ASM create mode 100644 v4.0/src/CMD/COMMAND/TSPC.ASM create mode 100644 v4.0/src/CMD/COMMAND/TUCODE.ASM create mode 100644 v4.0/src/CMD/COMMAND/UINIT.ASM (limited to 'v4.0/src/CMD/COMMAND') diff --git a/v4.0/src/CMD/COMMAND/COMEQU.ASM b/v4.0/src/CMD/COMMAND/COMEQU.ASM new file mode 100644 index 0000000..40273e3 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/COMEQU.ASM @@ -0,0 +1,241 @@ +; SCCSID = @(#)comequ.asm 1.1 85/05/14 +; SCCSID = @(#)comequ.asm 1.1 85/05/14 +;************************************* +; COMMAND EQUs which are not switch dependant + +EMGDEBUG = FALSE + +SYM EQU ">" + +LINESPERPAGE EQU 25 ;AC000; default lines per page +NORMPERLIN EQU 1 +WIDEPERLIN EQU 5 +COMBUFLEN EQU 128 ; Length of commmand buffer +BatLen EQU 32 ; buffer for batch files +YES_ECHO EQU 1 ; echo line +NO_ECHO EQU 0 ; don't echo line +No_Echo_Char EQU "@" ; don't echo line if this is first char +call_in_progress EQU 1 ; indicate we're in the CALL command +length_call EQU 4 ; length of CALL +max_nest EQU 10 ; max # levels of batch nesting allowed +fail_allowed EQU 00001000b ; critical error +retry_allowed EQU 00010000b ; critical error +Ignore_allowed EQU 00100000b ; critical error +nullcommand EQU 1 ; no command on command line +end_of_line EQU -1 ;AN000; end of line return from parser +end_of_line_out EQU 0 ;AN000; end of line for output +end_of_line_in EQU 0dh ;AN000; end of line for input +result_number EQU 1 ;AN000; number returned from parser +result_string EQU 3 ;AN000; string returned from parser +result_filespec EQU 5 ;AN000; filespec returned from parser +result_drive EQU 6 ;AN000; drive returned from parser +result_date EQU 7 ;AN000; date returned from parser +result_time EQU 8 ;AN000; time returned from parser +result_no_error EQU 0 ;AN000; no error returned from parser +no_cont_flag EQU 0 ;AN000; no control flags for message +util_msg_class EQU -1 ;AN000; message class for utility +ext_msg_class EQU 1 ;AN000; message class for extended error +parse_msg_class EQU 2 ;AN000; message class for parse error +crit_msg_class EQU 3 ;AN000; message class for critical error +ext_crlf_class EQU 081h ;AN054; message class for extended error with no CRLF +colon_char EQU ":" ;AN000; colon character +crt_ioctl_ln EQU 14 ;AN000; default length of data for display ioctl +text_mode EQU 1 ;AN000; text mode return from ioctl +get_generic EQU 07Fh ;AN000; generic ioctl - get device info +set_crit_dev EQU 0100H ;AN000; device attribute for critical error on I/0 +mult_ansi EQU 01Ah ;AC064; multiplex for ansi.sys +mult_shell_get EQU 01902h ;AC065; multiplex for Shell - get next command +mult_shell_brk EQU 01903h ;AN000; multiplex for Shell - ^C batch check +shell_action equ 0ffh ;AN000; SHELL - return for taking SHELL specific action +bat_not_open EQU -1 ;AN000; batch handle will be set to this if not open +bat_open_handle EQU 19 ;AN000; handle will be in this position in JFN table +Ptr_seg_pos equ 7 ;AN000; Offset from start of message block for subst segment +Ptr_off_pos equ 5 ;AN000; Offset from start of message block for subst offset +Parm_off_pos equ word ptr 2 ;AN000; Offset from start of subst list for subst offset +parm_block_size equ 11 ;AN000; size of message subst block +blank equ " " ;AN000; blank character +no_subst equ 0 ;AN000; no substitutions for messages +one_subst equ 1 ;AN000; one substitution for messages +no_handle_out equ -1 ;AN000; use function 1 thru 12 for message retriever +res_subst equ 2 ;AN000; offset from start of message definition to number of subst +read_open_mode equ 0000000000000000b ;AN024; extended open mode for read +read_open_flag equ 0000000100000001b ;AN000; extended open flags for read +write_open_mode equ 0000000000000001b ;AN024; extended open mode for read +write_open_flag equ 0000000100000001b ;AN000; extended open flags for read +creat_open_flag equ 0000000100010010b ;AN000; extended open flags for read +get_CPSW equ 3 ;AN000; minor function for get CPSW status +CPSW_off equ 0 ;AN000; CPSW return from function - OFF +Get_XA equ 2 ;AN030; minor function for get extended attributes +Set_XA equ 4 ;AN000; minor function for set extended attributes +file_no_cpage equ 0 ;AN000; file has no code page tag +file_inv_cpage equ -1 ;AN000; file has invalid code page tag +do_xa equ -1 ;AN000; flag to get extended attributes +inv_cp_tag equ 0 ;AC039; tag for invalid code page +no_xa_seg equ -1 ;AN000; no segment for extended attributes - COPY +capital_A equ 'A' ;AC000; +vbar equ '|' ;AC000; +labracket equ '<' ;AC000; +rabracket equ '>' ;AC000; +dollar equ '$' ;AC000; +lparen equ '(' ;AC000; +rparen equ ')' ;AC000; +nullrparen equ 29h ;AC000; +in_word equ 4e49h ;AC000; 'NI' ('IN' backwards) +do_word equ 4f44h ;AC000; 'OD' ('DO' backwards) +star equ '*' ;AC000; +plus_chr equ '+' ;AC000; +small_a equ 'a' ;AC000; +small_z equ 'z' ;AC000; +dot_chr equ '.' ;AC000; +tab_chr equ 9 ;AN032; +equal_chr equ '=' ;AN032; +semicolon equ ';' ;AN049; +dot_qmark equ 2e3fh ;AC000; '.?' +dot_colon equ 2e3ah ;AC000; '.:' +capital_n equ 0 ;AC000; result from Y/N call if N entered +capital_y equ 1 ;AC000; result from Y/N call if Y entered +AppendInstall equ 0B700H ;AN020; append install check +AppendDOS equ 0B702H ;AN020; append DOS version check +AppendGetState equ 0B706H ;AN020; append get current state +AppendSetState equ 0B707H ;AN020; append set current state +AppendTruename equ 0B711H ;AN042; Get file's real location for Batch +search_attr equ attr_read_only+attr_hidden+attr_directory ;AC042; + +;************************************* +;* PARSE ERROR MESSAGES +;************************************* + +MoreArgs_Ptr equ 1 ;AN000;"Too many parameters" message number +LessArgs_Ptr equ 2 ;AN000;"Required parameter missing" message number +BadSwt_Ptr equ 3 ;AN000;"Invalid switch" message number +BadParm_Ptr equ 10 ;AN000;"Invalid parameter" message number + +;************************************* +;* EQUATES FOR MESSAGE RETRIEVER +;************************************* + +GET_EXTENDED_MSG EQU 0 ;AN000; get extended message address +SET_EXTENDED_MSG EQU 1 ;AN000; set extended message address +GET_PARSE_MSG EQU 2 ;AN000; get parse message address +SET_PARSE_MSG EQU 3 ;AN000; set parse message address +GET_CRITICAL_MSG EQU 4 ;AN000; get critical message address +SET_CRITICAL_MSG EQU 5 ;AN000; set critical message address +MESSAGE_2F EQU 46 ;AN000; minor code for message retriever + +;********************************* +;* EQUATES FOR INT 10H +;********************************* + +VIDEO_IO_INT EQU 10H ;AN000; equate for int 10h +SET_VIDEO_MODE EQU 0 ;AN000; set video mode +SET_CURSOR_POSITION EQU 2 ;AN000; set new cursor position +SCROLL_VIDEO_PAGE EQU 6 ;AN000; scroll active page up +VIDEO_ATTRIBUTE EQU 7 ;AN000; attribute to be used on blank line +SET_COLOR_PALETTE EQU 11 ;AN000; set color for video +GET_VIDEO_STATE EQU 15 ;AN000; get current video state +VIDEO_ALPHA EQU 3 ;AN000; alpha video is 3 or below +VIDEO_BW EQU 7 ;AN000; mode for 80X25 black & white + +AltPipeChr equ "|" ; alternate pipe character + +FCB EQU 5CH + +VARSTRUC STRUC +ISDIR DB ? +SIZ DB ? +TTAIL DW ? +INFO DB ? +BUF DB DIRSTRLEN + 20 DUP (?) +VARSTRUC ENDS + +fCheckDrive equ 00000001b +fSwitchAllowed equ 00000010b + +; +; Test switches +; +fParse EQU 0001h ; display results of parseline + +; +; Batch segment structure +; +; BYTE type of segment +; BYTE echo state of parent on entry to batch file +; WORD segment of last batch file +; WORD segment for FOR command +; BYTE FOR flag state on entry to batch file +; DWORD offset for next line +; 10 WORD pointers to parameters. -1 is empty parameter +; ASCIZ file name (with . and ..) +; BYTES CR-terminated parameters +; BYTE 0 flag to indicate end of parameters +; + +BatchType equ 0 + +BatchSegment struc +BatType DB BatchType ; signature +Batechoflag DB 0 ; G state of echo +Batlast DW 0 ; G segment of last batch file +Batforptr DW 0 ; G segment for FOR command +Batforflag DB 0 ; G state of FOR +BatSeek DD ? ; lseek position of next char +BatParm DW 10 dup (?) ; pointers to parameters +BatFile DB ? ; beginning of batch file name +BatchSegment ends + +ANULL equ 0 ; terminates an argv string +ARGMAX equ 64 ; max args on a command line +ARGBLEN equ 2*128 ; 1char each plus term NUL +tplen equ 64 ; max size of one argument +arg_cnt_error equ 1 ; number of args > MAXARG +arg_buf_ovflow equ 2 ; overflowed argbuffer + +argv_ele STRUC ; elements in the argv array + argpointer DW (?) ; pointer to the argstring + argflags DB (?) ; cparse flags for this argstring + argstartel DW (?) ; the result of cparse's [STARTEL] + arglen DW (?) ; cparse's char count + one (for null) + argsw_word DW (?) ; any switches after this? what kinds? + arg_ocomptr DW (?) ; pointer into original command string +argv_ele ENDS + +arg_unit STRUC + argv DB (ARGMAX * SIZE argv_ele) DUP (?) + argvcnt DW (?) ; number of arguments + argswinfo DW (?) ; Switch information for entire line + argbuf DW ARGBLEN DUP (?) ; storage for argv strings + argforcombuf db COMBUFLEN DUP (?) ; Original for loop command string +arg_unit ENDS + +parseflags RECORD special_delim:1, unused:4, path_sep:1, wildcard:1, sw_flag:1 + +SwitchV EQU 10h +SwitchB EQU 08h +SwitchA EQU 04h +SwitchP EQU 02h +SwitchW EQU 01h +fSwitch EQU 8000h +fBadSwitch EQU 4000h + +SwitchDir EQU SwitchP + SwitchW + fSwitch +SwitchCopy EQU SwitchV + SwitchA + SwitchB + fSwitch + +break +; TRAP snares the operating system for a service call +; AX, as well as any other registers MS-DOS takes a fancy to, will be crunched. +trap MACRO dos_function,dos_info + ifnb + mov AX, (dos_function SHL 8) + dos_info + else + mov AX, (dos_function SHL 8) + endif + int int_command +ENDM + +; +; Equates for initialization +; +initInit equ 01h ; initialization in progress +initSpecial equ 02h ; in initialization time/date routine +initCtrlC equ 04h ; already in ^C handler diff --git a/v4.0/src/CMD/COMMAND/COMMAND.LNK b/v4.0/src/CMD/COMMAND/COMMAND.LNK new file mode 100644 index 0000000..29a639a --- /dev/null +++ b/v4.0/src/CMD/COMMAND/COMMAND.LNK @@ -0,0 +1,6 @@ +/map COMMAND1.OBJ COMMAND2.OBJ RUCODE.OBJ RDATA.OBJ INIT.OBJ IPARSE.OBJ + +UINIT.OBJ TCODE.OBJ TBATCH.OBJ TBATCH2.OBJ TFOR.OBJ TCMD1A.OBJ TCMD1B.OBJ + +TCMD2A.OBJ TCMD2B.OBJ TENV.OBJ TENV2.OBJ TMISC1.OBJ TMISC2.OBJ TPIPE.OBJ + +PARSE2.OBJ PATH1.OBJ PATH2.OBJ TUCODE.OBJ COPY.OBJ COPYPR1.OBJ COPYPR2.OBJ + +CPARSE.OBJ TPARSE.OBJ TPRINTF.OBJ TDATA.OBJ TSPC.OBJ,COMMAND.EXE,,; + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/COMMAND.SKL b/v4.0/src/CMD/COMMAND/COMMAND.SKL new file mode 100644 index 0000000..44b1eef --- /dev/null +++ b/v4.0/src/CMD/COMMAND/COMMAND.SKL @@ -0,0 +1,213 @@ + +;************************* +;* MESSAGE SKELETON FILE * +;************************* + +:util COMMAND ;AC000; + +:class 1 ;AC000; Transient extended errors + +:use EXTEND2 ;AC000; "File not found" +:use EXTEND3 ;AC000; "Path not found" +:use EXTEND8 ;AC000; "Insufficient memory" + +:class 2 ;AC000; Transient parse errors + +:class 3 ;AC000; Resident extended errors +:use -1 EXTEND999 ;AN000; "Extended error #" + +:class 4 ;AC000; Resident parse errors +:use -1 PARSE999 ;AN000; "Parse error #" + +:class A ;AC000; resident messages + +:use 220 COMMON17 ;AC000; "File allocation table bad, drive %1" +:use 223 COMMON28 ;AC000; "Press any key to continue" +:def 201 "A" ;AC000; +:def 202 "R" ;AC000; +:def 203 "I" ;AC000; +:def 204 "F" ;AC000; +:def 205 "Y" ;AC000; +:def 206 "N" ;AC000; +:def 210 "Abort" ;AC000; +:def 211 ", Retry" ;AC000; +:def 212 ", Ignore" ;AC000; +:def 213 ", Fail" ;AC000; +:def 214 "?" ;AC000; +:def 215 "reading",0 ;AC000; +:def 216 "writing",0 ;AC000; +:def 217 " %1 drive %2",CR,LF ;AC000; +:def 218 " %1 device %2",CR,LF ;AC000; +:def 219 "Please insert volume %1 serial %2-%3",CR,LF ;AC009; +:def 221 "Invalid COMMAND.COM",CR,LF ;AC000; +:def 222 "Insert disk with %1 in drive %2",CR,LF ;AC000; +:def 224 CR,LF,"Terminate batch job (Y/N)?" ;AC000; +:def 225 "Cannot execute %1",CR,LF ;AC000; +:def 226 "Error in EXE file",CR,LF ;AC000; +:def 227 "Program too big to fit in memory",CR,LF ;AC000; +:def 228 CR,LF,"No free file handles" ;AC000; +:def 229 "Bad Command or file name",CR,LF ;AC000; +:use 230 EXTEND5 ;AC000; +:def 231 CR,LF,"Memory allocation error" ;AC000; +:def 232 CR,LF,"Cannot load COMMAND, system halted",CR,LF;AC000; +:def 233 CR,LF,"Cannot start COMMAND, exiting",CR,LF ;AC000; +:def 234 CR,LF,"Top level process aborted, cannot continue",CR,LF;AC000; +:def 235 CR,LF ;AC000; + + +:class B ;AC000; Initialization messages + +:use 461 COMMON1 ;AC000; "Incorrect DOS version" +:def 463 "Out of environment space",CR,LF ;AC000; +:def 464 CR,LF,CR,LF,"MS DOS ",CR,LF + "Version 4.00 (C)Copyright International Business Machines Corp 1981,1988",CR,LF + " (C)Copyright Microsoft Corp 1981, 1988",CR,LF ;AC000; +:def 465 "Specified COMMAND search directory bad",CR,LF ;AC025; +:def 466 "Specified COMMAND search directory bad access denied",CR,LF ;AC025; + +:class C ;AC000; Parse messages + +:use PARSE1 ;AC000; "Too many parameters" +:use PARSE2 ;AC000; "Required parameter missing" +:use PARSE3 ;AC000; "Invalid switch" +:use PARSE4 ;AC000; "Invalid keyword" +:use PARSE6 ;AC000; "Parameter value not in allowed range" +:use PARSE7 ;AC000; "Parameter value not allowed" +:use PARSE8 ;AC000; "Parameter value not allowed" +:use PARSE9 ;AC000; "Parameter format not correct" +:use PARSE10 ;AC000; "Invalid parameter" +:use PARSE11 ;AC000; "Invalid parameter combination" + +:class D ;AC000; Extended errors - critical + +:use EXTEND19 ;AC000; "Write protect" +:use EXTEND20 ;AC000; "Invalid unit" +:use EXTEND21 ;AC000; "Drive not ready" +:use EXTEND22 ;AC000; "Invalid device request" +:use EXTEND23 ;AC000; "Data error" +:use EXTEND24 ;AC000; "Invalid device request parameters" +:use EXTEND25 ;AC000; "Seek error" +:use EXTEND26 ;AC000; "Invalid media type" +:use EXTEND27 ;AC000; "Sector not found" +:use EXTEND28 ;AC000; "Printer out of paper" +:use EXTEND29 ;AC000; "Write fault error" +:use EXTEND30 ;AC000; "Read fault error" +:use EXTEND31 ;AC000; "General Failure" +:use EXTEND32 ;AC000; "Sharing Violation" +:use EXTEND33 ;AC000; "Lock Violation" +:use EXTEND34 ;AC000; "Invalid Disk Change" +:use EXTEND35 ;AC000; "FCB unavailable" +:use EXTEND36 ;AC000; "System resource exhausted" +:use EXTEND37 ;AC000; "Code page mismatch" +:use EXTEND38 ;AC026; "Out of input" +:use EXTEND39 ;AC026; "Insufficient disk space" + +:class E ;AC000; extended errors + +:use EXTEND1 ;AC000; "Invalid Function" +:use EXTEND2 ;AC000; "File not found" +:use EXTEND3 ;AC000; "Path not found" +:use EXTEND4 ;AC000; "Too many open files" +:use EXTEND5 ;AC000; "Access denied" +:use EXTEND6 ;AC000; "Invalid handle" +:use EXTEND7 ;AC000; "Memory control blocks destroyed" +:use EXTEND8 ;AC000; "Insufficient memory" +:use EXTEND9 ;AC000; "Invalid memory block address" +:use EXTEND10 ;AC000; "Invalid Environment" +:use EXTEND11 ;AC000; "Invalid format" +:use EXTEND12 ;AC000; "Invalid function parameter" +:use EXTEND13 ;AC000; "Invalid data" +:use EXTEND15 ;AC000; "Invalid drive specification" +:use EXTEND16 ;AC000; "Attempt to remove current directory" +:use EXTEND17 ;AC000; "Not same device" +:use EXTEND18 ;AC000; "No more files" +:use EXTEND80 ;AC000; "File already exists" +:use EXTEND82 ;AC000; "Can not make directory entry" +:use EXTEND83 ;AC000; "Fail requested to Critical Error" +:use EXTEND84 ;AC000; "Too many attaches" +:use EXTEND85 ;AC000; "Device or file already attached" +:use EXTEND86 ;AC000; "Invalid password" +:use EXTEND87 ;AC000; "Invalid parameter" +:use EXTEND88 ;AC000; "File system data fault" +:use EXTEND89 ;AC000; "Function not supported by file system" +:use EXTEND90 ;AC000; + + +:class F ;AC000; Transient messages + +:use 1020 COMMON4 ;AC000; "%1 bytes free",CR,LF +:use 1015 COMMON18 ;AC000; "File cannot be copied onto itself",CR,LF +:use 1004 COMMON20 ;AC000; "Insufficient disk space",CR,LF +:use 1026 COMMON22 ;AC000; "Invalid code page",CR,LF +:use 1031 COMMON23 ;AC000; "Invalid date" +:use 1035 COMMON24 ;AC000; "Invalid time" +:use 1062 COMMON25 ;AC000; "Invalid path" +:use 1028 COMMON28 ;AC000; "Press any key to continue" +:use 1045 COMMON32 ;AC000; "Unable to create directory",CR,LF +:use 1041 COMMON33 ;AC000; "Volume in drive %1 has no label" +:use 1042 COMMON34 ;AC000; "Volume in drive %1 is %2" +:use 1043 COMMON36 ;AC000; "Volume Serial Number is %1" +:def 1002 "Duplicate file name or file not found",CR,LF ;AC000; +:def 1003 "Invalid path or file name",CR,LF ;AC000; +:def 1007 "Out of environment space",CR,LF ;AC000; +:def 1008 "File creation error",CR,LF ;AC000; +:def 1009 "Batch file missing",CR,LF ;AC000; +:def 1010 CR,LF,"Insert disk with batch file",CR,LF ;AC000; +:def 1011 "Bad command or file name",CR,LF ;AC000; +:use 1014 EXTEND5 ;AC000; +:def 1016 "Content of destination lost before copy",CR,LF ;AC000; +:def 1017 "Invalid filename or file not found",CR,LF ;AC000; +:def 1018 "%1 File(s) copied",CR,LF ;AC000; +:def 1019 "%1 File(s) " ;AC000; +:use 1021 EXTEND15 ;AC000; +:def 1022 "Code page %1 not prepared for system",CR,LF ;AC000; +:def 1023 "Code page %1 not prepared for all devices",CR,LF ;AC000; +:def 1024 "Active code page: %1",CR,LF ;AC000; +:def 1025 "NLSFUNC not installed",CR,LF ;AC000; +:def 1027 "Current drive is no longer valid" ;AC000; +:def 1029 "Label not found",CR,LF ;AC000; +:def 1030 "Syntax error",CR,LF ;AC000; +:def 1032 "Current date is %1 %2",CR,LF ;AC000; +:def 1033 "SunMonTueWedThuFriSat" ;AC000; +:def 1034 "Enter new date (%1): " ;AC031; +:def 1036 "Current time is %1",CR,LF ;AC000; +:def 1037 "Enter new time: " ;AC031; +:def 1038 ", Delete (Y/N)?" ;AC000; +:def 1039 "All files in directory will be deleted!",CR,LF + "Are you sure (Y/N)?" ;AC000; +:def 1040 "Microsoft DOS Version %1.%2",CR,LF ;AC000; +:def 1044 "Invalid directory",CR,LF ;AC000; +:def 1046 "Invalid path, not directory,",CR,LF,"or directory not empty",CR,LF ;AC000; +:def 1047 "Must specify ON or OFF",CR,LF ;AC000; +:def 1048 "Directory of %1",CR,LF ;AC000; +:def 1049 "No Path",CR,LF ;AC000; +:def 1050 "Invalid drive in search path",CR,LF ;AC000; +:def 1051 "Invalid device",CR,LF ;AC000; +:def 1052 "FOR cannot be nested",CR,LF ;AC000; +:def 1053 "Intermediate file error during pipe",CR,LF ;AC000; +:def 1054 "Cannot do binary reads from a device",CR,LF ;AC000; +:def 1055 "BREAK is %1",CR,LF ;AC000; +:def 1056 "VERIFY is %1",CR,LF ;AC000; +:def 1057 "ECHO is %1",CR,LF ;AC000; +:def 1059 "off",0 ;AC000; +:def 1060 "on",0 ;AC000; +:def 1061 "Error writing to device",CR,LF ;AC000; +:def 1063 "%1" ;AC000; +:def 1064 "%1" ;AC000; +:def 1065 "%1" ;AC000; +:def 1066 "%1" ;AC000; +:def 1067 9 ;AC000; +:def 1068 " " ;AC000; +:def 1069 8," ",8 ;AC000; +:def 1070 CR,LF ;AC000; +:def 1071 "%1" ;AC000; +:def 1072 "mm-dd-yy" ;AC000; +:def 1073 "dd-mm-yy" ;AC000; +:def 1074 "yy-mm-dd" ;AC000; +:def 1075 "%1 %2" ;AC000; +:def 1076 "%1" ;AC000; +:def 1077 " %1 %2" ;AC053; +:def 1078 "Directory already exists",CR,LF ;AC000; + +:end ;AC000; + diff --git a/v4.0/src/CMD/COMMAND/COMMAND1.ASM b/v4.0/src/CMD/COMMAND/COMMAND1.ASM new file mode 100644 index 0000000..3ee909a --- /dev/null +++ b/v4.0/src/CMD/COMMAND/COMMAND1.ASM @@ -0,0 +1,638 @@ + page 80,132 +; SCCSID = @(#)command1.asm 1.1 85/05/14 +; SCCSID = @(#)command1.asm 1.1 85/05/14 +TITLE COMMAND - resident code for COMMAND.COM +NAME COMMAND + +;***************************************************************************** +; +; MODULE: COMMAND.COM +; +; DESCRIPTIVE NAME: Default DOS command interpreter +; +; FUNCTION: This version of COMMAND is divided into three distinct +; parts. First is the resident portion, which includes +; handlers for interrupts 23H (Cntrl-C), 24H (fatal +; error), and 2EH (command line execute); it also has +; code to test and, if necessary, reload the transient +; portion. Following the resident is the init code, which +; is overwritten after use. Then comes the transient +; portion, which includes all command processing (whether +; internal or external). The transient portion loads at +; the end of physical memory, and it may be overlayed by +; programs that need as much memory as possible. When the +; resident portion of command regains control from a user +; program, a check sum is performed on the transient +; portion to see if it must be reloaded. Thus programs +; which do not need maximum memory will save the time +; required to reload COMMAND when they terminate. +; +; ENTRY POINT: PROGSTART +; +; INPUT: command line at offset 81H +; +; EXIT_NORMAL: No exit from root level command processor. Can exit +; from a secondary command processor via the EXIT +; internal command. +; +; EXIT_ERROR: Exit to prior command processor if possible, otherwise +; hang the system. +; +; INTERNAL REFERENCES: +; +; ROUTINES: See the COMMAND Subroutine Description Document +; (COMMAND.DOC) +; +; DATA AREAS: See the COMMAND Subroutine Description Document +; (COMMAND.DOC) +; +; EXTERNAL REFERENCES: +; +; ROUTINES: none +; +; DATA AREAS: none +; +;***************************************************************************** +; +; REVISION HISTORY +; ---------------- +; +; DOS 1.00 to DOS 3.30 +; -------------------------- +; SEE REVISION LOG IN COPY.ASM ALSO +; +; REV 1.17 +; 05/19/82 Fixed bug in BADEXE error (relocation error must return to +; resident since the EXELOAD may have overwritten the transient. +; +; REV 1.18 +; 05/21/82 IBM version always looks on drive A +; MSVER always looks on default drive +; +; REV 1.19 +; 06/03/82 Drive spec now entered in command line +; 06/07/82 Added VER command (print DOS version number) and VOL command +; (print volume label) +; +; REV 1.20 +; 06/09/82 Prints "directory" after directories +; 06/13/82 MKDIR, CHDIR, PWD, RMDIR added +; +; REV 1.50 +; Some code for new 2.0 DOS, sort of HACKey. Not enough time to +; do it right. +; +; REV 1.70 +; EXEC used to fork off new processes +; +; REV 1.80 +; C switch for single command execution +; +; REV 1.90 +; Batch uses XENIX +; +; Rev 2.00 +; Lots of neato stuff +; IBM 2.00 level +; +; Rev 2.01 +; 'D' switch for date time suppression +; +; Rev 2.02 +; Default userpath is NUL rather than BIN +; same as IBM +; COMMAND split into pieces +; +; Rev 2.10 +; INTERNATIONAL SUPPORT +; +; Rev 2.50 +; all the 2.x new stuff -MU +; +; Rev 3.30 (Ellen G) +; CALL internal command (TBATCH2.ASM) +; CHCP internal command (TCMD2B.ASM) +; INT 24H support of abort, retry, ignore, and fail prompt +; @ sign suppression of batch file line +; Replaceable environment value support in batch files +; INT 2FH calls for APPEND +; Lots of PTR fixes! +; +; Beyond 3.30 to forever (Ellen G) +; ---------------------- +; +; A000 DOS 4.00 - Use SYSPARSE for internal commands +; Use Message Retriever services +; /MSG switch for resident extended error msg +; Convert to new capitalization support +; Better error recovery on CHCP command +; Code page file tag support +; TRUENAME internal command +; Extended screen line support +; /P switch on DEL/ERASE command +; Improved file redirection error recovery +; (removed) Improved batch file performance +; Unconditional DBCS support +; Volume serial number support +; (removed) COMMENT=?? support +; +; A001 PTM P20 Move system_cpage from TDATA to TSPC +; +; A002 PTM P74 Fix PRESCAN so that redirection symbols do not +; require delimiters. +; +; A003 PTM P5,P9,P111 Included in A000 development +; +; A004 PTM P86 Fix IF command to turn off piping before +; executing +; +; A005 DCR D17 If user specifies an extension on the command +; line search for that extension only. +; +; A006 DCR D15 New message for MkDir - "Directory already +; exists" +; +; A007 DCR D2 Change CTTY so that a write is done before XDUP +; +; A008 PTM P182 Change COPY to set default if invalid function +; returned from code page call. +; +; A009 PTM P179 Add CRLF to invalid disk change message +; +; A010 DCR D43 Allow APPEND to do a far call to SYSPARSE in +; transient COMMAND. +; +; A011 DCR D130 Change redirection to overwrite an EOF mark +; before appending to a file. +; +; A012 PTM P189 Fix redirection error recovery. +; +; A013 PTM P330 Change date format +; +; A014 PTM P455 Fix echo parsing +; +; A015 PTM P517 Fix DIR problem with * vs *. +; +; A016 PTM P354 Fix extended error message addressing +; +; A017 PTM P448 Fix appending to 0 length files +; +; A018 PTM P566,P3903 Fix parse error messages to print out parameter +; the parser fails on. Fail on duplicate switches. +; +; A019 PTM P542 Fix device name to be printed correctly during +; critical error +; +; A020 DCR D43 Set append state off while in DIR +; +; A021 PTM P709 Fix CTTY printing ascii characters. +; +; A022 DCR D209 Enhanced error recovery +; +; A023 PTM P911 Fix ANSI.SYS IOCTL structure. +; +; A024 PTM P899 Fix EXTOPEN open modes. +; +; A025 PTM P922 Fix messages and optimize PARSE switches +; +; A026 DCR D191 Change redirection error recovery support. +; +; A027 PTM P991 Fix so that KAUTOBAT & AUTOEXEC are terminated +; with a carriage return. +; +; A028 PTM P1076 Print a blank line before printing invalid +; date and invalid time messages. +; +; A029 PTM P1084 Eliminate calls to parse_check_eol in DATE +; and TIME. +; +; A030 DCR D201 New extended attribute format. +; +; A031 PTM P1149 Fix DATE/TIME add blank before prompt. +; +; A032 PTM P931 Fix =ON, =OFF for BREAK, VERIFY, ECHO +; +; A033 PTM P1298 Fix problem with system crashes on ECHO >"" +; +; A034 PTM P1387 Fix COPY D:fname+,, to work +; +; A035 PTM P1407 Fix so that >> (appending) to a device does +; do a read to determine eof. +; +; A036 PTM P1406 Use 69h instead of 44h to get volume serial +; so that ASSIGN works correctly. +; +; A037 PTM P1335 Fix COMMAND /C with FOR +; +; A038 PTM P1635 Fix COPY so that it doesn't accept /V /V +; +; A039 DCR D284 Change invalid code page tag from -1 to 0. +; +; A040 PTM P1787 Fix redirection to cause error when no file is +; specified. +; +; A041 PTM P1705 Close redirected files after internal APPEND +; executes. +; +; A042 PTM P1276 Fix problem of APPEND paths changes in batch +; files causing loss of batch file. +; +; A043 PTM P2208 Make sure redirection is not set up twice for +; CALL'ed batch files. +; +; A044 PTM P2315 Set switch on PARSE so that 0ah is not used +; as an end of line character +; +; A045 PTM P2560 Make sure we don't lose parse, critical error, +; and extended message pointers when we EXIT if +; COMMAND /P is the top level process. +; +; A046 PTM P2690 Change COPY message "fn File not found" to +; "File not found - fn" +; +; A047 PTM P2819 Fix transient reload prompt message +; +; A048 PTM P2824 Fix COPY path to be upper cased. This was broken +; when DBCS code was added. +; +; A049 PTM P2891 Fix PATH so that it doesn't accept extra characters +; on line. +; +; A050 PTM P3030 Fix TYPE to work properly on files > 64K +; +; A051 PTM P3011 Fix DIR header to be compatible with prior releases. +; +; A052 PTM P3063,P3228 Fix COPY message for invalid filename on target. +; +; A053 PTM P2865 Fix DIR to work in 40 column mode. +; +; A054 PTM P3407 Code reduction and critical error on single line +; PTM P3672 (Change to single parser exported under P3407) +; +; A055 PTM P3282 Reset message service variables in INT 23h to fix +; problems with breaking out of INT 24h +; +; A056 PTM P3389 Fix problem of environment overlaying transient. +; +; A057 PTM P3384 Fix COMMAND /C so that it works if there is no space +; before the "string". EX: COMMAND /CDIR +; +; A058 PTM P3493 Fix DBCS so that CPARSE eats second character of +; DBCS switch. +; +; A059 PTM P3394 Change the TIME command to right align the display of +; the time. +; +; A060 PTM P3672 Code reduction - change PARSE and EXTENDED ERROR +; messages to be disk based. Only keep them if /MSG +; is used. +; +; A061 PTM P3928 Fix so that transient doesn't reload when breaking +; out of internal commands, due to substitution blocks +; not being reset. +; +; A062 PTM P4079 Fix segment override for fetching address of environment +; of parent copy of COMMAND when no COMSPEC exists in +; secondary copy of environment. Change default slash in +; default comspec string to backslash. + +; A063 PTM P4140 REDIRECTOR and IFSFUNC changed interface for getting +; text for critical error messages. + +; A064 PTM P4934 Multiplex number for ANSI.SYS changed due to conflict +; 5/20/88 with Microsoft product already shipped. + +; A065 PTM P4935 Multiplex number for SHELL changed due to conflict with +; 5/20/88 with Microsoft product already shipped. + +; A066 PTM P4961 DIR /W /P scrolled first line off the screen in some +; 5/24/88 cases; where the listing would barely fit without the +; header and space remaining. + +; A067 PTM P5011 For /E: values of 993 to 1024 the COMSPEC was getting +; 6/6/88 trashed. Turns out that the SETBLOCK for the new +; environment was putting a "Z block" marker in the old +; environment. The fix is to move to the old environment +; to the new environment before doing the SETBLOCK. +;*********************************************************************************** + +.XCREF +.XLIST + INCLUDE DOSSYM.INC + INCLUDE comsw.asm + INCLUDE comequ.asm + INCLUDE resmsg.equ ;AN000; +.LIST +.CREF + +CODERES SEGMENT PUBLIC BYTE ;AC000; +CODERES ENDS + +DATARES SEGMENT PUBLIC BYTE + EXTRN BATCH:WORD + EXTRN ECHOFLAG:BYTE + EXTRN disp_class:byte ;AN055; + EXTRN execemes_block:byte ;AC000; + EXTRN execemes_off:word ;AC000; + EXTRN execemes_subst:byte ;AC000; + EXTRN execemes_seg:word ;AC000; + EXTRN EXTCOM:BYTE + EXTRN FORFLAG:BYTE + EXTRN IFFlag:BYTE + EXTRN InitFlag:BYTE + EXTRN NEST:WORD + EXTRN number_subst:byte ;AC000; + EXTRN PIPEFLAG:BYTE + EXTRN RETCODE:WORD + EXTRN SINGLECOM:WORD +DATARES ENDS + +BATARENA SEGMENT PUBLIC PARA ;AC000; +BATARENA ENDS + +BATSEG SEGMENT PUBLIC PARA ;AC000; +BATSEG ENDS + +ENVARENA SEGMENT PUBLIC PARA ;AC000; +ENVARENA ENDS + +ENVIRONMENT SEGMENT PUBLIC PARA ; Default COMMAND environment +ENVIRONMENT ENDS + +INIT SEGMENT PUBLIC PARA + EXTRN CONPROC:NEAR + EXTRN init_contc_specialcase:near +INIT ENDS + +TAIL SEGMENT PUBLIC PARA +TAIL ENDS + +TRANCODE SEGMENT PUBLIC PARA +TRANCODE ENDS + +TRANDATA SEGMENT PUBLIC BYTE +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE +TRANSPACE ENDS + +TRANTAIL SEGMENT PUBLIC PARA +TRANTAIL ENDS + +RESGROUP GROUP CODERES,DATARES,BATARENA,BATSEG,ENVARENA,ENVIRONMENT,INIT,TAIL +TRANGROUP GROUP TRANCODE,TRANDATA,TRANSPACE,TRANTAIL + + INCLUDE envdata.asm + +; START OF RESIDENT PORTION + +CODERES SEGMENT PUBLIC BYTE ;AC000; + + + PUBLIC EXT_EXEC + PUBLIC CONTC + PUBLIC Exec_Wait + +ASSUME CS:RESGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + + EXTRN lodcom:near + EXTRN LODCOM1:near + + ORG 0 +ZERO = $ + + ORG 80h-1 + PUBLIC RESCOM +RESCOM LABEL BYTE + + ORG 100H + +PROGSTART: + JMP RESGROUP:CONPROC + +; +; COMMAND has issued an EXEC system call and it has returned an error. We +; examine the error code and select an appropriate message. +; +EXEC_ERR: + push ds ;AC000; get transient segment + pop es ;AC000; into ES + push cs ;AC000; get resident segment + pop ds ;AC000; into DS +ASSUME DS:RESGROUP ;AN000; + MOV BX,RBADNAM ;AC000; Get message number for Bad command + CMP AX,error_file_not_found + JZ GOTEXECEMES + MOV BX,TOOBIG ;AC000; Get message number for file not found + CMP AX,error_not_enough_memory + JZ GOTEXECEMES + MOV BX,EXEBAD ;AC000; Get message number for bad exe file + CMP AX,error_bad_format + JZ GOTEXECEMES + MOV BX,AccDen ;AC000; Get message number for access denied + CMP AX,error_access_denied + JZ GOTEXECEMES ;AC000; go print message + +DEFAULT_MESSAGE: + MOV BX,EXECEMES ;AC000; Get message number for default message + MOV EXECEMES_OFF,DX ;AN000; put offset of EXEC string in subst block + MOV EXECEMES_SEG,ES ;AN000; put segment of EXEC string in subst block + MOV AL,EXECEMES_SUBST ;AN000; get number of substitutions + MOV NUMBER_SUBST,AL ;AN000; + MOV SI,OFFSET RESGROUP:EXECEMES_BLOCK ;AN000; get address of subst block +GOTEXECEMES: + PUSH CS + POP ES ;AC000; get resident segment into ES +ASSUME ES:RESGROUP ;AN000; + MOV DX,BX ;AN000; get message number in DX + INVOKE RPRINT + JMP SHORT NOEXEC +; +; The transient has set up everything for an EXEC system call. For +; cleanliness, we issue the EXEC here in the resident so that we may be able +; to recover cleanly upon success. +; +EXT_EXEC: + push dx ;AN000; save the command name offset + INT int_command ; Do the EXEC + pop dx ;AN000; restore the command name offset + JC EXEC_ERR ; EXEC failed +; +; The exec has completed. Retrieve the exit code. +; +EXEC_WAIT: + push cs ;AC000; get resident segment + pop ds ;AC000; into DS + MOV AH,WAITPROCESS ;AC000; Get errorlevel + INT int_command ; Get the return code + MOV [RETCODE],AX +; +; We need to test to see if we can reload the transient. THe external command +; may have overwritten part of the transient. +; +NOEXEC: + JMP LODCOM +; +; This is the default system INT 23 handler. All processes (including +; COMMAND) get it by default. There are some games that are played: We +; ignore ^C during most of the INIT code. This is because we may perform an +; ALLOC and diddle the header! Also, if we are prompting for date/time in the +; init code, we are to treat ^C as empty responses. +; +CONTC PROC FAR + ASSUME CS:ResGroup,DS:NOTHING,ES:NOTHING,SS:NOTHING + test InitFlag,initINIT ; in initialization? + jz NotAtInit ; no + test InitFlag,initSpecial ; doing special stuff? + jz CmdIRet ; no, ignore ^C + jmp resgroup:init_contc_specialcase ; Yes, go handle it +CmdIret: + iret ; yes, ignore the ^C +NotAtInit: + test InitFlag,initCtrlC ; are we already in a ^C? + jz NotInit ; nope too. +; +; We are interrupting ourselves in this ^C handler. We need to set carry +; and return to the user sans flags only if the system call was a 1-12 one. +; Otherwise, we ignore the ^C. +; + cmp ah,1 + jb CmdIRet + cmp ah,12 + ja CmdIRet + add sp,6 ; remove int frame + stc + ret 2 ; remove those flags... +; +; We have now received a ^C for some process (maybe ourselves but not at INIT). +; +; Note that we are running on the user's stack!!! Bad news if any of the +; system calls below go and issue another INT 24... Massive stack overflow! +; Another bad point is that SavHand will save an already saved handle, thus +; losing a possible redirection... +; +; All we need to do is set the flag to indicate nested ^C. The above code +; will correctly flag the ^C diring the message output and prompting while +; ignoring the ^C the rest of the time. +; +; Clean up: flush disk. If we are in the middle of a batch file, we ask if +; he wants to terminate it. If he does, then we turn off all internal flags +; and let the DOS abort. +; +NotInit: + or InitFlag,initCtrlC ; nested ^c is on + STI + PUSH CS ; El Yucko! Change the user's DS!! + POP DS +ASSUME DS:RESGROUP + MOV DISP_CLASS,UTIL_MSG_CLASS ;AN055; reset display class + MOV NUMBER_SUBST,NO_SUBST ;AN055; reset number of substitutions + MOV AX,SingleCom + OR AX,AX + JNZ NoReset + PUSH AX + MOV AH,DISK_RESET + INT int_command ; Reset disks in case files were open + POP AX +NoReset: +; +; In the generalized version of FOR, PIPE and BATCH, we would walk the entire +; active list and free each segment. Here, we just free the single batch +; segment. +; + TEST Batch,-1 + JZ CONTCTERM + OR AX,AX + JNZ Contcterm + invoke SavHand + invoke ASKEND ; See if user wants to terminate batch +; +; If the carry flag is clear, we do NOT free up the batch file +; + JNC ContBatch + mov cl,echoflag ;AN000; get current echo flag + PUSH BX ;G + +ClearBatch: + MOV ES,[BATCH] ; get batch segment + mov di,batfile ;AN000; get offset of batch file name + mov ax,mult_shell_brk ;AN000; does the SHELL want this terminated? + int 2fh ;AN000; call the SHELL + cmp al,shell_action ;AN000; does shell want this batch? + jz shell_bat_cont ;AN000; yes - keep it + + MOV BX,ES:[BATFORPTR] ;G get old FOR segment + cmp bx,0 ;G is a FOR in progress + jz no_bat_for ;G no - don't deallocate + push es ;G + mov es,bx ;G yes - free it up... + MOV AH,DEALLOC ;G + INT 21H ;G + pop es ;G restore to batch segment + +no_bat_for: + mov cl,ES:[batechoflag] ;G get old echo flag + MOV BX,ES:[BATLAST] ;G get old batch segment + MOV AH,DEALLOC ; free it up... + INT 21H + MOV [BATCH],BX ;G get ready to deallocate next batch + DEC NEST ;G Is there another batch file? + JNZ CLEARBATCH ;G Keep going until no batch file + +; +; We are terminating a batch file; restore the echo status +; + +shell_bat_cont: ;AN000; continue batch for SHELL + + POP BX ;G + MOV ECHOFLAG,CL ;G reset echo status + MOV PIPEFLAG,0 ;G turn off pipeflag +ContBatch: + invoke CRLF ;G print out crlf before returning + invoke RestHand +; +; Yes, we are terminating. Turn off flags and allow the DOS to abort. +; +CONTCTERM: + XOR AX,AX ; Indicate no read + MOV BP,AX +; +; The following resetting of the state flags is good for the generalized batch +; processing. +; + MOV IfFlag,AL ; turn off iffing + MOV [FORFLAG],AL ; Turn off for processing + call ResPipeOff + CMP [SINGLECOM],AX ; See if we need to set SINGLECOM + JZ NOSETSING + MOV [SINGLECOM],-1 ; Cause termination on pipe, batch, for +NOSETSING: +; +; If we are doing an internal command, go through the reload process. If we +; are doing an external, let DOS abort the process. In both cases, we are +; now done with the ^C processing. +; + AND InitFlag,NOT initCtrlC + CMP [EXTCOM],AL + JNZ DODAB ; Internal ^C + JMP LODCOM1 +DODAB: + STC ; Tell DOS to abort + RET ; Leave flags on stack +ContC ENDP + +public ResPipeOff + assume ds:nothing,es:nothing +ResPipeOff: + SaveReg + xor ax,ax + xchg PipeFlag,al + or al,al + jz NoPipePop + shr EchoFlag,1 +NoPipePop: + RestoreReg + return +CODERES ENDS + END PROGSTART diff --git a/v4.0/src/CMD/COMMAND/COMMAND2.ASM b/v4.0/src/CMD/COMMAND/COMMAND2.ASM new file mode 100644 index 0000000..0f6c5b5 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/COMMAND2.ASM @@ -0,0 +1,619 @@ + page 80,132 +; SCCSID = @(#)command2.asm 4.3 85/10/16 +; SCCSID = @(#)command2.asm 4.3 85/10/16 +TITLE COMMAND2 - resident code for COMMAND.COM part II +NAME COMMAND2 +.XCREF +.XLIST + INCLUDE DOSSYM.INC + INCLUDE comsw.asm + INCLUDE comequ.asm + INCLUDE resmsg.equ ;AN000; +.LIST +.CREF + +tokenized = FALSE + +CODERES SEGMENT PUBLIC BYTE ;AC000; +CODERES ENDS + +DATARES SEGMENT PUBLIC BYTE + EXTRN append_state:word ;AN020; + EXTRN append_flag:byte ;AN020; + EXTRN COMDRV:BYTE + EXTRN comprmt1_block:byte ;AN000; + EXTRN comprmt1_subst:byte ;AN000; + EXTRN COMSPEC:BYTE + EXTRN cpdrv:byte + EXTRN envirseg:word + EXTRN EXTCOM:BYTE + EXTRN HANDLE01:WORD + EXTRN InitFlag:BYTE + EXTRN INT_2E_RET:DWORD ;AC000; + EXTRN IO_SAVE:WORD + EXTRN LOADING:BYTE + EXTRN LTPA:WORD + EXTRN MEMSIZ:WORD + EXTRN number_subst:byte ;AN000; + EXTRN OldTerm:DWORD ;AC000; + EXTRN PARENT:WORD ;AC000; + EXTRN PERMCOM:BYTE + EXTRN RDIRCHAR:BYTE + EXTRN RES_TPA:WORD + EXTRN RETCODE:WORD + EXTRN rsrc_xa_seg:word ;AN030; + EXTRN RSWITCHAR:BYTE + EXTRN SAVE_PDB:WORD + EXTRN SINGLECOM:WORD + EXTRN SUM:WORD + EXTRN TRANS:WORD + EXTRN TranVarEnd:BYTE + EXTRN TRANVARS:BYTE + EXTRN TRNSEG:WORD + EXTRN VERVAL:WORD +DATARES ENDS + +BATARENA SEGMENT PUBLIC PARA ;AC000; +BATARENA ENDS + +BATSEG SEGMENT PUBLIC PARA ;AC000; +BATSEG ENDS + +ENVARENA SEGMENT PUBLIC PARA ;AC000; +ENVARENA ENDS + +ENVIRONMENT SEGMENT PUBLIC PARA ; Default COMMAND environment +ENVIRONMENT ENDS + +INIT SEGMENT PUBLIC PARA + EXTRN envsiz:word + EXTRN oldenv:word + EXTRN resetenv:byte + EXTRN usedenv:word +INIT ENDS + +TAIL SEGMENT PUBLIC PARA +TAIL ENDS + +TRANCODE SEGMENT PUBLIC PARA +TRANCODE ENDS + +TRANDATA SEGMENT PUBLIC BYTE + EXTRN TRANDATAEND:BYTE +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE + EXTRN TRANSPACEEND:BYTE + EXTRN HEADCALL:DWORD +TRANSPACE ENDS + +TRANTAIL SEGMENT PUBLIC PARA +TRANTAIL ENDS + +RESGROUP GROUP CODERES,DATARES,BATARENA,BATSEG,ENVARENA,ENVIRONMENT,INIT,TAIL +TRANGROUP GROUP TRANCODE,TRANDATA,TRANSPACE,TRANTAIL + +; START OF RESIDENT PORTION + +CODERES SEGMENT PUBLIC BYTE ;AC000; + + PUBLIC CHKSUM + PUBLIC endinit + PUBLIC GETCOMDSK2 + PUBLIC INT_2E + PUBLIC LOADCOM + PUBLIC LODCOM + PUBLIC LODCOM1 + PUBLIC RESTHAND + PUBLIC SAVHAND + PUBLIC SETVECT + PUBLIC THEADFIX + PUBLIC TREMCHECK + PUBLIC tjmp + +ASSUME CS:RESGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + + EXTRN contc:near + EXTRN DSKERR:NEAR + EXTRN rstack:word +; +; If we cannot allocate enough memory for the transient or there was some +; other allocation error, we display a message and then die. +; +BADMEMERR: ; Allocation error loading transient + MOV DX,BMEMMES ;AC000; get message number +FATALC: + PUSH CS + POP DS + ASSUME DS:ResGroup + invoke RPRINT +; +; If this is NOT a permanent (top-level) COMMAND, then we exit; we can't do +; anything else! +; + CMP PERMCOM,0 + JZ FATALRET +; +; We are a permanent command. If we are in the process of the magic interrupt +; (Singlecom) then exit too. +; + CMP SINGLECOM,0 ; If PERMCOM and SINGLECOM + JNZ FATALRET ; Must take INT_2E exit +; +; Permanent command. We can't do ANYthing except halt. +; + MOV DX,HALTMES ;AC000; get message number + invoke RPRINT + STI +STALL: + JMP STALL ; Crash the system nicely + +FATALRET: + MOV DX,FRETMES ;AC000; get message number + invoke RPRINT +FATALRET2: + CMP [PERMCOM],0 ; If we get here and PERMCOM, + JNZ RET_2E ; must be INT_2E + invoke reset_msg_pointers ;AN000; reset critical & parse error messages + MOV AX,[PARENT] + MOV WORD PTR CS:[PDB_Parent_PID],AX + MOV AX,WORD PTR OldTerm + MOV WORD PTR CS:[PDB_Exit],AX + MOV AX,WORD PTR OldTerm+2 + MOV WORD PTR CS:[PDB_Exit+2],AX + MOV AX,(EXIT SHL 8) ; Return to lower level + INT int_command + +RET_2E: + PUSH CS + POP DS +ASSUME DS:RESGROUP,ES:NOTHING,SS:NOTHING + MOV [SINGLECOM],0 ; Turn off singlecom + MOV ES,[RES_TPA] + MOV AH,DEALLOC + INT int_command ; Free up space used by transient + MOV BX,[SAVE_PDB] + MOV AH,SET_CURRENT_PDB + INT int_command ; Current process is user + MOV AX,[RETCODE] + CMP [EXTCOM],0 + JNZ GOTECODE + XOR AX,AX ; Internals always return 0 +GOTECODE: + MOV [EXTCOM],1 ; Force external + JMP [INT_2E_RET] ;"IRET" + +INT_2E: ; Magic command executer +ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + POP WORD PTR [INT_2E_RET] + POP WORD PTR [INT_2E_RET+2] ;Get return address + POP AX ;Chuck flags + PUSH CS + POP ES + MOV DI,80H + MOV CX,64 + REP MOVSW + MOV AH,GET_CURRENT_PDB + INT int_command ; Get user's header + MOV [SAVE_PDB],BX + MOV AH,SET_CURRENT_PDB + MOV BX,CS + INT int_command ; Current process is me + MOV [SINGLECOM],81H + MOV [EXTCOM],1 ; Make sure this case forced + +LODCOM: ; Termination handler + CMP [EXTCOM],0 + jz lodcom1 ; if internal, memory already allocated + mov bx,0ffffh + MOV AH,ALLOC + INT int_command + CALL SetSize + ADD AX,20H + CMP BX,AX ; Is less than 512 byte buffer worth it? + JNC MEMOK +BADMEMERRJ: + JMP BADMEMERR ; Not enough memory + +; SetSize - get transient size in paragraphs +Procedure SetSize,NEAR + MOV AX,OFFSET TRANGROUP:TRANSPACEEND + 15 + MOV CL,4 + SHR AX,CL + return +EndProc SetSize + +MEMOK: + MOV AH,ALLOC + INT int_command + JC BADMEMERRJ ; Memory arenas probably trashed + MOV [EXTCOM],0 ; Flag not to ALLOC again + MOV [RES_TPA], AX ; Save current TPA segment + AND AX, 0F000H + ADD AX, 01000H ; Round up to next 64K boundary + JC BAD_TPA ; Memory wrap if carry set +; Make sure that new boundary is within allocated range + MOV DX, [RES_TPA] + ADD DX, BX ; Compute maximum address + CMP DX, AX ; Is 64K address out of range? + JBE BAD_TPA +; Must have 64K of usable space. + SUB DX, AX ; Compute the usable space + CMP DX, 01000H ; Is space >= 64K ? + JAE LTPASET +BAD_TPA: + MOV AX, [RES_TPA] +LTPASET: + MOV [LTPA],AX ; Usable TPA is 64k buffer aligned + MOV AX, [RES_TPA] ; Actual TPA is buffer allocated + ADD BX,AX + MOV [MEMSIZ],BX + CALL SetSize + SUB BX,AX + MOV [TRNSEG],BX ; Transient starts here +LODCOM1: + MOV AX,CS + MOV SS,AX +ASSUME SS:RESGROUP + MOV SP,OFFSET RESGROUP:RSTACK + MOV DS,AX +ASSUME DS:RESGROUP + CALL HEADFIX ; Make sure files closed stdin and stdout restored + XOR BP,BP ; Flag command ok + MOV AX,-1 + XCHG AX,[VERVAL] + CMP AX,-1 + JZ NOSETVER + MOV AH,SET_VERIFY_ON_WRITE ; AL has correct value + INT int_command +NOSETVER: + CMP [SINGLECOM],-1 + JNZ NOSNG + JMP FATALRET2 ; We have finished the single command +NOSNG: + CALL CHKSUM ; Check the transient + CMP DX,[SUM] + JZ HAVCOM ; Transient OK +BOGUS_COM: + MOV [LOADING],1 ; Flag DSKERR routine + CALL LOADCOM +CHKSAME: + + CALL CHKSUM + CMP DX,[SUM] + JZ HAVCOM ; Same COMMAND +ALSO_BOGUS: + CALL WRONGCOM + JMP SHORT CHKSAME +HAVCOM: + MOV AX,CHAR_OPER SHL 8 + INT int_command + MOV [RSWITCHAR],DL + CMP DL,'/' + JNZ USESLASH + mov cl,'\' + MOV [RDIRCHAR],cl ; Select alt path separator +USESLASH: + MOV [LOADING],0 ; Flag to DSKERR + MOV SI,OFFSET RESGROUP:TRANVARS + MOV DI,OFFSET TRANGROUP:HEADCALL + MOV ES,[TRNSEG] + CLD + MOV CX,OFFSET ResGroup:TranVarEnd + SUB CX,SI + REP MOVSB ; Transfer INFO to transient + MOV AX,[MEMSIZ] + MOV WORD PTR DS:[PDB_block_len],AX ; Adjust my own header + +; Just a public label so this spot can be found easily. +tjmp: + JMP DWORD PTR [TRANS] + +; Far call to REMCHECK for TRANSIENT +TREMCHECK PROC FAR + CALL REMCHECK + RET +TREMCHECK ENDP + +REMCHECK: +;All registers preserved. Returns ZF set if media removable, NZ if fixed +; AL is drive (0=DEF, 1=A,...). + SaveReg + MOV BX,AX + MOV AX,(IOCTL SHL 8) + 8 + INT 21h + jnc RCcont ; If an error occurred, assume the media + or ax,ax ; is NON-removable. + ; AX contains the non-zero error code + ; from the INT 21, so the OR AX,AX sets + ; Non-zero. This behavior makes Network + ; drives appear to be non-removable. + jmp SHORT ResRegs +RCcont: + AND AX,1 + NOT AX +ResRegs: + RestoreReg + return + +; Far call to HEADFIX for TRANSIENT +THEADFIX PROC FAR + CALL HEADFIX + RET +THEADFIX ENDP + +HEADFIX: + CALL SETVECT + XOR BX,BX ; Clean up header + MOV CX,[IO_SAVE] + MOV DX,WORD PTR DS:[PDB_JFN_Table] + CMP CL,DL + JZ CHK1 ; Stdin matches + MOV AH,CLOSE + INT int_command + MOV DS:[PDB_JFN_Table],CL ; Restore stdin +CHK1: + INC BX + CMP CH,DH ; Stdout matches + JZ CHKOTHERHAND + MOV AH,CLOSE + INT int_command + MOV DS:[PDB_JFN_Table+1],CH ; Restore stdout +CHKOTHERHAND: + ADD BX,4 ; Skip 2,3,4 + MOV CX,FilPerProc - 5 ; Already done 0,1,2,3,4 +CLOSELOOP: + MOV AH,CLOSE + INT int_command + INC BX + LOOP CLOSELOOP + push ds ;AN020; save data segment + push cs ;AN020; Get local segment into DS + pop ds ;AN020; + cmp append_flag,-1 ;AN020; Do we need to reset APPEND? + jnz append_fix_end ;AN030; no - just exit + mov ax,AppendSetState ;AN020; Set the state of Append + mov bx,Append_state ;AN020; back to the original state + int 2fh ;AN020; + mov append_flag,0 ;AN020; Set append flag to invalid +append_fix_end: ;AN030; + cmp [rsrc_xa_seg],no_xa_seg ;AN030; Is there any active XA segment? + jz xa_fix_end ;AN030; no - exit + push es ;AN030; Yes - deallocate it + mov es,rsrc_xa_seg ;AN030; + mov ax,(Dealloc SHL 8) ;AN030; Deallocate memory call + int int_command ;AN030; + pop es ;AN030; + mov [rsrc_xa_seg],no_xa_seg ;AN030; reset to no segment +xa_fix_end: + pop ds ;AN020; get data segment back + return + +SAVHAND: +ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + PUSH DS + PUSH BX ; Set stdin to sterr, stdout to stderr + PUSH AX + MOV AH,GET_CURRENT_PDB + INT int_command ; Get user's header + MOV DS,BX + LDS BX,DS:[PDB_JFN_POINTER] ; get pointer to JFN table... + MOV AX,WORD PTR DS:[BX] + MOV [HANDLE01],AX ; Save user's stdin, stdout + MOV AL,CS:[PDB_JFN_Table+2] ; get COMMAND stderr + MOV AH,AL + MOV WORD PTR DS:[BX],AX ; Dup stderr + POP AX + POP BX + POP DS + return + +ASSUME DS:RESGROUP +GETCOMDSK2: + CALL GETCOMDSK + JMP LODCOM1 ; Memory already allocated + +RESTHAND: + PUSH DS + PUSH BX ; Restore stdin, stdout to user + PUSH AX + MOV AH,GET_CURRENT_PDB + INT int_command ; Point to user's header + MOV AX,[HANDLE01] + MOV DS,BX +ASSUME DS:NOTHING + LDS BX,DS:[PDB_JFN_POINTER] ; get pointer to JFN table... + MOV WORD PTR DS:[BX],AX ; Stuff his old 0 and 1 + POP AX + POP BX + POP DS + return +ASSUME DS:RESGROUP,SS:RESGROUP + +HOPELESS: + MOV DX,COMBAD ;AC000; + JMP FATALC + +GETCOMDSK: + mov al,[comdrv] + CALL REMCHECK + jNZ HOPELESS ;Non-removable media +getcomdsk3: + cmp dx,combad ;AC000; + jnz getcomdsk4 + mov dx,combad ;AN000; get message number + invoke RPRINT ; Say command is invalid +getcomdsk4: + cmp [cpdrv],0 ;g is there a drive in the comspec? + jnz users_drive ;g yes - use it + mov ah,Get_default_drive ;g use default drive + int 21h ;g + add al,"A" ;g convert to ascii + mov [cpdrv],al ;g put in message to print out + +users_drive: ;g + mov dx,comprmt1 ;AC000; Prompt for diskette containing command +IF tokenized + or byte ptr [si],80h +endif + MOV AL,COMPRMT1_SUBST ;AN000; get number of substitutions + MOV SI,OFFSET RESGROUP:COMPRMT1_BLOCK ;AN000; get address of subst block + MOV NUMBER_SUBST,AL ;AN000; + invoke rprint +if tokenized + and byte ptr [si],NOT 80h +endif + mov dx,prompt ;AN047; Tell the user to strike a key + invoke rprint ;AN047; + CALL GetRawFlushedByte + return + +; flush world and get raw input +GetRawFlushedByte: + MOV AX,(STD_CON_INPUT_FLUSH SHL 8) OR RAW_CON_INPUT + INT int_command ; Get char without testing or echo + MOV AX,(STD_CON_INPUT_FLUSH SHL 8) + 0 + INT int_command + return + +LOADCOM: ; Load in transient + INC BP ; Flag command read + MOV DX,OFFSET RESGROUP:COMSPEC + MOV AX,OPEN SHL 8 + INT int_command ; Open COMMAND.COM + JNC READCOM + CMP AX,error_too_many_open_files + JNZ TRYDOOPEN + MOV DX,NOHANDMES ;AC000; + JMP FATALC ; Fatal, will never find a handle + +TRYDOOPEN: + CALL GETCOMDSK + JMP LOADCOM + +READCOM: + MOV BX,AX ; Handle + MOV DX,OFFSET RESGROUP:TRANSTART + XOR CX,CX ; Seek loc + MOV AX,LSEEK SHL 8 + INT int_command + JC WRONGCOM1 + MOV CX,OFFSET TRANGROUP:TRANSPACEEND - 100H + + PUSH DS + MOV DS,[TRNSEG] +ASSUME DS:NOTHING + MOV DX,100H + MOV AH,READ + INT int_command + POP DS +ASSUME DS:RESGROUP +WRONGCOM1: + PUSHF + PUSH AX + MOV AH,CLOSE + INT int_command ; Close COMMAND.COM + POP AX + POPF + JC WRONGCOM ; If error on READ + CMP AX,CX + retz ; Size matched +WRONGCOM: + MOV DX,COMBAD ;AC000; + CALL GETCOMDSK + JMP LOADCOM ; Try again + +CHKSUM: ; Compute transient checksum + PUSH DS + MOV DS,[TRNSEG] + MOV SI,100H + MOV CX,OFFSET TRANGROUP:TranDataEnd - 100H + +CHECK_SUM: + CLD + SHR CX,1 + XOR DX,DX +CHK: + LODSW + ADD DX,AX + ADC DX,0 + LOOP CHK + POP DS + return + +SETVECT: ; Set useful vectors + MOV DX,OFFSET RESGROUP:LODCOM + MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 22H + MOV WORD PTR DS:[PDB_EXIT],DX + MOV WORD PTR DS:[PDB_EXIT+2],DS + INT int_command + MOV DX,OFFSET RESGROUP:CONTC + INC AL + INT int_command + MOV DX,OFFSET RESGROUP:DSKERR + INC AL + INT int_command + return + + +; +; This routine moves the environment to a newly allocated segment +; at the end of initialization +; + +ENDINIT: + push ds ;g save segments + push es ;g + push cs ;g get resident segment to DS + pop ds ;g + ASSUME DS:RESGROUP + mov cx,usedenv ;g get number of bytes to move + mov es,envirseg ;g get target environment segment + + ASSUME ES:NOTHING + mov DS:[PDB_environ],es ;g put new environment in my header ;AM067; + mov ds,oldenv ;g source environment segment ;AM067; + ASSUME DS:NOTHING ;AM067; + xor si,si ;g set up offsets to start of segments ;AM067; + xor di,di ;g ;AM067; + cld ;g make sure we move the right way! ;AM067; + rep movsb ;g move it ;AM067; + xor ax,ax ;g ;AM067; + stosb ;g make sure there are double 0 at end ;AM067; + + cmp resetenv,1 ;eg Do we need to setblock to env end? + jnz noreset ;eg no - we already did it + mov bx,envsiz ;eg get size of environment in paragraphs + push es ;eg save environment - just to make sure + mov ah,SETBLOCK ;eg + int int_command ;eg + pop es ;eg + +noreset: + mov InitFlag,FALSE ;AC042; Turn off init flag + pop es ;g + pop ds ;g + jmp lodcom ;g allocate transient + +CODERES ENDS + +; This TAIL segment is used to produce a PARA aligned label in the resident +; group which is the location where the transient segments will be loaded +; initial. + +TAIL SEGMENT PUBLIC PARA + ORG 0 + PUBLIC TranStart +TRANSTART LABEL WORD +TAIL ENDS + +; This TAIL segment is used to produce a PARA aligned label in the transient +; group which is the location where the exec segments will be loaded +; initial. + +TRANTAIL SEGMENT PUBLIC PARA + ORG 0 +EXECSTART LABEL WORD +TRANTAIL ENDS + + END diff --git a/v4.0/src/CMD/COMMAND/COMSEG.ASM b/v4.0/src/CMD/COMMAND/COMSEG.ASM new file mode 100644 index 0000000..81cfa30 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/COMSEG.ASM @@ -0,0 +1,43 @@ +; SCCSID = @(#)comseg.asm 1.1 85/05/14 +; SCCSID = @(#)comseg.asm 1.1 85/05/14 +; The following are all of the segments used in the load order + +CODERES SEGMENT PUBLIC BYTE ;AC000; resident code +CODERES ENDS + +DATARES SEGMENT PUBLIC BYTE ;AC000; resident data +DATARES ENDS + +BATARENA SEGMENT PUBLIC PARA ;AC000; space for DOS ALLOCATE header +BATARENA ENDS + +BATSEG SEGMENT PUBLIC PARA ;AC000; AUTOEXEC batch segment +BATSEG ENDS + +ENVARENA SEGMENT PUBLIC PARA ;AC000; space for DOS ALLOCATE header +ENVARENA ENDS + +ENVIRONMENT SEGMENT PUBLIC PARA ;AC000; Default COMMAND environment +ENVIRONMENT ENDS + +INIT SEGMENT PUBLIC PARA ;AC000; Initialization code +INIT ENDS + +TAIL SEGMENT PUBLIC PARA ;AC000; End of Init - start of Transient +TAIL ENDS + +TRANCODE SEGMENT PUBLIC BYTE ;AC000; Transient code +TRANCODE ENDS + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; Transient data area +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; Transient modifiable data area +TRANSPACE ENDS + +TRANTAIL SEGMENT PUBLIC PARA ;AC000; End of Transient +TRANTAIL ENDS + +RESGROUP GROUP CODERES,DATARES,BATARENA,BATSEG,ENVARENA,ENVIRONMENT,INIT,TAIL +TRANGROUP GROUP TRANCODE,TRANDATA,TRANSPACE,TRANTAIL + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/COMSW.ASM b/v4.0/src/CMD/COMMAND/COMSW.ASM new file mode 100644 index 0000000..dbad747 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/COMSW.ASM @@ -0,0 +1,6 @@ +; SCCSID = @(#)comsw.asm 1.1 85/05/14 +; SCCSID = @(#)comsw.asm 1.1 85/05/14 + +include version.inc + + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/COPY.ASM b/v4.0/src/CMD/COMMAND/COPY.ASM new file mode 100644 index 0000000..37bb886 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/COPY.ASM @@ -0,0 +1,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 + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/COPYPR1.ASM b/v4.0/src/CMD/COMMAND/COPYPR1.ASM new file mode 100644 index 0000000..e727910 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/COPYPR1.ASM @@ -0,0 +1,276 @@ + page 80,132 +; SCCSID = @(#)copypr1.asm 1.1 85/05/14 +; SCCSID = @(#)copypr1.asm 1.1 85/05/14 + INCLUDE comsw.asm + +.xlist +.xcref + INCLUDE DOSSYM.INC +; INCLUDE DEVSYM.INC + INCLUDE comseg.asm + INCLUDE comequ.asm +.list +.cref + + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN DEVWMES_ptr:word + EXTRN ext_open_parms:byte ;AN000; + EXTRN ext_open_seg:word ;AN000; + EXTRN ext_open_off:word ;AN000; + EXTRN Extend_buf_sub:byte ;AN000; + EXTRN LOSTERR_ptr:word + EXTRN NOSPACE_ptr:word + EXTRN OVERWR_ptr:word +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN ASCII:BYTE + EXTRN BINARY:BYTE + EXTRN CFLAG:BYTE + EXTRN CONCAT:BYTE + EXTRN concat_xa:byte ;AC000; + EXTRN DESTBUF:BYTE + EXTRN DESTCLOSED:BYTE + EXTRN DESTHAND:WORD + EXTRN DESTISDEV:BYTE + EXTRN DESTSWITCH:WORD + EXTRN INEXACT:BYTE + EXTRN NOWRITE:BYTE + EXTRN NXTADD:WORD + EXTRN plus_comma:byte ;AN000; + EXTRN RDEOF:BYTE + EXTRN src_xa_seg:word ;AN000; + EXTRN SRCISDEV:BYTE + EXTRN string_ptr_2:word ;AN000; + EXTRN TERMREAD:BYTE + EXTRN TPA:WORD + EXTRN WRITTEN:WORD +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC BYTE + + EXTRN ENDCOPY:NEAR + + PUBLIC FLSHFIL + PUBLIC TRYFLUSH + +ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:NOTHING + +TRYFLUSH: + mov al,[CONCAT] + push ax + call FLSHFIL + pop ax + cmp al,[CONCAT] + return + +FLSHFIL: +; +; Write out any data remaining in memory. +; Inputs: +; [NXTADD] = No. of bytes to write +; [CFLAG] <> 0 if file has been created +; Outputs: +; [NXTADD] = 0 +; + MOV [TERMREAD],0 + cmp [CFLAG],0 + JZ NOTEXISTS + JMP EXISTS + +NOTEXISTS: + invoke BUILDDEST ; Find out all about the destination + invoke COMPNAME ; Source and dest. the same? + JNZ PROCDEST ; If not, go ahead + CMP [SRCISDEV],0 + JNZ PROCDEST ; Same name on device OK + CMP [CONCAT],0 ; Concatenation? + MOV DX,OFFSET TRANGROUP:OVERWR_ptr + JNZ NO_CONCAT_ERR ;AC000; If not, overwrite error + JMP COPERR ;AC000; + +NO_CONCAT_ERR: ;AC000; + MOV [NOWRITE],1 ; Flag not writting (just seeking) + +PROCDEST: + MOV AX,EXTOPEN SHL 8 ;AC000; open the file + mov si,offset trangroup:destbuf ;AN030; get file name + mov di,-1 ;AN030; indicate no parameters + cmp src_xa_seg,no_xa_seg ;AN030; is there an XA segment? + jz cont_no_xa ;AN030; no - no parameters + mov di,offset trangroup:Ext_open_parms ;AN030; get parameters + mov bx,src_xa_seg ;AN030; get extended attribute segment + mov ext_open_seg,bx ;AN030; put it in parameter list + mov ext_open_off,0 ;AN030; offset is 0 + +cont_no_xa: ;AN030; + mov bx,write_open_mode ;AN000; get open mode for COPY + xor cx,cx ;AN000; no special files + mov dx,write_open_flag ;AN000; set up open flags + + CMP [NOWRITE],0 + JNZ DODESTOPEN ; Don't actually create if NOWRITE set + mov dx,creat_open_flag ;AC000; set up create flags + +DODESTOPEN: + INT int_command +; +; We assume that the error is normal. TriageError will correct the DX value +; appropriately. +; + JNC dest_open_okay ;AC030; + +xa_set_error: ;AN030; error occurred on XA + invoke set_ext_error_msg ;AN030; get extended error + +ext_err_set: ;AN030; + mov string_ptr_2,offset trangroup:destbuf ;AN000; get address of failed string + mov Extend_buf_sub,one_subst ;AN030; put number of subst in control block + +COPERRJ2: ;AN030; + jmp COPERR ;AN030; go issue message + +dest_open_okay: ;AC030 + mov [DESTHAND],ax ; Save handle + mov [CFLAG],1 ; Destination now exists + mov bx,ax + mov cx,bx ;AN030; get handle into CX + invoke set_file_code_page ;AN030; set the code page for the target + jc ext_err_set ;AN030; if no error, continue + + mov [concat_xa],0 ;AN000; set first file flag off + mov ax,(IOCTL SHL 8) + INT int_command ; Get device stuff + mov [DESTISDEV],dl ; Set dest info + test dl,devid_ISDEV + jz exists ;AC030; Dest a device + + mov al,BYTE PTR [DESTSWITCH] + AND AL,SwitchA+SwitchB + JNZ TESTBOTH + MOV AL,[ASCII] ; Neither set, use current setting + OR AL,[BINARY] + JZ EXSETA ; Neither set, default to ASCII + +TESTBOTH: + JPE EXISTS ; Both are set, ignore + test AL,SwitchB + jz EXISTS ; Leave in cooked mode + mov ax,(IOCTL SHL 8) OR 1 + xor dh,dh + or dl,devid_RAW + mov [DESTISDEV],dl ; New value + INT int_command ; Set device to RAW mode + jmp short EXISTS + +COPERRJ: + jmp SHORT COPERR + +EXSETA: +; +; What we read in may have been in binary mode, flag zapped write OK +; + mov [ASCII],SwitchA ; Set ASCII mode + or [INEXACT],SwitchA ; ASCII -> INEXACT + +EXISTS: + cmp [NOWRITE],0 + jnz NOCHECKING ; If nowrite don't bother with name check + cmp plus_comma,1 ;g don't check if just doing +,, + jz NOCHECKING ;g + invoke COMPNAME ; Source and dest. the same? + JNZ NOCHECKING ; If not, go ahead + CMP [SRCISDEV],0 + JNZ NOCHECKING ; Same name on device OK +; +; At this point we know in append (would have gotten overwrite error on first +; destination create otherwise), and user trying to specify destination which +; has been scribbled already (if dest had been named first, NOWRITE would +; be set). +; + MOV DX,OFFSET TRANGROUP:LOSTERR_ptr ; Tell him he's not going to get it + invoke std_Eprintf ;AC022; + MOV [NXTADD],0 ; Set return + INC [TERMREAD] ; Tell Read to give up + +RET60: + return + +NOCHECKING: + mov bx,[DESTHAND] ; Get handle + XOR CX,CX + XCHG CX,[NXTADD] + JCXZ RET60 ; If Nothing to write, forget it + INC [WRITTEN] ; Flag that we wrote something + CMP [NOWRITE],0 ; If NOWRITE set, just seek CX bytes + JNZ SEEKEND + XOR DX,DX + PUSH DS + MOV DS,[TPA] +ASSUME DS:NOTHING + MOV AH,WRITE + INT int_command + POP DS +ASSUME DS:TRANGROUP + MOV DX,OFFSET TRANGROUP:NOSPACE_ptr + JC xa_set_error_Jmp ;AC022; Failure + sub cx,ax + retz ; Wrote all supposed to + test [DESTISDEV],devid_ISDEV + jz COPERR ; Is a file, error + test [DESTISDEV],devid_RAW + jnz DEVWRTERR ; Is a raw device, error + cmp [INEXACT],0 + retnz ; INEXACT so OK + dec cx + retz ; Wrote one byte less (the ^Z) + +DEVWRTERR: + MOV DX,OFFSET TRANGROUP:DEVWMES_ptr + +PUBLIC COPERR +COPERR: + INVOKE std_Eprintf ;AC022; + +COPERRP: + inc [DESTCLOSED] + cmp [CFLAG],0 + jz ENDCOPYJ ; Never actually got it open + MOV bx,[DESTHAND] + CMP BX,0 + JLE NoClose + MOV AH,CLOSE ; Close the file + INT int_command + +NoClose: + MOV DX,OFFSET TRANGROUP:DESTBUF + MOV AH,UNLINK + INT int_command ; And delete it + MOV [CFLAG],0 + +ENDCOPYJ: + JMP ENDCOPY + +XA_SET_ERROR_JMP: ;AN022; Go set up error message + jmp xa_set_error ;AN022; + +SEEKEND: + xor dx,dx ; Zero high half of offset + xchg dx,cx ; cx:dx is seek location + mov ax,(LSEEK SHL 8) OR 1 + INT int_command ; Seek ahead in the file + cmp [RDEOF],0 + retz +; +; If a ^Z has been read we must set the file size to the current +; file pointer location +; + MOV AH,WRITE + INT int_command ; CX is zero, truncates file + jc xa_set_error_Jmp ;AC022; Failure + return + +TRANCODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/COPYPR2.ASM b/v4.0/src/CMD/COMMAND/COPYPR2.ASM new file mode 100644 index 0000000..2913cab --- /dev/null +++ b/v4.0/src/CMD/COMMAND/COPYPR2.ASM @@ -0,0 +1,450 @@ + page 80,132 +; SCCSID = @(#)copypr2.asm 1.1 85/05/14 +; SCCSID = @(#)copypr2.asm 1.1 85/05/14 + INCLUDE comsw.asm + +.xlist +.xcref + INCLUDE DOSSYM.INC + INCLUDE comseg.asm + INCLUDE comequ.asm +.list +.cref + + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN FulDir_ptr:word ;AN052; +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN ASCII:BYTE + EXTRN BINARY:BYTE + EXTRN CONCAT:BYTE + EXTRN DESTBUF:BYTE + EXTRN DESTFCB:BYTE + EXTRN DESTINFO:BYTE + EXTRN DESTISDIR:BYTE + EXTRN DESTTAIL:WORD + EXTRN DESTVARS:BYTE + EXTRN DIRBUF:BYTE + EXTRN DIRCHAR:BYTE + EXTRN FIRSTDEST:BYTE + EXTRN INEXACT:BYTE + EXTRN MELCOPY:BYTE + EXTRN NXTADD:WORD + EXTRN PLUS:BYTE + EXTRN SDIRBUF:BYTE + EXTRN SRCINFO:BYTE + EXTRN srcxname:byte + EXTRN TPA:WORD + EXTRN trgxname:byte + EXTRN USERDIR1:BYTE +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC BYTE + + EXTRN BADPATH_ERR:NEAR ;AN022; + EXTRN COPERR:NEAR ;AN052; + EXTRN EXTEND_SETUP:NEAR ;AN022; + + PUBLIC BUILDPATH + PUBLIC SETSTARS + PUBLIC SETASC + +ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:NOTHING + +SETASC: +; +; Given switch vector in AX, +; Set ASCII switch if A is set +; Clear ASCII switch if B is set +; BINARY set if B specified +; Leave ASCII unchanged if neither or both are set +; Also sets INEXACT if ASCII is ever set. AL = ASCII on exit, flags set +; + AND AL,SwitchA+SwitchB + JPE LOADSW ; PE means both or neither are set + PUSH AX + AND AL,SwitchB + MOV [BINARY],AL + POP AX + AND AL,SwitchA + MOV [ASCII],AL + OR [INEXACT],AL + +LOADSW: + MOV AL,[ASCII] + OR AL,AL + return + +public builddest +BUILDDEST: + cmp [DESTISDIR],-1 + jnz KNOWABOUTDEST ; Already done the figuring + MOV DI,OFFSET TRANGROUP:USERDIR1 + mov bp,offset trangroup:DESTVARS + call BUILDPATH + invoke RESTUDIR1 + +; Now know all about the destination + +KNOWABOUTDEST: + xor al,al + xchg al,[FIRSTDEST] + or al,al + jnz FIRSTDST + jmp NOTFIRSTDEST + +FIRSTDST: + mov si,[DESTTAIL] ; Create an FCB of the original DEST + mov di,offset trangroup:DESTFCB + mov ax,PARSE_FILE_DESCRIPTOR SHL 8 + INT int_command + CMP BYTE PTR [SI],0 + JZ GoodParse +;AD052; MOV BYTE PTR [DI+1],"|" ; must be illegal file name character + mov dx,offset trangroup:fuldir_ptr ;AN052; Issue "File creation error" + jmp coperr ;AN052; + +GoodParse: + mov ax,word ptr [DESTBUF] ; Get drive + cmp ah,':' + jz DRVSPEC4 + mov al,'@' + +DRVSPEC4: + MOV CL,[ASCII] ; Save current ASCII setting + or al,20h + sub al,60h + mov [DESTFCB],al + mov al,[DESTINFO] + mov ah,[SRCINFO] + and ax,0202H + or al,al + jz NOTMELCOPY + cmp al,ah + jnz NOTMELCOPY + cmp [PLUS],0 + jz NOTMELCOPY + inc [MELCOPY] ; ambig source, ambig dest, and pluses + xor al,al + jmp short SETCONC + +NOTMELCOPY: + xor al,2 ; al=2 if unambig dest, =0 if ambig dest + and al,ah + shr al,1 ; al=1 if unambig dest AND ambig sorce + ; Implies concatenation +SETCONC: + or al,[PLUS] ; al=1 if concat + mov [CONCAT],al + shl al,1 + shl al,1 + mov [INEXACT],al ; Concat -> inexact copy + cmp [BINARY],0 + jnz NOTFIRSTDEST ; Binary explicitly given, all OK + mov [ASCII],al ; Concat -> ASCII + or cl,cl + jnz NOTFIRSTDEST ; ASCII flag set before, DATA read correctly + or al,al + JZ NOTFIRSTDEST ; ASCII flag did not change states +; +; At this point there may already be binary read data in the read buffer. +; We need to find the first ^Z (if there is one) and trim the amount +; of data in the buffer correctly. +; + MOV CX,[NXTADD] + JCXZ NOTFIRSTDEST ; No data, everything OK + MOV AL,1AH + PUSH ES + XOR DI,DI + MOV ES,[TPA] + REPNE SCASB ; Scan for EOF + POP ES + JNZ NOTFIRSTDEST ; No ^Z in buffer, everything OK + DEC DI ; Point at ^Z + MOV [NXTADD],DI ; New buffer + +NOTFIRSTDEST: + mov bx,offset trangroup:DIRBUF+1 ; Source of replacement chars + cmp [CONCAT],0 + jz GOTCHRSRC ; Not a concat + mov bx,offset trangroup:SDIRBUF+1 ; Source of replacement chars + +GOTCHRSRC: + mov si,offset trangroup:DESTFCB+1 ; Original dest name + mov di,[DESTTAIL] ; Where to put result + +public buildname +BUILDNAME: + mov cx,8 + +BUILDMAIN: + lodsb + cmp al,'?' + jnz NOTAMBIG + mov al,byte ptr [BX] + +NOTAMBIG: + cmp al,' ' + jz NOSTORE + stosb + +NOSTORE: + inc bx + loop BUILDMAIN + mov cl,3 + mov al,' ' + cmp byte ptr [SI],al + jz ENDDEST ; No extension + mov al,dot_chr + stosb + +BUILDEXT: + lodsb + cmp al,'?' + jnz NOTAMBIGE + mov al,byte ptr [BX] + +NOTAMBIGE: + cmp al,' ' + jz NOSTOREE + stosb + +NOSTOREE: + inc bx + loop BUILDEXT +ENDDEST: + xor al,al + stosb ; NUL terminate + return + +BUILDPATH: + test [BP.INFO],2 + jnz NOTPFILE ; If ambig don't bother with open + mov dx,bp + add dx,BUF ; Set DX to spec + + push di ;AN000; + 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 si,dx ;AN030; get file name offset + mov di,-1 ;AN030; no parm list + mov dx,read_open_flag ;AN000; set up open flags + INT int_command + pop di ;AN000; + jnc pure_file ;AN022; is pure file + invoke get_ext_error_number ;AN022; get the extended error + cmp ax,error_file_not_found ;AN022; if file not found - okay + jz notpfile ;AN022; + cmp ax,error_path_not_found ;AN022; if path not found - okay + jz notpfile ;AN022; + cmp ax,error_access_denied ;AN022; if access denied - okay + jz notpfile ;AN022; + jmp extend_setup ;AN022; exit with error + +pure_file: + mov bx,ax ; Is pure file + mov ax,IOCTL SHL 8 + INT int_command + mov ah,CLOSE + INT int_command + test dl,devid_ISDEV + jnz ISADEV ; If device, done + test [BP.INFO],4 + jz ISSIMPFILE ; If no path seps, done + +NOTPFILE: + mov dx,word ptr [BP.BUF] + cmp dl,0 ;AN034; If no drive specified, get + jz set_drive_spec ;AN034; default drive dir + cmp dh,':' + jz DRVSPEC5 + +set_drive_spec: ;AN034; + mov dl,'@' + +DRVSPEC5: + or dl,20h + sub dl,60h ; A = 1 + invoke SAVUDIR1 + jnc curdir_ok ;AN022; if error - exit + invoke get_ext_error_number ;AN022; get the extended error + jmp extend_setup ;AN022; exit with error + +curdir_ok: ;AN022; + mov dx,bp + add dx,BUF ; Set DX for upcomming CHDIRs + mov bh,[BP.INFO] + and bh,6 + cmp bh,6 ; Ambig and path ? + jnz CHECKAMB ; jmp if no + mov si,[BP.TTAIL] + mov bl,':' + cmp byte ptr [si-2],bl + jnz KNOWNOTSPEC + mov [BP.ISDIR],2 ; Know is d:/file + jmp short DOPCDJ + +KNOWNOTSPEC: + mov [BP.ISDIR],1 ; Know is path/file + dec si ; Point to the / + +DOPCDJ: + jmp DOPCD ;AC022; need long jump + +CHECKAMB: + cmp bh,2 + jnz CHECKCD + +ISSIMPFILE: +ISADEV: + mov [BP.ISDIR],0 ; Know is file since ambig but no path + return + +CHECKCD: + invoke SETREST1 + mov ah,CHDIR + INT int_command + jc NOTPDIR + mov di,dx + xor ax,ax + mov cx,ax + dec cx + +Kloop: ;AN000; 3/3/KK + MOV AL,ES:[DI] ;AN000; 3/3/KK + INC DI ;AN000; 3/3/KK + OR AL,AL ;AN000; 3/3/KK + JZ Done ;AN000; 3/3/KK + xor ah,ah ;AN000; 3/3/KK + invoke Testkanj ;AN000; 3/3/KK + JZ Kloop ;AN000; 3/3/KK + INC DI ;AN000; 3/3/KK + INC AH ;AN000; 3/3/KK + jmp Kloop ;AN000; 3/3/KK + +Done: ;AN000; 3/3/KK + dec di + mov al,[DIRCHAR] + mov [bp.ISDIR],2 ; assume d:/file + OR AH, AH ;AN000; 3/3/KK + JNZ Store_pchar ;AN000; 3/3/KK this is the trailing byte of ECS code + cmp al,[di-1] + jz GOTSRCSLSH + +Store_pchar: ;AN000; 3/3/KK + stosb + mov [bp.ISDIR],1 ; know path/file + +GOTSRCSLSH: + or [bp.INFO],6 + call SETSTARS + return + + +NOTPDIR: + invoke get_ext_error_number ;AN022; get the extended error + cmp ax,error_path_not_found ;AN022; if path not found - okay + jz notpdir_try ;AN022; + cmp ax,error_access_denied ;AN022; if access denied - okay + jnz extend_setupj ;AN022; otherwise - exit error + +notpdir_try: ;AN022; + mov [bp.ISDIR],0 ; assume pure file + mov bh,[bp.INFO] + test bh,4 + retz ; Know pure file, no path seps + mov [bp.ISDIR],2 ; assume d:/file + mov si,[bp.TTAIL] + cmp byte ptr [si],0 + jz BADCDERRJ2 ; Trailing '/' + mov bl,dot_chr + cmp byte ptr [si],bl + jz BADCDERRJ2 ; If . or .. pure cd should have worked + mov bl,':' + cmp byte ptr [si-2],bl + jz DOPCD ; Know d:/file + mov [bp.ISDIR],1 ; Know path/file + dec si ; Point at last '/' + +DOPCD: + xor bl,bl + xchg bl,[SI] ; Stick in a NUL + invoke SETREST1 + CMP DX,SI ;AN000; 3/3/KK + JAE LookBack ;AN000; 3/3/KK + PUSH SI ;AN000; 3/3/KK + PUSH CX ;AN000; 3/3/KK + MOV CX,SI ;AN000; 3/3/KK + MOV SI,DX ;AN000; 3/3/KK + +Kloop2: ;AN000; 3/3/KK + LODSB ;AN000; 3/3/KK + invoke TestKanj ;AN000; 3/3/KK + jz NotKanj4 ;AN000; 3/3/KK + LODSB ;AN000; 3/3/KK + CMP SI,CX ;AN000; 3/3/KK + JB Kloop2 ;AN000; 3/3/KK + POP CX ;AN000; 3/3/KK + POP SI ;AN000; 3/3/KK + JMP SHORT DoCdr ;AN000; 3/3/KK Last char is ECS code, don't check for + ; trailing path sep +NotKanj4: ;AN000; 3/3/KK + CMP SI,CX ;AN000; 3/3/KK + JB Kloop2 ;AN000; 3/3/KK + POP CX ;AN000; 3/3/KK + POP SI ;AN000; 3/3/KK + +LookBack: ;AN000; 3/3/KK + CMP BL,[SI-1] ; if double slash, then complain. + JZ BadCDErrJ2 + +DoCdr: ;AN000; 3/3/KK + mov ah,CHDIR + INT int_command + xchg bl,[SI] + retnc + invoke get_ext_error_number ;AN022; get the extended error + +EXTEND_SETUPJ: ;AN022; + JMP EXTEND_SETUP ;AN022; go issue the error message + +BADCDERRJ2: + jmp badpath_err ;AC022; go issue path not found message + +SETSTARS: + mov [bp.TTAIL],DI + add [bp.SIZ],12 + mov ax,dot_qmark + mov cx,8 + rep stosb + xchg al,ah + stosb + xchg al,ah + mov cl,3 + rep stosb + xor al,al + stosb + return + +PUBLIC CompName +COMPNAME: + + mov si,offset trangroup:DESTBUF ;g do name translate of target + mov di,offset trangroup:TRGXNAME ;g save for name comparison + mov ah,xnametrans ;g + int int_command ;g + + MOV si,offset trangroup:SRCXNAME ;g get name translate of source + MOV di,offset trangroup:TRGXNAME ;g get name translate of target + + + invoke STRCOMP + + return + +TRANCODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/CPARSE.ASM b/v4.0/src/CMD/COMMAND/CPARSE.ASM new file mode 100644 index 0000000..f751086 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/CPARSE.ASM @@ -0,0 +1,417 @@ + page 80,132 +; SCCSID = @(#)cparse.asm 1.1 85/05/14 +; SCCSID = @(#)cparse.asm 1.1 85/05/14 + INCLUDE comsw.asm + +.xlist +.xcref + INCLUDE DOSSYM.INC + INCLUDE DEVSYM.INC + INCLUDE comseg.asm + INCLUDE comequ.asm +.list +.cref + + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN BADCD_PTR:WORD ;AC022; + EXTRN BADCPMES_ptr:word ;AC000; +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN comma:byte + EXTRN cpyflag:byte + EXTRN CURDRV:BYTE + EXTRN ELCNT:BYTE + EXTRN ELPOS:BYTE + EXTRN EXPAND_STAR:BYTE + EXTRN SKPDEL:BYTE + EXTRN STARTEL:WORD + EXTRN SWITCHAR:BYTE + EXTRN switch_list:byte + EXTRN TPA:WORD +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC BYTE + +ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:NOTHING + + EXTRN CERROR:NEAR + + PUBLIC BADCDERR ;AC022; + PUBLIC CPARSE + +SWCOUNT EQU 5 ; Must agree with length of switch_list + +;-----------------------------------------------------------------------; +; ENTRY: ; +; DS:SI Points input buffer ; +; ES:DI Points to the token buffer ; +; BL Special delimiter for this call ; +; Always checked last ; +; set it to space if there is no special delimiter ; +; EXIT: ; +; DS:SI Points to next char in the input buffer ; +; ES:DI Points to the token buffer ; +; [STARTEL] Points to start of last element of path in token ; +; points to a NUL for no element strings 'd:' 'd:/' ; +; CX Character count ; +; BH Condition Code ; +; Bit 1H of BH set if switch character ; +; Token buffer contains char after ; +; switch character ; +; BP has switch bits set (ORing only) ; +; Bit 2H of BH set if ? or * in token ; +; if * found element ? filled ; +; Bit 4H of BH set if path sep in token ; +; Bit 80H of BH set if the special delimiter ; +; was skipped at the start of this token ; +; Token buffer always starts d: for non switch tokens ; +; CARRY SET ; +; if CR on input ; +; token buffer not altered ; +; ; +; DOES NOT RETURN ON BAD PATH, OR TRAILING SWITCH CHAR ERROR ; +; MODIFIES: ; +; CX, SI, AX, BH, DX and the Carry Flag ; ; +; ; +; -----------------------------------------------------------------------; +;--------------- +; Modifications to cparse: recognition of right and left parentheses +; as integral tokens, and removal of automatic upper-case conversion code. +; +; Both modifications were installed in the course of adding a coherent +; command-line parser to COMMAND.COM which builds a UNIX-style argv[]/argc +; structure for command-line arguments. This parser relies on cparse to +; recognize individual tokens. +; +; To process for-loops correctly, parentheses must therefore be +; recognized as tokens. The upper-case conversion code was removed so +; that commands (such as for and echo) would be able to use the "original" +; text of the command line. +; +; Note also the modification to prevent the automatic conversion of colons +; into spaces WITHIN THE SOURCE TEXT! +; +; Also note that BP is also clobbered if cparse recognizes any switches +; on the command line. +; +; Alan L, OS/MSDOS 14 August 1983 +;--------------- + +CPARSE: +ASSUME DS:TRANGROUP,ES:TRANGROUP + + xor ax,ax + mov [STARTEL],DI ; No path element (Is DI correct?) + mov [ELPOS],al ; Start in 8 char prefix + mov [SKPDEL],al ; No skip delimiter yet + mov bh,al ; Init nothing + pushf ; save flags + push di ; save the token buffer addrss + xor cx,cx ; no chars in token buffer + mov comma,cl ;g reset comma flag +moredelim: + LODSB + INVOKE DELIM + JNZ SCANCDONE + CMP AL,' ' + JZ moredelim + CMP AL,9 + JZ moredelim + xchg al,[SKPDEL] + or al,al + jz moredelim ; One non space/tab delimiter allowed + test bh,080h ;g has a special char been found? + jz no_comma ;g no - just exit + mov comma,1 ;g set comma flag +no_comma: + JMP x_done ; Nul argument + +SCANCDONE: + +;;;; IF NOT KANJI 3/3/KK +;--------------- +; Mod to avoid upper-case conversion. +; cmp cpyflag,1 3/3/KK +; jnz cpcont1 3/3/KK +; invoke UPCONV 3/3/KK +cpcont1: +;--------------- +;;;; ENDIF 3/3/KK + + cmp al,bl ; Special delimiter? + jnz nospec + or bh,80H + jmp short moredelim + +nospec: + cmp al,0DH ; a CR? + jne ncperror + jmp cperror + +ncperror: + cmp al,[SWITCHAR] ; is the char the switch char? + jne na_switch ; yes, process... + jmp a_switch + +na_switch: + mov dl,':' + cmp byte ptr [si],dl + jne anum_chard ; Drive not specified + +;;;; IF KANJI 3/3/KK +;--------------- +; Mod to avoid upper-case conversion. + cmp cpyflag,1 + jnz cpcont2 + invoke UPCONV +cpcont2: +;--------------- +;;;; ENDIF 3/3/KK + + call move_char + lodsb ; Get the ':' + call move_char + mov [STARTEL],di + mov [ELCNT],0 + jmp anum_test + +anum_chard: + mov [STARTEL],di + mov [ELCNT],0 ; Store of this char sets it to one + cmp cpyflag,1 ; Was CPARSE called from COPY? + jnz anum_char ; No, don't add drive spec. + invoke PATHCHRCMP ; Starts with a pathchar? + jnz anum_char ; no + push ax + mov al,[CURDRV] ; Insert drive spec + add al,capital_A + call move_char + mov al,':' + call move_char + pop ax + mov [STARTEL],di + mov [ELCNT],0 + +anum_char: + +;;;; IF KANJI 3/3/KK + invoke TESTKANJ + jz NOTKANJ ;AC048; + call move_char + lodsb + jmp short notspecial + +NOTKANJ: ;AN048; If not kanji + cmp cpyflag,1 ;AN048; and if we're in COPY + jnz testdot ;AN048; + invoke upconv ;AN048; upper case the char + +TESTDOT: +;;;; ENDIF 3/3/KK + + cmp al,dot_chr + jnz testquest + inc [ELPOS] ; flag in extension + mov [ELCNT],0FFH ; Store of the '.' resets it to 0 + +testquest: + cmp al,'?' + jnz testsplat + or bh,2 + +testsplat: + cmp al,star + jnz testpath + or bh,2 + cmp byte ptr [expand_star],0 + jnz expand_filename + jmp SHORT testpath + +badperr2j: + jmp badperr2 + +expand_filename: + mov ah,7 + cmp [ELPOS],0 + jz gotelcnt + mov ah,2 + +gotelcnt: + mov al,'?' + sub ah,[ELCNT] + jc badperr2j + xchg ah,cl + jcxz testpathx + +qmove: + xchg ah,cl + call move_char + xchg ah,cl + loop qmove + +testpathx: + xchg ah,cl + +testpath: + invoke PATHCHRCMP + jnz notspecial + or bh,4 + cmp byte ptr [expand_star],0 + jz no_err_check + test bh,2 ; If just hit a '/', cannot have ? or * yet + jnz badperr + +no_err_check: + mov [STARTEL],di ; New element + INC [STARTEL] ; Point to char after / + mov [ELCNT],0FFH ; Store of '/' sets it to 0 + mov [ELPOS],0 + +notspecial: + call move_char ; just an alphanum string +anum_test: + + lodsb + +;;;; IF NOT KANJI 3/3/KK +;--------------- +; Mod to avoid upper-case conversion. +; cmp cpyflag,1 3/3/KK +; jnz cpcont3 3/3/KK +; invoke UPCONV 3/3/KK +cpcont3: +;--------------- +;;;; ENDIF 3/3/KK + + INVOKE DELIM + je x_done + + cmp al,0DH + je x_done + cmp al,[SWITCHAR] + je x_done + cmp al,bl + je x_done + cmp al,':' ; ':' allowed as trailer because + ; of devices +;;;; IF KANJI 3/3/KK + je FOO15 + jmp anum_char +FOO15: +;;; ELSE 3/3/KK +;;; jne anum_charj 3/3/KK +;;; ENDIF 3/3/KK + +;--------------- +; Modification made for parseline. +; Why would it be necessary to change colons to spaces? In this +; case, EVERY colon is changed to a space; e.g., 'f:' yields 'f ', +; but so does 'echo foo:bar' yield 'echo foo bar'. +;--------------- + cmp cpyflag,2 ; Is CPARSE parsing the 1st token from + ; from PARSELINE? + jnz cpcont4 ; No, continue + call move_char ; Yes, save the ':' and go get another + jmp anum_test ; character. + +cpcont4: + inc si ;Skip the ':' + jmp short x_done + +anum_charj: + jmp anum_char + +badperr2: + mov dx,offset trangroup:BADCPMES_ptr + jmp CERROR + +badperr: +BADCDERR: ;AC022; Issue "Invalid Directory" + MOV DX,OFFSET TRANGROUP:BADCD_ptr ;AC022; message + JMP CERROR ;AC022; + +cperror: + dec si ; adjust the pointer + pop di ; retrive token buffer address + popf ; restore flags + stc ; set the carry bit + return + +x_done: + dec si ; adjust for next round +;--------------- +; Mod to recognize right and left parens as integral tokens. +x_done2: +;--------------- + jmp short out_token + +a_switch: + OR BH,1 ; Indicate switch + OR BP,fSwitch + INVOKE SCANOFF + INC SI + invoke testkanj ;AN057; See if DBCS lead byte + jz a_switch_notkanj ;AN057; no - continue processing + call move_char ;AN057; DBCS - store first byte + lodsb ;AN057; get second byte + call move_char ;AN057; store second byte + or bp,fBadSwitch ;AN057; DBCS switch is invalid + jmp short out_token ;AN057; don't bother checking switch +a_switch_notkanj: ;AN057; + cmp al,0DH + jne Store_swt + mov al,0 + stosb ; null at the end + OR BP,fBadSwitch + jmp cperror ; Trailing switch character error + ; BP = fSwitch but no switch + ; bit is set (unknown switch) +Store_swt: + call move_char ; store the character +; +;--------------- +; This upconv call must stay. It is used to identify copy-switches +; on the command line, and won't store anything into the output buffer. + invoke UPCONV +;--------------- +; + PUSH ES + PUSH DI + PUSH CX + PUSH CS + POP ES +ASSUME ES:TRANGROUP + MOV DI,OFFSET TRANGROUP:switch_list + MOV CX,SWCOUNT + OR BP,fBadSwitch + REPNE SCASB + JNZ out_tokenp + AND BP,NOT fBadSwitch + MOV AX,1 + SHL AX,CL + OR BP,AX + +out_tokenp: + POP CX + POP DI + POP ES + +ASSUME ES:NOTHING +out_token: + mov al,0 + stosb ; null at the end + pop di ; restore token buffer pointer + popf + clc ; clear carry flag + return + +move_char: + stosb ; store char in token buffer + inc cx ; increment char count + inc [ELCNT] ; increment element count for * substi + return + +TRANCODE ENDS + END diff --git a/v4.0/src/CMD/COMMAND/ENVDATA.ASM b/v4.0/src/CMD/COMMAND/ENVDATA.ASM new file mode 100644 index 0000000..ed4cd9e --- /dev/null +++ b/v4.0/src/CMD/COMMAND/ENVDATA.ASM @@ -0,0 +1,28 @@ +; SCCSID = @(#)envdata.asm 1.1 85/05/14 +; SCCSID = @(#)envdata.asm 1.1 85/05/14 +; This file is included by command.asm and is used as the default command +; environment. + +ENVARENA SEGMENT PUBLIC PARA + ORG 0 + DB 10h DUP (?) ;Pad for memory allocation addr mark +ENVARENA ENDS + +ENVIRONMENT SEGMENT PUBLIC PARA ; Default COMMAND environment + + PUBLIC ECOMSPEC,ENVIREND,PATHSTRING + + ORG 0 +PATHSTRING DB "PATH=" +USERPATH LABEL BYTE + + DB 0 ; Null path + DB "COMSPEC=" +ECOMSPEC DB "\COMMAND.COM" ;AC062 + DB 134 DUP (0) + +ENVIREND LABEL BYTE + +ENVIRONSIZ EQU $-PATHSTRING +ENVIRONSIZ2 EQU $-ECOMSPEC +ENVIRONMENT ENDS diff --git a/v4.0/src/CMD/COMMAND/FORDATA.ASM b/v4.0/src/CMD/COMMAND/FORDATA.ASM new file mode 100644 index 0000000..b46ba3d --- /dev/null +++ b/v4.0/src/CMD/COMMAND/FORDATA.ASM @@ -0,0 +1,19 @@ +; SCCSID = @(#)fordata.asm 1.1 85/05/14 +; SCCSID = @(#)fordata.asm 1.1 85/05/14 +; Data structure definitions included by tfor.asm + +for_info STRUC + for_args DB (SIZE arg_unit) DUP (?) ; argv[] structure + FOR_COM_START DB (?) ; beginning of + FOR_EXPAND DW (?) ; * or ? item in ? + FOR_MINARG DW (?) ; beginning of + FOR_MAXARG DW (?) ; end of + forbuf DW 64 DUP (?) ; temporary buffer + fordma DW 64 DUP (?) ; FindFirst/Next buffer + FOR_VAR DB (?) ; loop control variable +for_info ENDS + +; empty segment done for bogus addressing +for_segment segment +f LABEL BYTE +for_segment ends diff --git a/v4.0/src/CMD/COMMAND/IFEQU.ASM b/v4.0/src/CMD/COMMAND/IFEQU.ASM new file mode 100644 index 0000000..9c0ee29 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/IFEQU.ASM @@ -0,0 +1,18 @@ +; SCCSID = @(#)ifequ.asm 1.1 85/05/14 +; SCCSID = @(#)ifequ.asm 1.1 85/05/14 +;************************************* +; COMMAND EQUs which are switch dependant + +IF1 + IF IBM + %OUT DBCS Enabled IBM version + ELSE + %OUT Normal version + ENDIF + +;; IF KANJI 3/3/KK +;; %OUT Kanji version 3/3/KK +;; ENDIF 3/3/KK + +ENDIF + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/INIT.ASM b/v4.0/src/CMD/COMMAND/INIT.ASM new file mode 100644 index 0000000..3ac84b6 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/INIT.ASM @@ -0,0 +1,1685 @@ + page 80,132 +; SCCSID = @(#)init.asm 4.13 85/11/03 +; SCCSID = @(#)init.asm 4.13 85/11/03 +TITLE COMMAND Initialization + + INCLUDE comsw.asm + +.xlist +.xcref + INCLUDE DOSSYM.INC + include doscntry.inc ;AC000; + INCLUDE comseg.asm + INCLUDE comequ.asm + include resmsg.equ ;AN000; +.list +.cref + + +ENVIRONSIZ EQU 0A0H ;Must agree with values in EVIRONMENT segment +ENVIRONSIZ2 EQU 092H + +ENVBIG EQU 32768 +ENVSML EQU 160 +KOREA_COUNTRY_CODE EQU 82 + +CODERES SEGMENT PUBLIC BYTE ;AC000; + EXTRN CONTC:NEAR + EXTRN DskErr:NEAR + EXTRN endinit:near + EXTRN INT_2E:NEAR + EXTRN LODCOM:NEAR + EXTRN RSTACK:WORD +CODERES ENDS + +DATARES SEGMENT PUBLIC BYTE ;AC000; + EXTRN abort_char:byte ;AN000; + EXTRN append_state:word ;AN042; + EXTRN BADFAT_OP_SEG:WORD ;AN000; + EXTRN BATCH:WORD + EXTRN COM_FCB1:DWORD + EXTRN COM_FCB2:DWORD + EXTRN COM_PTR:DWORD + EXTRN com_xlat_addr:word + EXTRN COMDRV:BYTE + EXTRN COMPRMT1_SEG:WORD ;AN000; + EXTRN COMPRMT1_SEG2:WORD ;AN000; + EXTRN COMSPEC:BYTE + EXTRN comspec_print:word + EXTRN comspec_end:word + EXTRN cpdrv:byte + EXTRN crit_msg_off:word ;AN000; + EXTRN crit_msg_seg:word ;AN000; + EXTRN critical_msg_start:byte ;AN000; + EXTRN DATARESEND:BYTE ;AC000; + EXTRN dbcs_vector_addr:word ;AN000; + EXTRN DEVE_OP_SEG:WORD ;AN000; + EXTRN DEVE_OP_SEG2:WORD ;AN000; + EXTRN disp_class:byte ;AN000; + EXTRN DRVNUM_OP_SEG:WORD ;AN000; + EXTRN DRVNUM_OP_SEG2:WORD ;AN000; + EXTRN EchoFlag:BYTE + EXTRN ENVIRSEG:WORD + EXTRN ERR15_OP_SEG:WORD ;AN000; + EXTRN ERR15_OP_SEG2:WORD ;AN000; + EXTRN ERR15_OP_SEG3:WORD ;AN000; + EXTRN extended_msg_start:byte ;AN000; + EXTRN extmsgend:byte ;AN000; + EXTRN fFail:BYTE + EXTRN fucase_addr:word ;AN000; + EXTRN InitFlag:BYTE + EXTRN IO_SAVE:WORD + EXTRN LTPA:WORD ;AC000; + EXTRN MEMSIZ:WORD + EXTRN MYSEG:WORD ;AC000; + EXTRN MYSEG1:WORD + EXTRN MYSEG2:WORD + EXTRN nest:word + EXTRN number_subst:byte ;AN000; + EXTRN OldTerm:DWORD + EXTRN PARENT:WORD +;AD060; EXTRN pars_msg_off:word ;AN000; +;AD060; EXTRN pars_msg_seg:word ;AN000; + EXTRN parse_msg_start:byte ;AN000; + EXTRN parsemes_ptr:word ;AN000; + EXTRN PERMCOM:BYTE + EXTRN RES_TPA:WORD + EXTRN resmsgend:word ;AN000; + EXTRN RSWITCHAR:BYTE + EXTRN SINGLECOM:WORD + EXTRN SUM:WORD + EXTRN TRNSEG:WORD + EXTRN TrnMvFlg:BYTE +DATARES ENDS + +BATARENA SEGMENT PUBLIC PARA ;AC000; +BATARENA ENDS + +BATSEG SEGMENT PUBLIC PARA ;AC000; +BATSEG ENDS + +ENVARENA SEGMENT PUBLIC PARA ;AC000; +ENVARENA ENDS + +ENVIRONMENT SEGMENT PUBLIC PARA ; Default COMMAND environment + EXTRN ECOMSPEC:BYTE + EXTRN ENVIREND:BYTE + EXTRN PATHSTRING:BYTE +ENVIRONMENT ENDS + +TAIL SEGMENT PUBLIC PARA + EXTRN TRANSTART:WORD +TAIL ENDS + +TRANCODE SEGMENT PUBLIC BYTE ;AC000; + EXTRN DATINIT:FAR + EXTRN printf_init:far +TRANCODE ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN TRANSPACEEND:BYTE +TRANSPACE ENDS + +; This is the area used for the autoexec.bat file. BATARENA is a pad for the +; the address mark placed by DOS. + +BATARENA SEGMENT PUBLIC PARA + + ORG 0 + DB 10h DUP (?) ;Pad for memory allocation addr mark + +BATARENA ENDS + +BATSEG SEGMENT PUBLIC PARA ;Autoexec.bat segment + + ORG 0 + initbat batchsegment <> ;batch segment + DB 31 DUP (0) ;reserve area for batch file name & pad + +BATSEG ENDS + +; ******************************************************************* +; START OF INIT PORTION +; This code is overlayed the first time the TPA is used. + +INIT SEGMENT PUBLIC PARA + + EXTRN AUTOBAT:byte + EXTRN BADCSPFL:byte + EXTRN bslash:byte + EXTRN CHUCKENV:byte + EXTRN command_c_syn:byte ;AN000; + EXTRN command_d_syn:byte ;AN000; + EXTRN command_e_syn:byte ;AN000; + EXTRN command_f_syn:byte ;AN000; + EXTRN command_m_syn:byte ;AN000; + EXTRN command_p_syn:byte ;AN000; + EXTRN comnd1_syn:word ;AN000; + EXTRN comnd1_addr:dword ;AN000; + EXTRN COMSPECT:byte + EXTRN comspstring:byte + EXTRN dswitch:byte ;AN018; + EXTRN ECOMLOC:word + EXTRN EnvMax:WORD + EXTRN EnvSiz:WORD + EXTRN equalsign:byte + EXTRN eswitch:byte ;AN018; + EXTRN ext_msg:byte ;AN000; + EXTRN fslash:byte + EXTRN INITADD:dword + EXTRN initend:word + EXTRN init_parse:dword ;AN054; + EXTRN INTERNAT_INFO:BYTE ;AN000; 3/3/KK + EXTRN KAUTOBAT:byte ;AN000; 3/3/KK + EXTRN lcasea:byte + EXTRN lcasez:byte + EXTRN num_positionals:word ;AN000; + EXTRN oldenv:word + EXTRN old_parse_ptr:word ;AN057; + EXTRN parse_command:byte ;AN000; + EXTRN pars_msg_off:word ;AN060; + EXTRN pars_msg_seg:word ;AN060; + EXTRN PRDATTM:byte + EXTRN resetenv:word ;AC000; + EXTRN scswitch:byte + EXTRN space:byte + EXTRN triage_add:dword ;AC000; + EXTRN trnsize:word + EXTRN ucasea:byte + EXTRN usedenv:word + + +;AD054; EXTRN SYSPARSE:NEAR + + PUBLIC CONPROC + PUBLIC init_contc_specialcase + +ASSUME CS:RESGROUP,DS:RESGROUP,ES:RESGROUP,SS:RESGROUP + + ORG 0 +ZERO = $ + + +CONPROC: + MOV SP,OFFSET RESGROUP:RSTACK ; MUST be first instruction + + CALL SYSLOADMSG ;AN000; check dos version + JNC OKDOS ;AN000; if no problem - continue + + mov ax,badver ;AN000; set DOS version + invoke sysdispmsg ;AN000; must be incorrect version + mov ax,es + cmp es:[PDB_Parent_PID],AX ; If command is its own parent, +here: ; loop forever. + Jz here + int 20h ; Otherwise, exit. + +; +; Turn APPEND off during initialization processing +; +okdos: + mov ax,AppendInstall ;AN042; see if append installed + int 2fh ;AN042; + cmp al,0 ;AN042; append installed? + je set_msg_addr ;AN042; no - continue + mov ax,AppendDOS ;AN042; see if append DOS version right + int 2fh ;AN042; + cmp ax,-1 ;AN042; append version correct? + jne set_msg_addr ;AN042; no - continue + mov ax,AppendGetState ;AN042; Get the state of Append + int 2fh ;AN042; + mov append_state,bx ;AN042; save append state + xor bx,bx ;AN042; clear out state + mov ax,AppendSetState ;AN042; Set the state of Append + int 2fh ;AN042; set everything off + +set_msg_addr: +; +; Get addresses of old critical and parse errors and save so they can +; be reset if COMMAND needs to exit +; + + push es ;AN000; SAVE ES DESTROYED BY INT 2FH +;AD060; mov ah,multdos ;AN000; set up to call DOS through int 2fh +;AD060; mov al,message_2f ;AN000; call for message retriever + mov ax,(multdos shl 8 or message_2f);AN060; set up to call DOS through int 2fh + mov dl,get_parse_msg ;AN000; get parse message address + int 2fh ;AN000; + mov cs:pars_msg_seg,es ;AN000; save returned segment + mov cs:pars_msg_off,di ;AN000; save returned offset + +;AD060; mov ah,multdos ;AN000; set up to call DOS through int 2fh +;AD060; mov al,message_2f ;AN000; call for message retriever + mov ax,(multdos shl 8 or message_2f);AN060; set up to call DOS through int 2fh + mov dl,get_critical_msg ;AN000; get critical error message address + int 2fh ;AN000; + mov cs:crit_msg_seg,es ;AN000; save returned segment + mov cs:crit_msg_off,di ;AN000; save returned offset + pop es ;AN000; RESTORE ES DESTROYED BY INT 2FH + +; +; Set addresses of critical and parse errors in this level of COMMAND +; + +;AD060; mov ah,multdos ;AN000; set up to call DOS through int 2fh +;AD060; mov al,message_2f ;AN000; call for message retriever +;AD060; mov dl,set_parse_msg ;AN000; set up parse message address + mov di,offset resgroup:parse_msg_start ;AN000; start address +;AD060; int 2fh ;AN000; + call set_parse_2f ;AN060; set parse error address + + +;AD060; mov ah,multdos ;AN000; set up to call DOS through int 2fh +;AD060; mov al,message_2f ;AN000; call for message retriever + mov ax,(multdos shl 8 or message_2f);AN060; set up to call DOS through int 2fh + mov dl,set_critical_msg ;AN000; set up critical error message address + mov di,offset resgroup:critical_msg_start ;AN000; start address + int 2fh ;AN000; + + mov di,offset resgroup:dataresend+15 ;AN000; get address of resident end + mov [resmsgend],di ;AN000; save it + call sysloadmsg ;AN000; load message addresses + call get_msg_ptr ;AN000; set up pointers to some translated chars + mov ah,GetExtCntry ;g get extended country information + mov al,2 ;g minor function - ucase table + mov dx,-1 ;g + mov bx,-1 ;g + mov cx,5 ;g number of bytes we want + mov di,offset resgroup:com_xlat_addr ;g buffer to put address in + int int_command ;g + + mov ah,GetExtCntry ;AN000; get extended country info + mov al,4 ;AN000; get file ucase table + mov dx,-1 ;AN000; + mov bx,-1 ;AN000; + mov cx,5 ;AN000; number of bytes we want + mov di,offset resgroup:fucase_addr ;AN000; buffer for address + int int_command ;AN000; + + mov dx,offset resgroup:transtart+15 ;eg get end of init code + mov cl,4 ;eg change to paragraphs + shr dx,cl ;eg + mov ax,cs ;eg get current segment + add ax,dx ;eg calculate segment of end of init + mov [initend],ax ;eg save this + + push ds ;AN000; + mov ax, (ECS_call SHL 8) OR GetLeadBTbl ;AN000; get dbcs vector + int int_command ;AN000; + mov bx,ds ;AN000; get segment to bx + pop ds ;AN000; + mov dbcs_vector_addr,si ;AN000; save address of + mov dbcs_vector_addr+2,bx ;AN000; dbcs vector + + + mov ax,word ptr ds:[PDB_Parent_PID] ; Init PARENT so we can exit + mov [PARENT],ax ; correctly. + MOV AX,WORD PTR DS:[PDB_Exit] + MOV WORD PTR OldTerm,AX + MOV AX,WORD PTR DS:[PDB_Exit+2] + MOV WORD PTR OldTerm+2,AX + + MOV AX,OFFSET RESGROUP:ENVIREND + 15 + MOV CL,4 ; ax = size of resident part of + SHR AX,CL ; command in paragraphs. Add + MOV CX,CS ; this to CS and you get the + ADD AX,CX ; segment of the TPA. + + MOV [RES_TPA], AX ; Temporarily save the TPA segment + AND AX, 0F000H + ADD AX, 01000H ; Round up to next 64K boundary + JNC TPASET ; Memory wrap if carry set + MOV AX, [RES_TPA] +TPASET: + MOV [LTPA],AX ; Good enough for the moment + MOV AX,WORD PTR DS:[PDB_block_len] ; ax = # of paras given to command + + MOV [MYSEG1],DS ; These 3 variables are used as part of + MOV [MYSEG2],DS ; 3 long ptrs that the transient will + MOV [MYSEG],DS ; use to call resident routines. + MOV [MEMSIZ],AX ; Needed for execing other programs +; +; Compute maximum size of environment +; + MOV EnvMax,(Environsiz + 15) / 16 + (EnvMaximum-zero + 15)/16 - 1 +; +; Compute minimum size of environment +; + + MOV EnvSiz, ENVSML / 16 + + MOV DX,OFFSET TRANGROUP:TRANSPACEEND + 15 ; dx = size of transient + MOV CL,4 ; in paragraphs. + SHR DX,CL + mov [trnsize],dx ;eg save size of transient in paragraphs + + SUB AX,DX ; max seg addr - # para's needed for transient + MOV [TRNSEG],AX ; = seg addr to load the transient at. + MOV AX,DS:[PDB_environ] ; ax = environment segment + OR AX,AX ; If there is no environment segment, + JZ BUILDENV ; go compute one. + INC BYTE PTR [CHUCKENV] ; Flag no new ENVIRONSEG to set up + JMP SHORT ENVIRONPASSED ; Otherwise one was passed to us. + +BUILDENV: ; (this label isn't very accurate) + MOV AX,OFFSET RESGROUP:PATHSTRING ; Compute the segment of the + MOV CL,4 ; environment and put it in + SHR AX,CL ; ax. + MOV DX,DS + ADD AX,DX + +ENVIRONPASSED: + MOV [ENVIRSEG],AX ; Save the environment's segment and + MOV ES,AX ; load into es. +ASSUME ES:ENVIRONMENT + +GOTTHEENVIR: + MOV AX,CHAR_OPER SHL 8 ; Get the switch character and store it + INT int_command ; in RSWITCHAR. + MOV [RSWITCHAR],DL + + CMP DL,fslash ; If backslashes are being used as the + JNZ IUSESLASH ; path separator, change the forward + mov al,bslash ; slash in COMSPECT and ECOMSPEC (if + MOV [COMSPECT],al ; there is a new ENVIRONSEG) to + CMP BYTE PTR [CHUCKENV],0 ; backslash. + JNZ IUSESLASH + MOV ES:[ECOMSPEC],al ;eg + +IUSESLASH: +; +; Initialize the command drive +; + MOV AH,Get_Default_Drive + INT 21h + INC AL + MOV ComDrv,AL + + MOV AL,BYTE PTR DS:[FCB] ; al = default drive number for command + OR AL,AL + JZ NoComDrv ; no drive specified + + MOV AH,':' + MOV [COMDRV],AL + ADD AL,40H ; Convert number to uppercase character + + STD + CMP BYTE PTR [CHUCKENV],0 ; If a new environment is being built, + JNZ NOTWIDENV ; move the default comspec string in it + PUSH DS ; 2 bytes to make room for a drivespec. + PUSH ES ; The drivespec is in ax and is copied + POP DS ; on to the front of the string. + MOV DI,OFFSET ENVIRONMENT:ECOMSPEC + ENVIRONSIZ2 - 1 ;eg + MOV SI,OFFSET ENVIRONMENT:ECOMSPEC + ENVIRONSIZ2 - 3 ;eg + + MOV CX,ENVIRONSIZ2 - 2 + REP MOVSB + POP DS + MOV WORD PTR ES:[ECOMSPEC],AX + +NOTWIDENV: + CLD ; Add the drivespec to the string + MOV WORD PTR [AUTOBAT],AX ; used to reference autoexec.bat + MOV WORD PTR [KAUTOBAT],AX ;AN000; used to reference kautoexe.bat 3/3/KK + +NOCOMDRV: + INVOKE SETVECT ; Set interrupt vectors 22h, 23h, & 24h + +;********************************* +; PARSING STARTS HERE +;********************************* + + push cs ;AN000; get local segment + push cs ;AN000; into DS,ES + pop ds ;AN000; + pop es ;AN000; + +ASSUME DS:RESGROUP,ES:RESGROUP ;AN000; + + MOV SI,80H ;AC000; get command line + LODSB ;AC000; get length of line + MOV DI,SI ;AN000; get line position in DI + XOR AH,AH ;AC000; ax = length of command line +; +; Insure that the command line correctly ends with a CR +; + ADD DI,AX ;AC000; go to end of command line + MOV BYTE PTR [DI],0Dh ;AC000; insert a carriage return + xor cx,cx ;AC000; clear cx + mov num_positionals,cx ;AC000; initialize positionals +; +; Scan the command line looking for the parameters +; + +parse_command_line: + mov di,offset resgroup:parse_command;AN000; Get address of parse_command + mov cx,num_positionals ;AN000; Get number of positionals + xor dx,dx ;AN000; clear dx + mov old_parse_ptr,si ;AN057; save position before calling parser + call init_parse ;AN054; call parser + mov num_positionals,cx ;AN000; Save number of positionals + cmp ax,end_of_line ;AC000; are we at end of line? + jz ArgsDoneJ3 ;AC000; yes - exit + cmp ax,result_no_error ;AN000; did an error occur + jz parse_cont ;AN000; no - continue + +; +; Before issuing error message - make sure switch is not /C +; + +parse_line_error: + push si ;AN057; save line position + push ax ;AN057; save error number + cmp ax,BadSwt_Ptr ;AN057; Was error invalid switch? + jnz parse_line_error_disp ;AN057; No - just issue message + mov di,si ;AN057; Get terminating pointer in DI + mov si,old_parse_ptr ;AN057; Get starting pointer in SI + +init_chk_delim: + cmp si,di ;AN057; at end of parsed parameter? + jz parse_line_error_disp ;AN057; Yes - just display message + lodsb ;AN057; + cmp al,space ;AN057; Skip blank spaces + jz init_chk_delim ;AN057; + cmp al,tab_chr ;AN057; Skip tab characters + jz init_chk_delim ;AN057; + + cmp al,[rswitchar] ;AN057; Switch? + jnz parse_line_error_disp ;AN057; No - just issue message + lodsb ;AN057; Get the char after the switch + invoke itestkanj ;AN057; Is it DBCS? + jnz parse_line_error_disp ;AN057; Yes - can't be /C + invoke iupconv ;AN057; upper case it + cmp al,scswitch ;AN057; it is /C? + jnz parse_line_error_disp ;AN057; + pop dx ;AN057; even up stack + pop dx ;AN057; even up stack + jmp setSSwitch ;AN057; Yes - go set COMMAND /C + +parse_line_error_disp: + pop ax ;AN057; restore error number + pop si ;AN057; restore line position + mov disp_class,parse_msg_class ;AN000; set up parse error msg class + mov dx,ax ;AN000; get message number + call print_message ;AN000; issue error message + jmp short parse_command_line ;AN000; continue parsing + +parse_cont: +; +; See if a switch was entered +; + + cmp comnd1_syn,offset resgroup:command_f_syn ;AC000; was /F entered? + jz SetFSwitch ;AC000; yes go set fail switch + cmp comnd1_syn,offset resgroup:command_p_syn ;AC000; was /P entered? + Jz SetPSwitch ;AC000; yes go set up PERMCOM + cmp comnd1_syn,offset resgroup:command_d_syn ;AC000; was /D entered? + jz SetDSwitch ;AC000; yes go set date switch + cmp comnd1_syn,offset resgroup:command_c_syn ;AC000; was /C entered? + jz SetSSwitch ;AC000; yes go set up SINGLECOM + cmp comnd1_syn,offset resgroup:command_e_syn ;AC000; was /E entered? + jz SetESwitch ;AC000; yes go set up environment + cmp comnd1_syn,offset resgroup:command_m_syn ;AN000; was /MSG entered? + jz SetMSwitchjmp ;AN000; yes go set up message flag + jmp chkotherargs ;AC000; Must be something else + +SetMSwitchjmp: ;AN018; long jump needed + jmp SetMswitch ;AN018; + +ArgsdoneJ3: ;AN018; long jump needed + jmp ArgsDone ;AN018; + +SetFSwitch: + cmp fFail,-1 ;AN018; has fail switch been set? + jnz failok ;AN018; no - set it + mov ax,moreargs_ptr ;AN018; set up too many arguments + jmp parse_line_error ;AN018; go issue error message + +failok: + MOV fFail,-1 ;AC000; fail all INT 24s. + JMP parse_command_line ;AC000; + +SetPSwitch: +; +; We have a permanent COMMAND switch /P. Flag this and stash the +; termination address. +; + cmp [permcom],0 ;AN018; has /p switch been set? + jz permcomok ;AN018; no - set it + mov ax,moreargs_ptr ;AN018; set up too many arguments + jmp parse_line_error ;AN018; go issue error message + +permcomok: + INC [PERMCOM] + MOV WORD PTR [oldTerm],OFFSET RESGROUP:LODCOM + MOV WORD PTR [oldTerm+2],DS +; +; Make sure that we display the date and time. If the flag was not +; initialized, set it to indicate yes, do prompt. +; + CMP BYTE PTR [PRDATTM],-1 + JNZ parse_command_line_jmp ;AC018; keep parsing + MOV BYTE PTR [PRDATTM],0 ; If not set explicit, set to prompt + +Parse_command_line_jmp: ;AN018; + JMP parse_command_line ;AC000; keep parsing + +ArgsDoneJump: + JMP ArgsDone + +SetDSwitch: +; +; Flag no date/time prompting. +; + cmp dswitch,0 ;AN018; has /D switch been set? + jz setdateok ;AN018; no - set it + mov ax,moreargs_ptr ;AN018; set up too many arguments + jmp parse_line_error ;AN018; go issue error message + +setdateok: + inc dswitch ;AN018; indicate /D entered + MOV BYTE PTR [PRDATTM],1 ; User explicitly says no date time + JMP parse_command_line ;AC000; continue parsing + +SetSSwitch: +; +; Set up pointer to command line, flag no date/time and turn off singlecom. +; + MOV [SINGLECOM],SI ; Point to the rest of the command line + MOV [PERMCOM],0 ; A SINGLECOM must not be a PERMCOM + MOV BYTE PTR [PRDATTM],1 ; No date or time either, explicit + JMP ArgsDone +; +; Look for environment-size setting switch +; +; The environment size is represented in decimal bytes and is +; converted into pargraphs (rounded up to the next paragraph). +; + +SetESwitch: + cmp eswitch,0 ;AN018; has fail switch been set? + jz eswitchok ;AN018; no - set it + mov ax,moreargs_ptr ;AN018; set up too many arguments + jmp parse_line_error ;AN018; go issue error message + +eswitchok: + inc eswitch ;AN018; indicate /E entered + mov di,offset resgroup:comnd1_addr ;AN000; get number returned + mov bx,word ptr [di] ;AN000; into bx + + ADD BX, 0FH ; Round up to next paragraph + mov cl,4 ;AC000; convert to pargraphs + SHR BX, cl ;AC000; by right 4 + + MOV EnvSiz,BX ; EnvSiz is in paragraphs + JMP parse_command_line ;AC000; continue parsing command line + +SetMSwitch: + cmp ext_msg,set_extended_msg ;AN018; has /MSG switch been set? + jnz setMswitchok ;AN018; no - set it + mov ax,moreargs_ptr ;AN018; set up too many arguments + jmp parse_line_error ;AN018; go issue error message +setMswitchok: + MOV Ext_msg,set_extended_msg ;AN000; set /MSG switch + JMP parse_command_line ;AN000; keep parsing + +ARGSDONEJ: + JMP ARGSDONE + +; +; We have a non-switch character here. +; +CHKOTHERARGS: + push ds ;AN054; + push si ;AC000; save place in command line + lds si,comnd1_addr ;AN000; get address of filespec + assume ds:nothing ;AN054; + + mov dx,si ;AN000; put in dx also + MOV AX,(OPEN SHL 8) OR 2 ; Read and write + INT int_command + JC CHKSRCHSPEC ; Wasn't a file + MOV BX,AX + MOV AX,IOCTL SHL 8 + INT int_command + TEST DL,80H + JNZ ISADEVICE + +BADSETCON: ;AN022; + MOV AH,CLOSE ; Close initial handle, wasn't a device + INT int_command + JMP CHKSRCHSPEC + +ISADEVICE: + XOR DH,DH + OR DL,3 ; Make sure has CON attributes + MOV AX,(IOCTL SHL 8) OR 1 + INT int_command + JC BADSETCON ;AN022; Can't set attributes - quit + MOV DX,BX ; Save new handle +;eg POP BX ; Throw away saved SI +;eg POP BX ; Throw away saved CX + PUSH CX + MOV CX,3 + XOR BX,BX + +RCCLLOOP: ; Close 0,1 and 2 + MOV AH,CLOSE + INT int_command + INC BX + LOOP RCCLLOOP + MOV BX,DX ; New device handle + MOV AH,XDUP + INT int_command ; Dup to 0 + MOV AH,XDUP + INT int_command ; Dup to 1 + MOV AH,XDUP + INT int_command ; Dup to 2 + MOV AH,CLOSE + INT int_command ; Close initial handle + POP CX + pop si ;AN000; restore position of command line + pop ds ;AN054; + JMP parse_command_line ;AC000; continue parsing + +CHKSRCHSPEC: ; Not a device, so must be directory spec + + MOV BYTE PTR [CHUCKENV],0 ; If search specified -- no inheritance + MOV AX,OFFSET RESGROUP:PATHSTRING ; Figure environment pointer + MOV CL,4 + SHR AX,CL +;AD054; MOV DX,DS + MOV DX,CS ;AC054; + ADD AX,DX + MOV [ENVIRSEG],AX + + MOV ES,AX + push si ;AN000; remember location of file + xor cx,cx ;AN000; clear cx for counting + +countloop: + lodsb ;AN000; get a character + inc cx ;AN000; increment counter + cmp al,end_of_line_out ;AN000; are we at end of line? + jnz countloop ;AN000; no - keep counting + + mov al,space + dec si ;AN000; move back one + MOV BYTE PTR [SI],al ;AN000; put a space at end of line + pop si ;AC000; get location back + + MOV DI,[ECOMLOC] + +COMTRLOOP: + LODSB + DEC CX + CMP AL,space + JZ SETCOMSR + STOSB + +;;; IF KANJI 3/3/KK + XOR AH,AH +;;; ENDIF 3/3/KK + + JCXZ SETCOMSR + +;;;; IF KANJI 3/3/KK + PUSH DS ;AN054; Make sure we have + PUSH CS ;AN054; local DS for + POP DS ;AN054; ITESTKANJ + INVOKE ITESTKANJ + POP DS ;AN054; restore PARSER DS + JZ COMTRLOOP + DEC CX + MOVSB + INC AH + JCXZ SETCOMSR +;;;; ENDIF 3/3/KK + + JMP SHORT COMTRLOOP + +SETCOMSR: + PUSH CX + + PUSH CS ;AN054; Get local segment + POP DS ;AN054; + assume ds:resgroup ;AN054; + + PUSH DS + MOV SI,OFFSET RESGROUP:COMSPECT + MOV CX,14 + + MOV AL,ES:[DI-1] + +;;;; IF KANJI 3/3/KK + OR AH,AH + JNZ INOTROOT ; Last char was KANJI second byte, might be '\' +;;;; ENDIF 3/3/KK + + CALL PATHCHRCMPR + JNZ INOTROOT + INC SI ; Don't make a double / + DEC CX + +INOTROOT: + REP MOVSB + + MOV DX,[ECOMLOC] ; Now lets make sure its good! + PUSH ES + POP DS + + MOV AX,OPEN SHL 8 + INT int_command ; Open COMMAND.COM + POP DS + JC SETCOMSRBAD ; No COMMAND.COM here + MOV BX,AX ; Handle + MOV AH,CLOSE + INT int_command ; Close COMMAND.COM + +SETCOMSRRET: + POP CX + POP SI + POP DS ;AN054; + assume ds:resgroup ;AN054; + +ARGSDONEJ2: + PUSH CS ;AN000; Make sure local ES is + POP ES ;AN000; restored + JMP parse_command_line ;AC000; continue parsing command line + +SETCOMSRBAD: + MOV DX,BADCOMLKMES_ptr ;AC000; get message number + invoke triageError + cmp ax, 65 + jnz doprt + mov dx,BADCOMACCMES_ptr ;AC000; get error message number +doprt: + call print_message + MOV SI,OFFSET RESGROUP:COMSPECT + MOV DI,[ECOMLOC] + MOV CX,14 + REP MOVSB ; Get my default back + + JMP SHORT SETCOMSRRET + +;********************************* +; PARSING ENDS HERE +;********************************* + +ARGSDONE: + mov es,[envirseg] ;AC000; get environment back + ASSUME ES:ENVIRONMENT ;AN000; +;AD060; cmp ext_msg,set_extended_msg ;AN000; was /msg specified? +;AD060; jnz check_permcom ;AN000; No, go check permcom +;AD060; cmp [permcom],0 ;AN000; Yes - was permcom set? +;AD060; jz permcom_error ;AN000; No - error cannot have /MSG without /P + +;AD060; mov ah,multdos ;AN000; set up to call DOS through int 2fh +;AD060; mov al,message_2f ;AN000; call for message retriever +;AD060; mov dl,set_extended_msg ;AN000; set up extended error message address +;AD060; push es ;AN016; save environment segment +;AD060; push cs ;AN016; get local segment to ES +;AD060; pop es ;AN016; +;AD060; mov di,offset resgroup:extended_msg_start ;AN000; start address +;AD060; int 2fh ;AN000; +;AD060; pop es ;AN016; restore environment segment +;AD060; mov di,offset resgroup:extmsgend+15 ;AN000; get address of resident end +;AD060; mov [resmsgend],di ;AN000; save it +;AD060; call sysloadmsg ;AN000; load message addresses +;AD060; jmp short process_permcom ;AN000; now go process /P switch + +;AD060;permcom_error: +;AD060; mov disp_class,parse_msg_class ;AN000; set up parse error msg class +;AD060; mov dx,LessArgs_Ptr ;AN000; get message number for "Required parameter missing" +;AD060; call print_message ;AN000; issue error message +;AD060; jmp short comreturns ;AN000; we already know /P wasn't entered + +;AD060;check_permcom: + CMP [PERMCOM],0 + JZ COMRETURNS + +;AD060;process_permcom: + PUSH ES ; Save environment pointer + MOV AH,SET_CURRENT_PDB + MOV BX,DS + MOV ES,BX + INT int_command ; Current process is me + MOV DI,PDB_Exit ; Diddle the addresses in my header + MOV AX,OFFSET RESGROUP:LODCOM + STOSW + MOV AX,DS + STOSW + MOV AX,OFFSET RESGROUP:CONTC + STOSW + MOV AX,DS + STOSW + MOV AX,OFFSET RESGROUP:DskErr + STOSW + MOV AX,DS + STOSW + MOV WORD PTR DS:[PDB_Parent_PID],DS ; Parent is me forever + + MOV DX,OFFSET RESGROUP:INT_2E + MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 02EH + INT int_command ;Set magic interrupt + POP ES ;Remember environment + +COMRETURNS: + MOV AX,WORD PTR DS:[PDB_Parent_PID] + MOV [PARENT],AX ; Save parent + MOV WORD PTR DS:[PDB_Parent_PID],DS ; Parent is me + MOV AX,WORD PTR DS:[PDB_JFN_Table] + MOV [IO_SAVE],AX ; Get the default stdin and out + MOV WORD PTR [COM_PTR+2],DS ; Set all these to resident + MOV WORD PTR [COM_FCB1+2],DS + MOV WORD PTR [COM_FCB2+2],DS + MOV DI,OFFSET RESGROUP:COMSPEC + + MOV SI,[ECOMLOC] + CMP BYTE PTR [CHUCKENV],0 + + MOV AX,DS ; XCHG ES,DS + PUSH ES + POP DS + MOV ES,AX + + JZ COPYCOMSP ; All set up for copy + + PUSH CS + POP DS + + MOV SI,OFFSET RESGROUP:COMSPSTRING + PUSH ES + PUSH DI + CALL IFINDE + MOV SI,DI + PUSH ES + POP DS + POP DI + POP ES + JNC COPYCOMSP + +COMSPECNOFND: + MOV SI,CS:[ECOMLOC] ;AC062 + ADD SI,OFFSET RESGROUP:PATHSTRING + PUSH CS + POP DS + +assume es:resgroup +COPYCOMSP: + mov es:comspec_print,di ; Save ptr to beginning of comspec path + cmp byte ptr [si+1],':' ; Is there a drive specifier in comspec + jnz COPYCOMSPLOOP ; If not, do not skip over first 2 bytes + add es:comspec_print,2 + +COPYCOMSPLOOP: + LODSB + STOSB + OR AL,AL + JNZ COPYCOMSPLOOP + mov es:comspec_end,di ; Save ptr to end of comspec path + dec es:comspec_end + mov ah,es:comdrv + add ah,'A'-1 + mov es:cpdrv,ah ; Load drive letter in comprmt2 +assume es:environment + + call setup_for_messages ;AN060; set up parse and extended error messages + PUSH CS + POP DS + MOV BX,[RESMSGEND] ;AC000; get end of resident + MOV CL,4 + SHR BX,CL +Public EnvMaximum +EnvMaximum: +; +; NOTE: The transient has to loaded directly after shrinking to the +; resident size. +; There is an assumption made when loading the transient that it +; still intact after the resident portion. +; If any other ALLOC/DEALLOC/SETBLOCK operations are performed +; inbetween, then there is a real good chance that the non-resident +; portion will be overwritten by arena information. +; + MOV AH,SETBLOCK + INT int_command ; Shrink me to the resident only +; +; Load in the transient and compute the checksum. We may do this in one of +; two ways: First, cheat and use the transient loading code that exists in +; the resident piece. This may be OK except that it will hit the disk. +; +; But we do not need to hit the disk! The transient is already loaded but is +; in the wrong place. We need to block transfer it up to the correct spot. +; +GOTENVIR: + MOV TrnMvFlg, 1 ; Indicate that transient has been moved + PUSH ES + MOV SI,OFFSET RESGroup:TranStart + MOV DI,0 + mov ES,Trnseg + MOV CX,OFFSET TRANGROUP:TRANSPACEEND +; +; We need to ensure that we do not have the potential of overwriting our +; existing code in this move +; It is OK to move if (SI+CX+Segment of Transient < TrnSeg). +; + push cx + mov ax,cx ; Get size of transient in bytes + add ax,si ; Calculate end of transient section + mov cl,4 + shr ax,cl ; Convert to paragraphs + inc ax ; Round up (for partial paragraph) + mov cx,ds + add ax,cx ; Add in current segment + cmp ax,Trnseg ; See if there is overlap + pop cx +; If we are too close to be safe, call LOADCOM instead of moving the code. + jb Ok_To_Move + invoke LOADCOM + jmp short Trans_Loaded +Ok_To_Move: +; +; Everything is set for an upward move. WRONG! We must move downward. +; + ADD SI,CX + DEC SI + ADD DI,CX + DEC DI + STD + REP MOVSB + CLD + +Trans_Loaded: + POP ES + + INVOKE CHKSUM ; Compute the checksum + MOV [SUM],DX ; Save it + + CMP BYTE PTR [PRDATTM],0 ;eg + JNZ NOBATCHSEG ;eg Don't do AUTOEXEC or date time +; +; Allocate batch segment for D:/autoexec.bat + no arguments +; + MOV BX,((SIZE BatchSegment) + 15 + 1 + 0Fh)/16 ;eg + MOV AH,ALLOC ;eg + INT int_command ;eg + JC NOBATCHSEG ;eg didn't allocate - pretend no batch + MOV BATCH,AX ;eg save batch segment + +NOBATCHSEG: + MOV BX, 0FFFFH ; Get size of largest block for env + MOV AH, ALLOC + INT int_command + +; Only allocate maximum 64K worth of environment + + SUB BX,TRNSIZE ;eg subtract # of transient paragraphs + SUB BX,128 ;eg make sure we have 2K left + MOV EnvMax, BX + CMP BX, 4096 ; 64K = 4096 paragraphs + JB MAXOK + MOV BX, 4096-1 + MOV EnvMax, BX +MAXOK: + + MOV AH, ALLOC ; Get max size + INT int_command + + mov bx,[envirseg] ;g get old environment segment + mov oldenv,bx ;g save it + mov usedenv,0 ;g initialize env size counter + MOV DS,bx + ASSUME DS:NOTHING + MOV [ENVIRSEG],AX + MOV ES,AX + XOR SI,SI + MOV DI,SI + MOV BX,EnvMax ; Copy over as much of the environment + ; as possible + SHL BX,1 + SHL BX,1 + SHL BX,1 + SHL BX,1 + MOV EnvMax, BX ; Convert EnvMax to bytes + DEC BX ; Dec by one to leave room for double 0 + XOR DX,DX ; Use DX to indicate that there was + ; no environment size error. +Public Nxtstr +Nxtstr: + CALL GetStrLen ; Get the size of the current env string + push ds ;g get addressability to environment + push cs ;g counter + pop ds ;g + ASSUME DS:RESGROUP + add usedenv,cx ;g add the string length to env size + pop ds ;g + ASSUME DS:NOTHING + CMP CX,1 ; End of environment was encountered. + JZ EnvExit + SUB BX,CX + JAE OKCpyStr ; Can't fit in all of enviroment. + INC DX ; Out of env space msg must be displayed + JMP EnvExit +OKCpyStr: + JMP Nxtstr +EnvExit: + + PUSH CS + POP DS + ASSUME DS:RESGroup + OR DX,DX ; DX will be non-zero if error + JZ EnvNoErr + MOV DX,OUTENVERR_ptr ;AC000; get message number + call print_message + +EnvNoErr: + ; BX now has the left over size of the maximum environment + ; We want to shrink the environment down to the minimum size + ; Set the environment size to max(Envsiz,Env used) + + MOV CX, EnvMax + SUB CX, BX ; CX now has the environment used + ADD CX, 16 ; Round up to next paragraph + SHR CX, 1 + SHR CX, 1 + SHR CX, 1 + SHR CX, 1 + CMP CX, Envsiz ; Is environment used > Envsiz + JB EnvSet + MOV Envsiz, CX +EnvSet: + MOV BX, Envsiz ; Set environment to size needed + mov ax,es ;eg get environment segment + add ax,bx ;eg add number of environment paragraphs + cmp ax,initend ;eg does this go past end of init? + ja envsetok ;eg yes - do the setblock + mov ax,es ;eg no - get back the environment segment + mov bx,initend ;eg get the segment at end of init + sub bx,ax ;eg setblock envir segment to end of init code + mov resetenv,1 ;eg set flag so we know to set envir later + +envsetok: + MOV AH, SETBLOCK + INT int_command + + IF MSVER + CMP [SINGLECOM],0 + JNZ NOPHEAD ; Don't print header if SINGLECOM + MOV DX,HEADER_ptr ;AC000; get message number + call print_message +NOPHEAD: + ENDIF + + CMP [BATCH],0 ;eg did we set up a batch segment? + JNZ dodate ;eg yes - go initialize it + JMP NODTTM ; Don't do AUTOEXEC or date time +; +; Allocate batch segment for D:/autoexec.bat + no arguments +; +dodate: + MOV AX,BATCH ;eg get batch segment + MOV EchoFlag,3 ; set batch echo + MOV NEST,1 ; g set nest flag to 1 batch + MOV ES,AX +; +; Initialize the segment +; + XOR DI,DI + MOV AL,BatchType + STOSB + MOV AL,1 ; G initialize echo for batch exit + STOSB ; G + XOR AX,AX ; initialize to zero + STOSW ; G batch segment of last job - batlast + STOSW ; G segment for FOR + STOSB ; G FOR flag + STOSW ; position in file - batseek + STOSW +; +; Clean out the parameters +; + MOV AX,-1 ; initialize to no parameters + MOV CX,10 + REP STOSW +; +; Decide whether we should grab the default drive +; + CMP BYTE PTR [AUTOBAT],0 + + JNZ NOAUTSET + MOV AH,GET_DEFAULT_DRIVE + INT int_command + ADD AL,ucasea + + MOV [AUTOBAT],AL + MOV [KAUTOBAT],AL ;AN000; 3/3/KK + +NOAUTSET: +; +; Copy in the batch file name (including NUL) +; + MOV SI,OFFSET RESGROUP:AUTOBAT + MOV CX,8 + REP MOVSW + MOVSB ;AN027; move in carraige return to terminate string + + MOV DX,OFFSET RESGROUP:AUTOBAT + MOV AX,OPEN SHL 8 + INT int_command ; See if AUTOEXEC.BAT exists + JC NOABAT + MOV BX,AX + MOV AH,CLOSE + INT int_command + JMP DRV0 ;AC000; go process autoexec + +NOABAT: + push ax + call setup_seg + mov word ptr [triage_add+2],ax + pop ax + call triage_add + cmp ax, 65 + jz AccDenErr ;AN000; was network access denied + + +; If AUTOEXEC.BAT is not found, then check for KAUTOEXE.BAT. Changed +; by Ellen to check only when in Korea. The country information +; returned will overlay the old parse data area, but we don't care +; since we won't need the parse information or country information. +; We only care about the country code returned in BX. + + MOV DX,OFFSET RESGROUP:INTERNAT_INFO ;AN000; Set up internat vars + MOV AX,INTERNATIONAL SHL 8 ;AN000; get country dependent info + INT 21H ;AN000; + JC NOKABAT ;AN000; Error - don't bother with it + CMP BX,KOREA_COUNTRY_CODE ;AN000; Are we speaking Korean? + JNZ OPENERR ;AN000; No, don't check for KAUTOEXE + + MOV DI, OFFSET BatFile ;AN000; 3/3/KK + MOV SI,OFFSET RESGROUP:KAUTOBAT ;AN000; Another trial to do 3/3/KK + MOV CX,8 ;AN000; auto execution for the 3/3/KK + REP MOVSW ;AN000; non-English country 3/3/KK + MOVSB ;AN027; move in carraige return to terminate string + MOV DX,OFFSET RESGROUP:KAUTOBAT ;AN000; 3/3/KK + MOV AX,OPEN SHL 8 ;AN000; 3/3/KK + INT int_command ;AN000; See if KAUTOEXE.BAT exists 3/3/KK + JC NOKABAT ;AN000; 3/3/KK + MOV BX,AX ;AN000; 3/3/KK + MOV AH,CLOSE ;AN000; 3/3/KK + INT int_command ;AN000; 3/3/KK + JMP SHORT DRV0 ;AN000; 3/3/KK + +NOKABAT: ;AN000; 3/3/KK + call triage_add ;AN000; get extended error + cmp ax, 65 ;AN000; network access denied? + jnz openerr ;AN000; no - go deallocate batch + +AccDenErr: ;AN000; yes - put out message + mov DX,ACCDEN ;AC000; get message number + call print_message + +openerr: + MOV ES,[BATCH] ; Not found--turn off batch job + MOV AH,DEALLOC + INT int_command + MOV [BATCH],0 ; AFTER DEALLOC in case of ^C + MOV EchoFlag,1 + mov nest,0 ;g indicate no batch in progress + +DODTTM: + MOV AX,OFFSET TRANGROUP:DATINIT + MOV WORD PTR[INITADD],AX + MOV AX,[TRNSEG] + MOV WORD PTR[INITADD+2],AX + CALL DWORD PTR [INITADD] + +NODTTM: + + IF IBMVER + CMP [SINGLECOM],0 + JNZ DRV0 ; Don't print header if SINGLECOM + MOV DX,HEADER_ptr ;AC000; get message number + call print_message + ENDIF + +DRV0: ; Reset APPEND state + push ds ;AN042; save data segment + push cs ;AN042; Get local segment into DS + pop ds ;AN042; + mov ax,AppendSetState ;AN042; Set the state of Append + mov bx,Append_state ;AN042; back to the original state + int 2fh ;AN042; + pop ds ;AN042; get data segment back + JMP ENDINIT ;G Finish initializing + +; +; Get length of string pointed to by DS:SI. Length includes NULL. +; Length is returned in CX +; +GetStrLen: + xor cx,cx +NxtChar: + lodsb + inc cx + or al,al + jnz NxtChar + ret +; +; If the transient has been loaded in TranSeg, then we need to use that +; segment for calls to routines in the transient area. Otherwise, the current +; code segment is used +; Segment returned in AX. +; +setup_seg: + mov ax,[trnseg] + cmp TrnMvFlg, 1 ; Has transient portion been moved + jz setup_end + push bx + mov bx,cs + mov ax,OFFSET RESGroup:TranStart + shr ax,1 + shr ax,1 + shr ax,1 + shr ax,1 + add ax,bx + pop bx +setup_end: + ret + +print_message: + push ax + PUSH DS ;AN000; save data and extra segment + PUSH ES ;AN000; registers + MOV AX,CS ;AN000; get local segment + MOV ES,AX ;AN000; set ES and DS to point to it + MOV DS,AX ;AN000; +;AD054; PUSH BX ;AC000; save BX register +;AD054; PUSH CX ;AC000; save CX register +;AD054; PUSH DX ;AC000; save DX register +;AD054; MOV AX,DX ;AC000; get message number +;AD054; MOV DH,DISP_CLASS ;AC000; get display class +;AD054; MOV DL,NO_CONT_FLAG ;AN000; set control flags off +;AD054; MOV BX,NO_HANDLE_OUT ;AC000; set message handler to use function 1-12 +;AD054; XOR CH,CH ;AC000; clear upper part of cx +;AD054; MOV CL,NUMBER_SUBST ;AC000; set number of substitutions +;AD054; invoke SYSDISPMSG ;AC000; display the message +;AD054; MOV DISP_CLASS,UTIL_MSG_CLASS ;AC000; reset display class +;AD054; MOV NUMBER_SUBST,NO_SUBST ;AC000; reset number of substitutions +;AD054; POP DX ;AC000; restore registers +;AD054; POP CX ;AC000; +;AD054; POP BX ;AC000; + invoke rprint ;AC054; + + POP ES ;AN000; + POP DS ;AN000; + pop ax + ret + +PATHCHRCMPR: + push dx + mov dl,fslash + CMP [RSWITCHAR],dl + JZ RNOSLASHT + CMP AL,dl + JZ RET41 +RNOSLASHT: + CMP AL,bslash +RET41: + pop dx + RET + + +IFINDE: + CALL IFIND ; FIND THE NAME + JC IFIND2 ; CARRY MEANS NOT FOUND + JMP ISCASB1 ; SCAN FOR = SIGN +; +; On return of FIND1, ES:DI points to beginning of name +; +IFIND: + CLD + CALL ICOUNT0 ; CX = LENGTH OF NAME + MOV ES,[ENVIRSEG] + XOR DI,DI + +IFIND1: + PUSH CX + PUSH SI + PUSH DI + +IFIND11: + LODSB + +;;;; IF KANJI 3/3/KK + INVOKE ITESTKANJ + JZ NOTKANJ4 + DEC SI + LODSW + INC DI + INC DI + CMP AX,ES:[DI-2] + JNZ IFIND12 + DEC CX + LOOP IFIND11 + JMP SHORT IFIND12 + +NOTKANJ4: +;;;; ENDIF 3/3/KK + + CALL IUPCONV + INC DI + CMP AL,ES:[DI-1] + JNZ IFIND12 + LOOP IFIND11 + +IFIND12: + POP DI + POP SI + POP CX + JZ IFIND2 + PUSH CX + CALL ISCASB2 ; SCAN FOR A NUL + POP CX + CMP BYTE PTR ES:[DI],0 + JNZ IFIND1 + STC ; INDICATE NOT FOUND + +IFIND2: + RET + +ICOUNT0: + PUSH DS + POP ES + MOV DI,SI + + PUSH DI ; COUNT NUMBER OF CHARS UNTIL "=" + CALL ISCASB1 + JMP SHORT ICOUNTX + PUSH DI ; COUNT NUMBER OF CHARS UNTIL NUL + CALL ISCASB2 + +ICOUNTX: + POP CX + SUB DI,CX + XCHG DI,CX + RET + +ISCASB1: + MOV AL,equalsign ; SCAN FOR AN = + JMP SHORT ISCASBX + +ISCASB2: + XOR AL,AL ; SCAN FOR A NUL + +ISCASBX: + MOV CX,100H + REPNZ SCASB + RET + + +; **************************************************************** +; * +; * ROUTINE: IUPCONV (ADDED BY EMG 4.00) +; * +; * FUNCTION: This routine returns the upper case equivalent of +; * the character in AL from the file upper case table +; * in DOS if character if above ascii 128, else +; * subtracts 20H if between "a" and "z". +; * +; * INPUT: DS set to resident +; * AL char to be upper cased +; * FUCASE_ADDR set to the file upper case table +; * +; * OUTPUT: AL upper cased character +; * +; **************************************************************** + +assume ds:resgroup ;AN000; + +iupconv proc near ;AN000; + + cmp al,80h ;AN000; see if char is > ascii 128 + jb other_fucase ;AN000; no - upper case math + sub al,80h ;AN000; only upper 128 chars in table + push ds ;AN000; + push bx ;AN000; + lds bx,dword ptr fucase_addr+1 ;AN000; get table address + add bx,2 ;AN000; skip over first word + xlat ds:byte ptr [bx] ;AN000; convert to upper case + pop bx ;AN000; + pop ds ;AN000; + jmp short iupconv_end ;AN000; we finished - exit + +other_fucase: ;AN000; + cmp al,lcasea ;AC000; if between "a" and "z", + jb iupconv_end ;AC000; subtract 20h to get + cmp al,lcasez ;AC000; upper case equivalent. + ja iupconv_end ;AC000; + sub al,20h ;AC000; Change lower-case to upper + +iupconv_end: ;AN000; + ret + +iupconv endp ;AN000; + +init_contc_specialcase: + ; This routine is called if control-C + add sp,6 ; is type during the date/time prompt + push si ; at initialization time. The desired + mov si,dx ; response is to make it look like the + mov word ptr [si+1],0d00h ; user typed by "popping" the + pop si ; INT 21h stuff off the stack, putting + iret ; a in the user's buffer, and + ; returning directly to the user. + ; In this case the user is TCODE. + +; **************************************************************** +; * +; * ROUTINE: GET_MSG_PTR +; * +; * FUNCTION: Fill in translatable char table starting at +; * at Abort_char with translated characters. +; Set segments of resident messages. +; * +; * INPUT: none +; * +; * OUTPUT: none +; * +; **************************************************************** + +CHAR_START EQU 201 ;AN000; first character translate is 1 +CHAR_END EQU 207 ;AN000; last is 6 + +GET_MSG_PTR PROC NEAR ;AN000; + + MOV AX,CHAR_START ;AN000; get first char translation + MOV BX,OFFSET RESGROUP:ABORT_CHAR ;AN000; get first char offset +MOVEMES: ;AN000; + MOV DH,-1 ;AN000; utility message + INVOKE SYSGETMSG ;AN000; get the offset of the char + MOV CL,BYTE PTR [SI] ;AN000; get the character in CL + MOV BYTE PTR [BX],CL ;AN000; put the character in the table + INC BX ;AN000; point to next position in table + INC AX ;AN000; increment message number + CMP AX,CHAR_END ;AN000; are we at the end? + JNZ MOVEMES ;AN000; no - keep loading + + MOV AX,DS ;AN000; get data segment + MOV DRVNUM_OP_SEG,AX ;AN000; set up segments for + MOV DRVNUM_OP_SEG2,AX ;AN000; message substitutions + MOV DEVE_OP_SEG,AX ;AN000; used in the resident + MOV DEVE_OP_SEG2,AX ;AN000; portion of command + MOV ERR15_OP_SEG,AX ;AN000; during initialization + MOV ERR15_OP_SEG2,AX ;AN000; to save resident + MOV ERR15_OP_SEG3,AX ;AN000; space. + MOV BADFAT_OP_SEG,AX ;AN000; + MOV COMPRMT1_SEG,AX ;AN000; + MOV COMPRMT1_SEG2,AX ;AN000; + + RET ;AN000; + +GET_MSG_PTR ENDP ;AN000; + + +; **************************************************************** +; * +; * ROUTINE: Setup_for_messages +; * +; * FUNCTION: Sets up system for PARSE and EXTENDED ERROR +; * messages as follows: +; * +; * IF /P and /MSG are entered +; * keep PARSE and EXTENDED ERRORS in memory +; * ELSE IF /P is entered +; * use PARSE and EXTENDED ERRORS on disk +; * remove PARSE ERRORS from memory +; * ELSE +; * remove PARSE ERRORS from memory +; * ENDIF +; * +; * INPUT: PERMCOM Set up with user input +; * EXT_MSG Set up with user input +; * System set up to retain PARSE ERRORS +; * +; * OUTPUT: registers unchanged +; * +; **************************************************************** + + +setup_for_messages proc near ;AN060; + + push ds ;AN060; save data segment + push es ;AN060; save environment segment + push ax ;AN060; + push dx ;AN060; + push di ;AN060; + mov ax,cs ;AN060; get local segment to ES and DS + mov ds,ax ;AN060; + mov es,ax ;AN060; + + cmp [permcom],0 ;AN060; was permcom set? + jz no_permcom ;AN060; No - don't worry about messages + cmp ext_msg,set_extended_msg ;AN060; was /msg specified? + jz permcom_slash_msg ;AN060; Yes - go process it + push es ;AN060; + mov ax,1 ;AN060; Set ES to 1 as a flag to the message + mov es,ax ;AN060; services that messages are on disk + mov di,offset resgroup:extended_msg_start-100h ;AN060; start address + call set_ext_2f ;AN060; set extended error address + mov di,offset resgroup:parse_msg_start-0100h ;AN060; start address + call set_parse_2f ;AN060; set parse error address + pop es ;AN060; + IF2 ;AN060;; + IFNDEF READ_DISK_INFO ;AN060;; + Extrn READ_DISK_PROC:Far ;AN060;; + ENDIF ;AN060;; + ENDIF ;AN060;; + MOV AX,DOS_GET_EXT_PARSE_ADD ;AN060;; 2FH Interface + MOV DL,DOS_SET_ADDR ;AN060;; Set the READ_DISK_PROC address + LEA DI,READ_DISK_PROC ;AN060;; + INT 2FH ;AN060;; Private interface + jmp short permcom_end ;AN060; and exit + +permcom_slash_msg: ;AN060; Keep messages in memory + mov di,offset resgroup:extended_msg_start ;AN060; start address + call set_ext_2f ;AN060; set the extended message address + mov di,offset resgroup:extmsgend+15 ;AN060; get address of resident end + mov [resmsgend],di ;AN060; save it + jmp short permcom_end ;AN060; exit + +no_permcom: ;AN060; + cmp ext_msg,set_extended_msg ;AN060; was /msg specified? + jnz no_slash_msg ;AN060; no - no error + mov disp_class,parse_msg_class ;AN060; set up parse error msg class + mov dx,LessArgs_Ptr ;AN060; get message number for "Required parameter missing" + call print_message ;AN060; issue error message + +no_slash_msg: + mov ax,(multdos shl 8 or message_2f);AN060; reset parse message pointers + mov dl,set_parse_msg ;AN060; set up parse message address + mov di,pars_msg_off ;AN060; old offset of parse messages + mov es,pars_msg_seg ;AN060; old segment of parse messages + int 2fh ;AN060; go set it + +permcom_end: + call sysloadmsg ;AN060; load message addresses + pop di ;AN060; + pop dx ;AN060; + pop ax ;AN060; + pop es ;AN060; get environment back + pop ds ;AN060; + + ret ;AN060; + +setup_for_messages endp ;AN060; + +; **************************************************************** +; * +; * ROUTINE: Set_parse_2f +; * +; * FUNCTION: Does the INT 2Fh to DOS to set the PARSE +; * message address that will later be retrieved +; * by the message services. +; * +; * INPUT: ES set to segment of messages +; * DI points to offset of messages +; * +; * OUTPUT: none +; * +; **************************************************************** + +Set_parse_2f proc near ;AN060; + + mov ax,(multdos shl 8 or message_2f);AN060; set up to call DOS through int 2fh + mov dl,set_parse_msg ;AN060; set up parse message address + int 2fh ;AN060; + + ret ;AN060; + +Set_parse_2f endp ;AN060; + +; **************************************************************** +; * +; * ROUTINE: Set_ext_2f +; * +; * FUNCTION: Does the INT 2Fh to DOS to set the EXTENDED +; * message address that will later be retrieved +; * by the message services. +; * +; * INPUT: ES set to segment of messages +; * DI points to offset of messages +; * +; * OUTPUT: none +; * +; **************************************************************** + +Set_ext_2f proc near ;AN060; + + mov ax,(multdos shl 8 or message_2f);AN060; set up to call DOS through int 2fh + mov dl,set_extended_msg ;AN060; set up extended error message address + int 2fh ;AN060; + + ret ;AN060; + +Set_ext_2f endp ;AN060; + + +ASSUME DS:RESGROUP, ES:RESGROUP + +.xlist +.xcref + +INCLUDE SYSMSG.INC ;AN000; include message services + +.list +.cref + +MSG_UTILNAME ;AN000; define utility name + +MSG_SERVICES ;AC026; include message services macro + +include msgdcl.inc + +INIT ENDS + + END diff --git a/v4.0/src/CMD/COMMAND/IPARSE.ASM b/v4.0/src/CMD/COMMAND/IPARSE.ASM new file mode 100644 index 0000000..5205fe9 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/IPARSE.ASM @@ -0,0 +1,38 @@ + page 80,132 +; SCCSID = @(#)iparse.asm 4.1 87/04/28 +; SCCSID = @(#)iparse.asm 4.1 87/04/28 +TITLE COMMAND interface to SYSPARSE + +.xlist +.xcref + INCLUDE comseg.asm ;AN000; +.list +.cref + + +INIT SEGMENT PUBLIC PARA ;AN000; + +ASSUME CS:RESGROUP,DS:RESGROUP,ES:NOTHING,SS:NOTHING ;AN000; + + +;AD054; public SYSPARSE ;AN000; + + DateSW equ 0 ;AN000; do not Check date format + TimeSW equ 0 ;AN000; do not Check time format + CmpxSW equ 0 ;AN000; do not check complex list + KeySW equ 0 ;AN025; do not support keywords + Val2SW equ 0 ;AN025; do not Support value definition 2 + Val3SW equ 0 ;AN000; do not Support value definition 3 + QusSW equ 0 ;AN025; do not include quoted string + DrvSW equ 0 ;AN025; do not include drive only + +.xlist +.xcref +;AD054; INCLUDE parse.asm ;AN000; +.list +.cref + + +INIT ends ;AN000; + end ;AN000; + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/MAKEFILE b/v4.0/src/CMD/COMMAND/MAKEFILE new file mode 100644 index 0000000..707fb00 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/MAKEFILE @@ -0,0 +1,134 @@ +#************************** makefile for cmd\append *************************** + +msg =..\..\messages +dos =..\..\dos +inc =..\..\inc +hinc =..\..\h + +# +####################### dependencies begin here. ######################### +# + +all: command.com + +$(inc)\dossym.inc: $(inc)\dosmac.inc $(inc)\bpb.inc \ + $(inc)\buffer.inc $(inc)\sysvar.inc $(inc)\vector.inc \ + $(inc)\mult.inc $(inc)\dirent.inc $(inc)\dpb.inc $(inc)\curdir.inc \ + $(inc)\cpmfcb.inc $(inc)\find.inc $(inc)\pdb.inc $(inc)\exe.inc \ + $(inc)\sf.inc $(inc)\arena.inc $(inc)\intnat.inc $(inc)\mi.inc \ + $(inc)\filemode.inc $(inc)\error.inc $(inc)\syscall.inc + echo "touch $(inc)\dossym.inc" + +command.ctl: command.skl $(msg)\$(COUNTRY).msg makefile + +command1.obj: command1.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc comsw.asm comequ.asm resmsg.equ \ + envdata.asm + +command2.obj: command2.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc comsw.asm comequ.asm resmsg.equ \ + envdata.asm + +copy.obj: copy.asm comsw.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc comseg.asm comequ.asm + +copypr1.obj: copypr1.asm comsw.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc comseg.asm comequ.asm + +copypr2.obj: copypr2.asm comsw.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc comseg.asm comequ.asm + +cparse.obj: cparse.asm comsw.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc comseg.asm comequ.asm + +init.obj: init.asm $(inc)\dossym.inc $(inc)\devsym.inc \ + comsw.asm comseg.asm comequ.asm resmsg.equ $(inc)\sysmsg.inc \ + $(inc)\msgserv.asm command.ctl + +iparse.obj: iparse.asm comseg.asm $(inc)\parse.asm $(inc)\psdata.inc + +parse2.obj: parse2.asm $(inc)\dossym.inc $(inc)\devsym.inc comsw.asm \ + comseg.asm comequ.asm + +path1.obj: path1.asm $(inc)\dossym.inc $(inc)\devsym.inc comsw.asm \ + comseg.asm comequ.asm + +path2.obj: path2.asm $(inc)\dossym.inc $(inc)\devsym.inc comsw.asm \ + comseg.asm comequ.asm + +rdata.obj: rdata.asm comsw.asm comseg.asm $(inc)\sysmsg.inc \ + $(inc)\msgserv.asm command.cla command.cl3 command.cl4 \ + command.cld command.clc command.cle command.ctl + +rucode.obj: rucode.asm $(inc)\dossym.inc $(inc)\devsym.inc \ + $(inc)\doscntry.inc resmsg.equ $(inc)\sysmsg.inc \ + $(inc)\msgserv.asm comsw.asm comseg.asm comequ.asm command.ctl + +tbatch.obj: tbatch.asm comsw.asm $(inc)\dossym.inc $(inc)\doscntry.inc \ + $(inc)\devsym.inc comseg.asm comequ.asm ifequ.asm + +tbatch2.obj: tbatch2.asm comsw.asm $(inc)\dossym.inc $(inc)\doscntry.inc \ + $(inc)\devsym.inc comseg.asm comequ.asm ifequ.asm + +tcmd1a.obj: tcmd1a.asm comsw.asm $(inc)\dossym.inc $(inc)\ioctl.inc \ + $(inc)\devsym.inc comseg.asm comequ.asm ifequ.asm + +tcmd1b.obj: tcmd1b.asm comsw.asm $(inc)\dossym.inc $(inc)\ioctl.inc \ + $(inc)\devsym.inc comseg.asm comequ.asm ifequ.asm $(inc)\ea.inc + +tcmd2a.obj: tcmd2a.asm comsw.asm $(inc)\dossym.inc $(inc)\ioctl.inc \ + $(inc)\devsym.inc comseg.asm comequ.asm ifequ.asm + +tcmd2b.obj: tcmd2b.asm comsw.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc comseg.asm comequ.asm ifequ.asm + +tcode.obj: tcode.asm comsw.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc comseg.asm comequ.asm ifequ.asm \ + $(inc)\mshalo.asm + +tdata.obj: tdata.asm comsw.asm comseg.asm $(inc)\curdir.inc \ + $(inc)\error.inc ifequ.asm comequ.asm $(inc)\sysmsg.inc \ + $(inc)\msgserv.asm tranmsg.asm command.clf command.cl1 command.cl2 \ + command.ctl $(inc)\ea.inc + +tenv.obj: tenv.asm comsw.asm $(inc)\dossym.inc $(inc)\devsym.inc \ + comseg.asm comequ.asm ifequ.asm $(inc)\doscntry.inc + +tenv2.obj: tenv2.asm comsw.asm $(inc)\dossym.inc $(inc)\devsym.inc \ + comseg.asm comequ.asm ifequ.asm + +tfor.obj: tfor.asm comsw.asm $(inc)\dossym.inc $(inc)\devsym.inc \ + comseg.asm comequ.asm ifequ.asm fordata.asm + +tmisc1.obj: tmisc1.asm comsw.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc comseg.asm comequ.asm ifequ.asm + +tmisc2.obj: tmisc2.asm comsw.asm $(inc)\dossym.inc $(inc)\ioctl.inc \ + $(inc)\devsym.inc comseg.asm comequ.asm ifequ.asm + +tparse.obj: tparse.asm comseg.asm $(inc)\parse.asm $(inc)\psdata.inc + +tpipe.obj: tpipe.asm comsw.asm $(inc)\dossym.inc \ + $(inc)\devsym.inc comseg.asm comequ.asm ifequ.asm + +tprintf.obj: tprintf.asm comsw.asm $(inc)\dosmac.inc \ + comseg.asm comequ.asm $(inc)\sysmsg.inc $(inc)\msgserv.asm \ + command.ctl + +tspc.obj: tspc.asm comsw.asm $(inc)\dossym.inc comequ.asm \ + ifequ.asm comseg.asm $(inc)\ea.inc + +tucode.obj: tucode.asm $(inc)\dosmac.inc $(inc)\dossym.inc \ + comsw.asm comseg.asm comequ.asm ifequ.asm + +uinit.obj: uinit.asm comsw.asm comseg.asm ifequ.asm command.clb \ + $(inc)\sysmsg.inc $(inc)\msgserv.asm command.ctl + +command.com: command1.obj command2.obj rucode.obj rdata.obj init.obj iparse.obj \ + uinit.obj tcode.obj tbatch.obj tbatch2.obj tfor.obj tcmd1a.obj tcmd1b.obj \ + tcmd2a.obj tcmd2b.obj tenv.obj tenv2.obj tmisc1.obj tmisc2.obj tpipe.obj \ + parse2.obj path1.obj path2.obj tucode.obj copy.obj copypr1.obj copypr2.obj \ + cparse.obj tparse.obj tprintf.obj tdata.obj tspc.obj + link @command.lnk + exe2bin command.exe command.com + del command.exe diff --git a/v4.0/src/CMD/COMMAND/PARSE2.ASM b/v4.0/src/CMD/COMMAND/PARSE2.ASM new file mode 100644 index 0000000..2695927 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/PARSE2.ASM @@ -0,0 +1,422 @@ + page 80,132 +; SCCSID = @(#)parse.asm 1.1 85/05/14 +; SCCSID = @(#)parse.asm 1.1 85/05/14 +.sall +.xlist +.xcref + INCLUDE DOSSYM.INC + INCLUDE DEVSYM.INC + include comsw.asm + include comseg.asm + include comequ.asm +.list +.cref + + +break +;---------------------------------------------------------------------------- +; PARSE.ASM contains the routines to perform command line parsing. +; Parse and Path share a buffer and argv[] definitions. +; Invoking maps the unparsed command line in COMBUF into an +; array of pointers to the parsed tokens. The resulting array, argv[], +; also contains extra information provided by cparse about each token +; should be executed prior to +; +; Alan L, OS/MSDOS August 15, 1983 +; +; +; ENTRY: +; : command line in COMTAB. +; EXIT: +; : success flag, argcnt (number of args), argv[]. +; NOTE(S): +; * handily turns an array index into an absolute pointer. +; The computation depends on the size of an argv[] element (arg_ele). +; * calls for chunks of the command line. +; does not function as specified; see for more details. +; * now knows about the flags the internals of COMMAND.COM +; need to know about. This extra information is stored in a switch_flag +; word with each command-line argument; the switches themselves will not +; appear in the resulting arg structure. +; * With the exception of CARRY, flags are generally preserved across calls. +;--------------- +; CONSTANTS: +;--------------- + DEBUGx equ FALSE ; prints out debug info +;--------------- +; DATA: +;--------------- + +DATARES SEGMENT PUBLIC BYTE + EXTRN FORFLAG:BYTE +DATARES ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN combuf:byte + EXTRN cpyflag:byte + EXTRN expand_star:byte + EXTRN RESSEG:word + EXTRN STARTEL:word +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC BYTE ;AC000; + PUBLIC argv_calc ; convert array index into address + PUBLIC parseline + + +assume cs:trangroup, ds:trangroup, es:trangroup, ss:nothing + + +break +;---------------------------------------------------------------------------- +; PARSELINE takes an MSDOS command line and maps it into a UNIX-style +; argv[argvcnt] array. The most important difference between this array and +; the tradition UNIX format is the extra cparse information included with +; each argument element. +;--------------- +; ENTRY: +; (BL special delimiter for cparse -- not implemented) +;--------------- +; EXIT: +; CF set if error +; AL error code (carry set). Note AH clobbered in any event. +; argv[] array of cparse flags and pointers to arguments +; argvcnt argument count +;--------------- +; NOTE(S): +; * BL (special delimiter) is ignored, for now (set to space). +; * Parseflags record contains cparse flags, as follows: +; sw_flag -- was this arg a switch? +; wildcard -- whether or not it contained a * or ? +; path_sep -- maybe it was a pathname +; unused -- for future expansion +; special_delim -- was there an initial special delimiter? +; * argv[] and argvcnt are undefined if CF/AL indicates an error. +; * Relationship between input, cparse output, and comtail can be +; found in the following chart. Despite the claim of the cparse +; documentation that, "Token buffer always starts d: for non switch +; tokens", such is not the case (see column two, row two). +; Similarly, [STARTEL] is not null when the command line is one of +; the forms, "d:", "d:\", or "d:/". In fact, *STARTEL (i.e., what +; STARTEL addresses) will be null. This is clearly just a +; documentation error. +; * cparse also returns a switch code in BP for each switch it +; recognizes on the command line. +; * arglen for each token does NOT include the terminating null. +; * Finally, note that interesting constructions like 'foodir/*.exe' +; parse as three separate tokens, and the asterisk is NOT a wildcard. +; For example, 'for %i in (foodir/*.exe) do echo %i' will first +; echo 'foodir', then '*', then '.exe'. Using cparse for command- +; line parsing may result in slightly different behavior than +; previously observed with the old COMMAND.COM command-line parser. +; +; Input Cparse Command Line (80H) +; \alan\foo.bat c:\alan\foo.bat \alan\foo.bat +; alan\foo.bat alan\foo.bat alan\foo.bat +; foo.bat foo.bat foo.bat +; c:\alan\foo.bat c:\alan\foo.bat c:\alan\foo.bat +; c:alan\foo.bat c:alan\foo.bat c:alan\foo.bat +; c:foo.bat c:foo.bat c:foo.bat +;--------------- +; CONSTANTS: +;--------------- +;--------------- +; DATA: +;--------------- + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN arg:byte + EXTRN argbufptr:word + EXTRN comptr:word + EXTRN last_arg:word + EXTRN tpbuf:byte +TRANSPACE ENDS + +;--------------- +parseline: +;--------------- + + push AX ; most of these are clobbered + push BX ; by cparse... + push CX + push DX + push DI + push SI + pushf + mov cpyflag,0 ; Turn "CPARSE called from COPY flag" off + + mov [LAST_ARG], -1 ; last argument at which to accumulate + xor ax,ax + mov cx,SIZE arg_unit + mov di,offset trangroup:arg + rep stosb + mov argbufptr,offset trangroup:arg.argbuf + mov arg.argswinfo, 0 ; switch information, and info to date + mov arg.argvcnt, 0 ; initialize argvcnt/argv[] + mov SI, OFFSET TRANGROUP:combuf+2 ; prescan leaves cooked input in combuf + +; This next section of code (up to pcont:) makes sure that si is set up for +; parsing. It should point at COMBUF if FORFLAG is set and arg.argforcombuf +; otherwise. This is done so that commands can get arg pointers into their +; original command line (or an exact copy of it) in arg_ocomptr. +; Arg.argforcombuf is used so that the for loop processor will always be able +; to get a hold of its original command line; even after COMBUF is blasted by +; the command to be repeated or the transient part of command has been +; reloaded. + + push ds + mov ds,[RESSEG] + assume ds:resgroup + cmp FORFLAG,0 + pop ds + assume ds:trangroup + jnz pcont + mov di,OFFSET TRANGROUP:arg.argforcombuf + xor ch,ch + mov cl,[COMBUF+1] + inc cl + rep movsb + mov si,OFFSET TRANGROUP:arg.argforcombuf + +pcont: + mov DI, OFFSET TRANGROUP:tpbuf ; destination is temporary token buffer + mov BL, ' ' ; no special delimiter, for now + +parseloop: + mov comptr,si ; save ptr into original command buffer + xor BP, BP ; switch information put here by cparse + mov byte ptr [expand_star],0 ; don't expand *'s to ?'s + invoke scanoff ; skip leading blanks... + invoke cparse ; byte off a token (args in SI, DI, BL) + jnc More_prse + or BP,BP ; Check for trailing switch character + jz parsedone + call newarg ; We hit CR but BP is non-zero. The + ; typical cause of this is that a + ; switch char IMMEDIATELY preceeds + ; the CR. We have an argument, but it + ; is sort of an error. + jmp short parsedone ; We're done (found the CR). + +More_prse: + mov cpyflag,2 ; tell CPARSE that 1st token is done + call newarg ; add to argv array (CX has char count) + jnc parseloop ; was everything OK? + jmp short parse_error ; NO, it wasn't -- bug out (CF set) + +parsedone: ; successful completion of parseline + popf + clc + jmp short parse_exit + +parse_error: ; error entry (er, exit) point + popf + stc +parse_exit: ; depend on not changing CF + pop SI + pop DI + pop DX + pop CX + pop BX + pop AX + ret + +;--------------- +; parseline ends +;---------------------------------------------------------------------------- + + +break +;---------------------------------------------------------------------------- +; NEWARG adds the supplied argstring and cparse data to arg.argv[]. +; ENTRY: +; BH argflags +; CX character count in argstring +; DI pointer to argstring +; comptr ptr to starting loc of current token in original command +; [STARTEL] cparse's answer to where the last element starts +; EXIT: +; argbufptr points to next free section of argbuffer +; arg.argbuf contains null-terminated argument strings +; arg.argvcnt argument count +; arg.argv[] array of flags and pointers +; arg.arg_ocomptr ptr to starting loc of current token in original command +; CF set if error +; AL carry set: error code; otherwise, zero +;--------------- +newarg: +;--------------- + + push BX + push CX + push DX ; one never knows, do one? + push DI + push SI + pushf + call arg_switch ; if it's a switch, record switch info + ; LEAVE SWITCH ON COMMAND LINE!! +;;; jc newarg_done ; previous arg's switches -- and leave + + cmp arg.argvcnt, ARGMAX ; check to ensure we've not + jge too_many_args ; exceeded array limits + mov DH, BH ; save argflags + mov BX, arg.argvcnt ; argv[argvcnt++] = arg data + inc arg.argvcnt + mov AX, OFFSET TRANGROUP:arg.argv + call argv_calc ; convert offset to pointer + mov [BX].argsw_word, 0 ; no switch information, yet... + mov [BX].arglen, CX ; argv[argvcnt].arglen = arg length + mov [BX].argflags, DH ; argv[argvcnt].argflags = cparse flags + mov SI, argbufptr + mov [BX].argpointer, SI ; argv[argvcnt].argpointer = [argbufptr] + add SI, [STARTEL] ; save startel from new location + sub SI, DI ; form pointer into argbuf + mov [BX].argstartel, SI ; argv[argvcnt].argstartel = new [STARTEL] + mov si,[comptr] + mov [BX].arg_ocomptr,si ; arg_ocomptr=ptr into original com line + + mov SI, DI ; now save argstring in argbuffer + mov DI, argbufptr ; load the argbuf pointer and make + add DI, CX ; sure we're not about to run off + cmp DI, OFFSET TRANGROUP:arg.argbuf+ARGBLEN-1 + jge buf_ovflow ; the end of the buffer (plus null byte) + sub DI, CX ; adjust the pointer + cld + rep movsb ; and save the string in argbuffer + mov AL, ANULL ; tack a null byte on the end + stosb + mov argbufptr, DI ; update argbufptr after copy + +newarg_done: + popf + clc + jmp short newarg_exit + +too_many_args: + mov AX, arg_cnt_error + jmp short newarg_error + +buf_ovflow: + mov AX, arg_buf_ovflow + +newarg_error: + popf + stc + +newarg_exit: + pop SI + pop DI + pop DX + pop CX + pop BX + ret + +;--------------- +; NewArg ends +;---------------------------------------------------------------------------- + + +break +;---------------------------------------------------------------------------- +; ARG_SWITCH decides if an argument might really be a switch. In the +; event that it is, and we can recognize +; ENTRY: +; As in . +; EXIT: +; CF -- clear (wasn't a switch); set (was a switch) +; NOTE(S): +; * The mechanism mapping a switch into a bit-value depends entirely +; on the order of definition in the variable and the +; values chosen to define the bits in CMDT:COMEQU.ASM. Change either +; or the definitions in CMDT:COMEQU.ASM -- and rewrite +; this mechanism. This code taken from CMDT:TCODE.ASM. +; * The declared below is redundant to one declared in +; TDATA.ASM, and used in TCODE.ASM. +; * An ugly routine. +;--------------- +; CONSTANTS: +;--------------- +; Constants come from the definitions in CMDT:COMEQU.ASM. +;--------------- +; DATA: +;--------------- + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + extrn switch_list:byte + switch_count EQU $-switch_list +transpace ends + +;--------------- +Arg_Switch: +;--------------- + + push AX + push BX + push CX + push DI + pushf + test BH, MASK sw_flag ; is it a switch? (preserve flag word) + jz arg_no_switch0 + cmp [LAST_ARG], -1 ; have we encountered any REAL args yet? + je arg_no_switch1 ; no, so leading switches don't matter + mov BX, [LAST_ARG] ; yes, add switch info to last REAL arg + mov AX, OFFSET TRANGROUP:arg.argv + call argv_calc + or [BX].argsw_word, BP + or arg.argswinfo, BP + +arg_yes_switch: ; ah, sweet success... + popf + stc + jmp short arg_switch_exit + +arg_no_switch0: + mov AX, arg.argvcnt ; future switches should then affect + mov [LAST_ARG], AX ; this argument + +arg_no_switch1: ; wasn't a switch, or we're pretending + popf + clc + +arg_switch_exit: + pop DI + pop CX + pop BX + pop AX + ret + +;--------------- +; Arg_Switch ends +;---------------------------------------------------------------------------- + + +break +;---------------------------------------------------------------------------- +; ARGV_CALC maps an array index into a byte-offset from the base of +; the supplied array. Method used for computing the address is: +; Array Index * Array Elt Size + Base Addr = Elt Addr +; ENTRY: +; AX -- base of array +; BX -- array index +; EXIT: +; BX -- byte offset +;--------------- + +argv_calc: + push ax ; Save base + mov al,bl ; al = array index + mov bl,SIZE argv_ele ; bl = size of an argv element + mul bl ; ax = base offset + pop bx ; Get base + add ax,bx ; Add in base offset + xchg ax,bx ; Restore ax and put byte offset in bx + ret + +;--------------- +; argv_calc ends +;---------------------------------------------------------------------------- + + + +trancode ends + end diff --git a/v4.0/src/CMD/COMMAND/PATH1.ASM b/v4.0/src/CMD/COMMAND/PATH1.ASM new file mode 100644 index 0000000..4567174 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/PATH1.ASM @@ -0,0 +1,507 @@ + page 80,132 +; SCCSID = @(#)path1.asm 1.1 85/05/14 +; SCCSID = @(#)path1.asm 1.1 85/05/14 +.sall +.xlist +.xcref +INCLUDE DOSSYM.INC + include comsw.asm + include comseg.asm + include comequ.asm +.list +.cref + +break +;---------------------------------------------------------------------------- +; PATH.ASM contains the routines to perform pathname incovation. Path and +; Parse share a temporary buffer and argv[] definitions. , +; given a pathname, attempts to find a corresponding executable or batch +; file on disk. Directories specified in the user's search path will be +; searched for a matching file, if a match is not found in the current +; directory and if the pathname is actually only an MSDOS filename. +; assumes that the parsed command name can be found in +; argv[0] -- in other words, should be executed prior to +; . Alternatively, the command name and appropriate +; information could be placed in argv[0], or could be +; (easily) modified to make no assumptions about where its input is found. +; Please find enclosed yet another important routine, , which +; places the entire arg/argv[]/argbuf structure on a piece of newly +; allocated memory. This is handy for for-loop processing, and anything +; else that wants to save the whole shebang and then process other command +; lines. +; +; Alan L, OS/MSDOS August 15, 1983 +; +; ENTRY: +; : argv[0]. +; : bytes to allocate in addition to arg structure +; EXIT: +; : success flag, best pathname match in EXECPATH. +; : success flag, segment address of new memory +; NOTE(S): +; * handily turns an array index into an absolute pointer. +; The computation depends on the size of an argv[] element (arg_ele). +; * calls for chunks of the command line. +; does not function as specified; see for more details. +; * now knows about the flags the internals of COMMAND.COM +; need to know about. This extra information is stored in a switch_flag +; word with each command-line argument; the switches themselves will not +; appear in the resulting arg structure. +; * With the exception of CARRY, flags are generally preserved across calls. +;--------------- +; CONSTANTS: +;--------------- + DEBUGx equ FALSE ; prints out debug info +;--------------- +; DATA: +;--------------- + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN baddrv_ptr:word +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN arg:byte + EXTRN BADPMES_ptr:word + EXTRN curdrv:byte + EXTRN EXECPATH:byte + EXTRN search_best_buf:byte + EXTRN search_error:word + EXTRN string_ptr_2:word + EXTRN tpbuf:byte +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC BYTE ;AC000; + +assume cs:trangroup, ds:trangroup, es:trangroup, ss:nothing + +break +;------------------------------------------------------------------------------ +; PATH_SEARCH tries to find the file it's given, somewhere. An initial value +; of *argv[0].argstartel == 0 implies that there is no command (empty line +; or 'd:' or 'd:/'). This check is done in strip; otherwise, strip formats +; the filename/pathname into tpbuf. Search(tpbuf) is executed to see if we +; have a match, either in the current working directory if we were handed +; a filename, or in the specified directory, given a pathname. If this call +; fails, and we were given a pathname, then Path_Search fails. Otherwise, +; Path_Crunch is repeatedly invoked on tpbuf[STARTEL] (if there's a drive +; prefix, we want to skip it) for each pathstring in userpath. Success on +; either the first invocation of search or on one of the succeeding calls +; sets up the appropriate information for copying the successful pathname +; prefix (if any) into the result buffer, followed by the successful filename +; match (from [search_best_buf]). The result is returned in in EXECPATH. +; ENTRY: +; argv[0] -- command name and associated information +; EXIT: +; AX -- non-zero indicates type of file found +; EXECPATH -- successful pathname (AX non-zero) +; NOTE(S): +; 1) Uses the temporary buffer, tpbuf, from the parse routines. +; 2) Some files are more equal than others. See search: for rankings. +; 3) Path_Search terminates as soon as a call to search succeeds, even +; if search returns an .exe or .bat. +; 5) Clobbers dma address. + +pbuflen equ 128 ; length of EXECPATH +path_sep_char equ ';' + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN fbuf:byte + EXTRN pathinfo:word + EXTRN psep_char:byte +TRANSPACE ENDS + +Procedure Path_Search,NEAR + + push BX + push CX + push DX ; could use a "stack 'em" instruction + push SI + push DI + push BP + pushf + test DS:arg.argv[0].argflags, (MASK wildcard) + (MASK sw_flag) + jz path_search_ok + +path_failure_jmp: + jmp path_failure ; ambiguous commands not allowed + +path_search_ok: + call store_pchar ; figure out the pathname separator + mov DX, OFFSET TRANGROUP:fbuf ; clobber old dma value with + trap set_dma ; a pointer to our dma buffer + push ES + invoke find_path ; get a handle (ES:DI) on user path + mov DS:pathinfo[0], ES ; and squirrel it away + mov DS:pathinfo[2], DI ; "old" pathstring pointer + mov DS:pathinfo[4], DI ; "new" pathstring pointer + pop ES + + mov BX, pbuflen ; copy/format argv[0] into temp buffer + mov SI, OFFSET TRANGROUP:EXECPATH + invoke strip + jc path_failure_jmp ; if possible, of course + + mov DX, SI ; search(EXECPATH, error_message) + mov [search_error], OFFSET TRANGROUP:BADDRV_ptr + invoke search ; must do at least one search + or AX, AX ; find anything? + jz path_noinit ; failure ... search farther + + mov BP, AX ; success... save filetype code + mov DI, OFFSET TRANGROUP:EXECPATH + mov SI, DS:arg.argv[0].argpointer + mov CX, DS:arg.argv[0].argstartel + sub CX, SI ; compute prefix bytes to copy +; +; We have the number of bytes in the prefix (up to the final component). +; We need to form the complete pathname including leading drive and current +; directory. +; +; Is there a drive letter present? +; + + mov ah,':' + cmp cx,2 ; room for drive letter? + jb AddDrive ; no, stick it in + cmp [si+1],ah ; colon present? + jz MoveDrive ; yes, just move it + +AddDrive: + mov al,curdrv ; get current drive + add al,"A" ; convert to uppercase letter + stosw ; store d: + jmp short CheckPath + +MoveDrive: + lodsw ; move d: + stosw + sub cx,2 ; 2 bytes less to move + +CheckPath: + or al,20h + mov dl,al + sub dl,"a"-1 ; convert to 1-based for current dir +; +; Stick in beginning path char +; + mov al,psep_char + stosb +; +; Is there a leading /? If so, then no current dir copy is necessary. +; Otherwise, get current dir for DL. +; + cmp cx,1 ; is there room for path char? + jb AddPath ; no, go add path + lodsb + dec cx + cmp al,psep_char ; is there a path separator? + jz MovePath ; yes, go move remainder of path + inc cx + dec si ; undo the lodsb + +AddPath: + SaveReg + mov si,di ; remainder of buffer + trap Current_dir +; +; The previous current dir will succeed a previous find_first already worked. +; +; Find end of string. +; + mov di,si + RestoreReg + mov al,psep_char + cmp byte ptr [di],0 ; root (empty dir string)? + jz MovePath ; yes, no need for path char + +ScanEnd: + cmp byte ptr [dI],0 ; end of string? + jz FoundEnd + inc di + jmp ScanEnd +; +; Stick in a trailing path char +; +FoundEnd: + stosb +; +; Move remaining part of path. Skip leading path char if present. +; +MovePath: + cmp [si],al ; first char a path char? + jnz CopyPath + inc si ; move past leading char + dec cx ; drop from count + +CopyPath: + jcxz CopyDone ; no chars to move! + rep movsb + +CopyDone: + jmp path_success ; run off and form complete pathname + +path_noinit: + test DS:arg.argv[0].argflags, MASK path_sep + jnz path_failure ; complete pathname specified ==> fail + + mov BH, path_sep_char ; semicolon terminates pathstring + mov DX, DS:arg.argv[0].argstartel ; this is where the last element starts + sub DX, DS:arg.argv[0].argpointer ; form pointer into EXECPATH, + add DX, OFFSET TRANGROUP:EXECPATH ; skipping over drive spec, if any + +path_loop: + call path_crunch ; pcrunch(EXECPATH, pathinfo) + mov BP, AX ; save filetype code + + lahf ; save flags, just in case + or BP, BP ; did path_crunch find anything? + jne path_found + sahf ; see? needed those flags, after all! + jnc path_loop ; is there anything left to the path? + +path_failure: + xor AX, AX +;; jmp short path_exit ; 3/3/KK + jmp path_exit ;AC000; 3/3/KK + +path_found: ; pathinfo[] points to winner + mov DI, OFFSET TRANGROUP:EXECPATH + mov CX, pathinfo[4] ; "new" pointer -- end of string + mov SI, pathinfo[2] ; "old" pointer -- beginning of string + +; +; BAS Nov 20/84 +; Look at the pathname and expand . and .. if they are the first element +; in the pathname (after the drive letter) +; + push ES + push pathinfo[0] + pop ES + cmp Byte Ptr ES:[SI+2],'.' ; Look for Current dir at start of path + jnz path_cpy + + push CX ; Save pointer to end of string + mov AL, ES:[SI] + mov [DI],AL ; Copy drive letter, :, and root char + mov AL, ES:[SI+1] ; to EXECPATH + mov [DI+1],AL + mov AL,psep_char + mov [DI+2],AL + push SI ; Save pointer to begining of string + mov DL,ES:[SI] ; Convert device letter for cur dir + or DL,20h + sub DL,"a"-1 + mov SI,DI ; pointer to EXECPATH + add SI, 3 ; Don't wipe out drive and root info + trap Current_dir + invoke DStrlen ; Determine length of present info + add SI,CX ; Don't copy over drive and root info + dec SI + mov DI,SI ; Point to end of target string + pop SI ; Restore pointer to begining of string + add SI, 3 ; Point past drive letter, :, . + pop CX ; Restore pointer to end of string + +path_cpy: + pop ES + sub CX, SI ; yields character count + push DS ; time to switch segments + push pathinfo[0] ; string lives in this segment + pop DS + cld +;; rep movsb 3/3/KK ; copy the prefix path into EXECPATH + +Kloop: ;AN000; 3/3/KK + lodsb ;AN000; 3/3/KK + stosb ;AN000; 3/3/KK + invoke testkanj ;AN000; 3/3/KK + jz NotKanj1 ;AN000; 3/3/KK + dec cx ;AN000; 3/3/KK + JCXZ PopDone ;AN000; Ignore boundary error 3/3/KK + movsb ;AN000; 3/3/KK + dec cx ;AN000; 3/3/KK + cmp cx,1 ;AN000; One char (the terminator) left ? 3/3/KK + ja Kloop ;AN000; no. 3/3/KK + +PopDone: ;AN000; 3/3/KK + POP DS ;AN000; Yes ES:DI->terminator, last char is 3/3/KK + mov AL, psep_char ;AN000; KANJI 3/3/KK + jmp Short path_store ;AN000; 3/3/KK + +NotKanj1: + loop Kloop + pop DS ; return to our segment + dec DI ; overwrite terminator + mov AL, psep_char ; with a pathname separator + cmp al,byte ptr [di-1] + jz path_success + +path_store: ;AN000; 3/3/KK + stosb + +path_success: + mov SI, OFFSET TRANGROUP:search_best_buf + xor CX, CX + +path_succ_loop: + lodsb ; append winning filename to path + stosb ; (including terminating null) + or al,al + jnz path_succ_loop + mov AX, BP ; retrieve filetype code + +path_exit: + popf + pop BP + pop DI + pop SI ; chill out... + pop DX + pop CX + pop BX + ret +EndProc Path_Search + +break +;---------------------------------------------------------------------------- +; STORE_PCHAR determines the pathname-element separator and squirrels +; it away. In other words, must we say '/bin/ls' or '\bin\ls'? +; ENTRY: +; EXIT: +; NOTE(S): +; * Uses , defined in . +;--------------- +;--------------- +Procedure Store_PChar,NEAR +;--------------- + + push AX + mov AL, '/' ; is the pathname-element separator + invoke pathchrcmp ; a regular slash? + jz store_slash ; if yes, remember slash + mov al,'\' + mov [psep_char], al ; otherwise, remember back-slash + pop ax + ret + +store_slash: + mov [psep_char], al + pop ax + return +;--------------- +EndProc Store_Pchar +;---------------------------------------------------------------------------- + +break +;---------------------------------------------------------------------------- +; PATH_CRUNCH takes a prefix from a prefix string, and a suffix from +; EXECPATH, and smooshes them into tpbuf. The caller may supply an +; additional separator to use for breaking up the path-string. Null is the +; default. Once the user-string has been formed, search is invoked to see +; what's out there. +; ENTRY: +; BH -- additional terminator character +; SI -- pointer into pathstring to be dissected +; DX -- pointer to stripped filename +; EXIT: +; AX -- non-zero (file type), zero (nothing found) +; SI -- moves along pathstring from call to call +; [search_best_buf] -- name of best file (AX non-zero) +; [tpbuf] -- clobbered +; NOTE(S): +; * Implicit in this code is the ability to specify when to search +; the current directory (if at all) through the PATH defined by +; the user, a la UNIX (e.g., PATH=;c:\bin;c:\etc searches the +; current directory before the bin and etc directories of drive c). +;--------------- +Procedure Path_Crunch,NEAR +;--------------- + push BX + push CX + push DX + push DI + push SI + pushf + call store_pchar ; figure out pathname separator + mov DI, OFFSET TRANGROUP:tpbuf ; destination of concatenated string + mov SI, pathinfo[4] ; "new" pointer to start with + mov pathinfo[2], SI ; becomes "old" pointer + push DS ; save old segment pointer + push pathinfo[0] ; replace with pointer to userpath's + pop DS ; segment + xor cl,cl ;AN000; clear flag for later use 3/3/KK + +path_cr_copy: + lodsb ; get a pathname byte + or al,al ; check for terminator(s) + jz path_seg ; null terminates segment & pathstring + cmp AL, BH + jz path_seg ; BH terminates a pathstring segment + invoke testkanj ;AN000; 3/3/KK + jz NotKanj2 ;AN000; 3/3/KK + stosb ;AN000; 3/3/KK + movsb ;AN000; 3/3/KK + MOV CL,1 ;AN000; CL=1 means latest stored char is DBCS 3/3/KK + jmp path_cr_copy ;AN000; 3/3/KK + +NotKanj2: ;AN000; 3/3/KK + xor cl,cl ;AN000; CL=0 means latest stored char is SBCS 3/3/KK + stosb ; save byte in concat buffer + jmp path_cr_copy ; loop until we see a terminator + +path_seg: + pop DS ; restore old data segment + mov pathinfo[4], SI ; save "new" pointer for next time + mov BL, AL ; remember if we saw null or not... + ;;; REMOVE NEXT 3 LINES FOR CURDIR SPEC + xor AX, AX ; in case nothing in pathstr... + cmp DI, OFFSET TRANGROUP:tpbuf ; was there really anything in pathstr? + je path_cr_leave ; if nothing was copied, pathstr empty + +path_cr_look: ; form complete pathname + mov al, psep_char ; add pathname separator for suffix + or cl,cl ;AN000; 3/3/KK + jnz path_cr_store ;AN000; this is a trailing byte of ECS code 3/3/KK + cmp al,byte ptr [di-1] + jz path_cr_l1 + +path_cr_store: ;AN000; 3/3/KK + stosb + +path_cr_l1: + mov SI, DX + +path_cr_l2: + lodsb ; tack the stripped filename onto + stosb ; the end of the path, up to and + or AL, AL ; including the terminating null + jnz path_cr_l2 + mov DX, OFFSET TRANGROUP:tpbuf ; and look for an appropriate file... + mov [search_error], OFFSET TRANGROUP:BADPMES_ptr + invoke search ; results are in AX & search_best_buf + +path_cr_leave: + or BL, BL ; did we finish off the pathstring? + jz path_cr_empty ; null in BL means all gone... + popf ; otherwise, plenty left + clc + jmp short path_cr_exit + +path_cr_empty: + popf + stc + +path_cr_exit: + pop SI + pop DI + pop DX + pop CX + pop BX + ret +;--------------- +EndProc Path_Crunch +;---------------------------------------------------------------------------- + + +trancode ends +END diff --git a/v4.0/src/CMD/COMMAND/PATH2.ASM b/v4.0/src/CMD/COMMAND/PATH2.ASM new file mode 100644 index 0000000..8f8d8b8 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/PATH2.ASM @@ -0,0 +1,458 @@ + page 80,132 +; SCCSID = @(#)path2.asm 1.1 85/05/14 +; SCCSID = @(#)path2.asm 1.1 85/05/14 +.sall +.xlist +.xcref +INCLUDE DOSSYM.INC + include comsw.asm + include comseg.asm + include comequ.asm +.list +.cref + + +DATARES SEGMENT PUBLIC BYTE + EXTRN FORFLAG:BYTE +DATARES ENDS + + +break +;---------------------------------------------------------------------------- +; PATH.ASM contains the routines to perform pathname incovation. Path and +; Parse share a temporary buffer and argv[] definitions. , +; given a pathname, attempts to find a corresponding executable or batch +; file on disk. Directories specified in the user's search path will be +; searched for a matching file, if a match is not found in the current +; directory and if the pathname is actually only an MSDOS filename. +; assumes that the parsed command name can be found in +; argv[0] -- in other words, should be executed prior to +; . Alternatively, the command name and appropriate +; information could be placed in argv[0], or could be +; (easily) modified to make no assumptions about where its input is found. +; Please find enclosed yet another important routine, , which +; places the entire arg/argv[]/argbuf structure on a piece of newly +; allocated memory. This is handy for for-loop processing, and anything +; else that wants to save the whole shebang and then process other command +; lines. +; +; Alan L, OS/MSDOS August 15, 1983 +; +; ENTRY: +; : argv[0]. +; : bytes to allocate in addition to arg structure +; EXIT: +; : success flag, best pathname match in EXECPATH. +; : success flag, segment address of new memory +; NOTE(S): +; * handily turns an array index into an absolute pointer. +; The computation depends on the size of an argv[] element (arg_ele). +; * calls for chunks of the command line. +; does not function as specified; see for more details. +; * now knows about the flags the internals of COMMAND.COM +; need to know about. This extra information is stored in a switch_flag +; word with each command-line argument; the switches themselves will not +; appear in the resulting arg structure. +; * With the exception of CARRY, flags are generally preserved across calls. +;--------------- +; CONSTANTS: +;--------------- + DEBUGx equ FALSE ; prints out debug info +;--------------- +; DATA: +;--------------- + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN arg:byte + EXTRN BADPMES_ptr:word + EXTRN curdrv:byte + EXTRN EXECPATH:byte + EXTRN ext_entered:byte ;AN005; + EXTRN fbuf:byte + EXTRN pathinfo:word + EXTRN psep_char:byte + EXTRN string_ptr_2:word + EXTRN tpbuf:byte +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC BYTE ;AC000; + +assume cs:trangroup, ds:trangroup, es:trangroup, ss:nothing + + +break +;---------------------------------------------------------------------------- +; SEARCH, when given a pathname, attempts to find a file with +; one of the following extensions: .com, .exe, .bat (highest to +; lowest priority). Where conflicts arise, the extension with +; the highest priority is favored. +; ENTRY: +; DX -- pointer to null-terminated pathname +; fbuf -- dma buffer for findfirst/next +; EXIT: +; AX -- 8) file found with .com extension +; 4) file found with .exe extension +; 2) file found with .bat extension +; 0) no such file to be found +; (if AX is non-zero:) +; [search_best] identical to AX +; [search_best_buf] null-terminated filename +; NOTES: +; 1) Requires caller to have allocated a dma buffer and executed a setdma. +;--------------- +; CONSTANTS: +;--------------- +search_file_not_found equ 0 +search_com equ 8 +search_exe equ 4 +search_bat equ 2 +fname_len equ 8 +fname_max_len equ 13 +dot equ '.' +wildchar equ '?' + +;--------------- +; DATA: +;--------------- +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN search_best:byte + EXTRN search_best_buf:byte + EXTRN search_curdir_buf:byte + EXTRN search_error:word +TRANSPACE ENDS + +;--------------- +Procedure Search,NEAR +;--------------- + push CX + push DX + push DI + push SI + pushf + + push DX ; check drivespec (save pname ptr) + mov DI, DX ; working copy of pathname + mov SI, OFFSET TRANGROUP:search_curdir_buf + xor DX, DX ; zero means current drive + cmp BYTE PTR [DI+1],':' ; is there a drive spec? + jne search_dir_check + mov DL, [DI] ; get the drive byte + and DL, NOT 20H ; uppercase the sucker + sub DL, '@' ; and convert to drive number + +search_dir_check: + trap Current_Dir ; can we get the drive's current + pop DX ; directory? If we can't we'll + jc search_invalid_drive ; assume it's a bad drive... + + mov CX, search_attr ; filetypes to search for + trap Find_First ; request first match, if any + jc search_no_file + mov search_best, search_file_not_found + mov [search_best_buf], ANULL ; nothing's been found, yet + +search_loop: + call search_ftype ; determine if .com, &c... + cmp AL, search_best ; better than what we've found so far? + jle search_next ; no, look for another + mov search_best, AL ; found something... save its code + mov SI, OFFSET TRANGROUP:fbuf.find_buf_pname + mov DI, OFFSET TRANGROUP:search_best_buf + mov CX, fname_max_len + cld + rep movsb ; save complete pathname representation + cmp AL, search_com ; have we found the best of all? + je search_done + +search_next: ; keep on looking + mov CX, search_attr + trap Find_Next ; next match + jnc search_loop + +search_done: ; it's all over with... + mov AL, search_best ; pick best to return with + cmp ext_entered,1 ;AN005; Did user request a specific ext? + jz search_exit ;AN005; no - exit + mov al,ext_entered ;AN005; yes - get the real file type back + mov search_best,al ;AN005; save the real file type + jmp short search_exit + +search_invalid_drive: ; Tell the user path/drive + mov DX, [search_error] ; appropriate error message + invoke std_printf ; and pretend no file found + +search_no_file: ; couldn't find a match + mov AX, search_file_not_found + +search_exit: + popf + pop SI + pop DI + pop DX + pop CX + ret +;--------------- +EndProc Search +;---------------------------------------------------------------------------- + + +break +;---------------------------------------------------------------------------- +; SEARCH_FTYPE determines the type of a file by examining its extension. +; ENTRY: +; fbuf -- dma buffer containing filename +; EXIT: +; AX -- file code, as given in search header +; NOTE(S): +; * Implicit assumption that NULL == search_file_not_found +;--------------- +; DATA: +;--------------- +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + extrn comext:byte,exeext:byte,batext:byte +trandata ends +;--------------- +Procedure Search_Ftype,NEAR +;--------------- + push DI + push si + mov AX, ANULL ; find the end of the filename + mov DI, OFFSET TRANGROUP:fbuf.find_buf_pname + mov CX, fname_max_len + cld + repnz scasb ; search for the terminating null + jnz ftype_exit ; weird... no null byte at end + sub di,5 ; . + E + X + T + NULL +; +; Compare .COM +; + mov si,offset trangroup:comext + mov ax,di + cmpsw + jnz ftype_exe + cmpsw + jnz ftype_exe + mov AX, search_com ; success! + jmp short ftype_exit +; +; Compare .EXE +; + +ftype_exe: ; still looking... now for '.exe' + mov di,ax + mov si,offset trangroup:exeext + cmpsw + jnz ftype_bat + cmpsw + jnz ftype_bat + mov AX, search_exe ; success! + jmp short ftype_exit +; +; Compare .BAT +; + +ftype_bat: ; still looking... now for '.bat' + mov di,ax + mov si,offset trangroup:batext + cmpsw + jnz ftype_fail + cmpsw + jnz ftype_fail + mov AX, search_bat ; success! + jmp short ftype_exit + +ftype_fail: ; file doesn't match what we need + mov ax,ANULL + +ftype_exit: + cmp ext_entered,1 ;AN005; was an extension entered? + jz ftype_done ;AN005; no - exit + cmp ax,ANULL ;AN005; was any match found + jz ftype_done ;AN005; no - exit + mov ext_entered,al ;AN005; save the match type found + mov AX, search_com ;AN005; send back best was found to stop search + +ftype_done: ;AN005; + pop SI + pop DI + ret + +;--------------- +EndProc Search_Ftype +;---------------------------------------------------------------------------- + + +break +;---------------------------------------------------------------------------- +; STRIP copies the source string (argv[0]) into the destination buffer, +; replacing any extension with wildcards. +; ENTRY: +; BX -- maximum length of destination buffer +; DS:SI -- address of destination buffer +; argv[0] -- command name to be stripped +; EXIT: +; CF -- set if failure, clear if successful +; NOTE(S): +;--------------- +Procedure Strip,NEAR +;--------------- + push AX + push BX + push CX + push DX + push DI + push SI + pushf + + mov ext_entered,1 ;AN005; assume no extension on file name + mov DX, DS:arg.argv[0].argpointer ; save pointer to beginning of argstring + mov DI, DS:arg.argv[0].argstartel ; beginning of last pathname element + cmp BYTE PTR [DI], 0 ; *STARTEL == NULL means no command + jz strip_error + mov CX, DX ; compute where end of argstring lies + add CX, DS:arg.argv[0].arglen + sub CX, DI ; and then find length of last element + inc CX ; include null as well + mov AL, dot ; let's find the filetype extension + cld + repnz scasb ; wind up pointing to either null or dot + jcxz process_ext ;AN005; if no extension found, just continue + mov ext_entered,0 ;AN005; we found an extension + mov al,ANULL ;AN005; continue scanning until the + repnz scasb ;AN005; end of line is reached. + +process_ext: ;AN005; + mov CX, DI ; pointer to end of argstring yields + sub CX, DX ; number of bytes to be copied + sub BX, 4 ; can argstring fit into dest. buffer? + cmp CX, BX + jg strip_error ; if not, we must have a bad pathname + mov DI, SI ; destination buffer + mov SI, DX ; source is beginning of pathname + cld + rep movsb ; SI=arg,DI=buffer,CX=argend-argbeg + cmp ext_entered,1 ;AN005; if an extension was entered + jnz skip_wilds ;AN005; don't set up wildcard ext. + + dec DI ; overwrite null or dot + stosb ; with a dot + mov AL, wildchar ; now add wildcards + stosb + stosb + stosb + mov AL, ANULL ; and a terminating null + stosb + +skip_wilds: ;AN005; + popf + clc ; chill out... + jmp short strip_exit + +strip_error: + popf + stc + +strip_exit: + pop SI + pop DI + pop DX + pop CX + pop BX + pop AX + ret +;--------------- +EndProc Strip +;---------------------------------------------------------------------------- + + +break +;---------------------------------------------------------------------------- +; SAVE_ARGS attempts to preserve the existing argv[]/argvcnt/argbuffer +; structure in newly allocated memory. The argv[] structure is found at the +; beginning of this area. The caller indicates how much extra space is +; needed in the resulting structure; Save_Args returns a segment number and +; an offset into that area, indicating where the caller may preserve its own +; data. Note that can be found at . +; ENTRY: +; BX -- size (in bytes) of extra area to allocate +; EXIT: +; AX -- segment of new area. +; CF -- set if unable to save a copy. +; NOTE(S): +; 1) The allocated area will be AT LEAST the size requested -- since +; the underlying MSDOS call, returns an integral number of +; paragraphs. +; 2) It is an error if MSDOS can't allocate AT LEAST as much memory +; as the caller of Save_Args requests. +; 3) AX is undefined if CF indicates an error. +;--------------- +Procedure Save_Args,NEAR +;--------------- + push BX + push CX + push DX + push DI + push SI + push BP + pushf + add BX, SIZE arg_unit + 0FH ; space for arg structure, round up + mov CL, 4 ; to paragraph size and convert + shr BX, CL ; size in bytes to size in paragraphs + trap Alloc + jc save_error + mov BP, AX ; save segment id + push ES ; save TRANGROUP address + mov ES, AX ; switch to new memory segment +assume ES:nothing + mov CX, SIZE arg_unit ; get back structure size + xor DI, DI ; destination is new memory area + mov SI, OFFSET TRANGROUP:arg ; source is arg structure + rep movsb ; move that sucker! + mov CX, arg.argvcnt ; adjust argv pointers + xor AX, AX ; base address for argv_calc + mov SI, OFFSET TRANGROUP:arg.argbuf - OFFSET arg_unit.argbuf + +save_ptr_loop: + dec CX ; exhausted all args? + jl save_done + mov BX, CX ; get arg index and + invoke argv_calc ; convert to a pointer + mov DX, DS:arg.argv[BX].argpointer + sub DX, SI ; adjust argpointer + mov ES:argv[BX].argpointer, DX + mov DX, DS:arg.argv[BX].argstartel + sub DX, SI ; and adjust argstartel + mov ES:argv[BX].argstartel, DX + mov DX, DS:arg.argv[BX].arg_ocomptr + sub DX, SI ; and adjust arg_ocomptr + mov ES:argv[BX].arg_ocomptr, DX + jmp save_ptr_loop + +save_done: + pop ES ; back we go to TRANGROUP +assume ES:trangroup + mov AX, BP ; restore segment id + jmp short save_ok + +save_error: + popf + stc + jmp short save_exit + +save_ok: + popf + clc +save_exit: + pop BP + pop SI + pop DI + pop DX + pop CX + pop BX + ret +;--------------- +EndProc Save_Args +;---------------------------------------------------------------------------- + +trancode ends +END diff --git a/v4.0/src/CMD/COMMAND/RDATA.ASM b/v4.0/src/CMD/COMMAND/RDATA.ASM new file mode 100644 index 0000000..65fd4bb --- /dev/null +++ b/v4.0/src/CMD/COMMAND/RDATA.ASM @@ -0,0 +1,611 @@ + page 80,132 +; SCCSID = @(#)rdata.asm 4.2 85/09/22 +; SCCSID = @(#)rdata.asm 4.2 85/09/22 +TITLE COMMAND Resident DATA + +include comsw.asm +.xlist +.xcref +include comseg.asm +.list +.cref + +; +; Equates for initialization (from COMEQU) +; +initInit equ 01h ; initialization in progress +initSpecial equ 02h ; in initialization time/date routine +initCtrlC equ 04h ; already in ^C handler + +Tokenized = FALSE + +CODERES SEGMENT PUBLIC BYTE ;AC000; + PUBLIC RSTACK + EXTRN EXT_EXEC:NEAR + EXTRN THEADFIX:NEAR + EXTRN TREMCHECK:NEAR + + DB (80H - 3) DUP (?) + +RSTACK LABEL WORD + +CODERES ENDS + +TRANCODE SEGMENT PUBLIC BYTE ;AC000; + EXTRN COMMAND:NEAR +TRANCODE ENDS + +; Data for resident portion + +DATARES SEGMENT PUBLIC BYTE + + IF Tokenized + PUBLIC IOTYP + PUBLIC MESADD + ENDIF + + PUBLIC abort_char + PUBLIC append_flag ;AN020; + PUBLIC append_state ;AN020; + PUBLIC BADFAT_BLOCK ;AC000; + PUBLIC BADFAT_OP_SEG ;AC000; + PUBLIC BADFAT_SUBST ;AC000; + PUBLIC BATCH + PUBLIC Batch_Abort + PUBLIC call_batch_flag + PUBLIC call_flag + PUBLIC CDEVAT ;AC000; + PUBLIC COM_FCB1 + PUBLIC COM_FCB2 + PUBLIC COM_PTR + PUBLIC COM_XLAT_ADDR + PUBLIC COMDRV + PUBLIC COMPRMT1_BLOCK ;AC000; + PUBLIC COMPRMT1_SEG ;AC000; + PUBLIC COMPRMT1_SEG2 ;AC000; + PUBLIC COMPRMT1_SUBST ;AC000; + PUBLIC COMSPEC + PUBLIC crit_msg_off ;AC000; + PUBLIC crit_msg_seg ;AC000; + PUBLIC critical_msg_start ;AC000; + PUBLIC comspec_print + PUBLIC comspec_end + PUBLIC cpdrv + PUBLIC crit_err_INFO + PUBLIC DATARESEND + PUBLIC dbcs_vector_addr ;AN000; + PUBLIC DEVE_OP_OFF ;AC000; + PUBLIC DEVE_OP_SEG ;AC000; + PUBLIC DEVE_OP_SEG2 ;AC000; + PUBLIC DEVEMES_BLOCK ;AC000; + PUBLIC DEVEMES_SUBST ;AC000; + PUBLIC DEVENAM ;AC000; + PUBLIC DISP_CLASS ;AN000; + PUBLIC DRVLET + PUBLIC DRVNUM_BLOCK ;AC000; + PUBLIC DRVNUM_OP_OFF ;AC000; + PUBLIC DRVNUM_OP_SEG ;AC000; + PUBLIC DRVNUM_OP_SEG2 ;AC000; + PUBLIC DRVNUM_SUBST ;AC000; + PUBLIC ECHOFLAG + PUBLIC ENVIRSEG + PUBLIC ERR15_OP_SEG ;AC000; + PUBLIC ERR15_OP_SEG2 ;AC000; + PUBLIC ERR15_OP_SEG3 ;AC000; + PUBLIC ERR15MES_BLOCK ;AC000; + PUBLIC ERR15MES_SUBST ;AC000; + PUBLIC ERRCD_24 + PUBLIC ErrType + PUBLIC EXEC_BLOCK + PUBLIC EXECEMES_BLOCK ;AC000; + PUBLIC EXECEMES_SUBST ;AC000; + PUBLIC EXECEMES_OFF ;AC000; + PUBLIC EXECEMES_SEG ;AC000; + PUBLIC EXTCOM + PUBLIC extended_msg_start ;AN000; + PUBLIC extmsgend ;AN000; + PUBLIC fail_char ;AC000; + PUBLIC fFail + PUBLIC FORFLAG + PUBLIC forptr + PUBLIC fucase_addr ;AN000; + PUBLIC HANDLE01 + PUBLIC IFFlag + PUBLIC ignore_char + PUBLIC In_Batch + PUBLIC InitFlag + PUBLIC INPIPEPTR + PUBLIC INT_2E_RET + PUBLIC IO_SAVE + PUBLIC LOADING + PUBLIC LTPA + PUBLIC MEMSIZ +;AD054; PUBLIC MESBAS ;AC000; + PUBLIC MYSEG + PUBLIC MYSEG1 + PUBLIC MYSEG2 + PUBLIC nest + PUBLIC next_batch + PUBLIC no_char + PUBLIC NULLFLAG + PUBLIC NUMBER_SUBST ;AN000; + PUBLIC olderrno + PUBLIC OldTerm + PUBLIC OUTPIPEPTR + PUBLIC PARENT +;AD060; PUBLIC pars_msg_off ;AN000; +;AD060; PUBLIC pars_msg_seg ;AN000; + PUBLIC parse_msg_start ;AN000; + PUBLIC PERMCOM + PUBLIC PIPE1 + PUBLIC pipe1t + PUBLIC PIPE2 + PUBLIC pipe2t + PUBLIC PIPEFILES + PUBLIC PIPEFLAG + PUBLIC PIPEPTR + PUBLIC PIPESTR + PUBLIC RDIRCHAR + PUBLIC RE_OUT_APP + PUBLIC RE_OUTSTR + PUBLIC RemMsg + PUBLIC resmsgend ;AN000; + PUBLIC RES_TPA + PUBLIC RESTDIR + PUBLIC ResTest + PUBLIC RETCODE + PUBLIC retry_char + PUBLIC rsrc_xa_seg ;AN030; + PUBLIC RSWITCHAR + PUBLIC SAVE_PDB + PUBLIC SINGLECOM + PUBLIC SUM + PUBLIC SUPPRESS + PUBLIC TRANS + PUBLIC TranVarEnd + PUBLIC TRANVARS + PUBLIC TRNSEG + PUBLIC TrnMvFlg + PUBLIC VERVAL + PUBLIC VolName + PUBLIC VOLSER ;AN000; + PUBLIC yes_char + +;AD054;MESBAS DW 19 ;AC000; error_write_protect +;AD054; DW 20 ;AC000; error_bad_unit +;AD054; DW 21 ;AC000; error_not_ready +;AD054; DW 22 ;AC000; error_bad_command +;AD054; DW 23 ;AC000; error_CRC +;AD054; DW 24 ;AC000; error_bad_length +;AD054; DW 25 ;AC000; error_Seek +;AD054; DW 26 ;AC000; error_not_DOS_disk +;AD054; DW 27 ;AC000; error_sector_not_found +;AD054; DW 28 ;AC000; error_out_of_paper +;AD054; DW 29 ;AC000; error_write_fault +;AD054; DW 30 ;AC000; error_read_fault +;AD054; DW 31 ;AC000; error_gen_failure +;AD054; DW 32 ;AC000; error_sharing_violation +;AD054; DW 33 ;AC000; error_lock_violation +;AD054; DW 34 ;AC000; error_wrong_disk +;AD054; DW 35 ;AC000; error_FCB_unavailable +;AD054; DW 36 ;AC000; error_sharing_buffer_exceeded +;AD054; DW 37 ;AC000; error_code_page_mismatch +;AD054; DW 38 ;AC026; error_out_of_input +;AD054; DW 39 ;AN026; error_insufficient_disk_space + + + +IF Tokenized +MESADD LABEL WORD + DW OFFSET ResGroup:NEWLIN ;"0" + DW OFFSET ResGroup:COM$1 ;"1" + DW OFFSET ResGroup:ERR3 ;"2" + DW OFFSET ResGroup:ALLOC$3 ;"3" + DW OFFSET ResGroup:FILE$4 ;"4" + DW OFFSET ResGroup:RROR$5 ;"5" + DW OFFSET ResGroup:CAN$6 ;"6" + DW OFFSET ResGroup:EMORY$7 ;"7" + DW OFFSET ResGroup:BAT$8 ;"8" + DW OFFSET ResGroup:INS$9 ;"9" + +ERR0 DB "Write protec","t"+80h +ERR1 DB "Bad uni","t"+80h +ERR2 DB "Not read","y"+80h +ERR3 DB "Bad command"," "+80h +ERR4 DB "Dat","a"+80h +ERR5 DB "Bad call forma","t"+80h +ERR6 DB "See","k"+80h +ERR7 DB "Non-DOS dis","k"+80h +ERR8 DB "Sector not foun","d"+80h +ERR9 DB "No pape","r"+80h +ERR10 DB "Write faul","t"+80h +ERR11 DB "Read faul","t"+80h +ERR12 DB "General Failur","e"+80h +ERR13 DB "Sharing Violatio","n"+80h +ERR14 DB "Lock Violatio","n"+80h +ERR15 DB "Invalid Disk Chang","e"+80h +ERR16 DB "FCB unavailabl","e"+80h +ERR17 DB "Sharing buffer exceede","d"+80h + +;--- Extra message for error 15 +Err15Mes db "Please Insert disk " +VolName db 11 dup(?) + db 13,10,"$" + +MREAD DB "read" +MWRITE DB "writ" +ERRMES DB " e5" +IOTYP DB "writin","g"+80h +DRVNUM DB " drive " +DRVLET DB "A" +NEWLIN DB 13,10+80h +DEVEMES DB " device " +DEVENAM DB 8 DUP (?) + DB 13,10,"$" ;Must be $ terminated +COM$1 DB " COMMAN","D"+80h +ALLOC$3 DB " allocation"," "+80h +FILE$4 DB " file"," "+80h +RROR$5 DB "rror"," "+80h +CAN$6 DB "Cannot"," "+80h +EMORY$7 DB "emor","y"+80h +BAT$8 DB " batc","h"+80h +INS$9 DB "Inser","t"+80h + + +CDEVAT DB ? +BADFAT DB "0File 3table bad",","+80h +COMBAD DB "0Invalid1.COM","0"+80h +comprmt1 DB "9 disk with"," "+80h +comprmt2 DB " in drive " +cpdrv DB " " +PROMPT DB "0and strike any key when ready","0"+80h +ENDBATMES DB "0Terminate8 job (Y/N)?"," "+80h +EXECEMES DB "EXEC failure","0"+80h +EXEBAD DB "E5in EXE4","0"+80h +TOOBIG DB "Program too big to fit in m7","0"+80h +NOHANDMES DB "0No free4handle","s"+80h +BMEMMES DB "0M73e","5"+80h +HALTMES DB "06load1, system halte","d"+80h +FRETMES DB "06start1, exiting","0"+80h +RBADNAM DB "2or4name","0"+80h +AccDen DB "Access Denied","0"+80h +Patricide DB 13,10,"Top level process aborted, cannot continue."," "+80h +COMSPEC_PRINT DW ? + +ELSE + + +parm_block_size EQU 11 ;AN000; size of message subst block +blank EQU " " ;AN000; blank character + +DISP_CLASS DB -1 ;AN000; utility message class +NUMBER_SUBST DB 0 ;AN000; number of message substitutions - def 0 + + +DRVNUM_SUBST db 2 ;AN000; number of subst +DRVNUM_BLOCK db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved +DRVNUM_OP_OFF dw 0 ;AN000;offset of arg +DRVNUM_OP_SEG dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_ASCIIZ ;AN000;character string + db 128 ;AN000;maximum width + db 0 ;AN000;minimum width + db blank ;AN000;pad character + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET RESGROUP:DRVLET ;AN000;offset of arg +DRVNUM_OP_SEG2 dw 0 ;AN000;segment of arg + db 2 ;AN000;second subst + db Char_field_Char ;AN000;one character + db 1 ;AN000;maximum width + db 1 ;AN000;minimum width + db blank ;AN000;pad character + +DRVLET DB "A" + +DEVEMES_SUBST db 2 ;AN000; number of subst +DEVEMES_BLOCK db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved +DEVE_OP_OFF dw 0 ;AN000;offset of arg +DEVE_OP_SEG dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_ASCIIZ ;AN000;character string + db 128 ;AN000;maximum width + db 0 ;AN000;minimum width + db blank ;AN000;pad character + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET RESGROUP:DEVENAM ;AN000;offset of arg +DEVE_OP_SEG2 dw 0 ;AN000;segment of arg + db 2 ;AN000;second subst + db Char_field_ASCIIZ ;AN000;character string + db 8 ;AN019;maximum width + db 8 ;AN019;minimum width + db blank ;AN000;pad character + +DEVENAM DB 8 DUP (?) + +;--- Extra message for error 15 +ERR15MES_SUBST db 3 ;AN000; number of subst +ERR15MES_BLOCK db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET RESGROUP:VOLNAME ;AN000;offset of arg +ERR15_OP_SEG dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_ASCIIZ ;AN000;character string + db 12 ;AN000;maximum width + db 12 ;AN000;minimum width + db blank ;AN000;pad character + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET RESGROUP:VOLSER+2;AN000;offset of arg +ERR15_OP_SEG2 dw 0 ;AN000;segment of arg + db 2 ;AN000;second subst + db right_align+Bin_Hex_Word ;AN000;long binary to decimal + db 4 ;AN000;maximum width + db 4 ;AN000;minimum width + db "0" ;AN000;pad character + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET RESGROUP:VOLSER ;AN000;offset of arg +ERR15_OP_SEG3 dw 0 ;AN000;segment of arg + db 3 ;AN000;third subst + db right_align+Bin_Hex_Word ;AN000;long binary to decimal + db 4 ;AN000;maximum width + db 4 ;AN000;minimum width + db "0" ;AN000;pad character + +;************************************ +;* DO NOT SEPARATE VOLNAME & VOLSER * +;************************************ + ;* +VolName DB 11 dup(?) ;* + DB 0 ;* +VolSer DD 0 ;* + ;* +;************************************ + + +CDEVAT DB ? + +BADFAT_SUBST db 1 ;AN000; number of subst +BADFAT_BLOCK db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET RESGROUP:DRVLET ;AN000;offset of arg +BADFAT_OP_SEG dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_Char ;AN000;one character + db 1 ;AN000;maximum width + db 1 ;AN000;minimum width + db blank ;AN000;pad character + + +COMPRMT1_SUBST db 2 ;AN000; number of subst +COMPRMT1_BLOCK db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved +COMSPEC_PRINT dw ? ;AN000;offset of arg +COMPRMT1_SEG dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_ASCIIZ ;AN000;character string + db 64 ;AN000;maximum width + db 0 ;AN000;minimum width + db blank ;AN000;pad character + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET RESGROUP:CPDRV ;AN000;offset of arg +COMPRMT1_SEG2 dw 0 ;AN000;segment of arg + db 2 ;AN000;second subst + db Char_field_Char ;AN000;one character + db 1 ;AN000;maximum width + db 1 ;AN000;minimum width + db blank ;AN000;pad character + +cpdrv DB " " +; +; Exec error messages +; +EXECEMES_SUBST db 1 ;AN000; number of subst +EXECEMES_BLOCK db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved +EXECEMES_OFF dw 0 ;AN000;offset of arg +EXECEMES_SEG dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_ASCIIZ ;AN000;character string + db 64 ;AN000;maximum width + db 0 ;AN000;minimum width + db blank ;AN000;pad character + +; +; These characters MUST remain in order +; +abort_char db "A" +retry_char db "R" +ignore_char db "I" +fail_char db "F" +yes_char db "Y" +no_char db "N" +; +; End of characters that MUST remain in order +; +ENDIF + +RemMsg DD ? ;Pointer to message in error 15 +ErrType DB ? ; Error message style, 0=old, 1=new + +INT_2E_RET DD ? ; Magic command executer return address +SAVE_PDB DW ? +PARENT DW ? +OldTerm DD ? +ERRCD_24 DW ? +HANDLE01 DW ? +LOADING DB 0 +BATCH DW 0 ; Assume no batch mode initially +COMSPEC DB 64 DUP(0) +comspec_end dw ? +TRANS DW OFFSET TRANGROUP:COMMAND +TRNSEG DW ? +; BAS DEBUG +TrnMvFlg DB 0 ; Indicate if transient portion has been moved + +In_Batch DB 0 ; Indicate if we are in Batch processing mode. +Batch_Abort DB 0 ; Indicate if user wants to abort from batch mode. + +COMDRV DB ? ; DRIVE SPEC TO LOAD AUTOEXEC AND COMMAND +MEMSIZ DW ? +SUM DW ? +EXTCOM DB 1 ; For init, pretend just did an external +RETCODE DW ? +CRIT_ERR_INFO DB ? ;G hold critical error flags for R,I,F +rsrc_xa_seg DW -1 ;AN030; holds segment of xa copy buffer + +; +; The echo flag needs to be pushed and popped around pipes and batch files. +; We implement this as a bit queue that is shr/shl for push and pop. +; +ECHOFLAG DB 00000001B ; low bit TRUE => echo commands +SUPPRESS DB 1 ; used for echo, 1=echo line +IO_SAVE DW ? +RESTDIR DB 0 +PERMCOM DB 0 ; TRUE => permanent command +SINGLECOM DW 0 ; TRUE => single command version +VERVAL DW -1 +fFail DB 0 ; TRUE => FAIL all INT 24s +IFFLAG DB 0 ; TRUE => If statement in progress + +FORFLAG DB 0 ; TRUE => FOR statement in progress +FORPTR DW 0 + +NEST DW 0 ; NESTED BATCH FILE COUNTER +CALL_FLAG DB 0 ; NO CALL (BATCH COMMAND) IN PROGRESS +CALL_BATCH_FLAG DB 0 +NEXT_BATCH DW 0 ; ADDRESS OF NEXT BATCH SEGMENT +NULLFLAG DB 0 ; FLAG IF NO COMMAND ON COMMAND LINE +COM_XLAT_ADDR DB 5 DUP (0) ;G BUFFER FOR TRANSLATE TABLE ADDRESS +FUCASE_ADDR DB 5 DUP (0) ;AN000; BUFFER FOR FILE UCASE ADDRESS +CRIT_MSG_OFF DW 0 ;AN000; SAVED CRITICAL ERROR MESSAGE OFFSET +CRIT_MSG_SEG DW 0 ;AN000; SAVED CRITICAL ERROR MESSAGE SEGMENT +;AD060; PARS_MSG_OFF DW 0 ;AN000; SAVED PARSE ERROR MESSAGE OFFSET +;AD060; PARS_MSG_SEG DW 0 ;AN000; SAVED PARSE ERROR MESSAGE SEGMENT +Dbcs_vector_addr DW 0 ;AN000; DBCS vector offset + DW 0 ;AN000; DBCS vector segment +APPEND_STATE DW 0 ;AN020; current state of append (if flag = -1) +APPEND_FLAG DB 0 ;AN020; set if APPEND state valid + +RE_OUT_APP DB 0 +RE_OUTSTR DB 64+3+13 DUP (?) + +; +; We flag the state of COMMAND in order to correctly handle the ^Cs at +; various times. Here is the breakdown: +; +; initINIT We are in the init code. +; initSpecial We are in the date/time prompt +; initCtrlC We are handling a ^C already. +; +; If we get a ^C in the initialization but not in the date/time prompt, we +; ignore the ^C. This is so the system calls work on nested commands. +; +; If we are in the date/time prompt at initialization, we stuff the user's +; input buffer with a CR to pretend an empty response. +; +; If we are already handling a ^C, we set the carry bit and return to the user +; (ourselves). We can then detect the carry set and properly retry the +; operation. +; + +InitFlag DB initINIT + +;These two bytes refed as a word +PIPEFLAG DB 0 +PIPEFILES DB 0 + +;--- 2.x data for piping +; +; All the "_" are substituted later, the one before the : is substituted +; by the current drive, and the others by the CreateTemp call with the +; unique file name. Note that the first 0 is the first char of the pipe +; name. -MU +; +;--- Order dependant, do not change + +Pipe1 db "_:/" +Pipe1T db 0 + db "_______.___",0 +Pipe2 db "_:/" +Pipe2T db 0 + db "_______.___",0 + +PIPEPTR DW ? +PIPESTR DB 129 DUP(?) +INPIPEPTR DW OFFSET ResGroup:PIPE1 +OUTPIPEPTR DW OFFSET ResGroup:PIPE2 + +EXEC_BLOCK LABEL BYTE ; The data block for EXEC calls +ENVIRSEG DW ? +COM_PTR LABEL DWORD + DW 80H ; Point at unformatted parameters + DW ? +COM_FCB1 LABEL DWORD + DW 5CH + DW ? +COM_FCB2 LABEL DWORD + DW 6CH + DW ? + +TRANVARS LABEL BYTE ; Variables passed to transient + DW OFFSET ResGroup:THEADFIX +MYSEG DW 0 ; Put our own segment here +LTPA DW 0 ; WILL STORE TPA SEGMENT HERE +RSWITCHAR DB "-" +RDIRCHAR DB "/" + DW OFFSET ResGroup:EXT_EXEC +MYSEG1 DW ? + DW OFFSET ResGroup:TREMCHECK +MYSEG2 DW 0 +ResTest DW 0 +RES_TPA DW 0 ; Original TPA (not rounded to 64K) +TranVarEnd LABEL BYTE + +olderrno dw ? + +RESMSGEND DW 0 ;AN000;; holds offset of msg end (end of resident) + +.xlist +.xcref + +INCLUDE SYSMSG.INC ;AN000; include message services + +.list +.cref + +ASSUME DS:RESGROUP,ES:RESGROUP,CS:RESGROUP + +MSG_UTILNAME ;AN000; define utility name + +;AD054; MSG_SERVICES ;AN000; get message services data and resident messages +MSG_SERVICES ;AN054; get message services data and resident messages + + +CRITICAL_MSG_START LABEL BYTE ;AN000; start of critical error messages + +MSG_SERVICES ;AN000; get critical error messages + +DATARESEND LABEL BYTE ;AC060; end of resident portion if /msg not used + +PARSE_MSG_START LABEL BYTE ;AN000; start of parse error messages + +MSG_SERVICES ;AN000; get parse error messages + +;AD060; DATARESEND LABEL BYTE ; end of resident portion if /msg not used + +EXTENDED_MSG_START LABEL BYTE ;AN000; start of extended error messages + +MSG_SERVICES ;AN000; get extended error messages + +EXTMSGEND LABEL BYTE ;AN000; end of extended error messages + +include msgdcl.inc + +DATARES ENDS + END diff --git a/v4.0/src/CMD/COMMAND/RESMSG.EQU b/v4.0/src/CMD/COMMAND/RESMSG.EQU new file mode 100644 index 0000000..9eb5187 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/RESMSG.EQU @@ -0,0 +1,43 @@ +; SCCSID = @(#)resmsg.equ 4.1 85/09/10 +; SCCSID = @(#)resmsg.equ 4.1 85/09/10 + +;**************************** +;* RESIDENT MESSAGE EQUATES * +;**************************** + +REQ_ABORT EQU 210 ;AC000; "Abort" +REQ_RETRY EQU 211 ;AC000; ", Retry" +REQ_IGNORE EQU 212 ;AC000; ", Ignore" +REQ_FAIL EQU 213 ;AC000; ", Fail" +REQ_END EQU 214 ;AC000; "? " +MREAD EQU 215 ;AC000; "reading" +MWRITE EQU 216 ;AC000; "writing" +DRVNUM EQU 217 ;AC000; "%1 drive %2" +DEVEMES EQU 218 ;AC000; "%1 device %2" +Err15Mes EQU 219 ;AC000; "Please insert volume %1 serial %2" +BADFAT EQU 220 ;AC000; "File allocation table bad, drive %1" +COMBAD EQU 221 ;AC000; 13,10,"Invalid COMMAND.COM",13,10" +comprmt1 EQU 222 ;AC000; "Insert disk with %1 in drive %1" +PROMPT EQU 223 ;AC000; "Press any key to continue" +ENDBATMES EQU 224 ;AC000; 13,10,"Terminate batch job (Y/N)? " +EXECEMES EQU 225 ;AC000; "Cannot execute %1",13,10 +EXEBAD EQU 226 ;AC000; "Error in EXE file",13,10 +TOOBIG EQU 227 ;AC000; "Program too big to fit in memory",13,10 +NOHANDMES EQU 228 ;AC000; 13,10,"No free file handles" +RBADNAM EQU 229 ;AC000; "Bad Command or file name",13,10 +AccDen EQU 230 ;AC000; Extended error - "Access denied",13,10 +BMEMMES EQU 231 ;AC000; 13,10,"Memory allocation error " +HALTMES EQU 232 ;AC000; 13,10,"Cannot load COMMAND, system halted" +FRETMES EQU 233 ;AC000; 13,10,"Cannot start COMMAND, exiting",13,10 +Patricide EQU 234 ;AC000; 13,10,"Top level process aborted, cannot continue." +NEWLIN EQU 235 ;AC000; 13,10 + +;************************ +;* INIT MESSAGE EQUATES * +;************************ + +BADVER EQU 461 ;AC000; "Incorrect DOS version",13,10,"$" +OUTENVERR_PTR EQU 463 ;AC000; "Out of environment space",13,10,0 +HEADER_PTR EQU 464 ;AC000; Long Copyright Notice +BADCOMLKMES_PTR EQU 465 ;AC000;"Specified COMMAND search directory bad",13,10,0 +BADCOMACCMES_PTR EQU 466 ;AC000; "Specified COMMAND search directory bad access denied",13,10,0 diff --git a/v4.0/src/CMD/COMMAND/RUCODE.ASM b/v4.0/src/CMD/COMMAND/RUCODE.ASM new file mode 100644 index 0000000..5a6f413 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/RUCODE.ASM @@ -0,0 +1,739 @@ + page 80,132 +; SCCSID = @(#)rucode.asm 4.5 85/07/22 +; SCCSID = @(#)rucode.asm 4.5 85/07/22 +TITLE COMMAND Language modifiable Code Resident + + +.xlist +.xcref +INCLUDE DOSSYM.INC ;AC000; +include doscntry.inc ;AC000; +DEBUG = 0 ; NEED TO SET IT TO WHAT IT IS IN DOSSYM.INC + + + INCLUDE DEVSYM.INC + INCLUDE comsw.asm + INCLUDE comseg.asm + INCLUDE comequ.asm + include resmsg.equ ;AN000; +.list +.cref + + +Tokenized = FALSE + +DATARES SEGMENT PUBLIC BYTE ;AC000; + EXTRN abort_char:byte + EXTRN badfat_block:byte ;AC000; + EXTRN badfat_subst:byte ;AC000; + EXTRN Batch_Abort:byte + EXTRN CDEVAT:BYTE + EXTRN COMSPEC:BYTE ;AN060; + EXTRN com_xlat_addr:word + EXTRN crit_err_info:byte + EXTRN crit_msg_off:word ;AC000; + EXTRN crit_msg_seg:word ;AC000; + EXTRN dbcs_vector_addr:dword ;AN000; + EXTRN devemes_block:byte ;AC000; + EXTRN devemes_subst:byte ;AC000; + EXTRN DEVENAM:BYTE + EXTRN deve_op_off:word ;AC000; + EXTRN disp_class:byte ;AC000; + EXTRN DRVLET:BYTE + EXTRN drvnum_block:byte ;AC000; + EXTRN drvnum_op_off:word ;AC000; + EXTRN drvnum_subst:byte ;AC000; + EXTRN err15mes_block:byte ;AC000; + EXTRN err15mes_subst:byte ;AC000; + EXTRN ERRCD_24:WORD + EXTRN ErrType:BYTE + EXTRN fail_char:byte + EXTRN fFail:BYTE + EXTRN FORFLAG:BYTE + EXTRN ignore_char:byte + EXTRN InitFlag:BYTE + EXTRN In_Batch:byte + EXTRN LOADING:BYTE +;AD054; EXTRN MESBAS:BYTE + EXTRN no_char:byte + EXTRN number_subst:byte ;AC000; + EXTRN olderrno:word + EXTRN PARENT:WORD +;AD060; EXTRN pars_msg_off:word ;AC000; +;AD060; EXTRN pars_msg_seg:word ;AC000; + EXTRN PERMCOM:BYTE + EXTRN RemMsg:DWORD + EXTRN retry_char:byte + EXTRN PIPEFLAG:BYTE + EXTRN SINGLECOM:WORD + EXTRN VolName:BYTE + EXTRN yes_char:byte + + IF Tokenized + EXTRN IOTYP:BYTE + EXTRN MESADD:BYTE + ENDIF + +DATARES ENDS + + +CODERES SEGMENT PUBLIC BYTE + + EXTRN GETCOMDSK2:NEAR + + PUBLIC ASKEND + PUBLIC CRLF + PUBLIC DSKERR + PUBLIC ITESTKANJ ;AN000; + PUBLIC RESET_MSG_POINTERS ;AC000; + PUBLIC RPRINT + +ASSUME CS:RESGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + +; +; AskEnd - prompt the user to see if he should terminate the batch file. If +; any system call returns with carry set or if RPRINT returns with carry set, +; we jump to the top and start over. +; +; Returns: carry set if response indicates that the batch file should +; be terminated. +; carry clear otherwise. +; + +ASSUME DS:RESGROUP +ASKEND: + MOV DX,ENDBATMES ;AC000; get batch terminate question + CALL RPRINT + MOV AX,(STD_CON_INPUT_FLUSH SHL 8)+STD_CON_INPUT + INT 21H + call in_char_xlat ;g change to upper case + CMP AL,no_char + retz ; carry is clear => no free + CMP AL,yes_char + JNZ ASKEND + stc ; carry set => free batch + return + +DSKERR: +ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + ; ****************************************************** + ; THIS IS THE DEFAULT DISK ERROR HANDLING CODE + ; AVAILABLE TO ALL USERS IF THEY DO NOT TRY TO + ; INTERCEPT INTERRUPT 24H. + ; ****************************************************** + STI + PUSH DS + PUSH ES + PUSH SI ;AN000; save si + PUSH CX + PUSH DI + PUSH CX + PUSH AX + MOV DS,BP + MOV AX,[SI.SDEVATT] + MOV [CDEVAT],AH + PUSH CS + POP ES + MOV DI,OFFSET RESGROUP:DEVENAM + MOV CX,8 + ADD SI,SDEVNAME ; Suck up device name (even on Block) + REP MOVSB + POP AX + POP CX + POP DI ; Stack just contains DS and ES + ; at this point + INVOKE SAVHAND + PUSH CS + POP DS ; Set up local data segment +ASSUME DS:RESGROUP + + PUSH DX + CALL CRLF + POP DX + MOV CRIT_ERR_INFO,AH ;G save so we know if R,I,F are valid + + ADD AL,'A' ; Compute drive letter (even on character) + MOV [DRVLET],AL + TEST AH,80H ; Check if hard disk error + JZ NOHARDE + TEST [CDEVAT],DEVTYP SHR 8 + JNZ NOHARDE + JMP FATERR + +NOHARDE: + MOV SI,MREAD ;AC000; + TEST AH,1 + JZ SAVMES + MOV SI,MWRITE ;AC000; + +SAVMES: + IF Tokenized + LODSW + MOV WORD PTR [IOTYP],AX + LODSW + MOV WORD PTR [IOTYP+2],AX + ENDIF + + mov olderrno,di ; keep code in a safe place + PUSH ES ;AN000; + PUSH DS ; GetExtendedError likes to STOMP + PUSH BP + PUSH SI + PUSH DX + PUSH CX + PUSH BX + mov ah,GetExtendedError ; get extended error code + INT 21H + POP BX + POP CX + POP DX + POP SI + POP BP + POP DS + mov word ptr cs:[RemMsg],di ;AC000; save pointer to remote message + mov word ptr cs:[RemMsg+2],es ;AC000; (only used on code 15) + pop ES ;AN000; + XOR AH,AH + mov di,ax ; REAL error code to DI +; +; DI is now the correct error code. Classify things to see what we are +; allowed to report. We convert DI into a 0-based index into a message table. +; This presumes that the int 24 errors (oldstyle) and new errors (sharing and +; the like) are contiguous. +; + SUB DI,error_write_protect + JAE HavCod + MOV DI,error_Gen_failure-error_write_protect +; +; DI now has the mapped error code. Old style errors are: +; FOOBAR ing drive ZZ. +; New style errors are: +; FOOBAR +; We need to figure out which the particular error belongs to. +; + +HAVCOD: + mov ErrType,0 ; assume Old style + cmp di,error_FCB_Unavailable-error_write_protect + jz SetStyle + cmp di,error_sharing_buffer_exceeded-error_write_protect + jnz GotStyle + +SetStyle: + mov ErrType,1 ; must be new type + +GotStyle: + MOV [ERRCD_24],DI + cmp di,error_handle_disk_full-error_write_protect ;AC026; + ; If the error message is unknown + jbe NormalError ; redirector, continue. Otherwise, +; +; We do not know how to handle this error. Ask IFSFUNC if she knows +; how to handle things +; + +;input to IFSFUNC: AL=1 +; BX=extended error number + +;output from IFSFUNC: AL=error type (0 or 1) +; 0= error (read/writ)ing (drive/device) xxx +; Abort, Retry, Ignore +; 1= +; Abort, Retry, Ignore +; ES:DI=pointer to message text +; carry set=>no message + + MOV DI,AX ; retrieve correct extended error... + mov ax,0500h ; Is the redir there? + int 2fh + cmp al,0ffh + jnz NoHandler ; No, go to NoHandler + push bx ;AN063; + mov bx,di ; Get ErrType and ptr to error msg ;AC063; + mov ax,0501h ;AC063; + int 2fh + pop bx ;AC063; + jc NoHandler + + mov ErrType,al + push ds + push es + pop ds + mov dx,di + mov cx,-1 ; Find the end of the error msg and turn + xor al,al ; the high byte on for rprint + repnz scasb + + IF Tokenized + or byte ptr [di-2],80h + call rprint ; Print the message + and byte ptr [di-2], NOT 80h ; Restore msg to original condition + ELSE + mov byte ptr [di-1],'$' + MOV AH,Std_con_string_output ;AC000; Print the message + INT 21h ;AN000; + mov byte ptr [di-1],0 ; Restore msg to original condition + ENDIF + + pop ds ; Clean up and continue processing + jmp short CheckErrType + +NoHandler: ; Redir isn't available or doesn't + mov ErrType,0 ; recognize the error. Reset vars and + mov di,olderrno ; regs to unextended err and continue + mov ERRCD_24,di ; normally. + +NormalError: +;AD054; SHL DI,1 +;AD054; MOV DI,WORD PTR [DI+MESBAS] ; Get pointer to error message + add DI,error_write_protect ;AN054; + XCHG DI,DX ; May need DX later + MOV DISP_CLASS,EXT_CRLF_CLASS ;AN054; printing extended error class + CALL RPRINT ; Print error type + +CheckErrType: + cmp ErrType,0 ; Check error style... + je ContOld + call CRLF ; if new style then done printing + jmp short ASK + +ContOld: + IF NOT Tokenized + MOV AX,SI ;AN000; get reading/writing for message + MOV DH,UTIL_MSG_CLASS ;AN000; this is a utility message + CALL SYSGETMSG ;AN000; get the message + ENDIF + + TEST [CDEVAT],DEVTYP SHR 8 + JZ BLKERR + MOV DX,DEVEMES ;AC000; get message number for device message + MOV DEVE_OP_OFF,SI ;AN000; put address of read/write in subst block + MOV AL,DEVEMES_SUBST ;AN000; get number of substitutions + MOV NUMBER_SUBST,AL ;AN000; + MOV SI,OFFSET RESGROUP:DEVEMES_BLOCK;AN000; get address of subst block + + CALL RPRINT ;AC000; print the message + JMP SHORT ASK ; Don't ralph on COMMAND + +BLKERR: + MOV DX,DRVNUM ;AN000; get drive message number + MOV DRVNUM_OP_OFF,SI ;AN000; put address of read/write in subst block + MOV AL,DRVNUM_SUBST ;AN000; get number of substitutions + MOV NUMBER_SUBST,AL ;AN000; + MOV SI,OFFSET RESGROUP:DRVNUM_BLOCK ;AN000; get address of subst block + CALL RPRINT + CMP [LOADING],0 + JZ ASK + INVOKE RESTHAND + JMP GETCOMDSK2 ; If error loading COMMAND, re-prompt + +ASK: + cmp [ERRCD_24],15 ; Wait! Error 15 has an extra message + jne Not15 + PUSH CX + push ds + pop es + lds si,[RemMsg] +assume ds:nothing + push di + mov di,offset resgroup:VolName + mov cx,16 ;AC000; extra message volume name & serial number + cld ; just in case! + rep movsb + pop di + push es + pop ds + POP CX +assume ds:resgroup + mov dx,Err15Mes ;AC000; get message number + MOV AL,ERR15MES_SUBST ;AN000; get number of substitutions + MOV NUMBER_SUBST,AL ;AN000; + MOV SI,OFFSET RESGROUP:ERR15MES_BLOCK ;AN000; get address of subst block + CALL RPRINT + +; PRINT OUT ABORT, RETRY, IGNORE, FAIL MESSAGE. ONLY PRINT OUT OPTIONS +; THAT ARE VALID + +Not15: + MOV DX,REQ_ABORT ;AC000;G print out abort message + CALL RPRINT ;G + TEST CRIT_ERR_INFO,RETRY_ALLOWED ;G is retry allowed? + JZ TRY_IGNORE ;G + MOV DX,REQ_RETRY ;AC000;G yes,print out retry message + CALL RPRINT ;G + +try_ignore: + TEST CRIT_ERR_INFO,IGNORE_ALLOWED ;G is ignore allowed? + JZ TRY_FAIL ;G + MOV DX,REQ_IGNORE ;AC000;G yes,print out ignore message + CALL RPRINT ;G + +try_fail: + TEST CRIT_ERR_INFO,FAIL_ALLOWED ;G is FAIL allowed? + JZ TERM_QUESTION ;G + MOV DX,REQ_FAIL ;AC000;G yes,print out FAIL message + CALL RPRINT ;G + +Term_Question: + MOV DX,REQ_END ;AC000;G terminate the string + CALL RPRINT ;G +; +; If the /f switch was given, we fail all requests... +; + TEST fFail,-1 + JZ DoPrompt + MOV AH,3 ; signal fail + JMP EExit + +DoPrompt: + MOV AX,(STD_CON_INPUT_FLUSH SHL 8)+STD_CON_INPUT + INT 21H ; Get response + + invoke TestKanjR ;AN000; 3/3/KK + jz notkanj ;AN000; 3/3/KK + MOV AX,(STD_CON_INPUT SHL 8) ;AN000; eat the 2nd byte of ECS code 3/3/KK + INT 21H ;AN000; 3/3/KK + CALL CRLF ;AN000; 3/3/KK + JMP ASK ;AN000; 3/3/KK + +notkanj: ;AN000; 3/3/KK + CALL CRLF + CALL IN_CHAR_XLAT ;G Convert to upper case + MOV AH,0 ; Return code for ignore + TEST CRIT_ERR_INFO,IGNORE_ALLOWED ;G is IGNORE allowed? + JZ USER_RETRY ;G + CMP AL,ignore_char ; Ignore? + JZ EEXITJ + +USER_RETRY: + INC AH ; return code for retry + TEST CRIT_ERR_INFO,RETRY_ALLOWED ;G is RETRY allowed? + JZ USER_ABORT ;G + CMP AL,retry_char ; Retry? + JZ EEXITJ + +USER_ABORT: + INC AH ; return code for abort - always allowed + CMP AL,abort_char ; Abort? + JZ abort_process ;G exit user program + INC AH ;G return code for fail + TEST CRIT_ERR_INFO,FAIL_ALLOWED ;G is FAIL allowed? + JZ ASKJ ;G + CMP AL,fail_char ;G fail? + JZ EEXITJ ;G + +ASKJ: + JMP ASK ;G + +EEXITJ: + JMP SHORT EEXIT ;G + +abort_process: + test InitFlag,initINIT ; Was command initialization interrupted + jz AbortCont ; No, handle it normally + cmp PERMCOM,0 ; Is this the top level process? + jz JustExit ; Yes, just exit + mov dx,Patricide ;AC000; No, load ptr to error msg + call RPRINT ; Print it + +DeadInTheWater: + jmp DeadInTheWater ; Loop until the user reboots + +JustExit: +ASSUME DS:RESGROUP + call reset_msg_pointers ;AN000; reset critical & parse message addresses + mov ax,[PARENT] ; Load real parent PID + mov word ptr ds:[PDB_Parent_PID],ax ; Put it back where it belongs + mov ax,(Exit SHL 8) OR 255 + int 21H + +AbortCont: + test byte ptr [In_Batch],-1 ; Are we accessing a batch file? + jz Not_Batch_Abort + mov byte ptr [Batch_Abort],1 ; set flag for abort + +Not_Batch_Abort: + mov dl,PipeFlag + invoke ResPipeOff + OR DL,DL + JZ CHECKFORA + CMP [SINGLECOM],0 + JZ CHECKFORA + MOV [SINGLECOM],-1 ; Make sure SINGLECOM exits + +CHECKFORA: + CMP [ERRCD_24],0 ; Write protect + JZ ABORTFOR + CMP [ERRCD_24],2 ; Drive not ready + JNZ EEXIT ; Don't abort the FOR + +ABORTFOR: + MOV [FORFLAG],0 ; Abort a FOR in progress + CMP [SINGLECOM],0 + JZ EEXIT + MOV [SINGLECOM],-1 ; Make sure SINGLECOM exits + +EEXIT: + MOV AL,AH + MOV DX,DI + +RESTHD: + INVOKE RESTHAND + POP CX + POP SI ;AN000; restore registers + POP ES + POP DS + IRET + +FATERR: + MOV DX,BADFAT ;AC000; + MOV AL,BADFAT_SUBST ;AN000; get number of substitutions + MOV NUMBER_SUBST,AL ;AN000; + MOV SI,OFFSET RESGROUP:BADFAT_BLOCK ;AN000; get address of subst block + CALL RPRINT + + IF Tokenized + MOV DX,OFFSET RESGROUP:ERRMES + CALL RPRINT + ENDIF + + MOV AL,2 ; Abort + JMP RESTHD + +;********************************************* +; Print routines for Tokenized resident messages + +ASSUME DS:RESGROUP,SS:RESGROUP + +CRLF: + MOV DX,NEWLIN ;AC000; + +; +; RPRINT prints out a message on the user's console. We clear carry before +; each system call. We do this so that the ^C checker may change things so +; that carry is set. If we detect a system call that returns with carry set, +; we merely return. +; +; Inputs: DX has the message number as an offset from DS. +; Outputs: Carry clear: no carries detected in the system calls +; Carry set: at least one system call returned with carry set +; Registers modified: none +; + +RPRINT: + +; +; If we are not tokenized, the message consists of a $-terminated string. +; Use CPM io to output it. +; + +if NOT tokenized + PUSH AX + PUSH BX ;AC000; save BX register + PUSH CX ;AC000; save CX register + PUSH DX ;AC000; save DX register + MOV AX,DX ;AC000; get message number + MOV DH,DISP_CLASS ;AC000; get display class + MOV DL,NO_CONT_FLAG ;AN000; set control flags off + MOV BX,NO_HANDLE_OUT ;AC000; set message handler to use function 1-12 + XOR CH,CH ;AC000; clear upper part of cx + MOV CL,NUMBER_SUBST ;AC000; set number of substitutions + CALL SYSDISPMSG ;AC000; display the message + MOV DISP_CLASS,UTIL_MSG_CLASS ;AC000; reset display class + MOV NUMBER_SUBST,NO_SUBST ;AC000; reset number of substitutions + POP DX ;AC000; restore registers + POP CX ;AC000; + POP BX ;AC000; + POP AX + + return +endif + +; +; If we are tokenized, output character-by-character. If there is a digit in +; the output, look up that substring in the tokenization table. Use the high +; bit to determine the end-of-string. +; + +If Tokenized + SaveReg + MOV SI,DX + +RPRINT1: + LODSB + PUSH AX ; save for EOS testing + AND AL,7FH + CMP AL,'0' + JB RPRINT2 + CMP AL,'9' + JA RPRINT2 + SUB AL,'0' + CBW ; DS must be RESGROUP if we get here + SHL AX,1 ; clear carry + XCHG SI,AX + MOV DX,[SI + OFFSET RESGroup:MesADD] + CALL RPrint + XCHG SI,AX + JMP SHORT RPRINT3 + +RPRINT2: + MOV DL,AL + MOV AH,STD_CON_OUTPUT + clc ; set ok flag + INT 21H + +RPRINT3: + POP AX + JC RPrint5 ; Abnormal termination? + TEST AL,80h ; High bit set indicates end (carry clear) + JZ RPRINT1 + +RPRINT5: + RestoreReg + RET +endif + + +;g +;g This routine returns the upper case of the character in AL +;g from the upper case table in DOS if character if above +;g ascii 128, else subtract 20H if between "a" and "z" +;g + +assume ds:resgroup + +in_char_xlat proc near + + cmp al,80h ;g see if char is above ascii 128 + jb other_xlat ;g no - upper case math + sub al,80h ;g only upper 128 characters in table + push ds + push bx + lds bx,dword ptr com_xlat_addr+1 ;g get table address + add bx,2 ;g skip over first word, of table + xlat ds:byte ptr [bx] ;g convert to upper case + pop bx + pop ds + jmp short in_char_xlat_end ;g we finished - exit + +other_xlat: + cmp al,'a' ;g if between "a" and "z", subtract + jb in_char_xlat_end ;g 20h to get upper case + cmp al,'z' ;g equivalent. + ja in_char_xlat_end ;g + sub al,20h ;g Lower-case changed to upper-case + +in_char_xlat_end: + + ret + +in_char_xlat endp +;---------------------- DBCS lead byte check. this is resident code ; 3/3/KK + +ITESTKANJ: ;AN000; +TestKanjR: ;AN000; 3/3/KK + push ds ;AN000; 3/3/KK + push si ;AN000; 3/3/KK + push ax ;AN000; 3/3/KK + lds si,dbcs_vector_addr ;AN000; GET DBCS VECTOR + +ktlop: ;AN000; 3/3/KK + cmp word ptr ds:[si],0 ;AN000; 3/3/KK end of Lead Byte Table + je notlead ;AN000; 3/3/KK + pop ax ;AN000; 3/3/KK + push ax ;AN000; 3/3/KK + cmp al, byte ptr ds:[si] ;AN000; 3/3/KK + jb notlead ;AN000; 3/3/KK + inc si ;AN000; 3/3/KK + cmp al, byte ptr ds:[si] ;AN000; 3/3/KK + jbe islead ;AN000; 3/3/KK + inc si ;AN000; 3/3/KK + jmp short ktlop ;AN000; 3/3/KK try another range + +Notlead: ;AN000; 3/3/KK + xor ax,ax ;AN000; 3/3/KK set zero + jmp short ktret ;AN000; 3/3/KK + +Islead: ;AN000; 3/3/KK + xor ax,ax ;AN000; 3/3/KK reset zero + inc ax ;AN000; 3/3/KK + +ktret: ;AN000; 3/3/KK + pop ax ;AN000; 3/3/KK + pop si ;AN000; 3/3/KK + pop ds ;AN000; 3/3/KK + return ;AN000; 3/3/KK + + +; **************************************************************** +; * +; * ROUTINE: RESET_MSG_POINTERS +; * +; * FUNCTION: Resets addresses for parse and critical error +; * messages in DOS via INT 2fh. This routine +; * is invoked before command exits. +; * +; * INPUT: none +; * +; * OUTPUT: none +; * +; **************************************************************** + +reset_msg_pointers proc near + +assume ds:resgroup, es:nothing + + push es ;AN000; save used registers + push ax ;AN000; + push dx ;AN000; + push di ;AN000; +;AD060; mov ah,multdos ;AN000; reset parse message pointers +;AD060; mov al,message_2f ;AN000; call for message retriever +;AD060; mov dl,set_parse_msg ;AN000; set up parse message address +;AD060; mov di,pars_msg_off ;AN000; old offset of parse messages +;AD060; mov es,pars_msg_seg ;AN000; old segment of parse messages +;AD060; int 2fh ;AN000; go set it + +;AD060; mov ah,multdos ;AN000; set up to call DOS through int 2fh +;AD060; mov al,message_2f ;AN000; call for message retriever + mov ax,(multdos shl 8 or message_2f);AN060; reset critical message pointers + mov dl,set_critical_msg ;AN000; set up critical error message address + mov di,crit_msg_off ;AN000; old offset of critical messages + mov es,crit_msg_seg ;AN000; old segment of critical messages + int 2fh ;AN000; go set it + pop di ;AN000; restore used registers + pop dx ;AN000; + pop ax ;AN000; + pop es ;AN000; + + ret + + +reset_msg_pointers endp + +PUBLIC MSG_SERV_ST ;AN000; +MSG_SERV_ST LABEL BYTE ;AN000; + +PUBLIC SYSGETMSG,SYSDISPMSG + +ASSUME DS:RESGROUP, ES:RESGROUP + +.xlist +.xcref + +INCLUDE SYSMSG.INC ;AN000; include message services + +.list +.cref + +MSG_UTILNAME ;AN000; define utility name + +MSG_SERVICES ;AC060; include message services macro + +PUBLIC RES_CODE_END ;AN000; +RES_CODE_END LABEL BYTE ;AN000; + +include msgdcl.inc + +CODERES ENDS + END diff --git a/v4.0/src/CMD/COMMAND/TBATCH.ASM b/v4.0/src/CMD/COMMAND/TBATCH.ASM new file mode 100644 index 0000000..6ec51b5 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TBATCH.ASM @@ -0,0 +1,1045 @@ + page 80,132 +; SCCSID = @(#)tbatch.asm 4.5 85/10/01 +; SCCSID = @(#)tbatch.asm 4.5 85/10/01 +TITLE Batch processing routines + + +.xlist +.xcref + INCLUDE comsw.asm + INCLUDE DOSSYM.INC + INCLUDE comseg.asm + INCLUDE comequ.asm + include doscntry.inc ;AN000; + include version.inc +.list +.cref + + +DATARES SEGMENT PUBLIC BYTE ;AC000; + EXTRN BATCH:WORD + EXTRN Batch_Abort:byte + EXTRN call_batch_flag:byte + EXTRN ECHOFLAG:BYTE + EXTRN forflag:byte + EXTRN forptr:word + EXTRN IFFlag:BYTE + EXTRN In_Batch:byte + EXTRN LTPA:WORD + EXTRN Nest:word + EXTRN next_batch:word + EXTRN nullflag:byte + EXTRN PIPEFLAG:BYTE + EXTRN RES_TPA:WORD + EXTRN SINGLECOM:WORD + EXTRN SUPPRESS:BYTE ;AC000; +DATARES ENDS + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN BADBAT_PTR:WORD + EXTRN Extend_buf_ptr:word ;AC000; + EXTRN Extend_buf_sub:byte ;AN022; + EXTRN msg_disp_class:byte ;AC000; + EXTRN NEEDBAT_PTR:WORD + EXTRN pausemes_ptr:word ;AC000; +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN BatBufPos:WORD + EXTRN BATHAND:WORD + EXTRN bwdbuf:byte ;AN022; + EXTRN BYTCNT:WORD + EXTRN COMBUF:BYTE + EXTRN EXECPATH:BYTE + EXTRN ID:BYTE + EXTRN RCH_ADDR:DWORD + EXTRN RESSEG:WORD + EXTRN string_ptr_2:word ;AC000; + EXTRN TPA:WORD + EXTRN TRAN_TPA:WORD +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC BYTE + +ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + + EXTRN cerror:near + EXTRN tcommand:near + +;--------------- + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + extrn arg:byte ; the arg structure! +transpace ends +;--------------- + +Break + +; +; Open the batch file. If we cannot find the batch file. If the media is +; changeable, we prompt for the change. Otherwise, we terminate the batch +; file. Leave segment registers alone. +; + +Procedure PromptBat,NEAR + ASSUME DS:ResGroup,ES:NOTHING + invoke BATOPEN ; attempt to open batch file + retnc + cmp dx,error_file_not_found ;AN022; Ask for diskette if file not found + jz Bat_Remcheck ;AN022; + cmp dx,error_path_not_found ;AN022; Ask for diskette if path not found + jz Bat_Remcheck ;AN022; Otherwise, issue message and exit + invoke output_batch_name ;AN022; set up batch name in bwdbuf + jmp short BatDie ;AN022; + +Bat_Remcheck: ;AN022; Go see if media is removable + CALL [RCH_ADDR] ; DX has error number + JZ AskForBat ; Media is removable +; +; The media is not changeable. Turn everything off. +; + invoke ForOff + invoke PipeOff + MOV IfFlag,AL ; No If in progress. + MOV DX,OFFSET TRANGROUP:BADBAT_ptr + +BatDie: + call BatchOff + PUSH CS + POP DS + ASSUME DS:TranGroup + invoke std_eprintf ;AC022; display message + +; +; TCOMMAND resets the stack. This is the equivalent of a non-local goto. +; + JMP TCOMMAND ; he cleans off stack + +; +; Ask the user to reinsert the batch file +; +ASKFORBAT: + ASSUME DS:ResGroup + PUSH DS + PUSH CS + POP DS + ASSUME DS:TranGroup + MOV DX,OFFSET TRANGROUP:NEEDBAT_ptr ;AN022; + invoke std_eprintf ;Prompt for batch file on stderr + mov dx,offset trangroup:pausemes_ptr ;AN000; get second part of message + invoke std_eprintf ;AN000; print it to stderr + CALL GetKeystroke + POP DS + ASSUME DS:ResGroup + jmp PromptBat +EndProc PromptBat + +;**************************************************************** +;* +;* ROUTINE: Output_batch_name +;* +;* FUNCTION: Sets up batch name to be printed on extended error +;* +;* INPUT: DX - extended error number +;* +;* OUTPUT: Ready to call print routine +;* +;**************************************************************** + +public output_batch_name ;AN022; + +Output_batch_name proc near ;AN022; + + push ds ;AN022; save resident segment + mov ds,[batch] ;AN022; get batch file segment +assume DS:nothing ;AN022; + mov SI,BatFile ;AN022; get offset of batch file + invoke dstrlen ;AN022; get length of string + mov di,offset Trangroup:bwdbuf ;AN022; target for batch name + rep movsb ;AN022; move the name + + push cs ;AN022; get local segment + pop ds ;AN022; +assume DS:trangroup ;AN022; + mov extend_buf_ptr,dx ;AN022; put message number in block + mov msg_disp_class,ext_msg_class ;AN022; set up extended error msg class + mov dx,offset TranGroup:Extend_Buf_ptr ;AN022; get extended message pointer + mov string_ptr_2,offset trangroup:bwdbuf ;AN022; point to substitution + mov extend_buf_sub,one_subst ;AN022; set up for one subst + pop ds ;AN022; restore data segment + + ret ;AN022; return + +Output_batch_name endp ;AN022; + +Break + +; +; read the next keystroke. Since there may be several characters in the queue +; after the one we ask for (function keys/Kanji), we need to flush the queue +; AFTER waiting. +; +Procedure GetKeyStroke,NEAR +; +; read any character at any mode, interim mode or not. +; + + PUSH DX ;AN000; 3/3/KK + MOV AX,(ECS_call SHL 8) OR GetInterimMode ;AN000; 3/3/KK + INT int_command ;AN000; 3/3/KK + PUSH DX ;AN000; save interim state 3/3/KK + MOV AX,(ECS_call SHL 8) OR SetInterimMode ;AN000; 3/3/KK + MOV DL,InterimMode ;AN000; 3/3/KK + INT int_command ;AN000; 3/3/KK + + MOV AX,(STD_CON_INPUT_FLUSH SHL 8) OR STD_CON_INPUT_no_echo + INT int_command ; Get character with KB buffer flush + MOV AX,(STD_CON_INPUT_FLUSH SHL 8) + 0 + INT int_command + + MOV AX,(ECS_call SHL 8) OR SetInterimMode ;AN000; 3/3/KK + POP DX ;AN000; restore interim state 3/3/KK + INT int_command ;AN000; 3/3/KK + POP DX ;AN000; 3/3/KK + + return +EndProc GetKeyStroke + +Break + +; +; ReadBat - read a single line from the batch file. Perform all substitutions +; as appropriate +; + +Procedure ReadBat,NEAR + ASSUME DS:ResGroup,ES:TranGroup + mov suppress,yes_echo ;g initialize line suppress status + test byte ptr [Batch_Abort],-1 + jnz Trying_To_Abort + mov byte ptr [In_Batch],1 ; set flag to indicate batch job + CALL PromptBat + +Trying_To_Abort: + MOV DI,OFFSET TRANGROUP:COMBUF+2 + +; +; Save position and try to scan for first non delimiter. +; + +TESTNOP: + MOV AX,DS + MOV DS,Batch + ASSUME DS:NOTHING + PUSH WORD PTR DS:[BatSeek] + PUSH WORD PTR DS:[BatSeek+2] ; save current location. + MOV DS,AX + ASSUME DS:ResGroup + invoke SkipDelim ; skip to first non-delim +; +; If the first non-delimiter is not a : (label), we reseek back to the +; beginning and read the line. +; + CMP AL,':' ; is it a label? + POP CX + POP DX ; restore position in bat file + JZ NopLine ; yes, resync everything. + TEST [BATCH],-1 ; are we done with the batch file? + JZ RdBat + + CMP AL, NO_ECHO_CHAR ;g see if user wants to suppress line + JNZ SET_BAT_POS ;g no - go and set batch file position + MOV SUPPRESS, NO_ECHO ;g yes set flag to indicate + jmp Rdbat ;g go read batch file + +SET_BAT_POS: ;g + PUSH DS + MOV DS,Batch + ASSUME DS:NOTHING + MOV WORD PTR DS:[BatSeek],DX ; reseek back to beginning + MOV WORD PTR DS:[BatSeek+2],CX + POP DS + ASSUME DS:ResGroup + MOV AX,(LSEEK SHL 8) + 0 ; seek back + INT int_command + MOV BatBufPos,-1 ; nuke batch buffer position + xor cx,cx ; Initialize line length to zero + JMP RdBat +; +; The first non-delimiter is a :. This line is not echoed and is ignored. +; We eat characters until a CR is seen. +; + +NOPLINE: + CALL SkipToEOL + invoke GetBatByt ; eat trailing LF + TEST [BATCH],-1 ; are we done with the batch file? + JNZ TESTNOP ; no, go get another line + return ; Hit EOF + +; +; Read a line into the buffer pointed to by ES:DI. If any %s are seen in the +; input, we are to consider two special cases: +; +; %0 to %9 These represent replaceable parameters from the batch segment +; %sym% This is a symbol from the environment +; + +RDBAT: + invoke GetBatByt + inc cx ; Inc the line length + cmp cx,COMBUFLEN ; Is it too long? + jae TooLong ; Yes - handle it, handle it +; +; See if we have a parameter character. +; + CMP AL,'%' ; Check for parameter + JZ NEEDPARM +; +; no parameter character. Store it as usual and see if we are done. +; + +SAVBATBYT: + STOSB + CMP AL,0DH ; End of line found? + JNZ RDBAT ; no, go for more +; +; We have read in an entire line. Decide whether we should echo the command +; line or not. +; + +Found_EOL: + SUB DI,OFFSET TRANGROUP:COMBUF+3 + MOV AX,DI ; remember that we've not counted the CR + MOV ES:[COMBUF+1],AL ; Set length of line + invoke GetBatByt ; Eat linefeed + invoke BATCLOSE + CMP SUPPRESS, NO_ECHO ;G + JZ Reset ;G + test [echoflag],1 ; To echo or not to echo, that is the + jnz try_nextflag + +Reset: + PUSH CS ; question. (Profound, huh?) + POP DS ; Go back to local segment + retz ; no echoing here... +; +; Echo the command line with appropriate CRLF... +; + + +try_nextflag: + cmp nullflag,nullcommand ;G was there a command last time? + jz No_crlf_print ;G no - don't print crlf + invoke CRLF2 ;G Print out prompt + +no_crlf_print: + invoke PRINT_PROMPT ;G + PUSH CS ;G change data segment + POP DS ;G + +ASSUME DS:TRANGROUP + mov dx,OFFSET TRANGROUP:COMBUF+2 ; get command line for echoing + invoke CRPRINT + invoke CRLF2 + return +; +; The line was too long. Eat remainder of input text up until the CR +; +TooLong: + ASSUME DS:ResGroup + cmp al,0dh ; Has the end of the line been reached? + jz Ltlcont ; Yes, continue + CALL SkipToEOL ; Eat remainder of line + +Ltlcont: + stosb ; Terminate the command + jmp Found_EOL ; Go process the valid part of the line +; +; We have found a parameter lead-in character. Check for the 0-9 case first +; + +NEEDPARM: + invoke GetBatByt ; get next character + CMP AL,'%' ; Check for two consecutive % + JZ SAVBATBYT ; if so, replace with a single % + CMP AL,0Dh ; Check for end-of-line + JZ SAVBATBYT ; yes, treat it normally +; +; We have found %. If the is in the range 0-9, we +; retrieve the appropriate parameter from the batch segment. Otherwise we +; see if the has a terminating % and then look up the contents +; in the environment +; +PAROK: + SUB AL,'0' + JB NEEDENV ; look for parameter in the environment + CMP AL,9 + JA NEEDENV +; +; We have found %. This is taken from the parameters in the +; allocated batch area. +; + CBW + MOV BX,AX ; move index into AX + SHL BX,1 ; convert word index into byte ptr + SaveReg + MOV ES,Batch +; +; The structure of the batch area is: +; +; BYTE type of segment +; DWORD offset for next line +; 10 WORD pointers to parameters. -1 is empty parameter +; ASCIZ file name (with . and ..) +; BYTES CR-terminated parameters +; BYTE 0 flag to indicate end of parameters +; +; Get pointer to BX'th argument +; + MOV SI,ES:BatParm[BX] + RestoreReg +; +; Is there a parameter here? +; + CMP SI,-1 ; Check if parameter exists + JNZ Yes_there_is ;G Yes go get it + JMP RDBAT ; Ignore if it doesn't +; +; Copy in the found parameter from batch segment +; + +Yes_there_is: + PUSH DS + MOV DS,Batch + ASSUME DS:NOTHING + dec cx ; Don't count '%' in line length + +CopyParm: + LODSB ; From resident segment + CMP AL,0DH ; Check for end of parameter + JZ EndParam + inc cx ; Inc the line length + cmp cx,COMBUFLEN ; Is it too long? + jae LineTooL ; Yes - handle it, handle it + STOSB + JMP CopyParm +; +; We have copied up to the limit. Stop copying and eat remainder of batch +; line. We need to make sure that the tooLong code isn't fooled into +; believing that we are at EOL. Clobber AL too. +; + +LineTooL: + XOR AL,AL + POP DS + ASSUME DS:RESGROUP + JMP TooLong +; +; We have copied in an entire parameter. Go back for more +; + +EndParam: + POP DS + JMP RDBat +; +; We have found % followed by something other than 0-9. We presume that there +; will be a following % character. In between is an environment variable that +; we will fetch and replace in the batch line with its value. +; + +NEEDENV: + SaveReg + MOV DI,OFFSET TRANGROUP:ID ; temp spot for name + ADD AL,'0' ; reconvert character + STOSB ; store it in appropriate place +; +; loop getting characters until the next % is found or until EOL +; + +GETENV1: + invoke GetBatByt ; get the byte + STOSB ; store it + CMP AL,0Dh ; EOL? + JNZ GETENV15 ; no, see if it the term char +; +; The user entered a string with a % but no trailing %. We copy the string. +; + mov byte ptr es:[di-1],0 ; nul terminate the string + mov si,offset TranGroup:ID ; point to buffer + pop di ; point to line buffer + push cs + pop ds + call StrCpy +IF IBMCOPYRIGHT + dec di + pop ds +ELSE + pop ds + jc LineTooL +ENDIF + jmp SavBatByt + +getenv15: + CMP AL,'%' ; terminating %? + JNZ GETENV1 ; no, go suck out more characters + mov al,'=' ; terminate with = + MOV ES:[DI-1],al +; +; ID now either has a =-terminated string which we are to find in the +; environment or a non =-terminated string which will not be found in the +; environment. +; +GETENV2: + MOV SI,OFFSET TRANGROUP:ID + PUSH CS + POP DS ; DS:SI POINTS TO NAME + ASSUME DS:TRANGROUP + PUSH CX + INVOKE FIND_NAME_IN_environment + ASSUME ES:RESGROUP + POP CX + PUSH ES + POP DS + assume ds:resgroup + PUSH CS + POP ES + ASSUME ES:TRANGROUP + MOV SI,DI + POP DI ; get back pointer to command line +; +; If the parameter was not found, there is no need to perform any replacement. +; We merely pretend that we've copied the parameter. +; +IF IBMCOPYRIGHT + JC GETENV6 +ELSE + jnc GETENV4 + pop ds + jmp rdbat +ENDIF +; +; ES:DI points to command line being built +; DS:SI points either to nul-terminated environment object AFTER = +; + +GETENV4: + ASSUME ES:NOTHING + call StrCpy + +IF IBMCOPYRIGHT + dec di + +GETENV6: + POP DS ; restore pointer to resgroup +ELSE + pop ds + jc LineTooL +ENDIF + JMP RDBAT ; no, go back to batch file + +EndProc ReadBat + +; +; SkipToEOL - read from batch file until end of line +; + +Procedure SkipToEOL,NEAR + + ASSUME DS:ResGroup,ES:NOTHING + + TEST Batch,-1 + retz ; no batch file in effect + invoke GetBatByt + CMP AL,0Dh ; eol character? + JNZ SkipToEOL ; no, go eat another + return + +EndProc SkipToEOL + +Break + +; +; Free Transient. Modify ES,AX,flags +; + +Procedure Free_TPA,NEAR + +ASSUME DS:TRANGROUP,ES:RESGROUP + + PUSH ES + MOV ES,[RESSEG] + MOV ES,[RES_TPA] + MOV AH,DEALLOC + INT int_command ; Make lots of free memory + POP ES + + return + +EndProc Free_TPA + +; +; Allocate transient. Modify AX,BX,DX,flags +; + +Procedure Alloc_TPA,NEAR + +ASSUME DS:TRANGROUP,ES:RESGROUP + + PUSH ES + MOV ES,[RESSEG] + MOV BX,0FFFFH ; Re-allocate the transient + MOV AH,ALLOC + INT int_command + PUSH BX ; Save size of block + MOV AH,ALLOC + INT int_command +; +; Attempt to align TPA on 64K boundary +; + POP BX ; Restore size of block + MOV [RES_TPA], AX ; Save segment to beginning of block + MOV [TRAN_TPA], AX +; +; Is the segment already aligned on a 64K boundary +; + MOV DX, AX ; Save segment + AND AX, 0FFFH ; Test if above boundary + JNZ Calc_TPA + MOV AX, DX + AND AX, 0F000H ; Test if multiple of 64K + JNZ NOROUND + +Calc_TPA: + MOV AX, DX + AND AX, 0F000H + ADD AX, 01000H ; Round up to next 64K boundary + JC NOROUND ; Memory wrap if carry set +; +; Make sure that new boundary is within allocated range +; + MOV DX, [RES_TPA] + ADD DX, BX ; Compute maximum address + CMP DX, AX ; Is 64K address out of range? + JB NOROUND +; +; Make sure that we won't overwrite the transient +; + MOV BX, CS ; CS is beginning of transient + CMP BX, AX + JB NOROUND +; +; The area from the 64K boundary to the beginning of the transient must +; be at least 64K. +; + SUB BX, AX + CMP BX, 4096 ; Size greater than 64K? + JAE ROUNDDONE + +NOROUND: + MOV AX, [RES_TPA] + +ROUNDDONE: + MOV [LTPA],AX ; Re-compute everything + MOV [TPA],AX + MOV BX,AX + MOV AX,CS + SUB AX,BX + PUSH BX + MOV BX,16 + MUL BX + POP BX + OR DX,DX + JZ SAVSIZ2 + MOV AX,-1 + +SAVSIZ2: +; +; AX is the number of bytes free in the buffer between the resident and the +; transient with a maximum of 64K-1. We round this down to a multiple of 512. +; + CMP AX,512 + JBE GotSize + AND AX,0FE00h ; NOT 511 = NOT 1FF + +GotSize: + MOV [BYTCNT],AX + POP ES + + return + +EndProc Alloc_TPA + +Break + +; +; The exec search has determined that the user has requested a batch file for +; execution. We parse the arguments, create the batch segment, and signal +; batch processing. +; +Procedure BatCom,NEAR + +ASSUME DS:TRANGROUP, ES:NOTHING + +; +; Batch parameters are read with ES set to segment of resident part +; + + MOV ES,[RESSEG] +ASSUME ES:RESGROUP + cmp es:[call_batch_flag],call_in_progress ;AN043; If in CALL, + jz skip_ioset ;AN043; redirection was already set up + invoke IOSET ; Set up any redirection + +skip_ioset: ;AN043; + CALL FREE_TPA ; G + cmp es:[call_batch_flag],call_in_progress ;G + jz getecho ; G if we're in a call, don't execute +; +; Since BATCH has lower precedence than PIPE or FOR. If a new BATCH file is +; being started it MUST be true that no FOR or PIPE is currently in progress. +; Don't execute if in call +; + invoke ForOff + +getecho: + invoke PipeOff + mov al,EchoFlag ; preserve echo state for chaining + + and al, 1 ; Save current echo state + push ax + + xor ax,ax ;G + test es:[batch],-1 ;G Are we in a batch file? + jz leavebat ;G No, nothing to save + mov ax,es:[batch] ;G get current batch segment + cmp es:[call_batch_flag],call_in_progress ;G + jz leavebat ;G +; +; We are in a chained batch file, save batlast from previous batch segment +; so that if we're in a CALL, we will return to the correct batch file. +; + push es ;G + mov es,ax ;G get current batch segment + mov ax,es:[batlast] ;G get previous batch segment + pop es ;G + +leavebat: ;G + push ax ;G keep segment until new one created + cmp es:[call_batch_flag],call_in_progress ;G are we in a CALL? + jz startbat ;G Yes, keep current batch segment + call BatchOff ;G No, deallocate old batch segment + +; +; Find length of batch file +; + +startbat: ;G + ASSUME ES:RESGROUP + MOV es:[CALL_BATCH_FLAG], 0 ;G reset call flag + mov SI, OFFSET TRANGROUP:EXECPATH + + mov ax,AppendTruename ;AN042; Get the real path where the batch file + int 2fh ;AN042; was found with APPEND + mov ah,Find_First ;AN042; The find_first will return it + mov dx,si ;AN042; Get the string + mov cx,search_attr ;AN042; filetypes to search for + int int_command ;AN042; + + invoke DStrLen +; +; Allocate batch area: +; BYTE type of segment +; WORD segment of last batch file +; WORD segment for FOR command +; BYTE FOR flag state on entry to batch file +; DWORD offset for next line +; 10 WORD pointers to parameters. -1 is empty parameter +; ASCIZ file name (with . and ..) +; BYTES CR-terminated parameters +; BYTE 0 flag to indicate end of parameters +; +; We allocate the maximum size for the command line and use setblock to shrink +; later when we've squeezed out the extra +; + + MOV BX,CX ; length of file name. + ADD BX,0Fh + (SIZE BatchSegment) + COMBUFLEN + 0Fh + ; structure + max len + round up + SaveReg + MOV CL,4 + SHR BX,CL ; convert to paragraphs + PUSH BX ;G save size of batch segment + MOV AH,ALLOC + INT int_command ; Allocate batch segment + POP BX ;G get size of batch segment +; +; This should *NEVER* return an error. The transient is MUCH bigger than +; the batch segment. This may not be true, however, in a multitasking system. +; G This error will occur with nesting of batch files. We also need to +; G make sure that we don't overlay the transient. +; + jc mem_error ;G not enough memory - exit + push ax ;G save batch segment + add ax,bx ;G get end of batch segment + add ax,20h ;G add some tpa work area + mov bx,cs ;G get the transient segment + cmp ax,bx ;G do we end before the transient + pop ax ;G get batch segment back + jb enough_mem ;G we have enough memory - continue + push es ;G no we're hitting the transient + mov es,ax + mov ax,DEALLOC SHL 8 ;G deallocate the batch segment + int int_command + pop es + +mem_error: + jmp no_memory ;G Set up for message and exit + +enough_mem: + MOV [BATCH],AX + CALL ALLOC_TPA +; +; Initialize batch segment +; + RestoreReg ; length of name + POP AX ;G get saved batch segment back + inc es:nest ;G increment # batch files in progress + PUSH ES + MOV ES,[BATCH] +ASSUME ES:NOTHING + MOV ES:[BatType],BatchType ; signal batch file type + MOV ES:[batlast],ax ;G save segment of last batch file + push DS ;G + mov DS,[resseg] ;G set to resident data +ASSUME DS:RESGROUP + xor ax,ax ;G + mov bl,forflag ;G get the current FOR state + mov ES:[batforflag],bl ;G save it in the batch segment + test bl,-1 ;G are we in a FOR? + jz for_not_on ;G no, for segment set to 0 + mov ax,forptr ;G yes, get current FOR segment + mov forflag,0 ;G reset forflag + +for_not_on: + mov ES:[batforptr],ax ;G save FOR segment in batch segment + XOR AX,AX + mov forptr,ax ;G make sure for segment is not active + mov bl,echoflag ;G + pop DS ;G + + mov byte ptr es:[Batechoflag],bl ;G save echo state of parent + MOV WORD PTR ES:[BatSeek],AX ; point to beginning of file + MOV WORD PTR ES:[BatSeek+2],AX +; +; Initialize pointers +; + DEC AX ; put -1 into AX + MOV DI,BatParm ; point to parm area + MOV BX,DI + MOV CX,10 + REP STOSW ; Init to no parms +; +; Move in batch file name +; + MOV CX,DX + rep movsb ; including NUL. +; +; Now copy the command line into batch segment, parsing the arguments along +; the way. Segment will look like this: +; +; CRCR...CRCR...CR 0 +; +; or, in the case of fewer arguments: +; +; CRCR...CR CR CR ... CR 0 +; + MOV SI,OFFSET TRANGROUP:COMBUF+2 + MOV CX,10 ; at most 10 arguments +; +; Look for beginning of next argument +; +EACHPARM: + invoke SCANOFF ; skip to argument +; +; AL is first non-delimiter. DS:SI points to char = AL +; + CMP AL,0DH ; end of road? + JZ HAVPARM ; yes, no more arguments +; +; If CX = 0 then we have stored the most parm we can. Skip store +; + JCXZ MOVPARM ; Only first 10 parms get pointers +; +; Go into allocated piece and stick in new argument pointer. +; + MOV ES:[BX],DI ; store batch pointer + ADD BX,2 ; advance arg counter +; +; Move the parameter into batch segment +; +MOVPARM: + LODSB ; get byte + INVOKE DELIM ; if delimiter + JZ ENDPARM ; then done with parm + STOSB ; store byte + CMP AL,0DH ; if CR then not delimiter + JZ HAVPARM ; but end of parm list, finish + JMP SHORT MOVPARM +; +; We have copied a parameter up until the first separator. Terminate it with +; CR +; + +ENDPARM: + MOV AL,0DH + STOSB + JCXZ EACHPARM ; if no parameters, don't dec + DEC CX ; remember that we've seen one. + JMP SHORT EACHPARM +; +; We have parsed the entire line. Terminate the arg list +; + +HAVPARM: + XOR AL,AL + STOSB ; Nul terminate the parms +; +; Now we know EXACTLY how big the BATCH segment is. Round up size (from DI) +; into paragraphs and setblock to the appropriate size +; + LEA BX,[DI+15] + MOV CL,4 + SHR BX,CL + MOV AH,SetBlock + INT int_command + + POP ES +ASSUME ES:RESGROUP + PUSH ES + POP DS ; Simply batch FCB setup +ASSUME DS:RESGROUP + CMP [SINGLECOM],-1 + JNZ NOBATSING + MOV [SINGLECOM],0FFF0H ; Flag single command BATCH job + +NOBATSING: +; +; Enter the batch file with the current echo state +; + pop ax ; Get original echo state + mov echoflag,al ;g restore it + JMP TCOMMAND + +; +; The following is executed if there isn't enough memory for batch segment +; + +NO_MEMORY: + assume ds:trangroup,es:resgroup + pop dx ;g even up our stack + pop ax ;g + pop ax ;g + call Alloc_tpa ;g reallocate memory + 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 ;g print error message and go... + +EndProc BatCom + +Procedure BatchOff + + ASSUME DS:NOTHING,ES:NOTHING + + SaveReg + PUSH DS ;G + PUSH BX ;G + MOV ES,ResSeg + MOV DS,ResSeg ;G + ASSUME ES:ResGroup,DS:Resgroup ;G + MOV AX,Batch ; Free the batch segment + OR AX,AX + JZ nofree + + PUSH ES + MOV ES,AX + test [echoflag],1 ;G Is echo on? + jnz echo_last_line ;G Yes - echo last line in file + mov suppress,no_echo ;G no - don't echo last line in file + +echo_last_line: + MOV BL,ES:[BATECHOFLAG] ;G Get echo state + mov [echoflag],bl ;G and restore it + MOV BX,ES:[BATFORPTR] ;G Get FOR segment + MOV FORPTR,BX ;G and restore it + MOV BL,ES:[BATFORFLAG] ;G Get FOR flag + MOV FORFLAG,BL ;G and restore it + MOV BX,es:[batlast] ;G get old batch segment + MOV AH,DEALLOC + INT int_command + POP ES + MOV Next_BATCH,BX ;G reset batch segment + DEC es:NEST ;G + + XOR AX,AX + MOV Batch,AX ; No batch in progress + +NoFree: + POP BX ;G + pop ds ;G + RestoreReg + + return + +EndProc BatchOff + + +IF IBMCOPYRIGHT + +Procedure StrCpy,near + + push ax +cycle: + lodsb + stosb + or al,al + jnz cycle + pop ax + + return + +EndProc StrCpy + +ELSE +; StrCpy - copy string, checking count in CX against COMBUFLEN +; Entry : DS:SI ==> source string +; ES:DI ==> destination string +; CX = current length of destination string +; Exit : string copied, CX updated, Carry set if length limit exceeded +Procedure StrCpy,NEAR + push ax +ccycle: + lodsb + inc cx + cmp cx,COMBUFLEN + jb ccopy + stc ; set carry to signal error + jmp short ccend +ccopy: + stosb + or al,al + jnz ccycle + +ccend: + dec cx ; discount extra byte + dec di ; back up pointer + pop ax + return ; return carry clear +EndProc StrCpy + +ENDIF + +TRANCODE ENDS + END + diff --git a/v4.0/src/CMD/COMMAND/TBATCH2.ASM b/v4.0/src/CMD/COMMAND/TBATCH2.ASM new file mode 100644 index 0000000..501c637 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TBATCH2.ASM @@ -0,0 +1,753 @@ + page 80,132 +; SCCSID = @(#)tbatch2.asm 4.2 85/07/22 +; SCCSID = @(#)tbatch2.asm 4.2 85/07/22 +TITLE Batch processing routines part II + + INCLUDE comsw.asm + +.xlist +.xcref + INCLUDE DOSSYM.INC + INCLUDE comseg.asm + INCLUDE comequ.asm +.list +.cref + + +DATARES SEGMENT PUBLIC BYTE ;AC000; + EXTRN BATCH:WORD + EXTRN Batch_Abort:byte + EXTRN call_batch_flag:byte + EXTRN call_flag:byte + EXTRN IFFlag:BYTE + EXTRN In_Batch:byte + EXTRN Nest:word + EXTRN PIPEFILES:BYTE + EXTRN RETCODE:WORD + EXTRN SINGLECOM:WORD +DATARES ENDS + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN BADLAB_PTR:WORD + EXTRN BatBufLen:WORD + EXTRN IFTAB:BYTE + EXTRN SYNTMES_PTR:WORD +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN arg:byte ; the arg structure! + EXTRN BatBuf:BYTE + EXTRN BatBufEnd:WORD + EXTRN BatBufPos:WORD + EXTRN BATHAND:WORD + EXTRN COMBUF:BYTE + EXTRN DIRBUF:BYTE + EXTRN GOTOLEN:WORD + EXTRN if_not_count:word + EXTRN IFNOTFLAG:BYTE + EXTRN RESSEG:WORD +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC BYTE + +ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + + EXTRN cerror:near + EXTRN docom1:near + EXTRN tcommand:near + + public $if,iferlev,goto,shift,ifexists,ifnot,forerror,$call + + +Break + +; Get one byte from the batch file and return it in AL. End-of-file returns +; and ends batch mode. DS must be set to resident segment. +; AH, DX destroyed. + +Procedure GETBATBYT,NEAR + +ASSUME DS:RESGROUP + + SaveReg + test byte ptr [Batch_Abort],-1 + jnz BatEOF + TEST Batch,-1 + JZ BatEOF + PUSH ES + MOV ES,Batch + ASSUME ES:NOTHING + ADD WORD PTR ES:[BatSeek],1 + ADC WORD PTR ES:[BatSeek+2],0 + POP ES +; +; See if we have bytes buffered... +; + MOV AX,CS + MOV DS,AX + ASSUME DS:TranGroup + MOV BX,BatBufPos + CMP BX,-1 + JNZ UnBuf +; +; There are no bytes in the buffer. Let's try to fill it up. +; + MOV DX,OFFSET TranGROUP:BatBuf + MOV CX,BatBufLen ; max to read. + MOV BX,BatHand + MOV AH,READ + INT int_command ; Get one more byte from batch file + jnc bat_read_ok ;AN022; if no error - continue + invoke get_ext_error_number ;AN022; get the error + push ds ;AN022; save local segment + mov ds,[resseg] ;AN022; get resident segment +assume ds:resgroup ;AN022; + mov dx,ax ;AN022; put error in DX + invoke output_batch_name ;AN022; set up to print the error + pop ds ;AN022; +assume ds:trangroup ;AN022; + invoke std_eprintf ;AN022; print out the error + mov byte ptr combuf+2,end_of_line_in;AN022; terminate the batch line for parsing + mov byte ptr combuf+3,end_of_line_out ;AN022; terminate the batch line for output + jmp bateof ;AN022; terminate the batch file + +bat_read_ok: ;AN022; + MOV CX,AX + JCXZ BATEOFDS + MOV BatBufEnd,CX + XOR BX,BX + MOV BatBufPos,BX +; +; Buffered bytes! +; +UnBuf: + MOV AL,BatBuf[BX] ; get next byte + INC BX + CMP BX,BatBufEnd ; beyond end of buffer? + JB SetBufPos + MOV BX,-1 + +SetBufPos: + MOV BatBufPos,BX + CMP AL,1AH ; ^Z for termination? + jnz GetByteDone + +BatEOFDS: + ASSUME DS:TranGroup + MOV DS,ResSeg + ASSUME DS:ResGroup + +BATEOF: + invoke BatchOff + CALL BATCLOSE + MOV AL,0DH ; If end-of-file, then end of line + test byte ptr [Batch_Abort],-1 + mov byte ptr [Batch_Abort],0 + jz Cont_Get_Byt + mov di,offset TRANGROUP:COMBUF+2 ; reset pointer to beginning of buffer + xor cx,cx ; zero line length + jmp short GetByteDone + +Cont_Get_Byt: + CMP [SINGLECOM],0FFF0H ; See if we need to set SINGLECOM + JNZ GetByteDone + CMP NEST,0 ;G See if we have nested batch files + JNZ GETBYTEDONE ;G Yes - don't exit just yet + MOV [SINGLECOM],-1 ; Cause termination + +GetByteDone: + RestoreReg + + return + +EndProc GetBatByt + + break <$If - conditional execution> +assume ds:trangroup,es:trangroup + +IFERRORP: + POP AX +IFERROR: +FORERROR: + MOV DX,OFFSET TRANGROUP:SYNTMES_ptr + JMP CERROR + +$IF: +; +; Turn off any pipes in progress. +; + push ds ;AN004; save local DS + mov ds,[resseg] ;AN004; get resident segment + assume ds:resgroup ;AN004; + cmp [PIPEFILES],0 ;AN004; Only turn off if present. + jz IFNoPipe ;AN004; no pipe - continue + invoke PipeDel ;AN004; turn off piping + +IFNoPipe: ;AN004; + pop ds ;AN004; get local DS back + assume ds:trangroup ;AN004; + MOV [IFNOTFLAG],0 + mov [if_not_count], 0 + MOV SI,81H + +IFREENT: + invoke SCANOFF + CMP AL,0DH + JZ IFERROR + MOV BP,SI + MOV DI,OFFSET TRANGROUP:IFTAB ; Prepare to search if table + MOV CH,0 + +IFINDCOM: + MOV SI,BP + MOV CL,[DI] + INC DI + JCXZ IFSTRING + JMP SHORT FIRSTCOMP + +IFCOMP: + JNZ IF_DIF ;AC000; + +FIRSTCOMP: + LODSB + MOV AH,ES:[DI] + INC DI + CMP AL,AH + JZ IFLP + OR AH,20H ; Try lower case + CMP AL,AH + +IFLP: + LOOP IFCOMP + +IF_DIF: ;AC000; + LAHF + ADD DI,CX ; Bump to next position without affecting flags + MOV BX,[DI] ; Get handler address + INC DI + INC DI + SAHF + JNZ IFINDCOM + LODSB + CMP AL,0DH + +IFERRORJ: + JZ IFERROR + invoke DELIM + JNZ IFINDCOM + invoke SCANOFF + JMP BX + +IFNOT: + NOT [IFNOTFLAG] + inc [if_not_count] + JMP IFREENT + +; +; We are comparing two strings for equality. First, find the end of the +; first string. +; + +IFSTRING: + PUSH SI ; save away pointer for later compare + XOR CX,CX ; count of chars in first string + +FIRST_STRING: + LODSB ; get character + CMP AL,0DH ; end of line? + JZ IFERRORP ; yes => error + invoke DELIM ; is it a delimiter? + JZ EQUAL_CHECK ; yes, go find equal sign + INC CX ; remember 1 byte for the length + JMP FIRST_STRING ; go back for more +; +; We have found the end of the first string. Unfortunately, we CANNOT use +; scanoff to find the next token; = is a valid separator and will be skipped +; over. +; + +EQUAL_CHECK: + CMP AL,'=' ; is char we have an = sign? + JZ EQUAL_CHECK2 ; yes, go find second one. + CMP AL,0DH ; end of line? + JZ IFERRORPj ;AC004; yes, syntax error + LODSB ; get next char + JMP EQUAL_CHECK +; +; The first = has been found. The next char had better be an = too. +; + +EQUAL_CHECK2: + LODSB ; get potential = char + CMP AL,'=' ; is it good? + jnz iferrorpj ; no, error +; +; Find beginning of second string. +; + invoke SCANOFF + CMP AL,0DH + jz iferrorpj + POP DI +; +; DS:SI points to second string +; CX has number of chars in first string +; ES:DI points to first string +; +; Perform compare to elicit match +; + REPE CMPSB + JZ MATCH ; match found! +; +; No match. Let's find out what was wrong. The character that did not match +; has been advanced over. Let's back up to it. +; + DEC SI +; +; If it is EOL, then syntax error +; + CMP BYTE PTR [SI],0DH + JZ IFERRORJ +; +; Advance pointer over remainder of unmatched text to next delimiter +; + +SKIPSTRINGEND: + LODSB + +NOTMATCH: + CMP AL,0DH + +IFERRORJ2: + JZ IFERRORJ + invoke DELIM + JNZ SKIPSTRINGEND +; +; Signal that we did NOT have a match +; + MOV AL,-1 + JMP SHORT IFRET + +iferrorpj: + jmp iferrorp +; +; The compare succeeded. Was the second string longer than the first? We +; do this by seeing if the next char is a delimiter. +; + +MATCH: + LODSB + invoke DELIM + JNZ NOTMATCH ; not same. + XOR AL,AL + JMP SHORT IFRET + +IFEXISTS: +ifexist_attr EQU attr_hidden+attr_system + +moredelim: + lodsb ; move command line pointer over + invoke delim ; pathname -- have to do it ourselves + jnz moredelim ; 'cause parse_file_descriptor is dumb + mov DX, OFFSET TRANGROUP:dirbuf + trap set_dma + mov BX, 2 ; if(0) [|not](|1) exist[1|2] file(2|3) + add BX, [if_not_count] + mov AX, OFFSET TRANGROUP:arg.argv + invoke argv_calc ; convert arg index to pointer + mov DX, [BX].argpointer ; get pointer to supposed filename + mov CX, ifexist_attr ; filetypes to search for + trap Find_First ; request first match, if any + jc if_ex_c ; carry is how to determine error + xor AL, AL + jmp ifret + +if_ex_c: + mov AL, -1 ; false 'n' fall through... + +IFRET: + TEST [IFNOTFLAG],-1 + JZ REALTEST + NOT AL + +REALTEST: + OR AL,AL + JZ IFTRUE + JMP TCOMMAND + +IFTRUE: + invoke SCANOFF + MOV CX,SI + SUB CX,81H + SUB DS:[80H],CL + MOV CL,DS:[80H] + MOV [COMBUF+1],CL + MOV DI,OFFSET TRANGROUP:COMBUF+2 + CLD + REP MOVSB + MOV AL,0DH + STOSB +; +; Signal that an IF was done. This prevents the redirections from getting +; lost. +; + PUSH DS + MOV DS,ResSeg + ASSUME DS:RESGROUP + MOV IFFlag,-1 + POP DS + ASSUME DS:TRANGROUP +; +; Go do the command +; + JMP DOCOM1 + +iferrorj3: + jmp iferrorj2 + +IFERLEV: + MOV BH,10 + XOR BL,BL + +GETNUMLP: + LODSB + CMP AL,0DH + jz iferrorj3 + invoke DELIM + JZ GOTNUM + SUB AL,'0' + XCHG AL,BL + MUL BH + ADD AL,BL + XCHG AL,BL + JMP SHORT GETNUMLP + +GOTNUM: + PUSH DS + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + MOV AH,BYTE PTR [RETCODE] + POP DS +ASSUME DS:TRANGROUP + XOR AL,AL + CMP AH,BL + JAE IFRET + DEC AL + JMP SHORT IFRET + + + break +assume ds:trangroup,es:trangroup + +; +; Shift the parameters in the batch structure by 1 and set up the new argument. +; This is a NOP if no batch in progress. +; + +Procedure Shift,NEAR + + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + MOV AX,[BATCH] ; get batch pointer + OR AX,AX ; in batch mode? + retz ; no, done. + MOV ES,AX ; operate in batch segment + MOV DS,AX + +ASSUME DS:NOTHING,ES:NOTHING + +; +; Now move the batch args down by 1 word +; + MOV DI,BatParm ; point to parm table + LEA SI,[DI+2] ; make source = dest + 2 + MOV CX,9 ; move 9 parameters + REP MOVSW ; SHIFT down +; +; If the last parameter (the one not moved) is empty (= -1) then we are done. +; We have copied it into the previous position +; + CMP WORD PTR [DI],-1 ; if last one was not in use then + retz ; No new parm +; +; This last pointer is NOT nul. Get it and scan to find the next argument. +; Assume, first, that there is no next argument +; + MOV SI,[DI] + MOV WORD PTR [DI],-1 ; Assume no parm +; +; The parameters are CR separated. Scan for end of this parm +; +SKIPCRLP: + LODSB + CMP AL,0DH + JNZ SKIPCRLP +; +; We are now pointing at next arg. If it is 0 (end of original line) then we +; are finished. There ARE no more parms and the pointer has been previously +; initialized to indicate it. +; + CMP BYTE PTR [SI],0 + retz ; End of parms + MOV [DI],SI ; Pointer to next parm as %9 + + return + +EndProc Shift + +; +; Skip delim reads bytes from the batch file until a non-delimiter is seen. +; returns char in AL, carry set -> eof +; + +Procedure SkipDelim,NEAR + + ASSUME DS:ResGroup,ES:NOTHING + TEST Batch,-1 + JZ SkipErr ; batch file empty. OOPS! + CALL GetBatByt ; get a char + invoke Delim ; check for ignoreable chars + JZ SkipDelim ; ignore this char. + clc + return + +SkipErr: + stc + return + +EndProc SkipDelim + + break $Call + +; CALL is an internal command that transfers control to a .bat, .exe, or +; .com file. This routine strips the CALL off the command line, sets +; the CALL_FLAG to indicate a call in progress, and returns control to +; DOCOM1 in TCODE to reprocess the command line and execute the file +; being CALLed. + +$CALL: + +; strip off CALL from command line + + ASSUME DS:trangroup,ES:trangroup + push si + push di + push ax + push cx + mov si,offset trangroup:combuf+2 + invoke scanoff ;get to first non-delimeter + add si,length_call ;point to char past CALL + mov di,offset trangroup:combuf+2 + mov cx,combuflen-length_call ;get length of buffer + rep movsb ;move it + pop cx + pop ax + pop di + pop si + + +; set call flag to indicate call in progress + + push ds + mov ds,[resseg] + ASSUME DS:resgroup,ES:resgroup + mov call_flag, call_in_progress + mov call_batch_flag, call_in_progress +; +; Turn off any pipes in progress. +; + cmp [PIPEFILES],0 ; Only turn off if present. + jz NoPipe + invoke PipeDel +NoPipe: + pop ds + + ret + + break Goto + +GOTO: + +assume ds:trangroup,es:trangroup + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + TEST [BATCH],-1 + retz ; If not in batch mode, a nop + XOR DX,DX + PUSH DS + MOV DS,Batch + MOV WORD PTR DS:[BatSeek],DX ; Back to start + MOV WORD PTR DS:[BatSeek+2],DX ; Back to start + POP DS + +GotoOpen: + invoke promptBat + MOV DI,FCB+1 ; Get the label + MOV CX,11 + MOV AL,' ' + REPNE SCASB + JNZ NOINC + INC CX + +NOINC: + SUB CX,11 + NEG CX + MOV [GOTOLEN],CX +; +; At beginning of file. Skip to first non-delimiter char +; + CALL SkipDelim + JC BadGoto + CMP AL,':' + JZ CHKLABEL + +LABLKLP: ; Look for the label + CALL GETBATBYT + CMP AL,0AH + JNZ LABLKTST +; +; At beginning of line. Skip to first non-delimiter char +; + CALL SkipDelim + JC BadGoto + CMP AL,':' + JZ CHKLABEL + +LABLKTST: + TEST [BATCH],-1 + JNZ LABLKLP + +BadGoto: + CALL BATCLOSE + PUSH CS + POP DS + MOV DX,OFFSET TRANGROUP:BADLAB_ptr + JMP CERROR + +; +; Found the :. Skip to first non-delimiter char +; + +CHKLABEL: + CALL SkipDelim + JC BadGoto + MOV DI,FCB+1 + MOV CX,[GOTOLEN] + JMP SHORT GotByte + +NEXTCHRLP: + PUSH CX + CALL GETBATBYT + POP CX + +GotByte: + INVOKE TESTKANJ ;AN000; 3/3/KK + JZ NOTKANJ1 ;AN000; 3/3/KK + CMP AL, ES:[DI] ;AN000; 3/3/KK + JNZ LABLKTST ;AN000; 3/3/KK + INC DI ;AN000; 3/3/KK + DEC CX ;AN000; 3/3/KK + JCXZ LABLKTST ;AN000; 3/3/KK + PUSH CX ;AN000; 3/3/KK + CALL GETBATBYT ;AN000; 3/3/KK + POP CX ;AN000; 3/3/KK + CMP AL, ES:[DI] ;AN000; 3/3/KK + JMP SHORT KNEXTLABCHR ;AN000; 3/3/KK + +NOTKANJ1: ;AN000; 3/3/KK + OR AL,20H + CMP AL,ES:[DI] + JNZ TRYUPPER + JMP SHORT NEXTLABCHR + +TRYUPPER: + SUB AL,20H + CMP AL,ES:[DI] + +KNEXTLABCHR: ;AN000; 3/3/KK + JNZ LABLKTST + +NEXTLABCHR: + INC DI + LOOP NEXTCHRLP + CALL GETBATBYT + cmp [GOTOLEN],8 ; Is the label atleast 8 chars long? + jge gotocont ; Yes, then the next char doesn't matter + CMP AL,' ' + JA LABLKTST + +gotocont: + CMP AL,0DH + JZ SKIPLFEED + +TONEXTBATLIN: + CALL GETBATBYT + CMP AL,0DH + JNZ TONEXTBATLIN + +SKIPLFEED: + CALL GETBATBYT + CALL BatClose + + return + +Procedure BatClose,NEAR + + MOV BX,CS:[BATHAND] + CMP BX,5 + JB CloseReturn + MOV AH,CLOSE + INT int_command + +CloseReturn: + mov byte ptr [In_Batch],0 ; reset flag + return + +EndProc BatClose + +; +; Open the BATCH file, If open fails, AL is drive of batch file (A=1) +; Also, fills internal batch buffer. If access denied, then AX = -1 +; + +Procedure BatOpen,NEAR + +ASSUME DS:RESGROUP,ES:TRANGROUP + + PUSH DS + MOV DS,[BATCH] +ASSUME DS:NOTHING + + MOV DX,BatFile + MOV AX,OPEN SHL 8 + INT int_command ; Open the batch file + JC SETERRDL + MOV DX,WORD PTR DS:[BatSeek] + MOV CX,WORD PTR DS:[BatSeek+2] + POP DS +ASSUME DS:RESGROUP + + MOV [BATHAND],AX + MOV BX,AX + MOV AX,LSEEK SHL 8 ; Go to the right spot + INT int_command + MOV BatBufPos,-1 ; nuke batch buffer position + + return + +SETERRDL: + MOV BX,DX + invoke get_ext_error_number ;AN022; get the extended error + mov dx,ax ;AN022; save extended error in DX + MOV AL,[BX] ; Get drive spec + SUB AL,'@' ; A = 1 + POP DS + STC ; SUB mucked over carry + + return + +EndProc BatOpen + + +TRANCODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/TCMD1A.ASM b/v4.0/src/CMD/COMMAND/TCMD1A.ASM new file mode 100644 index 0000000..fd662b3 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TCMD1A.ASM @@ -0,0 +1,598 @@ + page 80,132 +; SCCSID = @(#)tcmd1a.asm 1.1 85/05/14 +; SCCSID = @(#)tcmd1a.asm 1.1 85/05/14 +TITLE PART4 COMMAND Transient routines. + +; Internal commands DIR,PAUSE,ERASE,TYPE,VOL,VER + + INCLUDE comsw.asm +.xlist +.xcref + INCLUDE DOSSYM.INC + INCLUDE comseg.asm + INCLUDE comequ.asm ;AC000; + include ioctl.inc ;AN000; +.list +.cref + +DATARES SEGMENT PUBLIC BYTE ;AN020; + EXTRN append_flag:byte ;AN020; + EXTRN append_state:word ;AN020; +DATARES ENDS ;AN020; + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN BadCD_ptr:word + EXTRN bits:word + EXTRN Bytmes_ptr:word + EXTRN comsw:word + EXTRN dir_w_syn:word ;AC000; + EXTRN dirdat_mo_day:word ;AC000; + EXTRN dirdat_yr:word ;AC000; + EXTRN dirdattim_ptr:word + EXTRN dirhead_ptr:word + EXTRN dirtim_hr_min:word ;AC000; + EXTRN Dirmes_ptr:word + EXTRN disp_file_size_ptr:word + EXTRN Dmes_ptr:word + EXTRN Extend_buf_ptr:word ;AN000; + EXTRN msg_disp_class:byte ;AN000; + EXTRN parse_dir:byte ;AC000; + EXTRN slash_p_syn:word ;AC000; + EXTRN string_buf_ptr:word + EXTRN tab_ptr:word ;AC000; +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN bytes_free:word + EXTRN charbuf:byte + EXTRN COM:byte + EXTRN Destisdir:byte + EXTRN Desttail:word + EXTRN dir_num:word + EXTRN Dirbuf:byte + EXTRN dirflag:byte ;AN015; + EXTRN display_ioctl:word ;AC000; + EXTRN display_mode:byte ;AC000; + EXTRN filecnt:word + EXTRN file_size_high:word + EXTRN file_size_low:word + EXTRN fullscr:word + EXTRN ID:byte + EXTRN lincnt:byte ;AC000; + EXTRN linlen:byte + EXTRN linperpag:word ;AC000; + EXTRN msg_numb:word ;AN022; + EXTRN parse1_addr:dword ;AC000; + EXTRN parse1_syn:word ;AC000; + EXTRN parse1_type:byte ;AC000; + EXTRN pathcnt:word ;AN000; + EXTRN pathpos:word ;AN000; + EXTRN resseg:word ;AN020; + EXTRN srcbuf:byte ;AC000; + EXTRN string_ptr_2:word +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC BYTE + +ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + +;--------------- + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN arg:byte ; the arg structure! +TRANSPACE ENDS +;--------------- + + EXTRN cerror:near + EXTRN std_printf:near + + + PUBLIC catalog + + + break Catalog - Directory command +assume ds:trangroup,es:trangroup + +; +; The DIR command displays the contents of a directory. +; +; **************************************************************** +; * +; * ROUTINE: CATALOG - display file(s) in directory +; * +; * FUNCTION: PARSE command line for drive, file, or path name. +; * DIR allows two switches, /P (pause) and /W (wide). +; * If an error occurs issue and error message and +; * transfer control to CERROR. +; * +; * INPUT: command line at offset 81H +; * +; * OUTPUT: none +; * +; **************************************************************** + +CATALOG: + +; +; Set up DTA for dir search firsts +; + mov dx,offset trangroup:Dirbuf ;AC000; Set Disk transfer address + mov ah,Set_DMA ;AC000; + int int_command ;AC000; +; +; Set up defaults for switches and parse the command line. +; + mov msg_numb,0 ;AN022; initialize message flag + mov di,offset trangroup:srcbuf ;AN000; get address of srcbuf + mov [pathpos],di ;AN000; this is start of path + mov [pathcnt],1 ;AN000; initialize length to 1 char + mov al,star ;AN000; initialize srcbuf to *,0d + stosb ;AN000; + mov al,end_of_line_in ;AN000; + stosb ;AN000; + mov si,81H ;AN000; Get command line + mov di,offset trangroup:parse_dir ;AN000; Get adderss of PARSE_DIR + xor cx,cx ;AC000; clear counter for positionals + mov ComSw,cx ;AC000; initialize flags + mov bits,cx ;AC000; initialize switches + mov linperpag,linesperpage ;AC000; Set default for lines per page + mov linlen,normperlin ;AC000; Set number of entries per line + mov lincnt,normperlin ;AC000; + +dirscan: + xor dx,dx ;AN000; + invoke parse_with_msg ;AC018; call parser + cmp ax,end_of_line ;AN000; are we at end of line? + jne dirscan_cont ;AN000; No - continue parsing + jmp scandone ;AN000; yes - go process + +dirscan_cont: + cmp ax,result_no_error ;AN000; did we have an error? + jz dirscan_cont2 ;AN000; No - continue parsing + jmp badparm ;AN000; yes - exit + +dirscan_cont2: + cmp parse1_syn,offset trangroup:dir_w_syn ;AN000; was /W entered? + je set_dir_width ;AN000; yes - go set wide lines + cmp parse1_syn,offset trangroup:slash_p_syn ;AN000; was /P entered? + je set_dir_pause ;AN000; yes - go set pause at end of screen +; +; Must be filespec since no other matches occurred. move filename to srcbuf +; + push si ;AC000; save position in line + lds si,parse1_addr ;AC000; get address of filespec + push si ;AN000; save address + invoke move_to_srcbuf ;AC000; move to srcbuf + pop dx ;AC000; get address in DX + +; +; The user may have specified a device. Search for the path and see if the +; attributes indicate a device. +; + mov ah,Find_First ;AC000; find the file + int int_command ;AC000; + jnc Dir_check_device ;AN022; if no error - check device + invoke get_ext_error_number ;AN022; get the extended error + cmp ax,error_no_more_files ;AN022; was error no file found + jz Dir_fspec_end ;AC022; yes -> obviously not a device + cmp ax,error_path_not_found ;AN022; was error no file found + jz Dir_fspec_end ;AC022; yes -> obviously not a device + jmp dir_err_setup ;AN022; otherwise - go issue error message + +dir_check_device: ;AN022; + test byte ptr (DirBuf+find_buf_attr),attr_device ;AC000; + jz Dir_fspec_end ;AC000; no, go do normal operation + mov ComSw,-2 ;AC000; signal device + +dir_fspec_end: + pop si ;AC000; restore position in line + jmp short dirscan ;AC000; keep parsing + +set_dir_width: + test byte ptr[bits],SwitchW ;AN018; /W already set? + jz ok_set_width ;AN018; no - okay to set width + mov ax,moreargs_ptr ;AN018; set up too many arguments + invoke setup_parse_error_msg ;AN018; set up an error message + jmp badparm ;AN018; exit + +ok_set_width: + or bits,switchw ;AC000; indicate /w was selected + mov linlen,wideperlin ;AC000; Set number of entries per line + mov lincnt,wideperlin ;AC000; + jmp short dirscan ;AC000; keep parsing + +set_dir_pause: + test byte ptr[bits],SwitchP ;AN018; /p already set? + jz ok_set_pause ;AN018; no - okay to set width + mov ax,moreargs_ptr ;AN018; set up too many arguments + invoke setup_parse_error_msg ;AN018; set up an error message + jmp badparm ;AN018; exit + +ok_set_pause: + or bits,switchp ;AC000; indicate /p was selected + push cx ;AN000; save necessary registers + push si ;AN000; + mov ax,(IOCTL SHL 8) + generic_ioctl_handle ;AN000; get lines per page on display + mov bx,stdout ;AN000; lines for stdout + mov ch,ioc_sc ;AN000; type is display + mov cl,get_generic ;AN000; get information + mov dx,offset trangroup:display_ioctl ;AN000; + int int_command ;AN000; + +lines_set: + dec linperpag ;AN000; lines per actual page should + dec linperpag ;AN000; two less than the max + mov ax,linperpag ;AN000; get number of lines into + mov [fullscr],ax ;AC000; screen line counter + pop si ;AN000; restore registers + pop cx ;AN000; + jmp dirscan ;AC000; keep parsing + +; +; The syntax is incorrect. Report only message we can. +; +BadParm: + jmp cerror ;AC000; invalid switches get displayed + +ScanDone: + +; +; Find and display the volume ID on the drive. +; + + invoke okvolarg ;AC000; + mov [filecnt],0 ;AC000; Keep track of how many files found + cmp comsw,0 ;AC000; did an error occur? + jnz doheader ;AC000; yes - don't bother to fix path + + mov dirflag,-1 ;AN015; set pathcrunch called from DIR + invoke pathcrunch ;AC000; set up FCB for dir + mov dirflag,0 ;AN015; reset dirflag + jc DirCheckPath ;AC015; no CHDIRs worked. + jz doheader ;AC015; chdirs worked - path\*.* + mov si,[desttail] ;AN015; get filename back + jmp short DoRealParse ;AN015; go parse it + +DirCheckPath: + mov ax,[msg_numb] ;AN022; get message number + cmp ax,0 ;AN022; Is there a message? + jnz dir_err_setup ;AN022; yes - there's an error + cmp [destisdir],0 ;AC000; Were pathchars found? + jz doparse ;AC000; no - no problem + inc comsw ;AC000; indicate error + jmp short doheader ;AC000; go print header + +DirNF: + mov ax,error_file_not_found ;AN022; get message number in control block + +dir_err_setup: + 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,ax ;AN022; + +DirError: + jmp Cerror + +; +; We have changed to something. We also have a file. Parse it into a +; reasonable form, leaving drive alone, leaving extention alone and leaving +; filename alone. We need to special case ... If we are at the root, the +; parse will fail and it will give us a file not found instead of file not +; found. +; +DoParse: + mov si,offset trangroup:srcbuf ;AN000; Get address of source + cmp byte ptr [si+1],colon_char ;AN000; Is there a drive? + jnz dir_no_drive ;AN000; no - keep going + lodsw ;AN000; bypass drive + +dir_no_drive: + cmp [si],".." + jnz DoRealParse + cmp byte ptr [si+2],0 + jnz DoRealParse + inc ComSw + jmp short DoHeader + +DoRealParse: + mov di,FCB ; where to put the file name + mov ax,(Parse_File_Descriptor SHL 8) OR 0EH + int int_command + +; +; Check to see if APPEND installed. If it is installed, set all flags +; off. This will be reset in the HEADFIX routine +; + +DoHeader: + mov ax,AppendInstall ;AN020; see if append installed + int 2fh ;AN020; + cmp al,0 ;AN020; append installed? + je DoHeaderCont ;AN020; no - continue + mov ax,AppendDOS ;AN020; see if append DOS version right + int 2fh ;AN020; + cmp ax,-1 ;AN020; append version correct? + jne DoHeaderCont ;AN020; no - continue + mov ax,AppendGetState ;AN020; Get the state of Append + int 2fh ;AN020; + push ds ;AN020; save current data segment + mov ds,[resseg] ;AN020; get resident segment + assume ds:resgroup ;AN020; + mov append_state,bx ;AN020; save append state + mov append_flag,-1 ;AN020; set append flag + xor bx,bx ;AN020; clear out state + mov ax,AppendSetState ;AN020; Set the state of Append + int 2fh ;AN020; set everything off + pop ds ;AN020; save current data segment + assume ds:trangroup ;AN020; + +; +; Display the header +; + +DoHeaderCont: + mov al,blank ;AN051; Print out a blank + invoke print_char ;AN051; before DIR header + invoke build_dir_string ; get current dir string + mov dx,offset trangroup:Dirhead_ptr + invoke printf_crlf ; bang! + +; +; If there were chars left after parse or device, then invalid file name +; + cmp ComSw,0 + jz DoSearch ; nothing left; good parse + jl DirNFFix ; not .. => error file not found + invoke RestUDir + mov dx,offset TranGroup:BadCD_ptr + jmp Cerror ; was .. => error directory not found +DirNFFix: + invoke RestUDir + jmp DirNF +; +; We are assured that everything is correct. Let's go and search. Use +; attributes that will include finding directories. perform the first search +; and reset our directory afterward. +; +DoSearch: + mov byte ptr DS:[FCB-7],0FFH + mov byte ptr DS:[FCB-1],010H +; +; Caution! Since we are using an extended FCB, we will *also* be returning +; the directory information as an extended FCB. We must bias all fetches into +; DIRBUF by 8 (Extended FCB part + drive) +; + mov ah,Dir_Search_First + mov dx,FCB-7 + int int_command + + push ax ;AN022; save return state + inc al ;AN022; did an error occur? + pop ax ;AN022; get return state back + jnz found_first_file ;AN022; no error - start dir + invoke set_ext_error_msg ;AN022; yes - set up error message + push dx ;AN022; save message + invoke restudir ;AN022; restore user's dir + pop dx ;AN022; restore message + cmp word ptr Extend_Buf_Ptr,Error_No_More_Files ;AN022; convert no more files to + jnz DirCerrorJ ;AN022; file not found + mov Extend_Buf_Ptr,Error_File_Not_Found ;AN022; + +DirCerrorJ: ;AN022; + jmp Cerror ;AN022; exit + +; +; Restore the user's directory. We preserve, though, the return from the +; previous system call for later checking. +; + +found_first_file: + push ax + invoke restudir + pop ax +; +; Main scanning loop. Entry has AL = Search first/next error code. Test for +; no more. +; +DIRSTART: + inc al ; FF = file not found + jnz Display + jmp DirDone ; Either an error or we are finished +; +; Note that we've seen a file and display the found file. +; + +Display: + inc [filecnt] ; Keep track of how many we find + mov si,offset trangroup:dirbuf+8 ; SI -> information returned by sys call + call shoname +; +; If we are displaying in wide mode, do not output the file info +; + test byte ptr[bits],SwitchW ; W switch set? + jz DirTest + jmp nexent ; If so, no size, date, or time + +; +; Test for directory. +; +DirTest: + test [dirbuf+8].dir_attr,attr_directory + jz fileent +; +; We have a directory. Display the field in place of the file size +; + mov dx,offset trangroup:Dmes_ptr + call std_printf + jmp short nofsiz +; +; We have a file. Display the file size +; +fileent: + mov dx,[DirBuf+8].dir_size_l + mov file_size_low,dx + mov dx,[DirBuf+8].dir_size_h + mov file_size_high,dx + mov dx,offset trangroup:disp_file_size_ptr + call std_printf +; +; Display time and date of last modification +; +nofsiz: + mov ax,[DirBuf+8].dir_date ; Get date +; +; If the date is 0, then we have found a 1.x level diskette. We skip the +; date/time fields as 1.x did not have them. +; + or ax,ax + jz nexent ; Skip if no date + mov bx,ax + and ax,1FH ; get day + mov dl,al + mov ax,bx + mov cl,5 + shr ax,cl ; Align month + and al,0FH ; Get month + mov dh,al + mov cl,bh + shr cl,1 ; Align year + xor ch,ch + add cx,80 ; Relative 1980 + cmp cl,100 + jb millenium + sub cl,100 + +millenium: + xchg dh,dl ;AN000; switch month & day + mov DirDat_yr,cx ;AC000; put year into message control block + mov DirDat_mo_day,dx ;AC000; put month and day into message control block + mov cx,[DirBuf+8].dir_time ; Get time + jcxz prbuf ; Time field present? + shr cx,1 + shr cx,1 + shr cx,1 + shr cl,1 + shr cl,1 ; Hours in CH, minutes in CL + xchg ch,cl ;AN000; switch hours & minutes + mov DirTim_hr_min,cx ;AC000; put hours and minutes into message subst block + +prbuf: + mov dx,offset trangroup:DirDatTim_ptr + call std_printf + invoke crlf2 ;AC066;end the line + dec byte ptr [fullscr] ;AC066;count the line + jnz endif04 ;AN066;IF the last on the screen THEN + call check_for_P ;AN066; pause if /P requested + endif04: ;AN066; + jmp scroll ; If not, just continue +;AD061; mov DirDat_yr,0 ;AC000; reset year, month and day +;AD061; mov DirDat_mo_day,0 ;AC000; in control block +;AD061; mov DirTim_hr_min,0 ;AC000; reset hour & minute in control block +; +; We are done displaying an entry. The code between "noexent:" and "scroll:" +; is only for /W case. +; +nexent: + mov bl,[lincnt] ;AN066;save for check for first entry on line + dec [lincnt] ;count this entry on the line + jnz else01 ;AX066;IF last entry on line THEN + mov al,[linlen] + mov [lincnt],al + invoke crlf2 + cmp [fullscr],0 ;AC066;IF have filled the screen THEN + jnz endif02 ;AN066; + call check_for_P ;AN066; reinitialize fullscr, + endif02: ;AN066; IF P requested THEN pause + jmp short endif01 ;AN066; + else01: ;AN066;ELSE since screen not full + cmp bl,[linlen] ;AN066; IF starting new line THEN + jne endif03 ; count the line + dec byte ptr [fullscr] ;AN066; ENDIF + endif03: ;AC066;We are outputting on the same line, between fields, we tab. + mov dx,offset trangroup:tab_ptr ;Output a tab + call std_printf + endif01: ;AX066; +; +; All we need to do now is to get the next directory entry. +; +scroll: + mov ah,Dir_Search_Next + mov dx,FCB-7 ; DX -> Unopened FCB + int int_command ; Search for a file to match FCB + jmp DirStart +; +; If no files have been found, display a not-found message +; +DirDone: + invoke get_ext_error_number ;AN022; get the extended error number + cmp ax,error_no_more_files ;AN022; was error file not found? + jnz dir_err_setup_jmp ;AN022; no - setup error message + test [filecnt],-1 + jnz Trailer + mov ax,error_file_not_found ;AN022; + +dir_err_setup_jmp: ;AN022; + jmp dir_err_setup ;AN022; go setup error msg & print it +; +; If we have printed the maximum number of files per line, terminate it with +; CRLF. +; +Trailer: + mov al,[linlen] + cmp al,[lincnt] ; Will be equal if just had CR/LF + jz mmessage + invoke crlf2 + cmp [fullscr],0 ;AN066;IF on last line of screen THEN + jnz endif06 ;AN066; pause before going on + call check_for_P ;AN066; to number and freespace + endif06: ;AN066; displays + +mmessage: + mov dx,offset trangroup:Dirmes_ptr + mov si,[filecnt] + mov dir_num,si + call std_printf + mov ah,Get_Drive_Freespace + mov dl,byte ptr DS:[FCB] + int int_command + cmp ax,-1 + retz + mul cx ; AX is bytes per cluster + mul bx + mov bytes_free,ax ;AC000; + mov bytes_free+2,dx ;AC000; + MOV DX,OFFSET TRANGROUP:BYTMES_ptr + jmp std_printf + +shoname: + mov di,offset trangroup:charbuf + mov cx,8 + rep movsb + mov al,' ' + stosb + mov cx,3 + rep movsb + xor ax,ax + stosb + push dx + mov dx,offset trangroup:charbuf + mov string_ptr_2,dx + mov dx,offset trangroup:string_buf_ptr + call std_printf + pop DX + return + +check_for_P PROC NEAR ;AN066; + +test byte ptr[bits],SwitchP ;P switch present? +jz endif05 ;AN066; + mov ax,linperpag ;AN000; transfer lines per page + mov [fullscr],ax ;AC000; to fullscr + invoke Pause +endif05: +ret ;AN066; + +check_for_P ENDP ;AN066; + +trancode ends + end diff --git a/v4.0/src/CMD/COMMAND/TCMD1B.ASM b/v4.0/src/CMD/COMMAND/TCMD1B.ASM new file mode 100644 index 0000000..7a45e9d --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TCMD1B.ASM @@ -0,0 +1,730 @@ + page 80,132 +; SCCSID = @(#)tcmd1b.asm 1.1 85/05/14 +; SCCSID = @(#)tcmd1b.asm 1.1 85/05/14 +TITLE PART4 COMMAND Transient routines. + +; Internal commands DIR,PAUSE,ERASE,TYPE,VOL,VER + +.xlist +.xcref + INCLUDE DOSSYM.INC + INCLUDE comseg.asm + INCLUDE comsw.asm ;AC000; + INCLUDE comequ.asm + INCLUDE ioctl.inc ;AN000; + INCLUDE ea.inc ;AN030; +.list +.cref + + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN badcpmes_ptr:word ;AC022; + EXTRN Extend_buf_ptr:word ;AC000; + EXTRN Extend_buf_sub:byte ;AN000; + EXTRN inornot_ptr:word + EXTRN msg_disp_class:byte ;AC000; + EXTRN parse_erase:byte ;AC000; + EXTRN parse_mrdir:byte ;AC000; + EXTRN parse_rename:byte ;AC000; + EXTRN parse_vol:byte ;AC000; + EXTRN PauseMes_ptr:word + EXTRN renerr_ptr:word + EXTRN slash_p_syn:word ;AC000; + EXTRN volmes_ptr:word ;AC000; + EXTRN volmes_ptr_2:word ;AC000; + EXTRN volsermes_ptr:word ;AC000; + EXTRN xa_cp:byte ;AN030; +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN bytcnt:word + EXTRN charbuf:byte + EXTRN comsw:word + EXTRN cpyflag:byte ;AC000; + EXTRN curdrv:byte + EXTRN destinfo:byte + EXTRN destisdir:byte + EXTRN dirbuf:byte + EXTRN msg_numb:word ;AN022; + EXTRN one_char_val:byte + EXTRN parse1_addr:dword ;AN000; + EXTRN parse1_syn:word ;AN000; + EXTRN srcbuf:byte ;AN000; + EXTRN string_ptr_2:word ;AN000; + EXTRN TPA:word + EXTRN vol_drv:byte + EXTRN vol_ioctl_buf:byte ;AC000; + EXTRN vol_label:byte ;AC000; + EXTRN vol_serial:dword ;AC000; + EXTRN xa_cp_out:byte ;AN030; + EXTRN xa_cp_length:word ;AN030; + EXTRN xa_list_attr:word ;AC030; + EXTRN zflag:byte +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC BYTE + +ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + +;--------------- + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN arg:byte ; the arg structure! +transpace ends +;--------------- + + EXTRN cerror:near + EXTRN error_output:near + EXTRN notest2:near + EXTRN slashp_erase:near ;AN000; + EXTRN std_printf:near + EXTRN tcommand:near + + PUBLIC badpath_err ;AN022; + PUBLIC crename + PUBLIC erase + PUBLIC extend_setup ;AN022; + PUBLIC Get_ext_error_number ;AN022; + PUBLIC Get_file_code_page_tag ;AN000; + PUBLIC pause + PUBLIC Set_ext_error_msg ;AN000; + PUBLIC set_file_code_page ;AN000; + PUBLIC typefil + PUBLIC volume + + +assume ds:trangroup,es:trangroup + + break Pause +assume ds:trangroup,es:trangroup + +PAUSE: + mov dx,offset trangroup:pausemes_ptr + call std_printf + invoke GetKeystroke + invoke crlf2 + return + + break Erase + +;**************************************************************** +;* +;* ROUTINE: DEL/ERASE - erase file(s) +;* +;* FUNCTION: PARSE command line for file or path name and /P +;* and invoke PATHCRUNCH. If an error occurs, set +;* up an error message and transfer control to CERROR. +;* Otherwise, transfer control to NOTEST2 if /P not +;* entered or SLASHP_ERASE if /P entered. +;* +;* INPUT: command line at offset 81H +;* +;* OUTPUT: if no error: +;* FCB at 5ch set up with filename(s) entered +;* Current directory set to entered directory +;* +;**************************************************************** + +assume ds:trangroup,es:trangroup + +ERASE: + mov si,81H ;AC000; get command line + mov comsw,0 ;AN000; clear switch indicator + mov di,offset trangroup:parse_erase ;AN000; Get adderss of PARSE_erase + xor cx,cx ;AN000; clear cx,dx + +erase_scan: + xor dx,dx ;AN000; + invoke parse_with_msg ;AC018; call parser + cmp ax,end_of_line ;AN000; are we at end of line? + jz good_line ;AN000; yes - done parsing + cmp ax,result_no_error ;AC000; did we have an error? + jnz errj2 ;AC000; yes exit + + cmp parse1_syn,offset trangroup:slash_p_syn ;AN000; was /P entered? + je set_erase_prompt ;AN000; yes - go set prompt + +; +; Must be filespec since no other matches occurred. move filename to srcbuf +; + push si ;AC000; save position in line + lds si,parse1_addr ;AC000; get address of filespec + cmp byte ptr[si+1],colon_char ;AC000; drive specified? + jnz Erase_drive_ok ;AC000; no - continue + cmp byte ptr[si+2],end_of_line_out ;AC000; was only drive entered? + jnz erase_drive_ok ;AC000; no - continue + mov ax,error_file_not_found ;AN022; get message number in control block + jmp short extend_setup ;AC000; exit + +erase_drive_ok: + invoke move_to_srcbuf ;AC000; move to srcbuf + pop si ;AC000; get position back + jmp short erase_scan ;AN000; continue parsing + +set_erase_prompt: + cmp comsw,0 ;AN018; was /P already entered? + jz ok_to_set_erase_prompt ;AN018; no go set switch + mov ax,moreargs_ptr ;AN018; set up too many arguments + invoke setup_parse_error_msg ;AN018; set up an error message + jmp short errj2 ;AN018; exit + +ok_to_set_erase_prompt: ;AN018; + inc comsw ;AN000; indicate /p specified + jmp short erase_scan ;AN000; continue parsing + +good_line: ;G We know line is good + invoke pathcrunch + jnc checkdr + mov ax,[msg_numb] ;AN022; get message number + cmp ax,0 ;AN022; was message flag set? + jnz extend_setup ;AN022; yes - print out message + cmp [destisdir],0 ; No CHDIRs worked + jnz badpath_err ;AC022; see if they should have + +checkdr: + cmp comsw,0 ;AN000; was /p specified + jz notest2j ;AN000; no - go to notest2 + jmp slashp_erase ;AN000; yes - go to slashp_erase + +notest2j: + jmp notest2 + +badpath_err: ;AN022; "Path not found" message + mov ax,error_path_not_found ;AN022; set up error number + +extend_setup: ;AN022; + mov msg_disp_class,ext_msg_class ;AN022; set up extended error msg class + mov dx,offset TranGroup:Extend_Buf_ptr ;AC022; get extended message pointer + mov Extend_Buf_ptr,ax ;AN022; get message number in control block +errj2: ;AC022; exit jump + jmp Cerror ;AN022; + + break Rename + +; **************************************************************** +; * +; * ROUTINE: CRENAME - rename file(s) +; * +; * FUNCTION: PARSE command line for one full filespec and one +; * filename. Invoke PATHCRUNCH on the full filespec. +; * Make sure the second filespec only contains a +; * filename. If both openands are valid, attempt +; * to rename the file. +; * +; * INPUT: command line at offset 81H +; * +; * OUTPUT: none +; * +; **************************************************************** + +assume ds:trangroup,es:trangroup + +CRENAME: + + mov si,81H ;AC000; Point to command line + mov di,offset trangroup:parse_rename;AN000; Get adderss of PARSE_RENAME + xor cx,cx ;AN000; clear cx,dx + xor dx,dx ;AN000; + invoke parse_with_msg ;AC018; call parser + cmp ax,result_no_error ;AC000; did we have an error? + jz crename_no_parse_error ;AC000; no - continue + JMP crename_parse_error ;AC000; Yes, fail. (need long jump) + +; +; Get first file name returned from parse into our buffer +; +crename_no_parse_error: + push si ;AN000; save position in line + lds si,parse1_addr ;AN000; get address of filespec + invoke move_to_srcbuf ;AN000; move to srcbuf + pop si ;AN000; restore position in line + + xor dx,dx ;AN000; clear dx + invoke parse_with_msg ;AC018; call parser + cmp ax,result_no_error ;AN000; did we have an error? + JNZ crename_parse_error ;AN000; Yes, fail. + +; +; Check the second file name for drive letter colon +; + push si ;AN000; save position in line + lds si,parse1_addr ;AC000; get address of path + + mov al,':' ;AC000; + cmp [si+1],al ;AC000; Does the 2nd parm have a drive spec? + jnz ren_no_drive ;AN000; Yes, error + 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,BadParm_ptr ;AN000; get "Invalid parameter" message number + + pop si ;AN000; +crename_parse_error: ;AC022; + jmp short errj ;AC000; + +; +; Get second file name returned from parse into the fCB. Save +; character after file name so we can later check to make sure it +; isn't a path character. +; + +ren_no_drive: + mov di,FCB+10H ;AC000; set up to parse second file name + mov ax,(Parse_File_Descriptor SHL 8) OR 01H ;AC000; + int int_command ;AC000; do the function + lodsb ;AC000; Load char after filename + mov one_char_val,al ;AN000; save char after filename + pop si ;AN000; get line position back + +; +; We have source and target. See if any args beyond. +; + + mov di,offset trangroup:parse_rename;AC000; get address of parse_rename + invoke parse_check_eol ;AC000; are we at end of line? + jnz crename_parse_error ;AN000; no, fail. + + invoke pathcrunch + mov dx,offset trangroup:badcpmes_ptr + jz errj2 ; If 1st parm a dir, print error msg + jnc notest3 + mov ax,[msg_numb] ;AN022; get message number + cmp ax,0 ;AN022; was message flag set? + jnz extend_setup ;AN022; yes - print out message + cmp [destisdir],0 ; No CHDIRs worked + jz notest3 ; see if they should have + Jmp badpath_err ;AC022; set up error + +notest3: + mov al,one_char_val ;AN000; move char into AX + mov dx,offset trangroup:inornot_ptr ; Load invalid fname error ptr + invoke pathchrcmp ; Is the char in al a path sep? + jz errj ; Yes, error - 2nd arg must be + ; filename only. + + mov ah,FCB_Rename + mov dx,FCB + int int_command + cmp al, 0FFH ; Did an error occur?? + jnz renameok + + invoke get_ext_error_number ;AN022; get extended error + SaveReg ;AC022; Save results + mov al, 0FFH ; Restore original error state + +renameok: + push ax + invoke restudir + pop ax + inc al + retnz + + RestoreReg ;AC022; get the error number back + cmp ax,error_file_not_found ;AN022; error file not found? + jz use_renerr ;AN022; yes - use generic error message + cmp ax,error_access_denied ;AN022; error file not found? + jz use_renerr ;AN022; yes - use generic error message + jmp extend_setup ;AN022; need long jump - use extended error + +use_renerr: + mov dx,offset trangroup:RenErr_ptr ;AC022; + +ERRJ: + jmp Cerror + +ret56: ret + + break Type + +;**************************************************************** +;* +;* ROUTINE: TYPEFIL - Display the contents of a file to the +;* standard output device +;* +;* SYNTAX: TYPE filespec +;* +;* FUNCTION: If a valid filespec is found, read the file until +;* 1Ah and display the contents to STDOUT. +;* +;* INPUT: command line at offset 81H +;* +;* OUTPUT: none +;* +;**************************************************************** + +assume ds:trangroup,es:trangroup + +TYPEFIL: + mov si,81H + mov di,offset trangroup:parse_mrdir ;AN000; Get adderss of PARSE_MRDIR + xor cx,cx ;AN000; clear cx,dx + xor dx,dx ;AN000; + invoke parse_with_msg ;AC018; call parser + cmp ax,result_no_error ;AC000; did we have an error? + jnz typefil_parse_error ;AN000; yes - issue error message + + push si ;AC000; save position in line + lds si,parse1_addr ;AC000; get address of filespec + invoke move_to_srcbuf ;AC000; move to srcbuf + pop si ;AC000; get position back + mov di,offset trangroup:parse_mrdir ;AC000; get address of parse_mrdir + invoke parse_check_eol ;AC000; are we at end of line? + jz gottarg ;AC000; yes - continue + +typefil_parse_error: ;AN000; no - set up error message and exit + jmp Cerror + +gottarg: + invoke setpath + test [destinfo],00000010b ; Does the filespec contain wildcards + jz nowilds ; No, continue processing + mov dx,offset trangroup:inornot_ptr ; Yes, report error + jmp Cerror +nowilds: + mov ax,ExtOpen SHL 8 ;AC000; open the file + mov bx,read_open_mode ;AN000; get open mode for TYPE + xor cx,cx ;AN000; no special files + mov dx,read_open_flag ;AN000; set up open flags + mov di,-1 ;AN030; no parm list + mov si,offset trangroup:srcbuf ;AN030; get file name + int int_command + jnc typecont ; If open worked, continue. Otherwise load + +Typerr: ;AN022; + push cs ;AN022; make sure we have local segment + pop ds ;AN022; + invoke set_ext_error_msg ;AN022; + +Typerr2: ;AN022; + mov string_ptr_2,offset trangroup:srcbuf ;AC022; get address of failed string + mov Extend_buf_sub,one_subst ;AC022; put number of subst in control block + jmp cerror ;AC022; exit + +typecont: + mov bx,ax ;AC000; get Handle + mov cx,stdout ;AN000; set output to STDOUT + call set_file_code_page ;AN000; Set code page on output device + jc typerr2 ;AN022; exit if error + + mov zflag,0 ; Reset ^Z flag + mov ds,[TPA] + xor dx,dx +ASSUME DS:NOTHING + +typelp: + cmp cs:[zflag],0 ;AC050; Is the ^Z flag set? + retnz ; Yes, return + mov cx,cs:[bytcnt] ;AC056; No, continue + mov ah,read + int int_command + jc typerr ;AN022; Exit if error + mov cx,ax + jcxz typelp_ret ;AC000; exit if nothing read + push ds + pop es ; Check to see if a ^Z was read. +assume es:nothing + xor di,di + push ax + mov al,1ah + repnz scasb + pop ax + xchg ax,cx + cmp ax,0 + jnz foundz ; Yes, handle it + cmp byte ptr [di-1],1ah ; No, double check + jnz typecont2 ; No ^Z, continue + +foundz: + sub cx,ax ; Otherwise change cx so that only those + dec cx ; bytes up to but NOT including the ^Z + push cs ; will be typed. + pop es +assume es:trangroup + not zflag ; Turn on ^Z flag so that the routine + +typecont2: ; will quit after this write. + push bx + mov bx,1 + mov ah,write + int int_command + pop bx + jc Error_outputj + cmp ax,cx + jz typelp + dec cx + cmp ax,cx + retz ; One less byte OK (^Z) + +Error_outputj: + mov bx,1 + mov ax,IOCTL SHL 8 + int int_command + test dl,devid_ISDEV + retnz ; If device, no error message + jmp error_output + +typelp_ret: + ret + + break Volume +assume ds:trangroup,es:trangroup + +; +; VOLUME command displays the volume ID on the specified drive +; +VOLUME: + + mov si,81H + mov di,offset trangroup:parse_vol ;AN000; Get adderss of PARSE_VOL + xor cx,cx ;AN000; clear cx,dx + xor dx,dx ;AN000; + invoke parse_with_msg ;AC018; call parser + cmp ax,end_of_line ;AC000; are we at end of line? + jz OkVolArg ;AC000; Yes, display default volume ID + cmp ax,result_no_error ;AC000; did we have an error? + jnz BadVolArg ;AC000; Yes, fail. +; +; We have parsed off the drive. See if there are any more chars left +; + + mov di,offset trangroup:parse_vol ;AC000; get address of parse_vol + xor dx,dx ;AC000; + invoke parse_check_eol ;AC000; call parser + jz OkVolArg ;AC000; yes, end of road +; +; The line was not interpretable. Report an error. +; +badvolarg: + jmp Cerror +; +; Find the Volume ID on the disk. +; +PUBLIC OkVolArg +OKVOLARG: + invoke crlf2 + mov al,blank ;AN051; Print out a blank + invoke print_char ;AN051; before volume message + push ds + pop es +; +; Volume IDs are only findable via extended FCBs or find_first with attributes +; of volume_id ONLY. +; + + mov di,FCB-7 ; Point to extended FCB beginning + mov al,-1 ; Tag to indicate Extention + stosb + xor ax,ax ; Zero padding to volume label + stosw + stosw + stosb + mov al,attr_volume_ID ; Look for volume label + stosb + inc di ; Skip drive byte; it is already set + mov cx,11 ; fill in remainder of file + mov al,'?' + rep stosb +; +; Set up transfer address (destination of search first information) +; + mov dx,offset trangroup:dirbuf + mov ah,set_DMA + int int_command +; +; Do the search +; + mov dx,FCB-7 + mov ah,Dir_Search_First + int int_command + +;******************************** +; Print volume ID info + + push ax ;AC000; AX return from SEARCH_FIRST for VOL ID + mov al,DS:[FCB] ;AC000; get drive letter + add al,'@' + cmp al,'@' + jnz drvok + mov al,[curdrv] + add al,capital_A +drvok: + mov vol_drv,al ;AC000; get drive letter into argument + pop ax ;AC000; get return code back + or al,al ;AC000; volume label found? + jz Get_vol_name ;AC000; volume label exists - go get it + mov dx,offset trangroup:VolMes_ptr_2 ;AC000; set up no volume message + jmp short print_serial ;AC000; go print it + +Get_vol_name: + mov di,offset trangroup:charbuf + mov dx,di + mov si,offset trangroup:dirbuf + 8 ;AN000; 3/3/KK + mov cx,11 ;AN000; 3/3/KK + rep movsb ;AN000; 3/3/KK + + xor al,al ;AC000; store a zero to terminate the string + stosb + mov dx,offset trangroup:VolMes_ptr ;AC000; set up message + +PRINT_SERIAL: + +; +; Attempt to get the volume serial number from the disk. If an error +; occurs, do not print volume serial number. +; + + push dx ;AN000; save message offset + mov ax,(GetSetMediaID SHL 8) ;AC036; Get the volume serial info + mov bl,DS:[FCB] ;AN000; get drive number from FCB + mov dx,offset trangroup:vol_ioctl_buf ;AN000;target buffer + int int_command ;AN000; do the call + pop dx ;AN000; get message offset back + jc printvol_end ;AN000; if error, just go print label + call std_printf ;AC000; go print volume message + mov al,blank ;AN051; Print out a blank + invoke print_char ;AN051; before volume message + mov dx,offset trangroup:VolSerMes_ptr ;AN000; get serial number message + +printvol_end: + jmp std_printf ;AC000; go print and exit + +;**************************************************************** +;* +;* ROUTINE: Set file Code page +;* +;* FUNCTION: Check CPSW status, if CPSW is on, get the file's +;* code page and attempt to invoke it on the +;* output device. +;* +;* INPUT: file handle in BX - unless copyflg is set +;* handle of output device in CX +;* +;* OUTPUT: if carry set (code page invoke failed) +;* ax = extended error +;* otherwise +;* ax modified +;* +;* +;**************************************************************** + +Set_file_code_page proc near ;AN000; + + push bx ;AN000; save registers + push di ;AN000; + push dx ;AN000; + + cmp cpyflag,1 ;AN000; were we called from COPY? + jz Already_have_cp ;AN000; yes - already have code page + call get_file_code_page_tag ;AN000; get the file's code page + jc cp_set_error ;AN000; if error - just continue + +already_have_cp: ;AN000; See what was returned. + mov ax,(file_times SHL 8)+set_XA ;AC030; set code page + mov di,offset trangroup:xa_cp_out ;AC030; offset of attr list + mov bx,cx ;AN000; get handle of output device + int int_command ;AN000; + jnc set_file_cp_end ;AN000; all okay - return +cp_set_error: + pop dx ;AC030; we don't restore DX for error - + call Set_Ext_Error_msg ;AN000; we return error message + jmp short set_file_cp_exit ;AC030; exit + +set_file_cp_end: ;AN000; finished + pop dx ;AN000; restore registers + +set_file_cp_exit: + pop di ;AN000; + pop bx ;AN000; + + ret ;AN000; return + +Set_file_code_page endp ;AN000; + + +;**************************************************************** +;* +;* ROUTINE: Get file Code page tag +;* +;* FUNCTION: Get code page file attribute. +;* +;* INPUT: file handle in BX +;* +;* OUTPUT: if error - carry set +;* otherwise - xa_list_attr set to file's code page +;* +;* AX and DI modified +;* +;**************************************************************** + + +Get_file_code_page_tag proc near ;AN000; + + push cx ;AN030; + push si ;AN030; + push di ;AN030; + mov xa_list_attr,0 ;AN030; initialize code page + mov ax,(file_times SHL 8)+get_XA ;AC030; get extended attributes + mov si,offset trangroup:xa_cp ;AN030; get xa request buffer + mov di,offset trangroup:xa_cp_out ;AC030; get xa output buffer + mov cx,xa_cp_length ;AN030; length of buffer + int int_command ;AN000; + pop di ;AN030; + pop si ;AN030; + pop cx ;AN030; + + ret ;AN000; return + +Get_file_code_page_tag endp ;AN000; + + +;**************************************************************** +;* +;* ROUTINE: Set_ext_error_msg +;* +;* FUNCTION: Sets up extended error message for printing +;* +;* INPUT: return from INT 21 +;* +;* OUTPUT: extended error message set up in extended error +;* buffer. +;* +;**************************************************************** + +Set_ext_error_msg proc near ;AN000; + + call get_ext_error_number ;AC022; get the extended 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,ax ;AN000; get message number in control block + stc ;AN000; make sure carry is set + + ret ;AN000; return + +Set_ext_error_msg endp ;AN000; + +;**************************************************************** +;* +;* ROUTINE: Get_ext_error_number +;* +;* FUNCTION: Does get extended error function call +;* +;* INPUT: return from INT 21 +;* +;* OUTPUT: AX - extended error number +;* +;**************************************************************** + +Get_ext_error_number proc near ;AN022; + + SaveReg ;AN022; save registers + mov ah,GetExtendedError ;AN022; get extended error + xor bx,bx ;AN022; clear BX + int int_command ;AN022; + RestoreReg ;AN022; restore registers + + ret ;AN022; return + +Get_ext_error_number endp ;AN022; + +trancode ends + end + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/TCMD2A.ASM b/v4.0/src/CMD/COMMAND/TCMD2A.ASM new file mode 100644 index 0000000..9dcb066 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TCMD2A.ASM @@ -0,0 +1,552 @@ + page 80,132 +; SCCSID = @(#)tcmd2a.asm 4.1 85/06/25 +; SCCSID = @(#)tcmd2a.asm 4.1 85/06/25 +TITLE PART5 COMMAND Transient routines. + + INCLUDE comsw.asm + +.xlist +.xcref + INCLUDE DOSSYM.INC + INCLUDE comequ.asm + INCLUDE comseg.asm + include ioctl.inc +.list +.cref + + +CODERES SEGMENT PUBLIC BYTE ;AC000; +CODERES ENDS + +DATARES SEGMENT PUBLIC BYTE ;AC000; +DATARES ENDS + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN arg_buf_ptr:word + EXTRN BadCurDrv:byte ;AC000; + EXTRN clsstring:byte + EXTRN dback_ptr:word + EXTRN display_ioctl:word ;AN000; + EXTRN display_width:word ;AN000; + EXTRN Extend_buf_ptr:word ;AN049; + EXTRN linperpag:word ;AN000; + EXTRN msg_disp_class:byte ;AN049; + EXTRN nulpath_ptr:word + EXTRN prompt_table:word + EXTRN string_buf_ptr:word ;AC000; + EXTRN vermes_ptr:word +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN Arg_Buf:byte + EXTRN bwdbuf:byte + EXTRN curdrv:byte + EXTRN dirchar:byte + EXTRN major_ver_num:word + EXTRN minor_ver_num:word + EXTRN srcxname:byte ;AN049; + EXTRN string_ptr_2:word +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC BYTE + +ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + +;--------------- + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN arg:byte ; the arg structure! +transpace ends +;--------------- + + EXTRN cerror:near ;AN049; + EXTRN crlf2:near + EXTRN drvbad:near + EXTRN std_printf:near + + PUBLIC build_dir_for_chdir + PUBLIC build_dir_for_prompt + PUBLIC build_dir_string + PUBLIC cls + PUBLIC path + PUBLIC print_char + PUBLIC print_drive + PUBLIC print_version + PUBLIC print_b + PUBLIC print_back + PUBLIC print_eq + PUBLIC print_esc + PUBLIC print_g + PUBLIC print_l + PUBLIC print_prompt + PUBLIC version + + break Version +assume ds:trangroup,es:trangroup + +VERSION: + call crlf2 + call print_version + jmp crlf2 + +print_version: + mov ah,Get_version + int int_command + push ax + xor ah,ah + mov major_ver_num,ax + pop ax + xchg ah,al + xor ah,ah + mov minor_ver_num,ax + mov dx,offset trangroup:vermes_ptr + jmp std_printf + +print_prompt: + push ds + push cs + pop ds ; MAKE SURE DS IS IN TRANGROUP + push es + invoke find_prompt ; LOOK FOR PROMPT STRING + jc PP0 ; CAN'T FIND ONE + cmp byte ptr es:[di],0 + jnz PP1 +PP0: + call print_drive ; USE DEFAULT PROMPT + mov al,sym + call print_char + jmp short PP5 + +PP1: + mov al,es:[di] ; GET A CHAR + inc di + or al,al + jz PP5 ; NUL TERMINATED + cmp al,dollar ; META CHARACTER? + jz PP2 ; NOPE +PPP1: + call print_char + jmp PP1 + +PP2: + mov al,es:[di] + inc di + mov bx,offset trangroup:prompt_table-3 + or al,al + jz PP5 + +PP3: + add bx,3 + invoke upconv + cmp al,[bx] + jz PP4 + cmp byte ptr [bx],0 + jnz PP3 + jmp PP1 + +PP4: + push es + push di + push cs + pop es + call [bx+1] + pop di + pop es + jmp PP1 + +PP5: + pop es ; RESTORE SEGMENTS + pop ds + return + + +print_back: + mov dx,offset trangroup:dback_ptr + jmp std_printf + +print_EQ: + mov al,'=' + jmp short print_char + +print_esc: + mov al,1BH + jmp short print_char + +print_G: + mov al,rabracket + jmp short print_char + +print_L: + mov al,labracket + jmp short print_char + +print_B: + mov al,vbar + +print_char: + push es + push ds + pop es + push di + push dx + mov dl,al ;AC000; Get char into al + mov ah,Std_CON_output ;AC000; print the char to stdout + int int_command ;AC000; + pop dx + pop di + pop es + ret + +print_drive: + mov ah,Get_Default_drive + int int_command + add al,capital_A + call print_char + ret + +ASSUME DS:TRANGROUP,ES:TRANGROUP + +build_dir_for_prompt: + xor dl,dl + mov si,offset trangroup:bwdbuf + mov di,SI + mov al,CurDrv + add al,'A' + mov ah,':' + stosw + mov al,[dirchar] + stosb + xchg si,di + mov string_ptr_2,di + mov ah,Current_dir + int int_command + mov dx,offset trangroup:string_buf_ptr + jnc DoPrint + mov dx,offset trangroup:BadCurDrv +DoPrint: + call std_printf + + ret + +build_dir_for_chdir: + call build_dir_string + mov dx,offset trangroup:bwdbuf + mov string_ptr_2,dx + mov dx,offset trangroup:string_buf_ptr + call std_printf + ret + +build_dir_string: + mov dl,ds:[FCB] + mov al,DL + add al,'@' + cmp al,'@' + jnz gotdrive + add al,[CURDRV] + inc al + +gotdrive: + push ax + mov si,offset trangroup:bwdbuf+3 + mov ah,Current_dir + int int_command + jnc dpbisok + push cs + pop ds + jmp drvbad + +dpbisok: + mov di,offset trangroup:bwdbuf + mov dx,di + pop ax + mov ah,':' + stosw + mov al,[dirchar] + stosb + + ret + + break Path +assume ds:trangroup,es:trangroup + +PATH: + xor al,al ;AN049; Set up holding buffer + mov di,offset Trangroup:srcxname ;AN049; for PATH while parsing + stosb ;AN049; Initialize PATH to null + dec di ;AN049; point to the start of buffer + invoke PGetarg ; Pre scan for arguments + jz disppath ; Print the current path + cmp al,semicolon ;AC049; NUL path argument? + jnz pathslp ;AC049; + inc si ;AN049; point past semicolon + jmp short scan_white ;AC049; Yes - make sure nothing else on line + +pathslp: ; Get the user specified path + lodsb ; Get a character + cmp al,end_of_line_in ;AC049; Is it end of line? + jz path_eol ;AC049; yes - end of command + + invoke testkanj ;See if DBCS + jz notkanj2 ;No - continue + stosb ;AC049; Yes - store the first byte + lodsb ;skip second byte of DBCS + +path_hold: ;AN049; + stosb ;AC049; Store a byte in the PATH buffer + jmp short pathslp ;continue parsing + +notkanj2: + invoke upconv ;upper case the character + cmp al,semicolon ;AC049; ';' not a delimiter on PATH + jz path_hold ;AC049; go store it + invoke delim ;delimiter? + jnz path_hold ;AC049; no - go store character + +scan_white: ;AN049; make sure were at EOL + lodsb ;AN049; get a character + cmp al,end_of_line_in ;AN049; end of line? + jz path_eol ;AN049; yes - go set path + cmp al,blank ;AN049; whitespace? + jz scan_white ;AN049; yes - continue scanning + cmp al,tab_chr ;AN049; whitespace? + jz scan_white ;AN049; yes - continue scanning + + mov dx,offset TranGroup:Extend_Buf_ptr ;AN049; no - set up error message + mov Extend_Buf_ptr,MoreArgs_ptr ;AN049; get "Too many parameters" message number + mov msg_disp_class,parse_msg_class ;AN049; set up parse error msg class + jmp cerror ;AN049; + +path_eol: ;AN049; Parsing was clean + xor al,al ;AN049; null terminate the PATH + stosb ;AN049; buffer + invoke find_path ;AN049; Find PATH in environment + invoke delete_path ;AC049; Delete any offending name + invoke scan_double_null ;AC049; Scan to end of environment + invoke move_name ;AC049; move in PATH= + mov si,offset Trangroup:srcxname ;AN049; Set up source as PATH buffer + +store_path: ;AN049; Store the PATH in the environment + lodsb ;AN049; Get a character + cmp al,end_of_line_out ;AN049; null character? + jz got_paths ;AN049; yes - exit + invoke store_char ;AN049; no - store character + jmp short store_path ;AN049; continue + +got_paths: ;AN049; we're finished + xor ax,ax ;null terminate the PATH in + stosw ; the environment + return + +disppath: + invoke find_path ;AN049; + call print_path + call crlf2 + return + +print_path: + cmp byte ptr es:[di],0 + jnz path1 + +path0: + mov dx,offset trangroup:nulpath_ptr + push cs + pop es + push cs + pop ds + jmp std_printf + +path1: + push es + pop ds + sub di,5 + mov si,di +ASSUME DS:RESGROUP + invoke scasb2 ; LOOK FOR NUL + cmp cx,0FFH + jz path0 + push cs + pop es + mov di,offset trangroup:arg_buf + mov dx,100h + sub dx,cx + xchg dx,cx + rep movsb + mov dx,offset trangroup:arg_buf_ptr + push cs + pop ds + jmp std_printf + +ASSUME DS:TRANGROUP + + break Cls + +; **************************************************************** +; * +; * ROUTINE: CLS +; * +; * FUNCTION: Clear the screen using INT 10h. If ANSI.SYS is +; * installed, send a control string to clear the +; * screen. +; * +; * INPUT: command line at offset 81H +; * +; * OUTPUT: none +; * +; **************************************************************** + +assume ds:trangroup,es:trangroup + +ANSI_installed equ 0ffh + +CLS: + mov ah,Mult_ANSI ;AN000; see if ANSI.SYS installed + mov al,0 ;AN000; + int 2fh ;AN000; + cmp al,ANSI_installed ;AN000; + jz ansicls ;AN000; installed - go do ANSI CLS + +check_lines: + mov ax,(IOCTL SHL 8) + generic_ioctl_handle ;AN000; get lines per page on display + mov bx,stdout ;AN000; lines for stdout + mov ch,ioc_sc ;AN000; type is display + mov cl,get_generic ;AN000; get information + mov dx,offset trangroup:display_ioctl ;AN000; + int int_command ;AN000; + jc no_variable ;AN000; function had error, use default + mov ax,linperpag ;AN000; get number of rows returned + mov dh,al ;AN000; set number of rows + mov ax,display_width ;AN000; get number of columns returned + mov dl,al ;AN000; set number of columns + jmp short regcls ;AN000; go do cls + +no_variable: + mov bx,stdout ;AC000; set handle as stdout + mov ax,IOCTL SHL 8 ;AC000; do ioctl - get device + int int_command ;AC000; info + test dl,devid_ISDEV ;AC000; is handle a device + jz ANSICLS ;AC000; If a file put out ANSI + test dl,devid_SPECIAL ;AC000; + jnz cls_normal ;AC000; If not special CON, do ANSI + +ansicls: + call ansi_cls ;AN000; clear the screen + jmp short cls_ret ;AN000; exit + +; +; Get video mode +; + +cls_normal: ;AC000; + + mov ah,get_video_state ;AC000; set up to get video state + int video_io_int ;AC000; do int 10h - BIOS video IO + cmp al,video_alpha ;AC000; see if in text mode + jbe DoAlpha + cmp al,video_bw ;AC000; see if black & white card + jz DoAlpha +; +; We are in graphics mode. Bogus IBM ROM does not scroll correctly. We will +; be just as bogus and set the mode that we just got. This will blank the +; screen too. +; + mov ah,set_video_mode ;AC000; set video mode call + int video_io_int ;AC000; do int 10h - BIOS video IO + jmp short cls_ret ;AC000; exit + +DoAlpha: +; +; Get video mode and number of columns to scroll +; + mov ah,get_video_state ;AC000; set up to get current video state + int video_io_int ;AC000; do int 10h - BIOS video IO + mov dl,ah + mov dh,linesperpage ;AC000; have 25 rows on the screen + +regcls: + call reg_cls ;AC000; go clear the screen + +cls_ret: + ret ;AC000; exit + +; **************************************************************** +; * +; * ROUTINE: REG_CLS +; * +; * FUNCTION: Clear the screen using INT 10H. +; * +; * INPUT: DL = NUMBER OF COLUMNS +; * DH = NUMBER OF ROWS +; * +; * OUTPUT: none +; * +; **************************************************************** + +reg_cls proc near ;AC000; + +; +; Set overscan to black. +; + + dec dh ;AC000; decrement rows and columns + dec dl ;AC000; to zero base + push dx ;AN000; save rows,columns + mov ah,set_color_palette ;AC000; set up to set the color to blank + xor bx,bx + int video_io_int ;AC000; do int 10h - BIOS video IO + pop dx ;AN000; retore rows,colums + + xor ax,ax ;AC000; zero out ax + mov CX,ax ;AC000; an cx +; +; Scroll active page +; + mov ah,scroll_video_page ;AC000; set up to scroll page up + mov bh,video_attribute ;AC000; attribute for blank line + xor bl,bl ;AC000; set BL to 0 + int video_io_int ;AC000; do int 10h - BIOS video IO +; +; Seek to cursor to 0,0 +; + mov ah,set_cursor_position ;AC000; set up to set cursor position + xor dx,dx ;AC000; row and column 0 + mov bh,0 ;AC000; + int video_io_int ;AC000; do into 10h - BIOS video IO + + ret ;AC000; + +reg_cls endp ;AC000; + + + +; **************************************************************** +; * +; * ROUTINE: ANSI_CLS +; * +; * FUNCTION: Clear the screen using by writing a control code +; * to STDOUT. +; * +; * INPUT: none +; * +; * OUTPUT: none +; * +; **************************************************************** + +ansi_cls proc near ;AC000; + + mov si,offset trangroup:clsstring + lodsb + mov cl,al + xor ch,ch + mov ah,Raw_CON_IO +clrloop: + lodsb + mov DL,al + int int_command + loop clrloop + return + +ansi_cls endp ;AC000; + +trancode ends + end + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/TCMD2B.ASM b/v4.0/src/CMD/COMMAND/TCMD2B.ASM new file mode 100644 index 0000000..4db1f11 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TCMD2B.ASM @@ -0,0 +1,597 @@ + page 80,132 +; SCCSID = @(#)tcmd2b.asm 4.1 85/09/22 +; SCCSID = @(#)tcmd2b.asm 4.1 85/09/22 +TITLE PART5 COMMAND Transient routines. + +.xlist +.xcref + INCLUDE comsw.asm + INCLUDE DOSSYM.INC + INCLUDE comseg.asm + INCLUDE comequ.asm +.list +.cref + + +CODERES SEGMENT PUBLIC BYTE ;AC000; + EXTRN LODCOM1:NEAR +CODERES ENDS + +DATARES SEGMENT PUBLIC BYTE ;AC000; + EXTRN crit_msg_off:word ;AC000; + EXTRN crit_msg_seg:word ;AC000; + EXTRN IO_SAVE:WORD + EXTRN OldTerm:DWORD + EXTRN PARENT:WORD +;AD060; EXTRN pars_msg_off:word ;AC000; +;AD060; EXTRN pars_msg_seg:word ;AC000; + EXTRN PERMCOM:BYTE ;AN045; + EXTRN RetCode:WORD +DATARES ENDS + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN ACRLF_PTR:WORD ;AN007; + EXTRN baddev_ptr:word + EXTRN CP_active_Ptr:word + EXTRN CP_not_all_Ptr:word + EXTRN CP_not_set_Ptr:word + EXTRN Extend_buf_ptr:word ;AN000; + EXTRN Extend_buf_sub:byte ;AN000; + EXTRN inv_code_page:word ;AC000; + EXTRN msg_disp_class:byte ;AN000; + EXTRN NLSFUNC_Ptr:word ;AC000; + EXTRN parse_chcp:byte ;AC000; + EXTRN parse_chdir:byte ;AC000; + EXTRN parse_ctty:byte ;AC000; + EXTRN string_buf_ptr:word ;AC000; + +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN COMBUF:BYTE + EXTRN parse_last:word ;AN018; + EXTRN parse1_addr:dword ;AC000; + EXTRN parse1_type:byte ;AC000; + EXTRN RESSEG:WORD + EXTRN srcbuf:byte + EXTRN srcxname:byte ;AC000; + EXTRN string_ptr_2:word + EXTRN system_cpage:word + EXTRN TRAN_TPA:WORD +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC BYTE + +ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + +;--------------- + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN arg:byte ; the arg structure! +TRANSPACE ENDS +;--------------- + + EXTRN cerror:near + + PUBLIC $exit + PUBLIC chcp + PUBLIC ctty + PUBLIC parse_check_eol ;AN000; + PUBLIC parse_with_msg ;AN018; + PUBLIC setup_parse_error_msg ;AN018; + PUBLIC truename ;AN000; + + break Ctty +assume ds:trangroup,es:trangroup + +; **************************************************************** +; * +; * ROUTINE: CTTY - Change console +; * +; * SYNTAX: CTTY device +; * +; * FUNCTION: If a valid console device is specified, CTTY will +; * duplicate the device handle to STDIN, STDOUT and +; * STDERR. This routine returns to LODCOM1. +; * +; * INPUT: command line at offset 81H +; * +; * OUTPUT: none +; * +; **************************************************************** + +CTTY: + push ds ;AN000; Get local ES + pop es ;AN000; + mov si,81H ;AC000; Get command argument for CTTY + + mov di,offset trangroup:parse_ctty ;AC000; Get adderss of PARSE_CTTY + xor cx,cx ;AC000; clear cx,dx + xor dx,dx ;AC000; + invoke cmd_parse ;AC000; call parser + cmp ax,end_of_line ;AN000; are we at end of line? + jz ctty_error ;AN000; yes - error + cmp ax,result_no_error ;AN000; did an error occur + jnz ctty_error ;AN000; YES -ERROR + + push si ;AN000; save position in line + lds si,parse1_addr ;AN000; get address of filespec + mov di,offset trangroup:srcbuf ;AN000; get address of srcbuf + +ctty_move_filename: ;AN000; put filespec in srcbuf + lodsb ;AN000; get a char from buffer + stosb ;AN000; store in srcbuf + cmp al,end_of_line_out ;AN000; it char a terminator? + jnz ctty_move_filename ;AN000; no - keep moving + pop si ;AN000; get line position back + mov di,offset trangroup:parse_ctty ;AC000; Get adderss of PARSE_CTTY + call parse_check_eol ;AN000; are we at end of line? + jz nocolon ;AN000; yes - continue + +ctty_error: + jmp isbaddev ;AC000; yes - exit + +nocolon: + mov dx,offset trangroup:srcbuf ;AN000; get address of srcbuf + MOV AX,(OPEN SHL 8) OR 2 ; Read and write + INT int_command ; Open new device + JC ISBADDEV + MOV BX,AX + MOV AX,IOCTL SHL 8 + INT int_command + TEST DL,80H + JNZ DEVISOK + +CLOSEDEV: ;AN007; + MOV AH,CLOSE ; Close initial handle + INT int_command + +ISBADDEV: + MOV DX,OFFSET TRANGROUP:BADDEV_ptr + invoke std_printf + JMP RESRET + +DEVISOK: + push dx ;AN007; save device info + mov ax,acrlf_ptr ;AN021; get message number for 0d, 0a + mov dh,util_msg_class ;AN021; this is a utility message + push bx ;AN021; save handle + invoke Tsysgetmsg ;AN021; get the address of the message + mov dx,si ;AN021; get address into dx + mov ax,(write shl 8) ;AN007; write to device + mov cx,2 ;AN007; write two bytes + int int_command ;AN007; + pop bx ;AN021; get back handle + pop dx ;AN007; get back device info + jc closedev ;AN007; if error, quit + XOR DH,DH + OR DL,3 ; Make sure has CON attributes + MOV AX,(IOCTL SHL 8) OR 1 + INT int_command + PUSH BX ; Save handle + MOV CX,3 + XOR BX,BX + +ICLLOOP: ; Close basic handles + MOV AH,CLOSE + INT int_command + INC BX + LOOP ICLLOOP + POP BX ; Get handle + MOV AH,XDUP + INT int_command ; Dup it to 0 + MOV AH,XDUP + INT int_command ; Dup to 1 + MOV AH,XDUP + INT int_command ; Dup to 2 + MOV AH,CLOSE ; Close initial handle + INT int_command + +RESRET: + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + PUSH DS + MOV AX,WORD PTR DS:[PDB_JFN_Table] ; Get new 0 and 1 + MOV [IO_SAVE],AX + MOV AX,OFFSET RESGROUP:LODCOM1 + PUSH AX + +ZMMMM PROC FAR + RET ; Force header to be checked +ZMMMM ENDP + + break Chcp + +;**************************************************************** +;* +;* ROUTINE: CHCP - Change code page internal command +;* (added DOS 3.30 07/21/86) +;* +;* SYNTAX: CHCP [xxx] +;* where xxx is a valid code page +;* +;* FUNCTION: If xxx is specified, CHCP will use INT 21H function +;* 6402H to set the code page to xxxx. If no parameters +;* are specified, CHCP will use INT 21H function 6401H +;* to get global code page and display it to the user. +;* +;* INPUT: command line at offset 81H +;* +;* OUTPUT: none +;* +;**************************************************************** + +NLSFUNC_installed equ 0ffh +set_global_cp equ 2 +get_global_cp equ 1 + +assume ds:trangroup,es:trangroup + +CHCP: + push ds ;AN000; Get local ES + pop es ;AN000; + mov si,81H ;AC000; Get command argument for CHCP + + mov di,offset trangroup:parse_chcp ;AN000; Get adderss of PARSE_CHCP + xor cx,cx ;AC000; clear cx,dx + xor dx,dx ;AC000; + call parse_with_msg ;AC018; call parser + cmp ax,end_of_line ;AN000; are we at end of line? + + jnz setcp ;AC000; no go get number & set code page + jmp getcp ;AC000; yes - no parm - get code page + +setcp: + cmp ax,result_no_error ;AN000; did we have an error? + jne cp_error ;AC018; yes - go issue message + + push cx ;AN000; save positional count + mov bx,offset trangroup:parse1_addr ;AN000; get number returned + mov cx,word ptr [bx] ;AN000; into cx + mov system_cpage,cx ;AN000; save user input number + pop cx ;AC000; restore positional count + mov di,offset trangroup:parse_chcp ;AN000; Get adderss of PARSE_CHCP + call parse_check_eol ;AN000; are we at end of line? + jnz cp_error ;AC000; no - exit + +okset: + mov ah,NLSFUNC ;AN000; see if NLSFUNC installed + mov al,0 ;AN000; + int 2fh ;AN000; + cmp al,NLSFUNC_installed ;AN000; + jz got_NLS ;AN000; Yes - continue + mov dx,offset trangroup:NLSFUNC_ptr ;AN000; no - set up error message + jmp short cp_error ;AN000; error exit + +got_NLS: + mov bx,system_cpage ;AN000; get user input code page + mov ah,getsetcdpg ;get/set global code page function + mov al,set_global_cp ;minor - set + int int_command + jnc chcp_return ;no error - exit +; +;added for p716 +; + cmp ax,error_file_not_found ;p716 was the error file not found? + jnz chcp_other_error ;no - country.sys was found + + mov ah,GetExtendedError ;p850 see if error is invalid data + xor bx,bx ; which is file was found but CP + int int_command ; information was not found. + cmp ax,error_invalid_data ;AC000; invalid code page + jnz no_countrysys ;no - use file not found + mov dx,offset trangroup:inv_code_page ;AN000; get message + jmp short cp_error ;AC000; error exit + +no_countrysys: + 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 + jmp short cp_error ;AC000; error exit + +chcp_other_error: +; +; end of p716 +; + mov ah,GetExtendedError ;error - see what it is + xor bx,bx + int int_command + cmp ax,65 ;was it access denied? + jnz none_set ;no - assume all failed + mov dx,offset trangroup:cp_not_all_ptr ;set up message + jmp short cp_error ;AC000; error exit + +none_set: + mov dx,offset trangroup:cp_not_set_ptr ;set up message +cp_error: ;AN000; + jmp cerror ;exit + +getcp: + mov ah,getsetcdpg ;get/set global code page function + mov al,get_global_cp ;minor - get + int int_command + mov system_cpage,bx ;get active cp for output + mov dx,offset trangroup:cp_active_ptr + invoke std_printf ;print it out + +chcp_return: + + RET + + break TRUENAME ;AN000; + + +; **************************************************************** +; * +; * ROUTINE: TRUENAME +; * +; * FUNCTION: Entry point for the internal TRUENAME command. +; * Parses the command line. If a path is found, set +; * SRCXNAME to path. If only a drive letter is +; * found, set SRCXNAME to the drive letter. If +; * no path is found, set the path of SRCXNAME to +; * dot (.) for current directory. Use the NAME +; * TRANSLATE system call to get the real name and +; * then display the real name. If an error occurs +; * issue an error message and transfer control to +; * CERROR. +; * +; * INPUT: command line at offset 81H +; * +; * OUTPUT: none +; * +; **************************************************************** + +assume ds:trangroup,es:trangroup ;AN000; + +TRUENAME: ;AN000; TRUENAME entry point + push ds ;AN000; Get local ES + pop es ;AN000; + mov si,81H ;AN000; Get command line + mov di,offset trangroup:parse_chdir ;AN000; Get adderss of PARSE_CHDIR + xor cx,cx ;AN000; clear cx,dx + xor dx,dx ;AN000; + call parse_with_msg ;AC018; call parser + + mov di,offset trangroup:srcxname ;AN000; get address of srcxname + cmp ax,end_of_line ;AN000; are we at end of line? + je tn_eol ;AN000; yes - go process + cmp ax,result_no_error ;AN000; did we have an error? + jne tn_parse_error ;AN000; yes - go issue message + cmp parse1_type,result_drive ;AN000; was a drive entered? + je tn_drive ;AN000; yes - go process + jmp short tn_filespec ;AN000; nothing else - must be filespec + +tn_eol: ;AN000; no parameters on line + mov ah,end_of_line_out ;AN000; set buffer to . + mov al,dot_chr ;AN000; for current dir + stosw ;AN000; store in srcxname + jmp short tn_doit ;AN000; go do command + +tn_drive: ;AN000; a drive was entered + push si ;AN000; save position in line + mov si,offset trangroup:parse1_addr ;AN000; get address of drive + lodsb ;AN000; get the drive number + add al,"A"-1 ;AN000; convert it to char + stosb ;AN000; store it in srcxname + mov ax,dot_colon ;AN000; get colon and . and + stosw ;AN000; store in srcxname + mov al,end_of_line_out ;AN000; put a terminator char + stosb ;AN000; + pop si ;AN000; get line position back + jmp short tn_check_eol ;AN000; check to make sure eol + +tn_filespec: ;AN000; a filespec was entered + push si ;AN000; save position in line + lds si,parse1_addr ;AN000; get address of filespec + +tn_move_filename: ;AN000; put filespec in srcxname + lodsb ;AN000; get a char from buffer + stosb ;AN000; store in srcxname + cmp al,end_of_line_out ;AN000; it char a terminator? + jnz tn_move_filename ;AN000; no - keep moving + pop si ;AN000; get line position back + +tn_check_eol: ;AN000; make sure no extra parms + mov di,offset trangroup:parse_chdir ;AN000; get address of parse_chdir + call parse_check_eol ;AN000; are we at end of line? + je tn_doit ;AN000; Yes - do the command + +tn_parse_error: ;AN000; A parse error occurred + jmp cerror ;AN000; Go to error routine + +tn_doit: ;AN000; + mov si,offset trangroup:srcxname ;AN000; set up srcxname as source + mov di,offset trangroup:combuf ;AN000; set up combuf as target (need big target) + mov ah,xnametrans ;AN000; do name translate call + int int_command ;AN000; + jnc tn_print_xname ;AN000; If no error - print result + + invoke Set_ext_error_msg ;AN000; get extended message + mov string_ptr_2,offset trangroup:srcxname ;AN000; get address of failed string + mov Extend_buf_sub,one_subst ;AN000; put number of subst in control block + jmp cerror ;AN000; Go to error routine + +tn_print_xname: ;AN000; + mov string_ptr_2,offset Trangroup:combuf ;AN000; Set up address of combuf + mov dx,offset trangroup:string_buf_ptr ;AN000; Set up address of print control block + invoke crlf2 ;AN000; print a crlf + invoke printf_crlf ;AN000; print it out + + ret ;AN000; + + break $Exit + +assume ds:trangroup,es:trangroup + +$EXIT: + push ds ;AN000; save data segment + mov ds,[resseg] ;AN000; get resident data segment + +assume ds:resgroup ;AN000; + + cmp [permcom],0 ;AN045; is this a permanent COMMAND? + jnz no_reset ;AN045; Yes - don't do anything +;AD060; mov ah,multdos ;AN000; reset parse message pointers +;AD060; mov al,message_2f ;AN000; call for message retriever +;AD060; mov dl,set_parse_msg ;AN000; set up parse message address +;AD060; mov di,pars_msg_off ;AN000; old offset of parse messages +;AD060; mov es,pars_msg_seg ;AN000; old segment of parse messages +;AD060; int 2fh ;AN000; go set it + +;AD060; mov ah,multdos ;AN000; set up to call DOS through int 2fh +;AD060; mov al,message_2f ;AN000; call for message retriever + mov ax,(multdos shl 8 or message_2f);AN060; reset parse message pointers + mov dl,set_critical_msg ;AN000; set up critical error message address + mov di,crit_msg_off ;AN000; old offset of critical messages + mov es,crit_msg_seg ;AN000; old segment of critical messages + int 2fh ;AN000; go set it +no_reset: ;AN045; + pop ds ;AN000; restore local data segment + +assume ds:trangroup ;AN000; + + MOV ES,[RESSEG] + +assume es:resgroup + + MOV AX,[PARENT] + MOV WORD PTR ES:[PDB_Parent_PID],AX + MOV AX,WORD PTR OldTerm + MOV WORD PTR ES:[PDB_Exit],AX + MOV AX,WORD PTR OldTerm+2 + MOV WORD PTR ES:[PDB_Exit+2],AX + + PUSH ES + MOV ES,[TRAN_TPA] + MOV AH,DEALLOC + INT int_command ; Now running in "free" space + POP ES + + MOV AH,Exit + MOV AL,BYTE PTR RetCode + INT int_command + + +; **************************************************************** +; * +; * ROUTINE: PARSE_CHECK_EOL +; * +; * FUNCTION: Calls parser to see if end of line occurred. +; * If not end of line, set up to print parse +; * error message. ASSUMES NO MORE PARAMETERS ARE +; * EXPECTED! +; * +; * INPUT: DS:SI last output from parser +; * ES:DI points to parse block +; * CX last output from parser +; * +; * OUTPUT: AX parser return code +; * +; * if end of line found +; * zero flag set +; * else +; * MSG_DISPLAY_CLASS set to parse error +; * +; **************************************************************** + +ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:NOTHING ;AN000; + +parse_check_eol Proc near ;AN000; + + xor dx,dx ;AN000; + mov [parse_last],si ;AN018; save start of parameter + invoke cmd_parse ;AN000; call parser + cmp al,end_of_line ;AN000; Are we at end of line? + jz parse_good_eol ;AN000; yes - no problem + + cmp ax,result_no_error ;AN018; was any error found? + jnz ok_to_setup_pmsg ;AN018; yes - continue + inc ax ;AN018; set AX to 1 and turn off zero flag + +ok_to_setup_pmsg: + call setup_parse_error_msg ;AN018; go set up error message + +parse_good_eol: + ret ;AN000; + +parse_check_eol endp ;AN000; + +; **************************************************************** +; * +; * ROUTINE: PARSE_WITH_MSG +; * +; * FUNCTION: Calls parser. If an error occurred, the error +; * message is set up. +; * +; * INPUT: DS:SI last output from parser +; * ES:DI points to parse block +; * CX last output from parser +; * +; * OUTPUT: AX parser return code +; * +; * if no error +; * outputs from parser +; * else +; * MSG_DISPLAY_CLASS set to parse error +; * error message set up for STD_PRINTF +; * +; **************************************************************** + +ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:NOTHING ;AN018; + +parse_with_msg Proc near ;AN018; + + mov [parse_last],si ;AN018; save start of parameter + invoke cmd_parse ;AN018; call parser + cmp al,end_of_line ;AN018; Are we at end of line? + jz parse_msg_good ;AN018; yes - no problem + cmp ax,result_no_error ;AN018; did an error occur + jz parse_msg_good ;AN018; yes - no problem + + call setup_parse_error_msg ;AN018; go set up error message + +parse_msg_good: + ret ;AN018; + +parse_with_msg endp ;AN018; + +; **************************************************************** +; * +; * ROUTINE: SETUP_PARSE_ERROR_MSG +; * +; * FUNCTION: Calls parser. If an error occurred, the error +; * message is set up. +; * +; * INPUT: AX Parse error number +; * SI Set to past last parameter +; * Parse_last Set to start of last parameter +; * +; * OUTPUT: MSG_DISPLAY_CLASS set to parse error +; * error message set up for STD_PRINTF +; * +; **************************************************************** + +ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:NOTHING ;AN018; + +SETUP_PARSE_ERROR_MSG Proc near ;AN018; + + mov msg_disp_class,parse_msg_class ;AC018; Set up parse message class + mov dx,offset TranGroup:Extend_Buf_ptr ;AC018; get extended message pointer + mov byte ptr [si],end_of_line_out ;AC018; terminate the parameter string + mov Extend_Buf_ptr,ax ;AC018; get message number in control block + cmp ax,lessargs_ptr ;AC018; if required parameter missing + jz Setup_parse_msg_ret ;AN018; no subst + mov si,[parse_last] ;AC018; get start of parameter + mov string_ptr_2,si ;AC018; get address of failed string + mov Extend_buf_sub,one_subst ;AC018; put number of subst in control block + +setup_parse_msg_ret: + inc si ;AN018; make sure zero flag not set + + ret ;AC018; + +SETUP_PARSE_ERROR_MSG Endp ;AN018; + +trancode ends + end diff --git a/v4.0/src/CMD/COMMAND/TCODE.ASM b/v4.0/src/CMD/COMMAND/TCODE.ASM new file mode 100644 index 0000000..17ad82d --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TCODE.ASM @@ -0,0 +1,540 @@ + page 80,132 +; SCCSID = @(#)tcode.asm 1.1 85/05/14 +; SCCSID = @(#)tcode.asm 1.1 85/05/14 +TITLE Part1 COMMAND Transient Routines + + INCLUDE comsw.asm +.xlist +.xcref + INCLUDE DOSSYM.INC + INCLUDE comseg.asm + INCLUDE comequ.asm +.list +.cref + + +CODERES SEGMENT PUBLIC BYTE ;AC000; + EXTRN EXEC_WAIT:NEAR +CODERES ENDS + +DATARES SEGMENT PUBLIC BYTE ;AC000; + EXTRN BATCH:WORD + EXTRN CALL_BATCH_FLAG:byte + EXTRN CALL_FLAG:BYTE + EXTRN ECHOFLAG:BYTE + EXTRN envirseg:word + EXTRN EXTCOM:BYTE + EXTRN FORFLAG:BYTE + EXTRN IFFLAG:BYTE + EXTRN next_batch:word + EXTRN nullflag:byte + EXTRN PIPEFILES:BYTE + EXTRN PIPEFLAG:BYTE + EXTRN RE_OUT_APP:BYTE + EXTRN RE_OUTSTR:BYTE + EXTRN RESTDIR:BYTE + EXTRN SINGLECOM:WORD + EXTRN VERVAL:WORD +DATARES ENDS + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN BadNam_Ptr:word ;AC000; +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN APPEND_EXEC:BYTE ;AN041; + EXTRN ARG1S:WORD + EXTRN ARG2S:WORD + EXTRN ARGTS:WORD + EXTRN BYTCNT:WORD + EXTRN COMBUF:BYTE + EXTRN COMSW:WORD + EXTRN CURDRV:BYTE + EXTRN HEADCALL:DWORD + EXTRN IDLEN:BYTE + EXTRN INTERNATVARS:BYTE + EXTRN PARM1:BYTE + EXTRN PARM2:BYTE + EXTRN RE_INSTR:BYTE + EXTRN RESSEG:WORD + EXTRN SPECDRV:BYTE + EXTRN STACK:WORD + EXTRN SWITCHAR:BYTE + EXTRN TPA:WORD + EXTRN UCOMBUF:BYTE + EXTRN USERDIR1:BYTE + IF IBM + EXTRN ROM_CALL:BYTE + EXTRN ROM_CS:WORD + EXTRN ROM_IP:WORD + ENDIF + +TRANSPACE ENDS + +; ******************************************************************** +; START OF TRANSIENT PORTION +; This code is loaded at the end of memory and may be overwritten by +; memory-intensive user programs. + +TRANCODE SEGMENT PUBLIC BYTE ;AC000; + +ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + + EXTRN $EXIT:NEAR + EXTRN DRVBAD:NEAR + EXTRN EXTERNAL:NEAR + EXTRN FNDCOM:NEAR + EXTRN FORPROC:NEAR + EXTRN PIPEPROC:NEAR + EXTRN PIPEPROCSTRT:NEAR + + PUBLIC COMMAND + PUBLIC DOCOM + PUBLIC DOCOM1 + PUBLIC NOPIPEPROC + PUBLIC TCOMMAND + + IF IBM + PUBLIC ROM_EXEC + PUBLIC ROM_SCAN + ENDIF + + ORG 0 +ZERO = $ + + ORG 100H ; Allow for 100H parameter area + +SETDRV: + MOV AH,SET_DEFAULT_DRIVE + INT int_command +; +; TCOMMAND is the recycle point in COMMAND. Nothing is known here. +; No registers (CS:IP) no flags, nothing. +; + +TCOMMAND: + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + MOV AX,-1 + XCHG AX,[VERVAL] + CMP AX,-1 + JZ NOSETVER2 + MOV AH,SET_VERIFY_ON_WRITE ; AL has correct value + INT int_command + +NOSETVER2: + CALL [HEADCALL] ; Make sure header fixed + XOR BP,BP ; Flag transient not read + CMP [SINGLECOM],-1 + JNZ COMMAND + +$EXITPREP: + PUSH CS + POP DS + JMP $EXIT ; Have finished the single command +ASSUME DS:NOTHING +; +; Main entry point from resident portion. +; +; If BP <> 0, then we have just loaded transient portion otherwise we are +; just beginning the processing of another command. +; + +COMMAND: + +; +; We are not always sure of the state of the world at this time. We presume +; worst case and initialize the relevant registers: segments and stack. +; + ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + CLD + MOV AX,CS + CLI + MOV SS,AX +ASSUME SS:TRANGROUP + MOV SP,OFFSET TRANGROUP:STACK + STI + MOV ES,AX + MOV DS,AX ;AN000; set DS to transient +ASSUME ES:TRANGROUP,DS:TRANGROUP ;AC000; + invoke TSYSLOADMSG ;AN000; preload messages + invoke SETSTDINOFF ;AN026; turn off critical error on STDIN + invoke SETSTDOUTOFF ;AN026; turn off critical error on STDOUT + mov append_exec,0 ;AN041; set internal append state off + + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + + MOV [UCOMBUF],COMBUFLEN ; Init UCOMBUF + MOV [COMBUF],COMBUFLEN ; Init COMBUF (Autoexec doing DATE) +; +; If we have just loaded the transient, then we do NOT need to initialize the +; command buffer. ???? DO WE NEED TO RESTORE THE USERS DIRECTORY ???? I +; guess not: the only circumstances in which we reload the command processor +; is after a transient program execution. In this case, we let the current +; directory lie where it may. +; + OR BP,BP ; See if just read + JZ TESTRDIR ; Not read, check user directory + MOV WORD PTR [UCOMBUF+1],0D01H ; Reset buffer + JMP SHORT NOSETBUF + +TESTRDIR: + CMP [RESTDIR],0 + JZ NOSETBUF ; User directory OK + PUSH DS +; +; We have an unusual situation to handle. The user *may* have changed his +; directory as a result of an internal command that got aborted. Restoring it +; twice may not help us: the problem may never go away. We just attempt it +; once and give up. +; + MOV [RESTDIR],0 ; Flag users dirs OK + PUSH CS + POP DS +ASSUME DS:TRANGROUP + MOV DX,OFFSET TRANGROUP:USERDIR1 + MOV AH,CHDIR + INT int_command ; Restore users directory + POP DS +ASSUME DS:RESGROUP + +NOSETBUF: + CMP [PIPEFILES],0 + JZ NOPCLOSE ; Don't bother if they don't exist + CMP [PIPEFLAG],0 + JNZ NOPCLOSE ; Don't del if still piping + INVOKE PIPEDEL + +NOPCLOSE: + MOV [EXTCOM],0 ; Flag internal command + MOV AX,CS ; Get segment we're in + MOV DS,AX +ASSUME DS:TRANGROUP + + PUSH AX + MOV DX,OFFSET TRANGROUP:INTERNATVARS + MOV AX,INTERNATIONAL SHL 8 + INT 21H + POP AX + SUB AX,[TPA] ; AX=size of TPA in paragraphs + PUSH BX + MOV BX,16 + MUL BX ; DX:AX=size of TPA in bytes + POP BX + OR DX,DX ; See if over 64K + JZ SAVSIZ ; OK if not + MOV AX,-1 ; If so, limit to 65535 bytes + +SAVSIZ: +; +; AX is the number of bytes free in the buffer between the resident and the +; transient with a maximum of 64K-1. We round this down to a multiple of 512. +; + CMP AX,512 + JBE GotSize + AND AX,0FE00h ; NOT 511 = NOT 1FF + +GotSize: + MOV [BYTCNT],AX ; Max no. of bytes that can be buffered + MOV DS,[RESSEG] ; All batch work must use resident seg. +ASSUME DS:RESGROUP + + TEST [ECHOFLAG],1 + JZ GETCOM ; Don't do the CRLF + INVOKE SINGLETEST + JB GETCOM + TEST [PIPEFLAG],-1 + JNZ GETCOM + TEST [FORFLAG],-1 ; G Don't print prompt in FOR + JNZ GETCOM ; G + TEST [BATCH], -1 ; G Don't print prompt if in batch + JNZ GETCOM ; G + INVOKE CRLF2 + +GETCOM: + MOV CALL_FLAG,0 ; G Reset call flags + MOV CALL_BATCH_FLAG,0 ; G + MOV AH,GET_DEFAULT_DRIVE + INT int_command + MOV [CURDRV],AL + TEST [PIPEFLAG],-1 ; Pipe has highest presedence + JZ NOPIPE + JMP PIPEPROC ; Continue the pipeline + +NOPIPE: + TEST [ECHOFLAG],1 + JZ NOPDRV ; No prompt if echo off + INVOKE SINGLETEST + JB NOPDRV + TEST [FORFLAG],-1 ; G Don't print prompt in FOR + JNZ NOPDRV ; G + TEST [BATCH], -1 ; G Don't print prompt if in batch + JNZ TESTFORBAT ; G + INVOKE PRINT_PROMPT ; Prompt the user + +NOPDRV: + TEST [FORFLAG],-1 ; FOR has next highest precedence + JZ TESTFORbat + JMP FORPROC ; Continue the FOR + +TESTFORBAT: + MOV [RE_INSTR],0 ; Turn redirection back off + MOV [RE_OUTSTR],0 + MOV [RE_OUT_APP],0 + MOV IFFlag,0 ; no more ifs... + TEST [BATCH],-1 ; Batch has lowest precedence + JZ ISNOBAT + + push es ;AN000; save ES + push ds ;AN000; save DS + mov ax,mult_shell_get ;AN000; check to see if SHELL has command + mov es,[batch] ;AN000; get batch segment + mov di,batfile ;AN000; get batch file name + push cs ;AN000; get local segment to DS + pop ds ;AN000; + mov dx,offset trangroup:combuf ;AN000; pass communications buffer + int 2fh ;AN000; call the shell + cmp al,shell_action ;AN000; does shell have a commmand? + pop ds ;AN000; restore DS + pop es ;AN000; restore ES + jz jdocom1 ;AN000; yes - go process command + + PUSH DS ;G + INVOKE READBAT ; Continue BATCH + POP DS ;G + mov nullflag,0 ;G reset no command flag + TEST [BATCH],-1 ;G + JNZ JDOCOM1 ;G if batch still in progress continue + MOV BX,NEXT_BATCH ;G + CMP BX,0 ;G see if there is a new batch file + JZ JDOCOM1 ;G no - go do command + MOV BATCH,BX ;G get segment of next batch file + MOV NEXT_BATCH,0 ;G reset next batch +JDOCOM1: + PUSH CS ;G + POP DS ;G + JMP SHORT DoCom1 ; echoing already done + +ISNOBAT: + CMP [SINGLECOM],0 + JZ REGCOM + MOV SI,-1 + XCHG SI,[SINGLECOM] + MOV DI,OFFSET TRANGROUP:COMBUF + 2 + XOR CX,CX + +SINGLELOOP: + LODSB + STOSB + INC CX + CMP AL,0DH + JNZ SINGLELOOP + DEC CX + PUSH CS + POP DS +ASSUME DS:TRANGROUP + MOV [COMBUF + 1],CL +; +; do NOT issue a trailing CRLF... +; + JMP DOCOM1 + +; +; We have a normal command. +; Printers are a bizarre quantity. Sometimes they are a stream and +; sometimes they aren't. At this point, we automatically close all spool +; files and turn on truncation mode. +; + +REGCOM: + MOV AX,(ServerCall SHL 8) + 9 + INT 21h + MOV AX,(ServerCall SHL 8) + 8 + MOV DL,1 + INT 21h + + PUSH CS + POP DS ; Need local segment to point to buffer + MOV DX,OFFSET TRANGROUP:UCOMBUF + MOV AH,STD_CON_STRING_INPUT + INT int_command ; Get a command + MOV CL,[UCOMBUF] + XOR CH,CH + ADD CX,3 + MOV SI,OFFSET TRANGROUP:UCOMBUF + MOV DI,OFFSET TRANGROUP:COMBUF + REP MOVSB ; Transfer it to the cooked buffer + +;--------------- + +transpace segment + extrn arg:byte ; the arg structure! +transpace ends +;--------------- + + +DOCOM: + INVOKE CRLF2 + +DOCOM1: + INVOKE PRESCAN ; Cook the input buffer + JZ NOPIPEPROC + JMP PIPEPROCSTRT ; Fire up the pipe + +nullcomj: + jmp nullcom + +NOPIPEPROC: + invoke parseline + jnc OkParse ; user error? or maybe we goofed? + +BadParse: + PUSH CS + POP DS + MOV DX,OFFSET TRANGROUP:BADNAM_ptr + INVOKE std_eprintf + JMP TCOMMAND + +OkParse: + test arg.argv[0].argflags, MASK wildcard + jnz BadParse ; ambiguous commands not allowed + cmp arg.argvcnt, 0 ; there WAS a command, wasn't there? + jz nullcomj + cmp arg.argv[0].arglen, 0 ; probably an unnecessary check... + jz nullcomj ; guarantees argv[0] at least x + + MOV SI,OFFSET TRANGROUP:COMBUF+2 + MOV DI,OFFSET TRANGROUP:IDLEN + MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR 01H ; Make FCB with blank scan-off + INT int_command + mov BX, arg.argv[0].argpointer + cmp BYTE PTR [BX+1],':' ; was a drive specified? + jne short drvgd ; no, use default of zero... + + mov DL, BYTE PTR [BX] ; pick-up drive letter + and DL, NOT 20H ; uppercase the sucker + sub DL, capital_A ; convert it to a drive number, A=0 + + CMP AL,-1 ; See what PARSE said about our drive letter. + JZ drvbadj2 ; It was invalid. + + mov DI, arg.argv[0].argstartel + cmp BYTE PTR [DI], 0 ; is there actually a command there? + jnz drvgd ; if not, we have: "d:", "d:\", "d:/" + jmp setdrv ; and set drive to new drive spec + +drvbadj2: + jmp drvbad + +DRVGD: + MOV AL,[DI] + MOV [SPECDRV],AL + MOV AL,' ' + MOV CX,9 + INC DI + REPNE SCASB ; Count no. of letters in command name + MOV AL,8 + SUB AL,CL + MOV [IDLEN],AL ; IDLEN is truly the length + MOV DI,81H + PUSH SI + + mov si, OFFSET TRANGROUP:COMBUF+2 ; Skip over all leading delims + invoke scanoff + +do_skipcom: + lodsb ; move command line pointer over + invoke delim ; pathname -- have to do it ourselves + jz do_skipped ; 'cause parse_file_descriptor is dumb + cmp AL, 0DH ; can't always depend on argv[0].arglen + jz do_skipped ; to be the same length as the user- + cmp AL, [SWITCHAR] ; specified command string + jnz do_skipcom + +do_skipped: + dec SI + XOR CX,CX + +COMTAIL: + LODSB + STOSB ; Move command tail to 80H + CMP AL,13 + LOOPNZ COMTAIL + DEC DI + MOV BP,DI + NOT CL + MOV BYTE PTR DS:[80H],CL + POP SI + +;----- +; Some of these comments are sadly at odds with this brave new code. +;----- +; If the command has 0 parameters must check here for +; any switches that might be present. +; SI -> first character after the command. + + mov DI, arg.argv[0].argsw_word + mov [COMSW], DI ; ah yes, the old addressing mode problem... + mov SI, arg.argv[1 * SIZE argv_ele].argpointer ; s = argv[1]; + OR SI,SI ; if (s == NULL) + JNZ DoParse + MOV SI,BP ; s = bp; (buffer end) + +DoParse: + MOV DI,FCB + MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR 01H + INT int_command + MOV [PARM1],AL ; Save result of parse + + mov DI, arg.argv[1*SIZE argv_ele].argsw_word + mov [ARG1S], DI + mov SI, arg.argv[2*SIZE argv_ele].argpointer ; s = argv[2]; + OR SI,SI ; if (s == NULL) + JNZ DoParse2 + MOV SI,BP ; s = bp; (bufend)1 + +DoParse2: + MOV DI,FCB+10H + MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR 01H + INT int_command ; Parse file name + MOV [PARM2],AL ; Save result + + mov DI, arg.argv[2*SIZE argv_ele].argsw_word + mov [ARG2S], DI + mov DI, arg.argv[0].argsw_word + not DI ; ARGTS doesn't include the flags + and DI, arg.argswinfo ; from COMSW... + mov [ARGTS], DI + + MOV AL,[IDLEN] + MOV DL,[SPECDRV] + or DL, DL ; if a drive was specified... + jnz externalj1 ; it MUST be external, by this time + dec al ; (I don't know why -- old code did it) + jmp fndcom ; otherwise, check internal com table + +externalj1: + jmp external + +nullcom: + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + TEST [BATCH], -1 ;G Are we in a batch file? + JZ nosetflag ;G only set flag if in batch + mov nullflag,nullcommand ;G set flag to indicate no command + +nosetflag: + CMP [SINGLECOM],-1 + JZ EXITJ + JMP GETCOM + +EXITJ: + JMP $EXITPREP + +IF IBM + include mshalo.asm +ENDIF + +TRANCODE ENDS + END diff --git a/v4.0/src/CMD/COMMAND/TDATA.ASM b/v4.0/src/CMD/COMMAND/TDATA.ASM new file mode 100644 index 0000000..c80c588 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TDATA.ASM @@ -0,0 +1,777 @@ + page 80,132 +; SCCSID = @(#)tdata.asm 4.3 85/05/17 +; SCCSID = @(#)tdata.asm 4.3 85/05/17 +TITLE COMMAND Transient Initialized DATA + +; MODIFICATION HISTORY +; +; EE 10-20-83 Changed the drive check indicator bytes (DCIB's) in +; COMTAB to be a flag byte in which bit 0 is now the +; DCIB(bit) and bit 1 is on if the command can take +; switches. + +fmt macro name,string,args + local a +a db string +PUBLIC name +name dw offset trangroup:a +irp val, + dw offset trangroup:val +endm +endm + +btab macro b,sym + db b + dw offset trangroup:sym + endm + +.xlist +.xcref + INCLUDE comsw.asm ;AC000; + INCLUDE comseg.asm + INCLUDE EA.inc ;AN030; + INCLUDE dirent.inc ;AN042; +.list +.cref + +BREAK MACRO subtitle + SUBTTL subtitle + PAGE +ENDM + +; +; WARNING: DO NOT INCLUDE DOSSYM.INC BECAUSE IT DESTROYS THE MACRO 'FMT' THAT +; has been defined above - RS. +; + INCLUDE CURDIR.INC + INCLUDE ERROR.INC + INCLUDE ifequ.asm + INCLUDE comequ.asm + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN arg_buf:BYTE + EXTRN bwdbuf:byte + EXTRN bytes_free:WORD + EXTRN charbuf:byte + EXTRN copy_Num:WORD + EXTRN cpyflag:BYTE + EXTRN DATE_OUTPUT:BYTE ;AC000; + EXTRN Dir_Num:WORD + EXTRN DRIVE_OUTPUT:BYTE ;AC000; + EXTRN file_size_high:WORD + EXTRN file_size_low:WORD + EXTRN major_ver_num:WORD + EXTRN minor_ver_num:WORD + EXTRN one_char_val:BYTE + EXTRN PARSE1_OUTPUT:BYTE ;AC000; + EXTRN srcbuf:byte + EXTRN string_ptr_2:WORD + EXTRN system_cpage:word + EXTRN TIME_OUTPUT:BYTE ;AC000; + EXTRN vol_drv:BYTE + EXTRN vol_serial:dword ;AN000; +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC BYTE ;AC000; + EXTRN $CALL:NEAR + EXTRN $CHDIR:NEAR + EXTRN $EXIT:NEAR + EXTRN $FOR:NEAR + EXTRN $IF:NEAR + EXTRN $MKDIR:NEAR + EXTRN $RMDIR:NEAR + EXTRN ADD_NAME_TO_ENVIRONMENT:NEAR + EXTRN ADD_PROMPT:NEAR + EXTRN build_dir_for_prompt:near + EXTRN CATALOG:NEAR + EXTRN CHCP:NEAR + EXTRN CLS:NEAR + EXTRN CNTRLC:NEAR + EXTRN COPY:NEAR + EXTRN CRENAME:NEAR + EXTRN CRLF2:NEAR + EXTRN CTIME:NEAR + EXTRN CTTY:NEAR + EXTRN DATE:NEAR + EXTRN ECHO:NEAR + EXTRN ERASE:NEAR + EXTRN GOTO:NEAR + EXTRN IFERLEV:NEAR + EXTRN IFEXISTS:NEAR + EXTRN IFNOT:NEAR + EXTRN PATH:NEAR + EXTRN PAUSE:NEAR + EXTRN PRINT_B:NEAR + EXTRN PRINT_BACK:NEAR + EXTRN PRINT_DATE:NEAR + EXTRN PRINT_CHAR:NEAR + EXTRN PRINT_DRIVE:NEAR + EXTRN PRINT_EQ:NEAR + EXTRN PRINT_ESC:NEAR + EXTRN PRINT_G:NEAR + EXTRN PRINT_L:NEAR + EXTRN PRINT_TIME:NEAR + EXTRN PRINT_VERSION:NEAR + EXTRN SHIFT:NEAR + EXTRN TCOMMAND:NEAR + EXTRN TRUENAME:NEAR ;AN000; + EXTRN TYPEFIL:NEAR + EXTRN VERSION:NEAR + EXTRN VOLUME:NEAR + EXTRN VERIFY:NEAR +; +; WARNING!!! No code may appear after this label!!!! +; +PUBLIC TranCodeLast +TranCodeLast LABEL BYTE +TRANCODE ENDS + +; Data for transient portion + +TRANDATA SEGMENT PUBLIC BYTE + + PUBLIC accden_ptr ;AN000; + PUBLIC acrlf_ptr ;AN000; + PUBLIC arg_buf_ptr ;AN000; + PUBLIC badbat_ptr ;AN000; + PUBLIC badcd_ptr ;AN000; + PUBLIC badCPmes_ptr ;AN000; + PUBLIC badcurdrv ;AN000; + PUBLIC baddat_ptr ;AN000; + PUBLIC baddev_ptr ;AN000; + PUBLIC baddrv_ptr ;AN000; + PUBLIC badlab_ptr ;AN000; + PUBLIC badmkd_ptr ;AN000; + PUBLIC badnam_ptr ;AN000; + PUBLIC bad_on_off_ptr ;AN000; + PUBLIC badPmes_ptr ;AN000; + PUBLIC badrmd_ptr ;AN000; + PUBLIC badtim_ptr ;AN000; + PUBLIC batext + PUBLIC bytmes_ptr ;AN000; + PUBLIC CLSSTRING + PUBLIC comext + PUBLIC COMSPECSTR + PUBLIC COMTAB + PUBLIC copied_ptr ;AN000; + PUBLIC cp_active_ptr ;AN000; + PUBLIC cp_not_all_ptr ;AN000; + PUBLIC cp_not_set_ptr ;AN000; + PUBLIC ctrlcmes_ptr ;AN000; + PUBLIC curdat_mo_day ;AN000; + PUBLIC curdat_ptr ;AN000; + PUBLIC curdat_yr ;AN000; + PUBLIC curtim_hr_min ;AN000; + PUBLIC curtim_ptr ;AN000; + PUBLIC curtim_sec_hn ;AN000; + PUBLIC dback_ptr ;AN000; + PUBLIC del_Y_N_ptr ;AN000; + PUBLIC devwmes_ptr ;AN000; + PUBLIC dirdattim_ptr ;AN000; + PUBLIC dirdat_mo_day ;AN000; + PUBLIC dirdat_yr ;AN000; + PUBLIC dirhead_ptr ;AN000; + PUBLIC dirmes_ptr ;AN000; + PUBLIC dirtim_hr_min ;AN000; + PUBLIC dirtim_sec_hn ;AN000; + PUBLIC DIR_W_SYN ;AN000; + PUBLIC disp_file_size_ptr ;AN000; + PUBLIC dmes_ptr ;AN000; + PUBLIC echomes_ptr ;AN000; + PUBLIC enverr_ptr ;AN000; + PUBLIC eurdat_ptr ;AN000; + PUBLIC exeext + PUBLIC extend_buf_off ;AN000; + PUBLIC extend_buf_ptr ;AN000; + PUBLIC extend_buf_seg ;AN000; + PUBLIC extend_buf_sub ;AN000; + PUBLIC file_name_ptr ;AN000; + PUBLIC fornestmes_ptr ;AN000; + PUBLIC fuldir_ptr ;AN000; + PUBLIC IFTAB + PUBLIC inBdev_ptr ;AN000; + PUBLIC inornot_ptr ;AN000; + PUBLIC Inv_code_page ;AN000; + PUBLIC inval_path_ptr ;AN000; + PUBLIC japdat_ptr ;AN000; + PUBLIC Losterr_ptr ;AN000; + PUBLIC md_exists_ptr ;AN006; + PUBLIC msg_cont_flag ;AN000; + PUBLIC msg_disp_class ;AN000; + PUBLIC needbat_ptr ;AN000; + PUBLIC newdat_format ;AN000; + PUBLIC newdat_ptr ;AN000; + PUBLIC newtim_ptr ;AN000; + PUBLIC NLSFUNC_ptr ;AN000; + PUBLIC nospace_ptr ;AN000; + PUBLIC no_values ;AN000; + PUBLIC nulpath_ptr ;AN000; + PUBLIC offmes_ptr ;AN000; + PUBLIC onmes_ptr ;AN000; + PUBLIC overwr_ptr ;AN000; + PUBLIC PARSE_BREAK ;AN000; + PUBLIC PARSE_CHCP ;AN000; + PUBLIC PARSE_CHDIR ;AN000; + PUBLIC PARSE_CTTY ;AN000; + PUBLIC PARSE_DATE ;AN000; + PUBLIC PARSE_DIR ;AN000; + PUBLIC PARSE_ERASE ;AN000; + PUBLIC PARSE_MRDIR ;AN000; + PUBLIC PARSE_RENAME ;AN000; + PUBLIC PARSE_TIME ;AN000; + PUBLIC PARSE_VOL ;AN000; + PUBLIC PATH_TEXT + PUBLIC pausemes_ptr ;AN000; + PUBLIC pipeEmes_ptr ;AN000; + PUBLIC promptdat_moday ;AN000; + PUBLIC promptdat_ptr ;AN000; + PUBLIC promptdat_yr ;AN000; + PUBLIC PROMPT_TABLE + PUBLIC PROMPT_TEXT + PUBLIC promtim_hr_min ;AN000; + PUBLIC promtim_ptr ;AN000; + PUBLIC promtim_sec_hn ;AN000; + PUBLIC renerr_ptr ;AN000; + PUBLIC SLASH_P_SYN ;AN000; + PUBLIC string_buf_ptr ;AN000; + PUBLIC suremes_ptr ;AN000; + PUBLIC switch_list + PUBLIC syntmes_ptr ;AN000; + PUBLIC tab_ptr ;AN000; + PUBLIC TRANDATAEND + PUBLIC usadat_ptr ;AN000; + PUBLIC verimes_ptr ;AN000; + PUBLIC vermes_ptr ;AN000; + PUBLIC volmes_ptr ;AN000; + PUBLIC volmes_ptr_2 ;AN000; + PUBLIC volsermes_ptr ;AN000; + PUBLIC WEEKTAB + PUBLIC xa_cp ;AN030; + +INCLUDE tranmsg.asm + +CLSSTRING DB 4,01BH,"[2J" ; ANSI Clear screen + +PROMPT_TABLE LABEL BYTE + btab "B",Print_B + btab "D",PRINT_DATE + btab "E",PRINT_ESC + btab "G",PRINT_G + btab "H",PRINT_BACK + btab "L",PRINT_L + btab "N",PRINT_DRIVE + btab "P",build_dir_for_prompt + btab "Q",PRINT_EQ + btab "T",PRINT_TIME + btab "V",PRINT_VERSION + btab "_",CRLF2 + btab "$",PRINT_CHAR + DB 0 ; NUL TERMINATED + +IFTAB LABEL BYTE ; Table of IF conditionals + DB 3,"NOT" ; First byte is count + DW OFFSET TRANGROUP:IFNOT + DB 10,"ERRORLEVEL" + DW OFFSET TRANGROUP:IFERLEV + DB 5,"EXIST" + DW OFFSET TRANGROUP:IFEXISTS + DB 0 + +; Table for internal command names +COMTAB DB 3,"DIR",fSwitchAllowed+fCheckDrive + DW OFFSET TRANGROUP:CATALOG ; In TCMD1.ASM + DB 4,"CALL",fSwitchAllowed + DW OFFSET TRANGROUP:$CALL ; In TBATCH2.ASM + DB 4,"CHCP",fSwitchAllowed + DW OFFSET TRANGROUP:CHCP ; In TCMD2B.ASM + DB 6,"RENAME",fSwitchAllowed+fCheckDrive ;AC018; P3903 + DW OFFSET TRANGROUP:CRENAME ; In TCMD1.ASM + DB 3,"REN",fSwitchAllowed+fCheckDrive ;AC018; P3903 + DW OFFSET TRANGROUP:CRENAME ; In TCMD1.ASM + DB 5,"ERASE",fSwitchAllowed+fCheckDrive + DW OFFSET TRANGROUP:ERASE ; In TCMD1.ASM + DB 3,"DEL",fSwitchAllowed+fCheckDrive + DW OFFSET TRANGROUP:ERASE ; In TCMD1.ASM + DB 4,"TYPE",fSwitchAllowed+fCheckDrive ;AC018; P3903 + DW OFFSET TRANGROUP:TYPEFIL ; In TCMD1.ASM + DB 3,"REM",fSwitchAllowed + DW OFFSET TRANGROUP:TCOMMAND ; In TCODE.ASM + DB 4,"COPY",fSwitchAllowed+fCheckDrive + DW OFFSET TRANGROUP:COPY ; In COPY.ASM + DB 5,"PAUSE",fSwitchAllowed + DW OFFSET TRANGROUP:PAUSE ; In TCMD1.ASM + DB 4,"DATE",fSwitchAllowed + DW OFFSET TRANGROUP:DATE ; In TPIPE.ASM + DB 4,"TIME",fSwitchAllowed ;AC018; P3903 + DW OFFSET TRANGROUP:CTIME ; In TPIPE.ASM + DB 3,"VER",0 + DW OFFSET TRANGROUP:VERSION ; In TCMD2.ASM + DB 3,"VOL",fSwitchAllowed+fCheckDrive ;AC018; P3903 + DW OFFSET TRANGROUP:VOLUME ; In TCMD1.ASM + DB 2,"CD",fSwitchAllowed+fCheckDrive ;AC018; P3903 + DW OFFSET TRANGROUP:$CHDIR ; In TENV.ASM + DB 5,"CHDIR",fSwitchAllowed+fCheckDrive ;AC018; P3903 + DW OFFSET TRANGROUP:$CHDIR ; In TENV.ASM + DB 2,"MD",fSwitchAllowed+fCheckDrive ;AC018; P3903 + DW OFFSET TRANGROUP:$MKDIR ; In TENV.ASM + DB 5,"MKDIR",fSwitchAllowed+fCheckDrive ;AC018; P3903 + DW OFFSET TRANGROUP:$MKDIR ; In TENV.ASM + DB 2,"RD",fSwitchAllowed+fCheckDrive ;AC018; P3903 + DW OFFSET TRANGROUP:$RMDIR ; In TENV.ASM + DB 5,"RMDIR",fSwitchAllowed+fCheckDrive ;AC018; P3903 + DW OFFSET TRANGROUP:$RMDIR ; In TENV.ASM + DB 5,"BREAK",fSwitchAllowed ;AC018; P3903 + DW OFFSET TRANGROUP:CNTRLC ; In TUCODE.ASM + DB 6,"VERIFY",fSwitchAllowed ;AC018; P3903 + DW OFFSET TRANGROUP:VERIFY ; In TUCODE.ASM + DB 3,"SET",fSwitchAllowed + DW OFFSET TRANGROUP:ADD_NAME_TO_ENVIRONMENT; In TENV.ASM + DB 6,"PROMPT",fSwitchAllowed + DW OFFSET TRANGROUP:ADD_PROMPT ; In TENV.ASM + DB 4,"PATH",fSwitchAllowed + DW OFFSET TRANGROUP:PATH ; In TCMD2.ASM + DB 4,"EXIT",0 + DW OFFSET TRANGROUP:$EXIT ; In TCMD2.ASM + DB 4,"CTTY",fCheckDrive+fSwitchAllowed + DW OFFSET TRANGROUP:CTTY ; In TCMD2.ASM + DB 4,"ECHO",fSwitchAllowed + DW OFFSET TRANGROUP:ECHO ; In TUCODE.ASM + DB 4,"GOTO",fSwitchAllowed + DW OFFSET TRANGROUP:GOTO ; In TBATCH.ASM + DB 5,"SHIFT",fSwitchAllowed + DW OFFSET TRANGROUP:SHIFT ; In TBATCH.ASM + DB 2,"IF",fSwitchAllowed + DW OFFSET TRANGROUP:$IF ; In TBATCH.ASM + DB 3,"FOR",fSwitchAllowed + DW OFFSET TRANGROUP:$FOR ; In TBATCH.ASM + DB 3,"CLS",0 + DW OFFSET TRANGROUP:CLS ; In TCMD2.ASM + DB 8,"TRUENAME",fSwitchAllowed+fCheckDrive ;AN000; P3903 changed + DW OFFSET TRANGROUP:TRUENAME ;AN000; + DB 0 ; Terminate command table + + +comext dB ".COM" +exeext dB ".EXE" +batext dB ".BAT" + +switch_list DB "VBAPW" ; flags we can recognize + + +XA_cp Label byte ;AN030; list for one extended attribute + DW 1 ;AN030; + DB EAISBINARY ;AN030; type + DW EASYSTEM ;AN030; flags + DB 2 ;AN030; name length + DB "CP" ;AN030; name + + + + +PUBLIC BatBufLen +BatBufLen DW BatLen + +; ***************************************************** +; EMG 4.00 +; DATA STARTING HERE WAS ADDED BY EMG FOR 4.00 +; FOR IMPLEMENTATION OF COMMON PARSE ROUTINE +; ***************************************************** + +; +; COMMON PARSE BLOCKS +; + +; +; Indicates no value list for PARSE. +; + +NO_VALUES DW 0 ;AN000; no values + +; +; PARSE control block for a required file specification (upper cased) +; + +FILE_REQUIRED LABEL BYTE ;AN000; + DW 0200H ;AN000; filespec - required + DW 1 ;AN000; capitalize - file table + DW TRANGROUP:PARSE1_OUTPUT ;AN000; result buffer + DW TRANGROUP:NO_VALUES ;AN000; + DB 0 ;AN000; no keywords + +; +; PARSE control block for an optional file specification (upper cased) +; or drive number +; + +FILE_OPTIONAL LABEL BYTE ;AN000; + DW 0301H ;AN000; filespec or drive number + ; optional + DW 1 ;AN000; capitalize - file table + DW TRANGROUP:PARSE1_OUTPUT ;AN000; result buffer + DW TRANGROUP:NO_VALUES ;AN000; + DB 0 ;AN000; no keywords + +; +; PARSE control block for an optional file specification (upper cased) +; + +FILE_OPTIONAL2 LABEL BYTE ;AN000; + DW 0201H ;AN000; filespec or drive number + ; optional + DW 1 ;AN000; capitalize - file table + DW TRANGROUP:PARSE1_OUTPUT ;AN000; result buffer + DW TRANGROUP:NO_VALUES ;AN000; + DB 0 ;AN000; no keywords + +; +; PARSE control block for an optional /P switch +; + +SLASH_P_SWITCH LABEL BYTE ;AN000; + DW 0 ;AN000; no match flags + DW 2 ;AN000; capitalize - char table + DW TRANGROUP:PARSE1_OUTPUT ;AN000; result buffer + DW TRANGROUP:NO_VALUES ;AN000; + DB 1 ;AN000; 1 keyword +SLASH_P_SYN DB "/P",0 ;AN000; /P switch + + + +; PARSE BLOCK FOR BREAK, VERIFY, ECHO + +; +; The following parse control block can be used for any command which +; needs only the optional "ON" and "OFF" keywords as operands. Allows +; the equal sign as an additional delimiter. Returns verified result +; in PARSE1_OUTPUT. Currently used for the BREAK, VERIFY, and ECHO +; internal commands. +; + +PARSE_BREAK LABEL BYTE ;AN000; + DW TRANGROUP:BREAK_PARMS ;AN000; + DB 0 ;AN032; no extra delimiter + +BREAK_PARMS LABEL BYTE ;AN000; + DB 0,1 ;AN000; 1 positional parm + DW TRANGROUP:BREAK_CONTROL1;AN000; + DB 0 ;AN000; no switches + DB 0 ;AN000; no keywords + +BREAK_CONTROL1 LABEL BYTE ;AN000; + DW 2001H ;AN000; string value - optional + DW 2 ;AN000; capitalize - char table + DW TRANGROUP:PARSE1_OUTPUT ;AN000; result buffer + DW TRANGROUP:BREAK_VALUES ;AN000; + DB 0 ;AN000; no keywords + +BREAK_VALUES LABEL BYTE ;AN000; + DB 3 ;AN000; + DB 0 ;AN000; no ranges + DB 0 ;AN000; no numeric values + DB 2 ;AN000; 2 string values + DB 0 ;AN000; returned if ON + DW TRANGROUP:BREAK_ON ;AN000; point to ON string + DB 'f' ;AN000; returned if OFF + DW TRANGROUP:BREAK_OFF ;AN000; point to OFF string + +BREAK_ON DB "ON",0 ;AN000; +BREAK_OFF DB "OFF",0 ;AN000; + +; +; PARSE BLOCK FOR CHCP +; + +; +; The following parse control block can be used for any command which +; needs only one optional three digit decimal parameter for operands. +; Returns verified result in PARSE1_OUTPUT. Currently used for the +; CHCP internal command. +; +CHCP_MINVAL EQU 100 ;AN000; +CHCP_MAXVAL EQU 999 ;AN000; + +PARSE_CHCP LABEL BYTE ;AN000; + DW TRANGROUP:CHCP_PARMS ;AN000; + DB 0 ;AN000; no extra delimiter + +CHCP_PARMS LABEL BYTE ;AN000; + DB 0,1 ;AN000; 1 positional parm + DW TRANGROUP:CHCP_CONTROL1 ;AN000; + DB 0 ;AN000; no switches + DB 0 ;AN000; no keywords + +CHCP_CONTROL1 LABEL BYTE ;AN000; + DW 8001H ;AN000; numeric value - optional + DW 0 ;AN000; no function flags + DW TRANGROUP:PARSE1_OUTPUT ;AN000; result buffer + DW TRANGROUP:CHCP_VALUES ;AN000; + DB 0 ;AN000; no keywords + +CHCP_VALUES LABEL BYTE ;AN000; + DB 1 ;AN000; + DB 1 ;AN000; 1 range + DB 1 ;AN000; returned if result + DD CHCP_MINVAL,CHCP_MAXVAL ;AN000; minimum & maximum value + DB 0 ;AN000; no numeric values + DB 0 ;AN000; no string values + + +; +; PARSE BLOCK FOR DATE +; + +; +; The following parse control block can be used for any command which +; needs only an optional date string as an operand. Returns unverified +; result in DATE_OUTPUT. Currently used for the DATE internal command. +; + +PARSE_DATE LABEL BYTE ;AN000; + DW TRANGROUP:DATE_PARMS ;AN000; + DB 0 ;AN000; no extra delimiter + +DATE_PARMS LABEL BYTE ;AN000; + DB 0,1 ;AN000; 1 positional parm + DW TRANGROUP:DATE_CONTROL1 ;AN000; + DB 0 ;AN000; no switches + DB 0 ;AN000; no keywords + +DATE_CONTROL1 LABEL BYTE ;AN000; + DW 1001H ;AN000; date - optional + DW 0 ;AN000; no function flags + DW TRANGROUP:DATE_OUTPUT ;AN000; result buffer + DW TRANGROUP:NO_VALUES ;AN000; + DB 0 ;AN000; no keywords + +; +; PARSE BLOCK FOR TIME +; + +; +; The following parse control block can be used for any command which +; needs only an optional time string as an operand. Returns unverified +; result in TIME_OUTPUT. Currently used for the TIME internal command. +; + +PARSE_TIME LABEL BYTE ;AN000; + DW TRANGROUP:TIME_PARMS ;AN000; + DB 0 ;AN000; no extra delimiter + +TIME_PARMS LABEL BYTE ;AN000; + DB 0,1 ;AN000; 1 positional parm + DW TRANGROUP:TIME_CONTROL1 ;AN000; + DB 0 ;AN000; no switches + DB 0 ;AN000; no keywords + +TIME_CONTROL1 LABEL BYTE ;AN000; + DW 0801H ;AN000; TIME - optional + DW 0 ;AN000; no function flags + DW TRANGROUP:TIME_OUTPUT ;AN000; result buffer + DW TRANGROUP:NO_VALUES ;AN000; + DB 0 ;AN000; no keywords + + +; +; PARSE BLOCK FOR VOL +; + +; +; The following parse control block can be used for any command which +; needs only an optional drive letter as an operand. Returns unverified +; drive number (one based) in DRIVE_OUTPUT. Currently used for the VOL +; internal command. +; + +PARSE_VOL LABEL BYTE ;AN000; + DW TRANGROUP:VOL_PARMS ;AN000; + DB 0 ;AN000; no extra delimiter + +VOL_PARMS LABEL BYTE ;AN000; + DB 0,1 ;AN000; 1 positional parm + DW TRANGROUP:DRIVE_CONTROL1;AN000; + DB 0 ;AN000; no switches + DB 0 ;AN000; no keywords + +DRIVE_CONTROL1 LABEL BYTE ;AN000; + DW 0101H ;AN000; DRIVE - optional + DW 1 ;AN000; capitalize - file table + DW TRANGROUP:DRIVE_OUTPUT ;AN000; result buffer + DW TRANGROUP:NO_VALUES ;AN000; + DB 0 ;AN000; no keywords + + +; +; PARSE BLOCK FOR MKDIR, RMDIR, TYPE +; + +; +; The following parse control block can be used for any command which +; needs only one required file specification as an operand. Returns a +; pointer to the unverified string in PARSE1_OUTPUT. Currently used +; for the MKDIR, RMDIR, and TYPE internal commands. +; + +PARSE_MRDIR LABEL BYTE ;AN000; + DW TRANGROUP:MRDIR_PARMS ;AN000; + DB 0 ;AN000; no extra delimiter + +MRDIR_PARMS LABEL BYTE ;AN000; + DB 1,1 ;AN000; 1 positional parm + DW TRANGROUP:FILE_REQUIRED ;AN000; + DB 0 ;AN000; no switches + DB 0 ;AN000; no keywords + +; +; PARSE BLOCK FOR CHDIR, TRUENAME +; + +; +; The following parse control block can be used for any command which +; needs only one optional file specification an operand. Returns a +; pointer to the unverified string in PARSE1_OUTPUT. Currently used +; for the CHDIR and TRUENAME internal commands. +; + +PARSE_CHDIR LABEL BYTE ;AN000; + DW TRANGROUP:CHDIR_PARMS ;AN000; + DB 0 ;AN000; no extra delimiter + +CHDIR_PARMS LABEL BYTE ;AN000; + DB 0,1 ;AN000; 1 positional parm + DW TRANGROUP:FILE_OPTIONAL ;AN000; + DB 0 ;AN000; no switches + DB 0 ;AN000; no keywords + +; +; PARSE BLOCK FOR ERASE +; + +; +; The following parse control block is used for the DEL/ERASE internal +; commands. This command has one required file specification and an +; optional switch (/p) as operands. The verified switch or unverified +; file specification is returned in PARSE1_OUTPUT. +; + +PARSE_ERASE LABEL BYTE ;AN000; + DW TRANGROUP:ERASE_PARMS ;AN000; + DB 0 ;AN000; no extra delimiter + +ERASE_PARMS LABEL BYTE ;AN000; + DB 1,1 ;AN000; 1 positional parm + DW TRANGROUP:FILE_REQUIRED ;AN000; + DB 1 ;AN000; 1 switch + DW TRANGROUP:SLASH_P_SWITCH;AN000; + DB 0 ;AN000; no keywords + +; +; PARSE BLOCK FOR DIR +; + +; +; The following parse control block is used for the DIR internal command. +; This command has one optional file specification and two optional +; switches (/p and /w) as operands. The verified switch or unverified +; file specification is returned in PARSE1_OUTPUT. +; + +PARSE_DIR LABEL BYTE ;AN000; + DW TRANGROUP:DIR_PARMS ;AN000; + DB 0 ;AN000; no extra delimiter + +DIR_PARMS LABEL BYTE ;AN000; + DB 0,1 ;AN000; 1 positional parm + DW TRANGROUP:FILE_OPTIONAL2;AN000; + DB 2 ;AN000; 2 switches + DW TRANGROUP:SLASH_P_SWITCH;AN000; + DW TRANGROUP:DIR_SWITCH1 ;AN000; + DB 0 ;AN000; no keywords + +DIR_SWITCH1 LABEL BYTE ;AN000; + DW 0 ;AN000; no match flags + DW 2 ;AN000; capitalize by char table + DW TRANGROUP:PARSE1_OUTPUT ;AN000; result buffer + DW TRANGROUP:NO_VALUES ;AN000; + DB 1 ;AN000; 1 keyword +DIR_W_SYN DB "/W",0 ;AN000; /W switch + +; +; PARSE BLOCK FOR RENAME +; + +; +; The following parse control block can be used for any command which +; needs only two required file specifications as operands. Returns +; pointers to the unverified string in PARSE1_OUTPUT. +; Currently used for the RENAME internal command. +; + +PARSE_RENAME LABEL BYTE ;AN000; + DW TRANGROUP:RENAME_PARMS ;AN000; + DB 0 ;AN000; no extra delimiter + +RENAME_PARMS LABEL BYTE ;AN000; + DB 2,2 ;AN000; 2 positional parms + DW TRANGROUP:FILE_REQUIRED ;AN000; + DW TRANGROUP:FILE_REQUIRED ;AN000; + DB 0 ;AN000; no switches + DB 0 ;AN000; no keywords + +; +; PARSE BLOCK FOR CTTY +; + +; +; The following parse control block can be used for any command which +; needs one required device name as an operand. Returns a pointer to +; unverified string in PARSE1_OUTPUT. Currently used for the CTTY +; internal command. +; + +PARSE_CTTY LABEL BYTE ;AN000; + DW TRANGROUP:CTTY_PARMS ;AN000; + DB 0 ;AN000; no extra delimiter + +CTTY_PARMS LABEL BYTE ;AN000; + DB 1,1 ;AN000; 1 positional parm + DW TRANGROUP:CTTY_CONTROL1 ;AN000; + DB 0 ;AN000; no switches + DB 0 ;AN000; no keywords + +CTTY_CONTROL1 LABEL BYTE ;AN000; + DW 2000H ;AN000; string value - required + DW 11H ;AN000; capitalize - file table + ;AN000; remove colon at end + DW TRANGROUP:PARSE1_OUTPUT ;AN000; result buffer + DW TRANGROUP:NO_VALUES ;AN000; + DB 0 ;AN000; no keywords + +TRANDATA ENDS + +TRANCODE SEGMENT PUBLIC BYTE ;AN000; + +.xlist +.xcref + +INCLUDE SYSMSG.INC ;AN000; + +.list +.cref + +ASSUME DS:TRANGROUP,ES:TRANGROUP,CS:TRANGROUP + +MSG_UTILNAME ;AN000; define utility name + +MSG_SERVICES ;AN000; The transient messages + +include msgdcl.inc + +TRANCODE ENDS ;AN000; + +TRANDATA SEGMENT PUBLIC BYTE + +TRANDATAEND LABEL BYTE + +TRANDATA ENDS ;AN000; + + END diff --git a/v4.0/src/CMD/COMMAND/TENV.ASM b/v4.0/src/CMD/COMMAND/TENV.ASM new file mode 100644 index 0000000..e1d43f6 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TENV.ASM @@ -0,0 +1,633 @@ + page 80,132 +; SCCSID = @(#)tenv.asm 4.2 85/08/16 +; SCCSID = @(#)tenv.asm 4.2 85/08/16 +TITLE Part6 COMMAND Transient routines. + +; Environment utilities and misc. routines + + INCLUDE comsw.asm + +.xlist +.xcref + INCLUDE DOSSYM.INC + INCLUDE comseg.asm + INCLUDE comequ.asm + INCLUDE DOSCNTRY.INC ;AN000; +.list +.cref + + +DATARES SEGMENT PUBLIC BYTE ;AC000; + EXTRN comdrv:byte + EXTRN comspec_end:word + EXTRN comspec_print:word + EXTRN cpdrv:byte + EXTRN dbcs_vector_addr:dword ;AN000; + EXTRN ENVIRSEG:WORD + EXTRN fucase_addr:word ;AC000; + EXTRN RESTDIR:BYTE +DATARES ENDS + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN arg_buf_ptr:word + EXTRN comspec:byte + EXTRN comspec_flag:byte + EXTRN comspecstr:byte + EXTRN ENVERR_PTR:WORD + EXTRN PATH_TEXT:byte + EXTRN PROMPT_TEXT:byte + EXTRN SYNTMES_PTR:WORD +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN Arg_Buf:BYTE + EXTRN RESSEG:WORD + EXTRN USERDIR1:BYTE +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC byte + +ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + + EXTRN cerror:near + + PUBLIC add_name_to_environment + PUBLIC add_prompt + PUBLIC delete_path + PUBLIC find_name_in_environment + PUBLIC find_path + PUBLIC find_prompt + PUBLIC move_name + PUBLIC restudir + PUBLIC restudir1 + PUBLIC scan_double_null + PUBLIC scasb2 + PUBLIC store_char + PUBLIC Testkanj ;AN000; 3/3/KK + PUBLIC upconv + +BREAK +ASSUME DS:TRANGROUP + + break Prompt command +assume ds:trangroup,es:trangroup + +ADD_PROMPT: + CALL DELETE_PROMPT ; DELETE ANY EXISTING PROMPT + CALL SCAN_DOUBLE_NULL + +ADD_PROMPT2: + PUSH SI + CALL GETARG + POP SI + retz ; PRE SCAN FOR ARGUMENTS + CALL MOVE_NAME ; MOVE IN NAME + CALL GETARG + PUSH SI + JMP SHORT ADD_NAME + + + break The SET command +assume ds:trangroup,es:trangroup + +; +; Input: DS:SI points to a CR terminated string +; Output: carry flag is set if no room +; otherwise name is added to environment +; + +DISP_ENVj: + jmp DISP_ENV + +ADD_NAME_TO_ENVIRONMENT: + CALL GETARG + JZ DISP_ENVj +; +; check if line contains exactly one equals sign +; + XOR BX,BX ;= COUNT IS 0 + PUSH SI ;SAVE POINTER TO BEGINNING OF LINE + +EQLP: + LODSB ;GET A CHAR + CMP AL,13 ;IF CR WE'RE ALL DONE + JZ QUEQ + CMP AL,'=' ;LOOK FOR = SIGN + JNZ EQLP ;NOT THERE, GET NEXT CHAR + INC BL ;OTHERWISE INCREMENT EQ COUNT + CMP BYTE PTR [SI],13 ;LOOK FOR CR FOLLOWING = SIGN + JNZ EQLP + INC BH ;SET BH=1 MEANS NO PARAMETERS + JMP EQLP ;AND LOOK FOR MORE + +QUEQ: + POP SI ;RESTORE BEGINNING OF LINE + DEC BL ;ZERO FLAG MEANS ONLY ONE EQ + JZ ONEQ ;GOOD LINE + MOV DX,OFFSET TRANGROUP:SYNTMES_ptr + JMP CERROR + +ONEQ: + PUSH BX + CALL DELETE_NAME_IN_ENVIRONMENT + POP BX + DEC BH + retz + + CALL SCAN_DOUBLE_NULL + mov bx,di ; Save ptr to beginning of env var name + CALL MOVE_NAME + push si + xchg bx,di ; Switch ptrs to beginning and end of + ; env var name +; +; We want to special-case COMSPEC. This is to reduce the amount of code +; necessary in the resident for re-reading the transient. Let's look for +; COMSPEC= +; + mov si,offset trangroup:comspecstr ; Load ptr to string "COMSPEC" + mov cx,4 ; If the new env var is comspec, set + repz cmpsw ; the comspec_flag +; +; Zero set => exact match +; + jnz not_comspec + mov comspec_flag,1 + +not_comspec: + mov di,bx ; Load ptr to end of env var name + +ADD_NAME: ; Add the value of the new env var + pop si ; to the environment. + push si + +add_name1: + LODSB + CMP AL,13 + jz add_name_ret + CALL STORE_CHAR + JMP ADD_NAME1 + +add_name_ret: + pop si + cmp comspec_flag,0 ; If the new env var is comspec, + retz ; copy the value into the +; +; We have changed the COMSPEC variable. We need to update the resident +; pieces necessary to reread in the info. First, skip all delimiters +; + invoke ScanOff + mov es,[resseg] ; comspec var in the resident + assume es:resgroup +; +; Make sure that the printer knows where the beginning of the string is +; + mov di,offset resgroup:comspec + mov bx,di +; +; Generate drive letter for display +; + xor ax,ax ;g assume no drive first + mov comdrv,al ;g + push ax ;AN000; 3/3/KK + mov al,[si] ;AN000; 3/3/KK + call testkanj ;AN000; 3/3/KK + pop ax ;AN000; 3/3/KK + jnz GotDrive + cmp byte ptr [si+1],':' ; drive specified? + jnz GotDrive + mov al,[si] ; get his specified drive + call UpConv ; convert to uppercase + sub al,'A' ; convert to 0-based + add di,2 + inc al ; convert to 1-based number + mov comdrv,al +; +; Stick the drive letter in the prompt message. Nothing special needs to be +; done here.. +; + + add al,'A'-1 + +GotDrive: ;g + mov comspec_print,di ;g point to beginning of name after drive + mov es:cpdrv,al +; +; Copy chars until delim +; + + mov di,bx + +copy_comspec: + lodsb + invoke Delim + jz CopyDone + cmp al,13 + jz CopyDone + stosb + jmp short copy_comspec + +CopyDone: + xor al,al ; Null terminate the string and quit + stosb + mov comspec_flag,0 + dec di + mov comspec_end,di + + ret + +DISP_ENV: + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + MOV DS,[ENVIRSEG] +ASSUME DS:NOTHING + XOR SI,SI + +PENVLP: + CMP BYTE PTR [SI],0 + retz + mov di,offset trangroup:arg_buf + +PENVLP2: + LODSB + stosb + OR AL,AL + JNZ PENVLP2 + mov dx,offset trangroup:arg_buf_ptr + push ds + push es + pop ds + invoke printf_crlf + pop ds + JMP PENVLP + +ASSUME DS:TRANGROUP + +DELETE_PATH: + MOV SI,OFFSET TRANGROUP:PATH_TEXT + JMP SHORT DELETE_NAME_IN_environment + +DELETE_PROMPT: + MOV SI,OFFSET TRANGROUP:PROMPT_TEXT + +DELETE_NAME_IN_environment: +; +; Input: DS:SI points to a "=" terminated string +; Output: carry flag is set if name not found +; otherwise name is deleted +; + PUSH SI + PUSH DS + CALL FIND ; ES:DI POINTS TO NAME + JC DEL1 + MOV SI,DI ; SAVE IT + CALL SCASB2 ; SCAN FOR THE NUL + XCHG SI,DI + CALL GETENVSIZ + SUB CX,SI + PUSH ES + POP DS ; ES:DI POINTS TO NAME, DS:SI POINTS TO NEXT NAME + REP MOVSB ; DELETE THE NAME + +DEL1: + POP DS + POP SI + return + +FIND_PATH: + MOV SI,OFFSET TRANGROUP:PATH_TEXT + JMP SHORT FIND_NAME_IN_environment + +FIND_PROMPT: + MOV SI,OFFSET TRANGROUP:PROMPT_TEXT + +FIND_NAME_IN_environment: +; +; Input: DS:SI points to a "=" terminated string +; Output: ES:DI points to the arguments in the environment +; zero is set if name not found +; carry flag is set if name not valid format +; + CALL FIND ; FIND THE NAME + retc ; CARRY MEANS NOT FOUND + JMP SCASB1 ; SCAN FOR = SIGN +; +; On return of FIND1, ES:DI points to beginning of name +; +FIND: + CLD + CALL COUNT0 ; CX = LENGTH OF NAME + MOV ES,[RESSEG] +ASSUME ES:RESGROUP + MOV ES,[ENVIRSEG] +ASSUME ES:NOTHING + XOR DI,DI + +FIND1: + PUSH CX + PUSH SI + PUSH DI + +FIND11: + LODSB + CALL TESTKANJ + JZ NOTKANJ3 + DEC SI + LODSW + INC DI + INC DI + CMP AX,ES:[DI-2] + JNZ FIND12 + DEC CX + LOOP FIND11 + JMP SHORT FIND12 + +NOTKANJ3: + CALL UPCONV + INC DI + CMP AL,ES:[DI-1] + JNZ FIND12 + LOOP FIND11 + +FIND12: + POP DI + POP SI + POP CX + retz + PUSH CX + CALL SCASB2 ; SCAN FOR A NUL + POP CX + CMP BYTE PTR ES:[DI],0 + JNZ FIND1 + STC ; INDICATE NOT FOUND + return + +COUNT0: + PUSH DS + POP ES + MOV DI,SI + +COUNT1: + PUSH DI ; COUNT NUMBER OF CHARS UNTIL "=" + CALL SCASB1 + JMP SHORT COUNTX + +COUNT2: + PUSH DI ; COUNT NUMBER OF CHARS UNTIL NUL + CALL SCASB2 + +COUNTX: + POP CX + SUB DI,CX + XCHG DI,CX + return + +MOVE_NAME: + CMP BYTE PTR DS:[SI],13 + retz + LODSB + +;;;; IF KANJI 3/3/KK + CALL TESTKANJ + JZ NOTKANJ1 + CALL STORE_CHAR + LODSB + CALL STORE_CHAR + JMP SHORT MOVE_NAME + +NOTKANJ1: +;;;; ENDIF 3/3/KK + + CALL UPCONV + CALL STORE_CHAR + CMP AL,'=' + JNZ MOVE_NAME + return + +GETARG: + MOV SI,80H + LODSB + OR AL,AL + retz + invoke SCANOFF + CMP AL,13 + return + +; +; Point ES:DI to the final NULL string. Note that in an empty environment, +; there is NO double NULL, merely a string that is empty. +; +SCAN_DOUBLE_NULL: + MOV ES,[RESSEG] +ASSUME ES:RESGROUP + MOV ES,[ENVIRSEG] +ASSUME ES:NOTHING + XOR DI,DI +; +; Top cycle-point. If the string here is empty, then we are done +; +SDN1: + cmp byte ptr es:[di],0 ; nul string? + retz ; yep, all done + CALL SCASB2 + JMP SDN1 + +SCASB1: + MOV AL,'=' ; SCAN FOR AN = + JMP SHORT SCASBX +SCASB2: + XOR AL,AL ; SCAN FOR A NUL +SCASBX: + MOV CX,100H + REPNZ SCASB + return + +TESTKANJ: + push ds ;AN000; 3/3/KK + push si ;AN000; 3/3/KK + push ax ;AN000; 3/3/KK + mov ds,cs:[resseg] ;AN000; Get resident segment + assume ds:resgroup ;AN000; + lds si,dbcs_vector_addr ;AN000; get DBCS vector +ktlop: ;AN000; 3/3/KK + cmp word ptr ds:[si],0 ;AN000; end of Table 3/3/KK + je notlead ;AN000; 3/3/KK + pop ax ;AN000; 3/3/KK + push ax ;AN000; 3/3/KK + cmp al, byte ptr ds:[si] ;AN000; 3/3/KK + jb notlead ;AN000; 3/3/KK + inc si ;AN000; 3/3/KK + cmp al, byte ptr ds:[si] ;AN000; 3/3/KK + jbe islead ;AN000; 3/3/KK + inc si ;AN000; 3/3/KK + jmp short ktlop ;AN000; try another range ; 3/3/KK +Notlead: ;AN000; 3/3/KK + xor ax,ax ;AN000; set zero 3/3/KK + jmp short ktret ;AN000; 3/3/KK +Islead: ;AN000; 3/3/KK + xor ax,ax ;AN000; reset zero 3/3/KK + inc ax ;AN000; 3/3/KK +ktret: ;AN000; 3/3/KK + pop ax ;AN000; 3/3/KK + pop si ;AN000; 3/3/KK + pop ds ;AN000; 3/3/KK + return ;AN000; 3/3/KK +;------------------------------------- ;3/3/KK + + +; **************************************************************** +; * +; * ROUTINE: UPCONV (ADDED BY EMG 4.00) +; * +; * FUNCTION: This routine returns the upper case equivalent of +; * the character in AL from the file upper case table +; * in DOS if character if above ascii 128, else +; * subtracts 20H if between "a" and "z". +; * +; * INPUT: AL char to be upper cased +; * FUCASE_ADDR set to the file upper case table +; * +; * OUTPUT: AL upper cased character +; * +; **************************************************************** + +assume ds:trangroup ;AN000; + +upconv proc near ;AN000; + + cmp al,80h ;AN000; see if char is > ascii 128 + jb oth_fucase ;AN000; no - upper case math + sub al,80h ;AN000; only upper 128 chars in table + push ds ;AN000; + push bx ;AN000; + mov ds,[resseg] ;AN000; get resident data segment +assume ds:resgroup ;AN000; + lds bx,dword ptr fucase_addr+1 ;AN000; get table address + add bx,2 ;AN000; skip over first word + xlat ds:byte ptr [bx] ;AN000; convert to upper case + pop bx ;AN000; + pop ds ;AN000; +assume ds:trangroup ;AN000; + jmp short upconv_end ;AN000; we finished - exit + +oth_fucase: ;AN000; + cmp al,small_a ;AC000; if between "a" and "z", + jb upconv_end ;AC000; subtract 20h to get + cmp al,small_z ;AC000; upper case equivalent. + ja upconv_end ;AC000; + sub al,20h ;AC000; Change lower-case to upper + +upconv_end: ;AN000; + ret + +upconv endp ;AN000; + + +; +; STORE A CHAR IN environment, GROWING IT IF NECESSARY +; +STORE_CHAR: + PUSH CX + PUSH BX + PUSH ES ;AN056; + PUSH DS ;AN056; Save local DS + MOV DS,[RESSEG] ;AN056; Get resident segment + ASSUME DS:RESGROUP ;AN056; + MOV ES,[ENVIRSEG] ;AN056; Get environment segment + ASSUME ES:NOTHING ;AN056; + POP DS ;AN056; Get local segment back + ASSUME DS:TRANGROUP ;AN056; + CALL GETENVSIZ + MOV BX,CX + SUB BX,2 ; SAVE ROOM FOR DOUBLE NULL + CMP DI,BX + JB STORE1 + + PUSH AX + PUSH CX + PUSH BX ; Save Size of environment + invoke FREE_TPA + POP BX + ADD BX,2 ; Recover true environment size + + CMP BX, 8000H ; Don't let environment grow > 32K + JB ENVSIZ_OK +BAD_ENV_SIZE: ;AN056; + STC + JMP ENVNOSET +ENVSIZ_OK: + + MOV CL,4 + SHR BX,CL ; Convert back to paragraphs + INC BX ; Try to grow environment by one para + MOV CX,ES ;AN056; Get environment segment + ADD CX,BX ;AN056; Add in size of environment + ADD CX,020H ;AN056; Add in some TPA + MOV AX,CS ;AN056; Get the transient segment + CMP CX,AX ;AN056; Are we hitting the transient? + JNB BAD_ENV_SIZE ;AN056; Yes - don't do it!!! + MOV AH,SETBLOCK + INT int_command +ENVNOSET: + PUSHF + PUSH ES + MOV ES,[RESSEG] + invoke ALLOC_TPA + POP ES + POPF + POP CX + POP AX + JNC STORE1 + POP ES ;AN056; + MOV DX,OFFSET TRANGROUP:ENVERR_ptr + JMP CERROR +STORE1: + STOSB + MOV WORD PTR ES:[DI],0 ; NULL IS AT END + POP ES ;AN056; + POP BX + POP CX + return + +GETENVSIZ: +;Get size of environment in bytes, rounded up to paragraph boundry +;ES has environment segment +;Size returned in CX, all other registers preserved + + PUSH ES + PUSH AX + MOV AX,ES + DEC AX ;Point at arena + MOV ES,AX + MOV AX,ES:[arena_size] + MOV CL,4 + SHL AX,CL ;Convert to bytes + MOV CX,AX + POP AX + POP ES + return + + +ASSUME DS:TRANGROUP + + +RESTUDIR1: + PUSH DS + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + CMP [RESTDIR],0 + POP DS +ASSUME DS:TRANGROUP + retz + +RESTUDIR: + MOV DX,OFFSET TRANGROUP:USERDIR1 + MOV AH,CHDIR + INT int_command ; Restore users DIR + XOR AL,AL + invoke SETREST +RET56: + return + +trancode ends + end diff --git a/v4.0/src/CMD/COMMAND/TENV2.ASM b/v4.0/src/CMD/COMMAND/TENV2.ASM new file mode 100644 index 0000000..0c47958 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TENV2.ASM @@ -0,0 +1,663 @@ + page 80,132 +; SCCSID = @(#)tenv2.asm 1.1 85/05/14 +; SCCSID = @(#)tenv2.asm 1.1 85/05/14 +TITLE Part6 COMMAND Transient routines. + +; Environment utilities and misc. routines + + INCLUDE comsw.asm + +.xlist +.xcref + INCLUDE DOSSYM.INC + INCLUDE comseg.asm + INCLUDE comequ.asm +.list +.cref + + +DATARES SEGMENT PUBLIC BYTE ;AC000; + EXTRN pipeflag:byte +DATARES ENDS + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN ACRLF_PTR:WORD + EXTRN BadCD_Ptr:WORD + EXTRN Badmkd_ptr:word + EXTRN BADRMD_PTR:WORD + EXTRN Extend_buf_ptr:word ;AN000; + EXTRN Extend_buf_sub:byte ;AN022; + EXTRN MD_exists_ptr:word ;AN006; + EXTRN msg_disp_class:byte ;AC000; + EXTRN NOSPACE_PTR:WORD + EXTRN parse_chdir:byte ;AC000; + EXTRN parse_mrdir:byte ;AC000; + EXTRN PIPEEMES_PTR:WORD + EXTRN string_buf_ptr:word +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN CURDRV:BYTE + EXTRN DESTINFO:BYTE + EXTRN DESTTAIL:WORD + EXTRN DIRCHAR:BYTE + EXTRN dirflag:byte ;AN015; + EXTRN KPARSE:BYTE ;AC000; 3/3/KK + EXTRN msg_numb:word ;AN022; + EXTRN parse1_addr:dword ;AC000; + EXTRN parse1_type:byte ;AC000; + EXTRN PATHPOS:WORD + EXTRN RESSEG:WORD + EXTRN srcxname:byte ;AC000; + EXTRN string_ptr_2:word + EXTRN SWITCHAR:BYTE + EXTRN USERDIR1:BYTE +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC byte + +ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + + EXTRN cerror:near + + PUBLIC $chdir + PUBLIC $mkdir + PUBLIC $rmdir + PUBLIC crlf2 + PUBLIC crprint + PUBLIC delim + PUBLIC error_output + PUBLIC fcb_to_ascz + PUBLIC pathchrcmp + PUBLIC pathcrunch + PUBLIC savudir + PUBLIC savudir1 + PUBLIC scanoff + PUBLIC strcomp + +break $Chdir + +; **************************************************************** +; * +; * ROUTINE: $CHDIR +; * +; * FUNCTION: Entry point for CHDIR command. Parse the command +; * line. If path is found, CHDIR to path. If a drive +; * letter is found, get and display the current dir +; * of the specified drive. If nothing is found, get +; * and display the current dir of the default drive. +; * +; * INPUT: command line at offset 81H +; * +; * OUTPUT: none +; * +; **************************************************************** + +assume ds:trangroup,es:trangroup + +$CHDIR: + + mov si,81H + mov di,offset trangroup:parse_chdir ;AN000; Get adderss of PARSE_CHDIR + xor cx,cx ;AN000; clear cx,dx + xor dx,dx ;AN000; + invoke parse_with_msg ;AC018; call parser + + cmp ax,end_of_line ;AC000; are we at end of line? + jz bwdJ ; No args + cmp ax,result_no_error ;AC000; did we have an error? + jnz ChDirErr ;AC018; yes - exit + + cmp parse1_type,result_drive ;AC000; was a drive entered? + jnz REALCD ; no +; +; D: was found. See if there is anything more. +; + mov di,offset trangroup:parse_chdir ;AC000; get address of parse_chdir + xor dx,dx ;AC000; + invoke parse_check_eol ;AC000; call parser + jnz ChDirErr ;AC000; + +bwdJ: + invoke build_dir_for_chdir ; Drive only specified + call crlf2 + return + +REALCD: + + push si ;AN000; save position in line + lds si,parse1_addr ;AN000; get address of filespec + invoke move_to_srcbuf ;AN000; move to srcbuf + pop si ;AN000; restore position in line + mov di,offset trangroup:parse_chdir ;AC000; get address of parse_chdir + xor dx,dx ;AC000; + invoke parse_check_eol ;AC000; call parser + jnz ChDirErr ;AC000; + + invoke SETPATH + TEST [DESTINFO],2 + JNZ BadChdir + MOV AH,CHDIR + INT int_command + retnc + + invoke get_ext_error_number ;AN022; get the extended error + cmp ax,error_path_not_found ;AN022; see if path not found + jz BadChDir ;AN022; yes - issue old message + call Set_Ext_Error_Subst ;AN022; + jmp short chdirerr ;AN022; + +BadChDir: + MOV DX,OFFSET TRANGROUP:BADCD_ptr + +ChDirErr: + invoke Std_Eprintf + return + +break $Mkdir + +assume ds:trangroup,es:trangroup + +$MKDIR: + CALL SETRMMK + JC MkDirErr + MOV AH,MKDIR + INT int_command + retnc + + invoke get_ext_error_number ;AN022; get the extended error + cmp ax,error_path_not_found ;AN022; see if path not found + jz MD_other_err ;AN022; yes - issue old message + cmp ax,error_access_denied ;AN022; access denied? + jz badmderr ;AN022; yes - see if file exists + + call Set_Ext_Error_Subst ;AN022; + jmp short MkDirerr ;AC022; yes - go print it + +BADMDERR: + mov dx,offset trangroup:srcxname ;AN006; Set Disk transfer address + mov ah,Set_DMA ;AN006; + int int_command ;AN006; + MOV AH,Find_First ;AN006; see if file/dir exists + mov cx,attr_directory ;AN006; search for directory + INT int_command ;AN006; + jc MD_other_err ;AN006; doesn't exist - must be something else + mov dl,srcxname.find_buf_attr ;AN006; we found a file/dir + test dl,attr_directory ;AN006; was it a directory? + jz MD_other_err ;AN006; no - must have been a file + mov dx,offset trangroup:MD_exists_ptr ;AN006; set up already exists error + jmp short MkDirErr ;AN006; make sure we didn't have network error +MD_other_err: ;AN006; + MOV DX,OFFSET TRANGROUP:BADMKD_ptr +MkDirErr: + invoke Std_Eprintf + return + +Break + +;**************************************************************** +;* +;* ROUTINE: SETRMMK +;* +;* FUNCTION: Parse routine for the internal MKDIR and RMDIR +;* commands. Parses the command line for a required +;* filespec. +;* +;* INPUT: command line at offset 81H +;* +;* OUTPUT: carry clear +;* DS:DX points to ASCIIZ argument +;* carry set +;* DS:DX has error message pointer +;* +;**************************************************************** + +SETRMMK: + mov si,81H + mov di,offset trangroup:parse_mrdir ;AN000; Get adderss of PARSE_MRDIR + xor cx,cx ;AN000; clear cx,dx + xor dx,dx ;AN000; + invoke parse_with_msg ;AC000; call parser + cmp ax,result_no_error ;AC000; did we have an error? + jnz NOARGERR ;AC000; yes - exit + + mov di,offset trangroup:srcxname ;AN000; get address of srcxname + push di ;AN000; save address + push si ;AN000; save position in line + lds si,parse1_addr ;AN000; get address of path + +mrdir_move_filename: ;AN000; put filespec in srcxname + lodsb ;get a char from buffer + stosb ;AN000; store in srcxname + cmp al,end_of_line_out ;AC000; it char a terminator? + jnz mrdir_move_filename ;AC000; no - keep moving + pop si ;AN000; get line position back + +; +; we have scanned an argument. See if any args beyond. +; + + mov di,offset trangroup:parse_mrdir ;AC000; get address of parse_mrdir + invoke parse_check_eol ;AC000; are we at end of line? + pop dx ;AC000; get address of SRCXNAME + retz ;yes - return no error +NOARGERR: + mov dx,offset TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer + XOR AX,AX + STC + return + +break $Rmdir + +assume ds:trangroup,es:trangroup + +$RMDIR: + CALL SETRMMK + JC RmDirErr + JNZ BADRDERR + MOV AH,RMDIR + INT int_command + retnc + + invoke get_ext_error_number ;AN022; get the extended error + cmp ax,error_path_not_found ;AN022; see if path not found + jz badrderr ;AN022; yes - issue old message + cmp ax,error_access_denied ;AN022; access denied? + jz badrderr ;AN022; yes - issue old message + + call Set_Ext_Error_Subst ;AN022; + jmp short RmDirerr ;AC022; yes - go print it + +BADRDERR: + MOV DX,OFFSET TRANGROUP:BADRMD_ptr + +RmDirErr: + invoke STD_Eprintf + return + +;**************************************************************** +;* +;* ROUTINE: Set_ext_error_subst +;* +;* FUNCTION: Sets up substitution for extended error +;* +;* INPUT: AX - extended error number +;* DX - offset of string +;* +;* OUTPUT: Extend_Buf_Ptr set up for STD_EPRINTF +;* +;**************************************************************** + +Set_ext_error_subst proc near ;AN022; + + mov msg_disp_class,ext_msg_class ;AN022; set up extended error msg class + mov string_ptr_2,dx ;AN022; get address of failed string + mov Extend_buf_sub,one_subst ;AN022; put number of subst in control block + mov dx,offset TranGroup:Extend_Buf_ptr ;AN022; get extended message pointer + mov Extend_Buf_ptr,ax ;AN022; get message number in control block + + ret ;AN022; return + +Set_ext_error_subst endp ;AN022; + + + + + +Break + +; +; SavUDir - move the user's current directory on a drive into UserDir1 +; SavUDir1 - move the user's current directory on a drive into a specified +; buffer +; +; Inputs: DL has 1-based drive number +; ES:DI has destination buffer (SavUDir1 only) +; Outputs: Carry Clear +; DS = TranGroup +; Carry Set +; AX has error code +; Registers Modified: AX, SI +; + +SAVUDIR: + MOV DI,OFFSET TRANGROUP:USERDIR1 + +SAVUDIR1: + MOV AL,DL + ADD AL,'@' + CMP AL,'@' + JNZ GOTUDRV + ADD AL,[CURDRV] + INC AL ; A = 1 + +GOTUDRV: + STOSB + MOV AH,[DIRCHAR] + MOV AL,':' + STOSW + PUSH ES + POP DS +ASSUME DS:NOTHING + + MOV SI,DI + MOV AH,CURRENT_DIR ; Get the Directory Text + INT int_command + retc + PUSH CS + POP DS +ASSUME DS:TRANGROUP + + return + + +CRLF2: + PUSH DX + MOV DX,OFFSET TRANGROUP:ACRLF_ptr + +PR: + PUSH DS + PUSH CS + POP DS + invoke std_printf + POP DS + POP DX + + return + +; +; These routines (SCANOFF, DELIM) are called in batch processing when DS +; may NOT be TRANGROUP +; +ASSUME DS:NOTHING,ES:NOTHING + +SCANOFF: + LODSB + CALL DELIM + JZ SCANOFF + DEC SI ; Point to first non-delimiter + return + +; +; Input: AL is character to classify +; Output: Z set if delimiter +; NZ set otherwise +; Registers modified: none +; + +DELIM: + CMP AL,' ' + retz + CMP AL,'=' + retz + CMP AL,',' + retz + CMP AL,';' + retz + CMP AL,9 ; Check for TAB character + retz + CMP AL,0ah ; Check for line feed character - BAS + return + + +ASSUME DS:TRANGROUP,ES:TRANGROUP + + +FCB_TO_ASCZ: ; Convert DS:SI to ASCIZ ES:DI + MOV CX,8 + +MAINNAME: + LODSB + CMP AL,' ' + JZ SKIPSPC + STOSB + +SKIPSPC: + LOOP MAINNAME + LODSB + CMP AL,' ' + JZ GOTNAME + MOV AH,AL + MOV AL,dot_chr + STOSB + XCHG AL,AH + STOSB + MOV CL,2 + +EXTNAME: + LODSB + CMP AL,' ' + JZ GOTNAME + STOSB + LOOP EXTNAME + +GOTNAME: + XOR AL,AL + STOSB + return + +STRCOMP: +; +; Compare ASCIZ DS:SI with ES:DI. +; SI,DI destroyed. +; + CMPSB + retnz ; Strings not equal + cmp byte ptr [SI-1],0 ; Hit NUL terminator? + retz ; Yes, strings equal + jmp short STRCOMP ; Equal so far, keep going + + +CRPRINT: + PUSH AX + MOV AL,13 + PUSH CX + PUSH DI + MOV DI,DX + MOV CX,-1 + PUSH ES + PUSH DS + POP ES + + REPNZ SCASB ; LOOK FOR TERMINATOR + mov byte ptr [di-1],0 ; nul terminate the string + POP ES + mov string_ptr_2,dx + mov dx,offset trangroup:string_buf_ptr + invoke std_printf + mov ds:byte ptr [di-1],13 ; now put the CR back + JC ERROR_OUTPUT + + POP DI + POP CX + POP AX + + return + +ERROR_OUTPUT: + PUSH CS + POP DS +ASSUME DS:TRANGROUP + MOV ES,[RESSEG] +ASSUME ES:RESGROUP + + MOV DX,OFFSET TRANGROUP:NOSPACE_ptr + CMP [PIPEFLAG],0 + JZ GO_TO_ERROR + + invoke PipeOff + MOV DX,OFFSET TRANGROUP:PIPEEMES_ptr +GO_TO_ERROR: + JMP CERROR + +ASSUME DS:TRANGROUP,ES:TRANGROUP + +PATHCHRCMP: +;---- Mod for path invocation ---- +PUBLIC pathchrcmp +;---- + + push ax + mov ah,'/' + CMP [SWITCHAR],ah + JZ NOSLASHT + CMP AL,'/' + jz pccont + +NOSLASHT: + CMP AL,'\' +pccont: + pop ax + + return + +; Drive taken from FCB +; User dir saved in userdir1 +; +; Zero set if path dir, CHDIR to this dir, FCB filled with ? +; NZ set if path/file, CHDIR to file, FCB has file (parsed fill ' ') +; [DESTTAIL] points to parse point +; Carry set if no CHDIRs worked, FCB not altered. +; DESTISDIR set non zero if PATHCHRs in path (via SETPATH) +; +PATHCRUNCH: + mov [msg_numb],0 ;AN022; Set up message flag + MOV DL,DS:[FCB] + CALL SAVUDIR + jc pcrunch_cderrJ ;AN022; if error on current dir - report + + invoke SETPATH + TEST [DESTINFO],2 + JNZ TRYPEEL ; If ? or * cannot be pure dir + + MOV AH,CHDIR + INT int_command + jnc chdir_worked ;AN022; no error - continue + + invoke get_ext_error_number ;AN022; get the extended error + cmp ax,error_path_not_found ;AN022; if path not found + jz trypeel ;AC022; keep trying + cmp ax,error_access_denied ;AN022; if access denied + jz trypeel ;AC022; keep trying + mov [msg_numb],ax ;AN022; set up message flag + jmp peelfail ;AN022; exit with other error + +chdir_worked: + invoke SETREST1 + MOV AL,'?' ; *.* is default file spec if pure dir + MOV DI,5DH + MOV CX,11 + REP STOSB + XOR AL,AL ; Set zero + return + +pcrunch_cderrj: ;AN022; need this for long jmp + jmp pcrunch_cderr ;AN022; + +TRYPEEL: + MOV SI,[PATHPOS] + DEC SI ; Point at NUL + MOV AL,[SI-1] + + CMP [KPARSE],0 + JNZ DELSTRT ; Last char is second KANJI byte, might be '\' + + CALL PATHCHRCMP + JZ PEELFAIL ; Trailing '/' + +DELSTRT: + MOV CX,SI + MOV SI,DX + PUSH DX +DELLOOP: + CMP SI,CX + JZ GOTDELE + LODSB + invoke TESTKANJ + JZ NOTKANJ8 + INC SI + JMP DELLOOP + +NOTKANJ8: + CALL PATHCHRCMP + JNZ DELLOOP + MOV DX,SI + DEC DX + JMP DELLOOP + +GOTDELE: + MOV SI,DX + POP DX + CMP SI,DX + JZ BADRET + MOV CX,SI + MOV SI,DX +DELLOOP2: ; Set value of KPARSE + CMP SI,CX + JZ TRYCD + MOV [KPARSE],0 + LODSB + INVOKE TESTKANJ + JZ DELLOOP2 + INC SI + INC [KPARSE] + JMP DELLOOP2 + +TRYCD: + push ax + mov al,dot_chr + CMP BYTE PTR [SI+1],al + pop ax + JZ PEELFAIL ; If . or .., pure cd should have worked + mov al,[si-1] + CMP al,':' ; Special case d:\file + JZ BADRET + + CMP [KPARSE],0 + JNZ NOTDOUBLESL ; Last char is second KANJI byte, might be '\' + + CALL PATHCHRCMP + JNZ NOTDOUBLESL +PEELFAIL: + STC ; // + return +NOTDOUBLESL: + MOV BYTE PTR [SI],0 + MOV AH,CHDIR + INT int_command + JNC CDSUCC +pcrunch_cderr: + invoke get_ext_error_number ;AN022; get the extended error + mov [msg_numb],ax ;AN022; set up message flag + or si,si ;AN022; set up zero flag to not zero + stc ;AN022; set up carry flag + return + +BADRET: + MOV AL,[SI] + CALL PATHCHRCMP ; Special case 'DIRCHAR'file + STC + retnz + XOR BL,BL + XCHG BL,[SI+1] + MOV AH,CHDIR + INT int_command + jc pcrunch_cderr ;AN022; go to error exit + MOV [SI+1],BL +CDSUCC: + invoke SETREST1 + INC SI ; Reset zero + MOV [DESTTAIL],SI + pushf ;AN015; save flags + cmp dirflag,-1 ;AN015; don't do parse if in DIR + jz pcrunch_end ;AN015; + MOV DI,FCB + MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR 02H ; Parse with default drive + INT int_command +pcrunch_end: + popf ;AN015; get flags back + return + +trancode ends + end + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/TFOR.ASM b/v4.0/src/CMD/COMMAND/TFOR.ASM new file mode 100644 index 0000000..8454d5c --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TFOR.ASM @@ -0,0 +1,551 @@ + page 80,132 +; SCCSID = @(#)tfor.asm 4.1 85/09/17 +; SCCSID = @(#)tfor.asm 4.1 85/09/17 +TITLE Part3 COMMAND Transient Routines + +; For loop processing routines + + +.xlist +.xcref + include comsw.asm + INCLUDE DOSSYM.INC + INCLUDE DEVSYM.INC + include comseg.asm + include comequ.asm +.list +.cref + + +DATARES SEGMENT PUBLIC BYTE ;AC000; + EXTRN BATCH:WORD + EXTRN ECHOFLAG:BYTE + EXTRN FORFLAG:BYTE + EXTRN FORPTR:WORD + EXTRN NEST:WORD + EXTRN NULLFLAG:BYTE + EXTRN PIPEFILES:BYTE + EXTRN SINGLECOM:WORD +DATARES ENDS + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN Extend_buf_ptr:word ;AN000; + extrn fornestmes_ptr:word + EXTRN msg_disp_class:byte ;AN000; + extrn string_buf_ptr:word +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + extrn arg:byte ; the arg structure! + EXTRN COMBUF:BYTE + EXTRN RESSEG:WORD + EXTRN string_ptr_2:word +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC BYTE + +ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + + EXTRN cerror:near + EXTRN docom:near + EXTRN docom1:near + EXTRN forerror:near + EXTRN tcommand:near + + PUBLIC $for + PUBLIC forproc + + +; All batch proccessing has DS set to segment of resident portion +ASSUME DS:RESGROUP,ES:TRANGROUP + + +FORTERM: + push cs ;AN037; Get local segment into + pop ds ;AN037; DS, ES + push cs ;AN037; + pop es ;AN037; + call ForOff + mov ds,ResSeg +ASSUME DS:RESGROUP + CMP [SINGLECOM],0FF00H + JNZ BATCRLF + CMP NEST,0 ;G See if we have nested batch files + JNZ BATCRLF ;G Yes - don't exit just yet + MOV [SINGLECOM],-1 ; Cause a terminate + JMP SHORT NOFORP2 + +BATCRLF: + test [ECHOFLAG],1 ;G Is echo on? + JZ NOFORP2 ;G no - exit + TEST [BATCH], -1 ;G print CRLF if in batch + JZ NOFORP2 ;G + invoke CRLF2 + +NOFORP2: + JMP TCOMMAND + + +;------ +; For-loop processing. For loops are of the form: +; for % in () do +; where may contain references of the form %, which are +; later substituted with the items in . The for-loop structure is +; set-up by the procedure '$for'; successive calls to 'forproc' execute +; once for each item in . All of the information needed for +; loop processing is stored on a piece of memory gotten from 'alloc'. This +; structure is actually fairly large, on the order of 700 bytes, and includes +; a complete copy of the original command-line structure as parsed by +; 'parseline', loop control variables, and a dma buffer for the +; 'FindFirst/FindNext' expansion of wildcard filenames in . When loop +; processing has completed, this chunk of memory is returned to the system. +; +; All of the previously defined variables, in 'datares', used for loop +; processing may be erased. Only one, (DW) ForPtr, need be allocated. +; +; The error message, 'for_alloc_mes', should be moved into the file +; containing all of the other error messages. +; +; Referencing the allocated for-loop structure is a little tricky. +; At the moment, a byte is defined as part of a new segment, 'for_segment'. +; When 'forproc' actually runs, ES and DS are set to point to the base of the +; new chunk of memory. References to this byte, 'f', thus assemble correctly +; as offsets of ES or DS. 'f' would not be necessary, except that the +; assembler translates an instruction such as 'mov AX, [for_minarg]' as an +; immediate move of the offset of 'for_minarg' into AX. In other words, in +; terms of PDP-11 mnemonics, the assembler ACTUALLY assembles +; mov AX, #for_minarg ; AX := 02CA (for example) +; instead of +; mov AX, for_minarg ; AX := [02CA] (contents of 02CA) +; By using 'f', we pretend that we are actually referencing an allocated +; structure, and the assembler coughs up the code we want. Notice that it +; doesn't matter whether we put brackets around the location or not -- the +; assembler is "smart" enough to know that we want an address instead of the +; contents of that location. +; +; Finally, there now exists the potential to easily implement nested loops. +; One method would be to have a link field in each for-structure pointing to +; its parent. Variable references that couldn't be resolved in the local +; frame would cause a search of prior frames. For-structures would still be +; allocated and released in exactly the same fashion. The only limit on the +; number of nested loops would be memory size (although at 700 bytes a pop, +; memory wouldn't last THAT long). Alternately, a small structure could be +; maintained in the resident data area. This structure would be an array of +; control-variable names and pointers to for-structure blocks. This would +; greatly speed up the resolution of non-local variable references. However, +; since space in the resident is precious, we would have to compromise on a +; "reasonable" level of nesting -- 10, 16, 32 levels, whatever. For-structure +; allocation and de-allocation would have to be modified slightly to take this +; new structure into account. +; +; Oops, just one more thing. Forbuf need not be a part of the for-structure. +; It could just as well be one structure allocated in 'transpace'. Actually, +; it may be easier to allocate it as part of 'for_segment'. +;------ + + include fordata.asm + +$for_exit: + jmp forterm ; exceeding maxarg means all done + +forproc: +assume DS:resgroup + mov AX, [ForPtr] + mov DS, AX + mov ES, AX ; operate in for-info area +assume DS:for_segment, ES:for_segment + + mov DX, OFFSET fordma + trap Set_Dma +for_begin: + cmp f.for_expand, 0 ; non-zero for_expand equals FALSE + je for_begin1 + inc f.for_minarg +for_begin1: + mov BX, f.for_minarg ; current item in to examine + cmp BX, f.for_maxarg + jg $for_exit ; exceeding maxarg means all done + mov AX, OFFSET for_args.argv + invoke argv_calc ; compute argv[x] address + + mov CX, [BX].argstartel + mov DX, [BX].argpointer + test [bx].argflags,00000100b ; Is there a path separator in this arg? + jnz forsub ; Yes, argstartel should be correct + mov si, [BX].argpointer + mov al,lparen + cmp byte ptr [si-1],al ; If the current token is the first + jnz forsub ; one in the list and originally had + inc cx ; the opening paren as its first char, + ; the argstartel ptr needs to be + ; advanced passed it before the prefix + ; length is computed. + mov al,':' + cmp byte ptr [si+1],al ; If the token begins with "(d:", + jnz forsub ; argstartel has to be moved over the + add cx,2 ; rest of the prefix as well. + +forsub: + sub CX, DX ; compute length of pathname prefix + cmp f.for_expand, 0 ; are we still expanding a name? + je for_find_next ; if so, get next matching filename + + test [BX].argflags, MASK wildcard + jnz for_find_first ; should we expand THIS (new) arg? + mov CX, [BX].arglen ; else, just copy all of it directly + jmp for_smoosh + +for_find_first: + PUSH CX + XOR CX,CX + trap Find_First ; and search for first filename match + POP CX + jmp for_result +for_find_next: + trap Find_Next ; search for next filename match + +for_result: + mov AX, -1 ; assume worst case + jc forCheck + mov ax,0 +forCheck: ; Find* returns 0 for SUCCESS + mov f.FOR_EXPAND, AX ; record success of findfirst/next + or AX, AX ; anything out there? + jnz for_begin ; if not, try next arg + +for_smoosh: + mov SI, [BX].argpointer ; copy argv[arg][0,CX] into destbuf + mov DI, OFFSET forbuf ; some days this will be the entire + rep movsb ; arg, some days just the path prefix + + cmp f.FOR_EXPAND, 0 ; if we're not expanding, we can + jnz for_make_com ; skip the following + + mov SI, OFFSET fordma.find_buf_pname +for_more: ; tack on matching filename + cmp BYTE PTR [SI], 0 + je for_make_com + movsb + jnz for_more + +for_make_com: + xor AL, AL ; tack a null byte onto the end + stosb ; of the substitute string + + xor CX, CX ; character count for command line + not CX ; negate it -- take advantage of loopnz + xor BX, BX ; argpointer + mov DI, OFFSET TRANGROUP:COMBUF+2 + mov bl, f.FOR_COM_START ; argindex + mov DH, f.FOR_VAR ; % is replaced by [forbuf] + ; time to form the string + push CS + pop ES +assume ES:trangroup + + mov AX, OFFSET for_args ; translate offset to pointer + invoke argv_calc + mov si,[bx].arg_ocomptr + inc si ; mov ptr passed beginning space + +for_make_loop: + mov al,[si] ; the arg, byte by byte + inc si + cmp AL,'%' ; looking for % + jne for_stosb ; no % ... add byte to string + cmp BYTE PTR [SI], DH ; got the right ? + jne for_stosb ; got a %, but wrong + inc SI ; skip over + + push SI + mov SI, OFFSET forbuf ; substitute the for + ; to make a final to execute +sloop: + lodsb ; grab all those bytes, and + stosb ; add 'em to the string, + or AL, AL ; until we run into a null + loopnz sloop + dec DI ; adjust length and pointer + inc CX ; so we can overwrite the null + + pop SI + jmp for_make_loop ; got back for more bytes +for_stosb: + stosb ; take a byte from the arg + dec CX ; and put it into the to be + ; executed (and note length, too) + cmp al,0dh ; If not done, loop. + jne for_make_loop + +for_made_com: ; finished all the args + not CL ; compute and record command length + mov [COMBUF+1], CL + + mov DS, [RESSEG] +assume DS:resgroup + + test [ECHOFLAG],1 ; shall we echo this , dearie? + jz noecho3 + cmp nullflag,nullcommand ;G was there a command last time? + jz No_crlf_pr ;G no - don't print crlf + invoke CRLF2 ;G Print out prompt + +no_crlf_pr: + mov nullflag,0 ;G reset no command flag + push CS + pop DS + assume DS:trangroup + push di + invoke PRINT_PROMPT ;G Prompt the user + pop di + mov BYTE PTR ES:[DI-1],0 ; yeah, PRINT it out... + mov string_ptr_2,OFFSET TRANGROUP:COMBUF+2 + mov dx,offset trangroup:string_buf_ptr + invoke std_printf + mov BYTE PTR ES:[DI-1], 0DH + jmp DoCom +noecho3: ; run silent, run deep... + assume DS:resgroup + mov nullflag,0 ;G reset no command flag + push CS + pop DS + assume DS:trangroup + jmp docom1 + + +fornesterrj: ; no multi-loop processing... yet! +assume ES:resgroup + call ForOff + jmp fornesterr + +forerrorj: + jmp forerror + + break $For +assume ds:trangroup,es:trangroup + +$for: + mov ES, [RESSEG] +assume ES:resgroup + + cmp ForFlag,0 ; is another one already running? + jnz fornesterrj ; if flag is set.... boom! + +; +; Turn off any pipes in progress. +; + cmp [PIPEFILES],0 ; Only turn off if present. + jz NoPipe + invoke PipeDel +NoPipe: + xor DX, DX ; counter (0 <= DX < argvcnt) + call nextarg ; move to next argv[n] + jc forerrorj ; no more args -- bad forloop + cmp AL,'%' ; next arg MUST start with '%'... + jne forerrorj + mov BP, AX ; save forloop variable + lodsb + or AL, AL ; and MUST end immediately... + jne forerrorj + + call nextarg ; let's make sure the next arg is 'in' + jc forerrorj + and AX, NOT 2020H ; uppercase the letters + cmp AX, in_word + jne forerrorj + lodsb + or AL, AL ; it, too, must end right away + je CheckLParen +; +; Not null. Perhaps there are no spaces between this and the (: +; FOR %i in(foo bar... +; Check for the Lparen here +; + CMP AL,lparen + JNZ forerrorj +; +; The token was in(... We strip off the "in" part to simulate a separator +; being there in the first place. +; + ADD [BX].argpointer,2 ; advance source pointer + ADD [BX].arg_ocomptr,2 ; advance original string + SUB [BX].arglen,2 ; decrement the appropriate length +; +; SI now points past the in(. Simulate a nextarg call that results in the +; current value. +; + MOV ax,[si-1] ; get lparen and next char + jmp short lpcheck + +CheckLParen: + call nextarg ; lparen delimits beginning of + jc forerrorj +lpcheck: + cmp al, lparen + jne forerrorj + cmp ah,0 + je for_paren_token + + cmp ah, rparen ; special case: null list + jne for_list_not_empty + jmp forterm + +for_list_not_empty: + inc [bx].argpointer ; Advance ptr past "(" + ; Adjust the rest of this argv entry + dec [bx].arglen ; to agree. + inc si ; Inc si so check for ")" works + jmp for_list + +for_paren_token: + call nextarg ; what have we in our ? + jc forerrorj + cmp ax, nullrparen ; special case: null list + jne for_list + jmp forterm + +forerrorjj: + jmp forerror + +for_list: ; skip over rest of + mov CX, DX ; first arg of +skip_list: + add si,[bx].arglen + sub si,3 ; si = ptr to last char of token + mov al,rparen + cmp byte ptr [si],al ; Is this the last element in + je for_end_list ; Yes, exit loop. + call nextarg ; No, get next arg + jc forerrorjj ; If no more and no rparen, error. + jmp skip_list +for_end_list: + mov DI, DX ; record position of last arg in + mov byte ptr [si],0 ; Zap the rparen + cmp ax,nullrparen ; Was this token only a rparen + jz for_do ; Yes, continue + inc di ; No, inc position of last arg + +for_do: + call nextarg ; now we had BETTER find a 'do'... + jc forerrorjj + and AX, NOT 2020H ; uppercase the letters + cmp AX, do_word + jne forerrorjj + lodsb + or AL, AL ; and it had BETTER be ONLY a 'do'... + jne forerrorjj + + call nextarg ; on to the beginning of + jc forerrorjj ; null not legal + + push AX + push BX + push CX + push DX ; preserve registers against disaster + push DI + push SI + push BP + invoke FREE_TPA ; need to make free memory, first +ASSUME ES:RESGROUP + call ForOff + mov BX, SIZE for_info - SIZE arg_unit + invoke Save_Args ; extra bytes needed for for-info + pushf + mov [ForPtr], AX + invoke ALLOC_TPA ; ALLOC_TPA clobbers registers... + popf + pop BP + pop SI + pop DI + pop DX + pop CX + pop BX + pop AX + jc for_alloc_err + + push ES ; save resgroup seg... + push [ForPtr] + pop ES +assume ES:for_segment ; make references to for-info segment + + dec CX ; forproc wants min pointing before + dec DI ; first arg, max right at last one + mov f.for_minarg, CX + mov f.for_maxarg, DI + mov f.for_com_start, DL + mov f.for_expand, -1 ; non-zero means FALSE + mov AX, BP + mov f.for_var, AH + pop ES +assume ES:resgroup + + inc [FORFLAG] + cmp [SINGLECOM], -1 + jnz for_ret + mov [SINGLECOM], 0FF00H +for_ret: + ret + +for_alloc_err: + 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 + +nextarg: + inc DX ; next argv[n] + cmp DX, arg.argvcnt ; make sure we don't run off end + jge nextarg_err ; of argv[]... + mov BX, DX + mov AX, OFFSET TRANGROUP:arg.argv + invoke argv_calc ; convert array index to pointer + mov SI, [BX].argpointer ; load pointer to argstring + lodsw ; and load first two chars + clc + ret +nextarg_err: + stc + ret + + +ASSUME DS:TRANGROUP,ES:TRANGROUP + +FORNESTERR: + PUSH DS + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + MOV DX,OFFSET TRANGROUP:FORNESTMES_ptr + CMP [SINGLECOM],0FF00H + JNZ NOFORP3 + MOV [SINGLECOM],-1 ; Cause termination +NOFORP3: + POP DS +ASSUME DS:TRANGROUP + JMP CERROR +; +; General routine called to free the for segment. We also clear the forflag +; too. Change no registers. +; +PUBLIC ForOff +ForOff: + assume DS:NOTHING,ES:NOTHING + SaveReg + mov es,ResSeg + assume es:ResGroup + mov AX,ForPtr + or ax,ax + jz FreeDone + push es + mov es,ax + mov ah,dealloc + int 21h + pop es +FreeDone: + mov ForPtr,0 + mov ForFlag,0 + RestoreReg + return + +trancode ends + end + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/TMISC1.ASM b/v4.0/src/CMD/COMMAND/TMISC1.ASM new file mode 100644 index 0000000..4b55aac --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TMISC1.ASM @@ -0,0 +1,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 + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/TMISC2.ASM b/v4.0/src/CMD/COMMAND/TMISC2.ASM new file mode 100644 index 0000000..cc30428 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TMISC2.ASM @@ -0,0 +1,487 @@ + page 80,132 +; SCCSID = @(#)tmisc2.asm 4.3 85/06/25 +; SCCSID = @(#)tmisc2.asm 4.3 85/06/25 +TITLE Part7 COMMAND Transient Routines + +; More misc routines + + +.xlist +.xcref + INCLUDE comsw.asm + INCLUDE DOSSYM.INC + INCLUDE comseg.asm + INCLUDE comequ.asm + INCLUDE ioctl.inc +.list +.cref + + +CODERES SEGMENT PUBLIC BYTE ;AC000; +CodeRes ENDS + +DATARES SEGMENT PUBLIC BYTE ;AC000; + EXTRN IFFlag:BYTE + EXTRN PIPEFLAG:BYTE + EXTRN RE_OUTSTR:BYTE + EXTRN RE_OUT_APP:BYTE +DATARES ENDS + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN AccDen_PTR:WORD + EXTRN Extend_buf_ptr:word ;AN000; + EXTRN FULDIR_PTR:WORD + EXTRN msg_disp_class:byte ;AN000; +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN DESTINFO:BYTE + EXTRN DESTISDIR:BYTE + EXTRN KPARSE:BYTE ;AC000; + EXTRN ONE_CHAR_VAL:BYTE ;AN011; + EXTRN PATHCNT:WORD + EXTRN PATHPOS:WORD + EXTRN PATHSW:WORD + EXTRN RE_INSTR:BYTE + EXTRN RESSEG:WORD + EXTRN SRCBUF:BYTE + EXTRN SWITCHAR:BYTE + + 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 CERROR:NEAR + + IF IBM + EXTRN ROM_EXEC:NEAR + EXTRN ROM_SCAN:NEAR + ENDIF + + PUBLIC IOSET + PUBLIC MOVE_TO_SRCBUF ;AN000; + PUBLIC PGETARG + PUBLIC SETPATH + PUBLIC TESTDOREIN + PUBLIC TESTDOREOUT + + +ASSUME DS:TRANGROUP + +SETPATH: +; +; Get an ASCIZ argument from the unformatted parms +; DESTISDIR set if pathchars in string +; DESTINFO set if ? or * in string +; + MOV AX,[PATHCNT] ;AC000; get length of string + MOV SI,[PATHPOS] ;AC000; get start of source buffer + +GETPATH: + MOV [DESTINFO],0 + MOV [DESTISDIR],0 + MOV SI,[PATHPOS] + MOV CX,[PATHCNT] + MOV DX,SI + JCXZ PATHDONE + PUSH CX + PUSH SI + INVOKE SWITCH + MOV [PATHSW],AX + POP BX + SUB BX,SI + POP CX + ADD CX,BX + MOV DX,SI + +SKIPPATH: + +;;;; IF KANJI 3/3/KK + MOV [KPARSE],0 + +SKIPPATH2: +;;;; ENDIF 3/3/KK + + JCXZ PATHDONE + DEC CX + LODSB + +;;;; IF KANJI 3/3/KK + INVOKE TESTKANJ + JZ TESTPPSEP + DEC CX + INC SI + INC [KPARSE] + JMP SKIPPATH2 + +TESTPPSEP: +;;;; ENDIF 3/3/KK + + INVOKE PATHCHRCMP + JNZ TESTPMETA + INC [DESTISDIR] + +TESTPMETA: + CMP AL,'?' + JNZ TESTPSTAR + OR [DESTINFO],2 + +TESTPSTAR: + CMP AL,star + JNZ TESTPDELIM + OR [DESTINFO],2 + +TESTPDELIM: + INVOKE DELIM + JZ PATHDONEDEC + CMP AL,[SWITCHAR] + JNZ SKIPPATH + +PATHDONEDEC: + DEC SI + +PATHDONE: + XOR AL,AL + XCHG AL,[SI] + INC SI + CMP AL,0DH + JNZ NOPSTORE + MOV [SI],AL ;Don't loose the CR + +NOPSTORE: + MOV [PATHPOS],SI + MOV [PATHCNT],CX + return + +PGETARG: + MOV SI,80H + LODSB + OR AL,AL + retz + CALL PSCANOFF + CMP AL,13 + return + +PSCANOFF: + LODSB + INVOKE DELIM + JNZ PSCANOFFD + CMP AL,';' + JNZ PSCANOFF ; ';' is not a delimiter + +PSCANOFFD: + DEC SI ; Point to first non-delimiter + return + +IOSET: +; +; ALL REGISTERS PRESERVED +; +ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + + PUSH DS + PUSH DX + PUSH AX + PUSH BX + PUSH CX + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + + CMP [PIPEFLAG],0 + JNZ NOREDIR ; Don't muck up the pipe + TEST IFFlag,-1 + JNZ NoRedir + CALL TESTDOREIN + CALL TESTDOREOUT + +NOREDIR: + POP CX + POP BX + POP AX + POP DX + POP DS +ASSUME DS:NOTHING + return + +TESTDOREIN: + +ASSUME DS:RESGROUP + + CMP [RE_INSTR],0 + retz + PUSH DS + PUSH CS + POP DS + MOV DX,OFFSET tranGROUP:RE_INSTR + MOV AX,(OPEN SHL 8) + MOV BX,AX + INT int_command + POP DS + JC REDIRERR + MOV BX,AX + MOV AL,0FFH +; +; Mega sleaze!! We move the SFN from the new handle spot into the old stdin +; spot. We invalidate the new JFN we got. +; + XCHG AL,[BX.PDB_JFN_Table] + MOV DS:[PDB_JFN_Table],AL + + return +; +; We had some kind of error on the redirection. Figure out what the +; appropriate message should be; BX has the system call that failed +; +REDIRERR: + PUSH CS + POP DS + Call TriageError +; +; At this point, we have recognized the network-generated access denied error. +; The correct message is in DX +; + CMP AX,65 + JZ CERRORJ ;AC000; just issue message returned + CMP BH,OPEN + JZ OpenError +; +; The error was for a create operation. Report the error as a creation error. +; + MOV DX,OFFSET TranGroup:FULDIR_PTR + +CERRORJ: + JMP CERROR +; +; The system call was an OPEN. Report either file not found or path not found. +; + +OpenError: + 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,ax ;AN000; get message number in control block + JMP CERROR + +TESTDOREOUT: + +ASSUME DS:RESGROUP + + CMP [RE_OUTSTR],0 + JNZ REOUTEXISTS ;AN017; need long jump + JMP NOREOUT ;AN017; + +REOUTEXISTS: + CMP [RE_OUT_APP],0 + JZ REOUTCRT +; +; The output redirection was for append. We open for write and seek to the +; end. +; + MOV DX,OFFSET RESGROUP:RE_OUTSTR + MOV AX,(OPEN SHL 8) OR 2 ;AC011; Open for read/write + PUSH AX + INT int_command + POP BX + JC OpenWriteError + + MOV BX,AX + MOV AX,IOCTL SHL 8 ;AN035; Get attributes of handle + INT int_command ;AN035; + TEST DL,devid_ISDEV ;AN035; Is it a device? + JNZ SET_REOUT ;AN035; Yes, don't read from it + + MOV AX,(LSEEK SHL 8) OR 2 + MOV CX,-1 ;AC011; MOVE TO EOF -1 + MOV DX,CX ;AC011; + INT int_command + PUSH CS ;AN011; Get transient seg to DS + POP DS ;AN011; + assume DS:Trangroup ;AN011; + MOV AX,(READ SHL 8) ;AN011; Read one byte from the + MOV CX,1 ;AN011; file into one_char_val + MOV DX,OFFSET Trangroup:ONE_CHAR_VAL;AN011; + INT int_command ;AN011; + JC OpenWriteError ;AN011; If error, exit + cmp ax,cx ;AN017; Did we read 1 byte? + jnz reout_0_length ;AN017; No - file must be 0 length + + cmp one_char_val,01ah ;AN011; Was char an eof mark? + mov DS,[resseg] ;AN011; Get resident segment back + assume DS:Resgroup ;AN011; + JNZ SET_REOUT ;AN011; No, just continue + MOV AX,(LSEEK SHL 8) OR 1 ;AN011; EOF mark found + MOV CX,-1 ;AN011; LSEEK back one byte + MOV DX,CX ;AN011; + INT int_command ;AN011; + JMP SHORT SET_REOUT + +reout_0_length: ;AN017; We have a 0 length file + mov DS,[resseg] ;AN017; Get resident segment back + assume DS:Resgroup ;AN017; + MOV AX,(LSEEK SHL 8) ;AN017; Move to beginning of file + XOR CX,CX ;AN017; Offset is 0 + MOV DX,CX ;AN017; + INT int_command ;AN017; + JMP SHORT SET_REOUT ;AN017; now finish setting up redirection + +OpenWriteError: + CMP AX,error_access_denied + STC ; preserve error + JNZ REOUTCRT ;AN017; need long jump + JMP REDIRERR ;AN017; + +REOUTCRT: + MOV DX,OFFSET RESGROUP:RE_OUTSTR + XOR CX,CX + MOV AH,CREAT + PUSH AX + INT int_command + POP BX + JNC NOREDIRERR ;AC011; + JMP REDIRERR ;AC011; + +NOREDIRERR: ;AN011; + MOV BX,AX + +SET_REOUT: +; +; Mega sleaze!! We move the SFN from the new handle spot into the old stdout +; spot. We invalidate the new JFN we got. +; + MOV AL,0FFH + XCHG AL,[BX.PDB_JFN_Table] + MOV DS:[PDB_JFN_Table+1],AL + +NOREOUT: + return + +; +; Compute length of string (including NUL) in DS:SI into CX. Change no other +; registers +; +Procedure DSTRLEN,NEAR + + SaveReg + XOR CX,CX + CLD + +DLoop: LODSB + INC CX + OR AL,AL + JNZ DLoop + SUB SI,CX + RestoreReg + return + +EndProc DSTRLEN + +Break + +; +; TriageError will examine the return from a carry-set system call and +; return the correct error if applicable. +; +; Inputs: outputs from a carry-settable system call +; No system calls may be done in the interrim +; Outputs: If carry was set on input +; carry set on output +; DX contains trangroup offset to printf message +; else +; No registers changed +; + +Procedure TriageError,NEAR + + retnc ; no carry => do nothing... + PUSHF + SaveReg + MOV AH,GetExtendedError + INT 21h + RestoreReg ; restore original AX + MOV DX,OFFSET TranGroup:AccDen_PTR + CMP AX,65 ; network access denied? + JZ NoMove ; Yes, return it. + MOV AX,BX + MOV DX,CX + +NoMove: + RestoreReg + popf + return + +EndProc TriageError + +PUBLIC Triage_Init +Triage_Init proc FAR + call TriageError + ret +Triage_Init endp + + +; **************************************************************** +; * +; * ROUTINE: MOVE_TO_SRCBUF +; * +; * FUNCTION: Move ASCIIZ string from DS:SI to SRCBUF. Change +; * terminating 0 to 0dH. Set PATHCNT to length of +; * string. Set PATHPOS to start of SRCBUF. +; * +; * INPUT: DS:SI points to ASCIIZ string +; * ES points to TRANGROUP +; * +; * OUTPUT: SRCBUF filled in with string terminated by 0dH +; * PATHCNT set to length of string +; * PATHPOS set to start of SRCBUF +; * CX,AX changed +; * +; **************************************************************** + +assume es:trangroup,ds:nothing ;AN000; + +MOVE_TO_SRCBUF PROC NEAR ;AN000; + + push si ;AN000; save si,di + push di ;AN000; + push cx ;AN000; + mov di,offset TRANGROUP:srcbuf ;AN000; set ES:DI to srcbuf + xor cx,cx ;AN000; clear cx for counint + mov ax,cx ;AN000; clear ax + push di ;AN000; save start of srcbuf + lodsb ;AN000; get a character from DS:SI + +mts_get_chars: ;AN000; + cmp al,0 ;AN000; was it a null char? + jz mts_end_string ;AN000; yes - exit + stosb ;AN000; no - store it in srcbuf + inc cx ;AN000; increment length count + lodsb ;AN000; get a character from DS:SI + jmp short mts_get_chars ;AN000; go check it + +mts_end_string: ;AN000; we've reached the end of line + mov al,end_of_line_in ;AN000; store 0dH in srcbuf + stosb ;AN000; + pop di ;AN000; restore start of srcbuf + + push cs ;AN000; set DS to local segment + pop ds ;AN000; +assume ds:trangroup ;AN000; + mov [pathcnt],cx ;AN000; set patchcnt to length count + mov [pathpos],di ;AN000; set pathpos to start of srcbuf + pop cx ;AN000; restore cx,di,si + pop di ;AN000; + pop si ;AN000; + + RET ;AN000; exit + +MOVE_TO_SRCBUF ENDP ;AN000; + +TRANCODE ENDS + END + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/TPARSE.ASM b/v4.0/src/CMD/COMMAND/TPARSE.ASM new file mode 100644 index 0000000..9268017 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TPARSE.ASM @@ -0,0 +1,76 @@ + page 80,132 +; SCCSID = @(#)tparse.asm 4.1 87/04/28 +; SCCSID = @(#)tparse.asm 4.1 87/04/28 +TITLE COMMAND interface to SYSPARSE + +.xlist +.xcref + INCLUDE comseg.asm ;AN000; +.list +.cref + +TRANSPACE SEGMENT PUBLIC BYTE ;AN000; + + CmpxSW equ 0 ;AN000; do not check complex list + KeySW equ 0 ;AN000; do not support keywords + Val2SW equ 0 ;AN000; do not Support value definition 2 + IncSW equ 0 ;AN000; do not include psdata.inc + QusSW equ 0 ;AN025; do not include quoted string + LFEOLSW equ 0 ;AN044; do not use 0ah as line terminator + +.xlist +.xcref + +include psdata.inc ;AN000; + +.list +.cref + +TRANSPACE ENDS ;AN000; + +TRANCODE SEGMENT PUBLIC BYTE ;AN000; + +ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING ;AN054; + +; **************************************************************** +; * +; * ROUTINE: CMD_PARSE +; * +; * FUNCTION: Interface for transient COMMAND to invoke +; * SYSPARSE. +; * +; * INPUT: inputs to SYSPARSE +; * +; * OUTPUT: outputs from SYSPARSE +; * +; **************************************************************** + + public Cmd_parse ;AN000; + +.xlist +.xcref + INCLUDE parse.asm ;AN000; +.list +.cref + +Cmd_parse Proc near ;AN000; + + call sysparse ;AN000; + + ret ;AN000; + +Cmd_parse endp ;AN000; + + public Append_parse ;AN010; + +Append_parse Proc Far ;AN010; + + call sysparse ;AN010; + + ret ;AN010; + +Append_parse endp ;AN010; + +trancode ends ;AN000; + end ;AN000; + \ No newline at end of file diff --git a/v4.0/src/CMD/COMMAND/TPIPE.ASM b/v4.0/src/CMD/COMMAND/TPIPE.ASM new file mode 100644 index 0000000..23f8417 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TPIPE.ASM @@ -0,0 +1,660 @@ + page 80,132 +; SCCSID = @(#)tpipe.asm 1.1 85/05/14 +; SCCSID = @(#)tpipe.asm 1.1 85/05/14 +TITLE PART8 COMMAND Transient routines. + + + INCLUDE comsw.asm +.xlist +.xcref + INCLUDE DOSSYM.INC + INCLUDE comseg.asm + INCLUDE comequ.asm +.list +.cref + + +DATARES SEGMENT PUBLIC BYTE ;AC000; + EXTRN ECHOFLAG:BYTE + EXTRN InitFlag:byte + EXTRN INPIPEPTR:WORD + EXTRN OUTPIPEPTR:WORD + EXTRN PIPE1:BYTE + EXTRN PIPE1T:BYTE + EXTRN PIPE2:BYTE + EXTRN PIPE2T:BYTE + EXTRN PIPEFILES:BYTE + EXTRN PIPEFLAG:BYTE + EXTRN PIPEPTR:WORD + EXTRN RESTDIR:BYTE + EXTRN SINGLECOM:WORD +DATARES ENDS + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN BADDAT_PTR:WORD + EXTRN BADTIM_PTR:WORD + EXTRN curdat_mo_day:word ;AN000; + EXTRN CURDAT_PTR:WORD + EXTRN curdat_yr:word ;AN000; + EXTRN curtim_hr_min:word ;AN000; + EXTRN CURTIM_PTR:WORD + EXTRN curtim_sec_hn:word ;AN000; + EXTRN eurdat_ptr:word + EXTRN japdat_ptr:word + EXTRN newdat_format:word ;AN000; + EXTRN NEWDAT_PTR:WORD + EXTRN NEWTIM_PTR:WORD + EXTRN parse_date:byte ;AN000; + EXTRN parse_time:byte ;AN000; + EXTRN PIPEEMES_PTR:WORD + EXTRN promtim_hr_min:word ;AN000; + EXTRN promtim_ptr:word ;AN000; + EXTRN promtim_sec_hn:word ;AN000; + EXTRN STRING_BUF_PTR:WORD ;AC000; + EXTRN SYNTMES_PTR:WORD + EXTRN usadat_ptr:word + +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN COMBUF:BYTE + EXTRN date_day:byte ;AN000; + EXTRN date_month:byte ;AN000; + EXTRN date_year:word ;AN000; + EXTRN INTERNATVARS:BYTE + EXTRN RESSEG:WORD + EXTRN time_fraction:byte ;AN000; + EXTRN time_hour:byte ;AN000; + EXTRN time_minutes:byte ;AN000; + EXTRN time_seconds:byte ;AN000; +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC BYTE +ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + + EXTRN CERROR:NEAR + EXTRN NOPIPEPROC:NEAR + EXTRN STD_PRINTF:NEAR + EXTRN TCOMMAND:NEAR + EXTRN TESTDOREIN:NEAR + EXTRN TESTDOREOUT:NEAR + EXTRN TESTKANJ:NEAR ;AN000;3/3/KK + EXTRN TSYSGETMSG:NEAR ;AN000; + + PUBLIC CTIME + PUBLIC DATE + PUBLIC DATINIT + PUBLIC PIPEDEL + PUBLIC PIPEERRSYN + PUBLIC PIPEPROC + PUBLIC PIPEPROCSTRT + PUBLIC PRINT_TIME + PUBLIC SETREST + PUBLIC SETREST1 + PUBLIC SINGLETEST + +SINGLETEST: + ASSUME DS:NOTHING + push ds + MOV DS,ResSeg + ASSUME DS:ResGroup + CMP [SINGLECOM],0 + JZ TestDone + CMP [SINGLECOM],0EFFFH +TestDone: + pop ds + return + + +ASSUME DS:TRANGROUP +SETREST1: + MOV AL,1 +SETREST: + PUSH DS + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + MOV [RESTDIR],AL + POP DS +ASSUME DS:TRANGROUP + return + +ASSUME DS:RESGROUP + +; +; Note that we need to handle the same thing that RestDir handles: the +; requirement that we try only once to restore the user's environment after +; and INT 24 or the like. If the condition that causes the INT 24 does not +; disappear, we just give up. +; + +PIPEDEL: + assume ds:nothing + push ds + PUSH DX + mov ds,ResSeg + assume ds:ResGroup + mov DX,OFFSET RESGROUP:PIPE1 ; Clean up in case ^C + MOV AH,UNLINK + INT int_command + MOV DX,OFFSET RESGROUP:PIPE2 + MOV AH,UNLINK + INT int_command + POP DX + call PipeOff + mov PipeFiles,0 + pop ds + return + +PIPEERRSYN: + MOV DX,OFFSET TRANGROUP:SYNTMES_ptr + CALL PIPEDEL + PUSH CS + POP DS + JMP CERROR +PIPEERR: + pushf + invoke triageError + SaveReg ; Save results from TriageError + MOV DX,OFFSET TRANGROUP:PIPEEMES_ptr + CALL PIPEDEL + PUSH CS + POP DS + invoke std_eprintf + RestoreReg ; Restore results from TriageError + popf + cmp ax, 65 + jnz tcommandj + JMP CERROR +tcommandj: + jmp tcommand + +PIPEPROCSTRT: +ASSUME DS:TRANGROUP,ES:TRANGROUP + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + INC [PIPEFILES] ; Flag that the pipe files exist + MOV AH,Get_Default_Drive ; Get current drive + INT int_command + ADD AL,capital_A + MOV [PIPE2],AL ; Make pipe files in root of def drv + MOV BX,OFFSET RESGROUP:PIPE1 + MOV [BX],AL + xor ah,ah ; nul terminate path names + mov [Pipe1T],ah + mov [Pipe2T],ah + MOV DX,BX + XOR CX,CX + mov ah,CreateTempFile ; the CreateTemp call + INT int_command + JC PIPEERR ; Couldn't create + MOV BX,AX + MOV AH,CLOSE ; Don't proliferate handles + INT int_command + + MOV DX,OFFSET RESGROUP:PIPE2 + mov ah,createTempFile ; the CreateTemp call + INT int_command + JC PIPEERR + MOV BX,AX + MOV AH,CLOSE + INT int_command + + CALL TESTDOREIN ; Set up a redirection if specified + MOV SI,[PIPEPTR] + CMP [SINGLECOM],-1 + JNZ NOSINGP + MOV [SINGLECOM],0F000H ; Flag single command pipe +NOSINGP: + JMP SHORT FIRSTPIPE + +PIPEPROC: +ASSUME DS:RESGROUP + AND [ECHOFLAG],0FEh ; force current echo to be off + MOV SI,[PIPEPTR] + LODSB + CMP AL,AltPipeChr ; Alternate pipe char? + JZ IsPipe1 ; Yes + CMP AL,vbar + jz IsPipe1 + jmp PIPEEND ; Pipe done +IsPipe1: + MOV DX,[INPIPEPTR] ; Get the input file name + MOV AX,(OPEN SHL 8) + INT int_command +PIPEERRJ: + jnc no_pipeerr + JMP PIPEERR ; Lost the pipe file +no_pipeerr: + MOV BX,AX + MOV AL,0FFH + XCHG AL,[BX.PDB_JFN_Table] + MOV DS:[PDB_JFN_Table],AL ; Redirect + +FIRSTPIPE: + MOV DI,OFFSET TRANGROUP:COMBUF + 2 + XOR CX,CX + CMP BYTE PTR [SI],0DH ; '|' + JNZ PIPEOK1 +PIPEERRSYNJ: + JMP PIPEERRSYN +PIPEOK1: + mov al,vbar + CMP BYTE PTR [SI],al ; '||' + JZ PIPEERRSYNJ + CMP BYTE PTR [SI],AltPipeChr ; '##' or '|#'? + JZ PipeErrSynJ ; Yes, Error +PIPECOMLP: + LODSB + STOSB + +;;;; IF KANJI 3/3/KK + CALL TESTKANJ + JZ NOTKANJ5 + MOVSB +; +; Added following 2 commands to the fix pipe bug. +; + inc cx ;AN000; 3/3/KK + inc cx ;AN000; 3/3/KK +; + JMP PIPECOMLP + +NOTKANJ5: +;;;; ENDIF ; 3/3/KK + + CMP AL,0DH + JZ LASTPIPE + INC CX + CMP AL,AltPipeChr + JZ IsPipe2 + CMP AL,vbar + JNZ PIPECOMLP +IsPipe2: + MOV BYTE PTR ES:[DI-1],0DH + DEC CX + MOV [COMBUF+1],CL + DEC SI + MOV [PIPEPTR],SI ; On to next pipe element + MOV DX,[OUTPIPEPTR] + PUSH CX + XOR CX,CX + MOV AX,(CREAT SHL 8) + INT int_command + POP CX + JC PIPEERRJ ; Lost the file + MOV BX,AX + MOV AL,0FFH + XCHG AL,[BX.PDB_JFN_Table] + MOV DS:[PDB_JFN_Table+1],AL + XCHG DX,[INPIPEPTR] ; Swap for next element of pipe + MOV [OUTPIPEPTR],DX + JMP SHORT PIPECOM + +LASTPIPE: + MOV [COMBUF+1],CL + DEC SI + MOV [PIPEPTR],SI ; Point at the CR (anything not '|' will do) + CALL TESTDOREOUT ; Set up the redirection if specified +PIPECOM: + PUSH CS + POP DS + JMP NOPIPEPROC ; Process the pipe element + +PIPEEND: + CALL PIPEDEL + CMP [SINGLECOM],0F000H + JNZ NOSINGP2 + MOV [SINGLECOM],-1 ; Make it return +NOSINGP2: + JMP TCOMMAND + +ASSUME DS:TRANGROUP,ES:TRANGROUP + +; Date and time are set during initialization and use +; this routines since they need to do a long return + +DATINIT PROC FAR + mov cs:[resseg],ds ; SetInitFlag needs resseg initialized + PUSH ES + PUSH DS ; Going to use the previous stack + MOV AX,CS ; Set up the appropriate segment registers + MOV ES,AX + MOV DS,AX + invoke TSYSLOADMSG ;AN000; preload messages + invoke SETSTDINON ;AN026; turn on critical error on STDIN + invoke SETSTDOUTOFF ;AN026; turn off critical error on STDOUT + MOV DX,OFFSET TRANGROUP:INTERNATVARS;Set up internat vars + MOV AX,INTERNATIONAL SHL 8 + INT 21H + MOV WORD PTR DS:[81H],13 ; Want to prompt for date during initialization + MOV [COMBUF],COMBUFLEN ; Init COMBUF + MOV WORD PTR [COMBUF+1],0D01H + CALL DATE + CALL CTIME + POP DS + POP ES + RET +DATINIT ENDP + +; DATE - Gets and sets the time + + + break Date + + +; **************************************************************** +; * +; * ROUTINE: DATE - Set system date +; * +; * FUNCTION: If a date is specified, set the system date, +; * otherwise display the current system date and +; * prompt the user for a new date. If an invalid +; * date is specified, issue an error message and +; * prompt for a new date. If the user enters +; * nothing when prompted for a date, terminate. +; * +; * INPUT: command line at offset 81H +; * +; * OUTPUT: none +; * +; **************************************************************** + +assume ds:trangroup,es:trangroup + +DATE: + MOV SI,81H ; Accepting argument for date inline + mov di,offset trangroup:parse_date ;AN000; Get adderss of PARSE_DATE + xor cx,cx ;AN000; clear counter for positionals + xor dx,dx ;AN000; + invoke cmd_parse ;AC000; call parser + cmp ax,end_of_line ;AC000; are we at end of line? + JZ PRMTDAT ;AC000; yes - go ask for date + cmp ax,result_no_error ;AN000; did we have an error? + jne daterr ;AN000; yes - go issue message + JMP COMDAT ;AC000; we have a date + +PRMTDAT: + ; Print "Current date is + + invoke GetDate ;AN000; get date for output + xchg dh,dl ;AN000; switch month & day + mov CurDat_yr,cx ;AC000; put year into message control block + mov CurDat_mo_day,dx ;AC000; put month and day into message control block + mov dx,offset trangroup:CurDat_ptr ;AC000; set up message for output + invoke std_printf +;AD061; mov CurDat_yr,0 ;AC000; reset year, month and day +;AD061; mov CurDat_mo_day,0 ;AC000; pointers in control block + +GET_NEW_DATE: ;AN000; + call getdat ;AC000; prompt user for date + cmp ax,end_of_line ;AC000; are we at end of line? + jz date_end ;AC000; yes - exit + cmp ax,result_no_error ;AN000; did we have an error? + jne daterr ;AN000; yes - go issue message +COMDAT: + mov cx,date_year ;AC000; get parts of date in + mov dh,date_month ;AC000; cx and dx for set + mov dl,date_day ;AC000; date function call. + push cx ;AC000; save date + push dx ;AC000; + mov cx,1 ;AC000; set 1 positional entered + xor dx,dx ;AN029; + invoke cmd_parse ;AN029; call parser + cmp al,end_of_line ;AN029; Are we at end of line? + pop dx ;AC000; retrieve date + pop cx ;AC000; + jnz daterr ;AC000; extra stuff on line - try again + MOV AH,SET_DATE ;yes - set date + INT int_command + OR AL,AL + JNZ DATERR +date_end: + ret + +DATERR: + invoke crlf2 ;AN028; print out a blank line + MOV DX,OFFSET TRANGROUP:BADDAT_ptr + invoke std_printf + JMP GET_NEW_DATE ;AC000; get date again + + +; TIME gets and sets the time + + break Time + +; **************************************************************** +; * +; * ROUTINE: TIME - Set system time +; * +; * FUNCTION: If a time is specified, set the system time, +; * otherwise display the current system time and +; * prompt the user for a new time. If an invalid +; * time is specified, issue an error message and +; * prompt for a new time. If the user enters +; * nothing when prompted for a time, terminate. +; * +; * INPUT: command line at offset 81H +; * +; * OUTPUT: none +; * +; **************************************************************** + +assume ds:trangroup,es:trangroup + +CTIME: + MOV SI,81H ; Accepting argument for time inline + mov di,offset trangroup:parse_time ;AN000; Get adderss of PARSE_time + xor cx,cx ;AN000; clear counter for positionals + xor dx,dx ;AN000; + invoke cmd_parse ;AC000; call parser + cmp ax,end_of_line ;AC000; are we at end of line? + JZ PRMTTIM ;AC000; yes - prompt for time + cmp ax,result_no_error ;AN000; did we have an error? + jne timerr ;AN000; yes - go issue message + JMP COMTIM ;AC000; we have a time + +PRMTTIM: + ;Printf "Current time is ... " + + MOV AH,GET_TIME ;AC000; get the current time + INT int_command ;AC000; Get time in CX:DX + xchg ch,cl ;AN000; switch hours & minutes + xchg dh,dl ;AN000; switch seconds & hundredths + mov CurTim_hr_min,cx ;AC000; put hours and minutes into message subst block + mov CurTim_sec_hn,dx ;AC000; put seconds and hundredths into message subst block + mov dx,offset trangroup:CurTim_ptr ;AC000; set up message for output + invoke std_printf +;AD061; mov CurTim_hr_min,0 ;AC000; reset hour, minutes, seconds, and hundredths +;AD061; mov CurTim_sec_hn,0 ;AC000; pointers in control block + +GET_NEW_TIME: + call gettim ;AC000; + cmp ax,end_of_line ;AC000; are we at end of line? + jz time_end ;AC000; + cmp ax,result_no_error ;AN000; did we have an error? + jne timerr ;AN000; yes - go issue message + +COMTIM: + mov ch,time_hour ;AC000; get parts of time in + mov cl,time_minutes ;AC000; cx and dx for set + mov dh,time_seconds ;AC000; time function call + mov dl,time_fraction ;AC000; + push cx ;AC000; save time + push dx ;AC000; + mov cx,1 ;AC000; set 1 positional parm entered + xor dx,dx ;AN029; + invoke cmd_parse ;AN029; call parser + cmp al,end_of_line ;AN029; Are we at end of line? + pop dx ;AC000; retieve time + pop cx ;AC000; + jnz timerr ;AC000; extra stuff on line - try again + +SAVTIM: + MOV AH,SET_TIME + INT int_command + OR AL,AL + JNZ TIMERR ;AC000; if an error occured, try again + +TIME_END: + + ret + +TIMERR: + invoke crlf2 ;AN028; print out a blank line + MOV DX,OFFSET TRANGROUP:BADTIM_ptr + invoke std_printf ; Print error message + JMP GET_NEW_TIME ;AC000; Try again + + +; +; Set the special flag in the INIT flag to the value in CX. +; +SetInitFlag: + mov ds,[RESSEG] +assume ds:resgroup + and InitFlag,NOT initSpecial + or InitFlag,cL + push cs + pop ds + return + +Public PipeOff +PipeOff: + ASSUME DS:NOTHING,ES:NOTHING + SaveReg + MOV DS,ResSeg + ASSUME DS:RESGroup + XOR AL,AL + XCHG PipeFlag,AL + OR AL,AL + JZ PipeOffDone + SHR EchoFlag,1 +PipeOffDone: + RestoreReg + return + + +PRINT_TIME: + + MOV AH,GET_TIME + INT int_command ; Get time in CX:DX + + PUSH ES + PUSH CS + POP ES + xchg ch,cl ;AN000; switch hours & minutes + xchg dh,dl ;AN000; switch seconds & hundredths + mov promTim_hr_min,cx ;AC000; put hours and minutes into message subst block + mov promTim_sec_hn,dx ;AC000; put seconds and hundredths into message subst block + mov dx,offset trangroup:promTim_ptr ;AC000; set up message for output + invoke std_printf +;AD061; mov promTim_hr_min,0 ;AC000; reset hour, minutes, seconds, and hundredths +;AD061; mov promTim_sec_hn,0 ;AC000; pointers in control block + + POP ES + return + + +; **************************************************************** +; * +; * ROUTINE: GETDAT - Prompt user for date +; * +; * FUNCTION: Gets the date format from the COUNTRY DEPENDENT +; * INFORMATION and issues the "Enter new date" +; * message with the proper date format. COMBUF +; * is reset to get a date from the command line. +; * The PARSE_DATE blocks are then reset and the +; * PARSE function call is issued. +; * +; * INPUT: NONE +; * +; * OUTPUT: COMBUF +; * PARSER RETURN CODES +; * +; **************************************************************** + + +GETDAT proc near ;AC000; + + mov ax,(International SHL 8) ; Determine what format the date + mov dx,5ch ; should be entered in and + int int_command ; print a message describing it + mov si,dx + lodsw + mov dx,usadat_ptr ;AC000; get mm-dd-yy + dec ax + js printformat + mov dx,eurdat_ptr ;AC000; get dd-mm-yy + jz printformat + mov dx,japdat_ptr ;AC000; get yy-mm-dd +printformat: + mov ax,dx ;AN000; get message number of format + mov dh,util_msg_class ;AN000; this is a utility message + call Tsysgetmsg ;AN000; get the address of the message + mov newdat_format,si ;AN000; put the address in subst block + MOV DX,OFFSET TRANGROUP:NEWDAT_ptr ;AC000; get address of message to print + invoke std_printf + mov newdat_format,no_subst ;AN000; reset subst block + + MOV AH,STD_CON_STRING_INPUT + MOV DX,OFFSET TRANGROUP:COMBUF + mov cx,initSpecial ; Set bit in InitFlag that indicates + call SetInitFlag ; prompting for date. + INT int_command ; Get input line + xor cx,cx ; Reset bit in InitFlag that indicates + call SetInitFlag ; prompting for date. + invoke CRLF2 + MOV SI,OFFSET TRANGROUP:COMBUF+2 + mov di,offset trangroup:parse_date ;AN000; Get adderss of PARSE_DATE + xor cx,cx ;AN000; clear counter for positionals + xor dx,dx ;AN000; + invoke cmd_parse ;AC000; call parser + + ret + +GETDAT endp ;AC000; + + +; **************************************************************** +; * +; * ROUTINE: GETTIME - Prompt user for time +; * +; * FUNCTION: Gets the time format from the COUNTRY DEPENDENT +; * INFORMATION and issues the "Enter new time" +; * message. COMBUF is reset to get a time from the +; * command line. The PARSE_TIME blocks are then +; * reset and the PARSE function call is issued. +; * +; * INPUT: NONE +; * +; * OUTPUT: COMBUF +; * PARSER RETURN CODES +; * +; **************************************************************** + + +GETTIM proc near ;AC000; + + XOR CX,CX ; Initialize hours and minutes to zero + MOV DX,OFFSET TRANGROUP:NEWTIM_ptr + invoke std_printf + MOV AH,STD_CON_STRING_INPUT + MOV DX,OFFSET TRANGROUP:COMBUF + mov cx,initSpecial ; Set bit in InitFlag that indicates + call SetInitFlag ; prompting for time. + INT int_command ; Get input line + xor cx,cx ; Reset bit in InitFlag that indicates + call SetInitFlag ; prompting for time. + invoke CRLF2 + MOV SI,OFFSET TRANGROUP:COMBUF+2 + mov di,offset trangroup:parse_time ;AN000; Get adderss of PARSE_TIME + xor cx,cx ;AN000; clear counter for positionals + xor dx,dx ;AN000; + invoke cmd_parse ;AC000; call parser + + ret + +GETTIM endp ;AC000; + +TRANCODE ENDS + END diff --git a/v4.0/src/CMD/COMMAND/TPRINTF.ASM b/v4.0/src/CMD/COMMAND/TPRINTF.ASM new file mode 100644 index 0000000..c502f83 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TPRINTF.ASM @@ -0,0 +1,365 @@ + page 80,132 +; SCCSID = @(#)tprintf.asm 4.3 85/07/02 +; SCCSID = @(#)tprintf.asm 4.3 85/07/02 +TITLE COMMAND Transient Printf routine + +;**************************************************************** +;* +;* ROUTINE: STD_PRINTF/STD_EPRINTF +;* +;* FUNCTION: Set up to print out a message using SYSDISPMSG. +;* Set up substitutions if utility message. Make +;* sure any changes to message variables in TDATA +;* are reset to avoid reloading the transient. +;* +;* INPUT: Msg_Disp_Class - set to message class +;* Msg_Cont_Flag - set to control flags +;* DS points to transient segment +;* +;* if utility message: +;* DX points to a block with message number +;* (word), number of substitutions (byte), +;* followed by substitution list if there +;* are substitutions. If substitutions +;* are not in transient segment they must +;* be set. +;* else +;* AX set to message number +;* +;* OUTPUT: none +;* +;**************************************************************** + +.xlist +.xcref + INCLUDE comsw.asm ;AC000; + INCLUDE DOSSYM.INC + INCLUDE comseg.asm + INCLUDE comequ.asm ;AN000; + INCLUDE SYSMSG.INC ;AN000; +.list +.cref + +datares segment public + extrn pipeflag:byte +datares ends + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN extend_buf_off:word ;AN000; + EXTRN Extend_Buf_ptr:word ;AN000; + EXTRN Extend_Buf_seg:word ;AN000; + EXTRN Msg_Cont_Flag:byte ;AN000; + EXTRN Msg_disp_Class:byte ;AN000; + EXTRN pipeemes_ptr:word +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN msg_flag:byte ;AN022; + EXTRN print_err_flag:word ;AN000; + EXTRN RESSEG:WORD + EXTRN String_ptr_2:word ;AC000; + EXTRN Subst_buffer:byte ;AN061; +;AD061; EXTRN String_ptr_2_sb:word ;AN000; + + ; include data area for message services + + MSG_UTILNAME ;AN000; define utility name + + MSG_SERVICES ;AN000; + +PRINTF_HANDLE DW ? ;AC000; + +TRANSPACE ENDS ;AC000; + +TRANCODE SEGMENT PUBLIC BYTE ;AC000; + + EXTRN cerror:near + EXTRN crlf2:near + EXTRN tcommand:near ;AN026; + +ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:NOTHING,SS:NOTHING ;AC000; + + PUBLIC SETSTDINOFF ;AN026; + PUBLIC SETSTDINON ;AN026; + PUBLIC SETSTDOUTOFF ;AN026; + PUBLIC SETSTDOUTON ;AN026; + PUBLIC TSYSGETMSG ;AN000; + PUBLIC TSYSLOADMSG ;AN000; + +PUBLIC Printf_Init +printf_init proc far + call std_printf + ret +printf_init endp + +Public Printf_Crlf +PRINTF_CRLF: + CALL STD_PRINTF + CALL CRLF2 + RET + +PUBLIC Std_EPrintf +STD_EPRINTF: + mov Printf_Handle,2 ;AC000;Print to STDERR + jmp short NEW_PRINTF ;AC000; +PUBLIC Std_Printf +STD_PRINTF: + mov Printf_Handle,1 ;AC000;Print to STDOUT + +NEW_PRINTF: + push ax ;AN000;save registers + push bx ;AN000; + push cx ;AN000; + push es ;AN000;get local ES + push ds ;AN000; + pop es ;AN000; + push di ;AN000; + push si ;AN000; + push dx ;AN000; + assume es:trangroup ;AN000; +;AD061; mov string_ptr_2_sb,0 ;AN000;initialize + mov print_err_flag,0 ;AN000; + +UTILITY_SETUP: + mov si,dx ;AN000;Get offset of message number + lodsw ;AN000;load message number + push ax ;AN000;save it + lodsb ;AN000;get number of substitutions + mov cl,al ;AN000;set up CX as # of subst + xor ch,ch ;AN000; SI now points to subst list + pop ax ;AN000;get message number back + cmp cx,0 ;AN000;Any substitutions? + jz READY_TO_PRINT ;AN000;No - continue + +;AD061; add dx,Ptr_Seg_Pos ;AN000;Point to position of first segment +;AD061; push cx ;AN000;save substitution count + +;AD061;SET_SUBST: +;AD061; mov bx,dx ;AN000;get dx into base register +;AD061; cmp word ptr [bx],0 ;AN000;has segment been set? +;AD061; jnz SUBST_SEG_SET ;AN000;if not 0, don't replace it +;AD061; test word ptr [bx+3],date_type ;AN000;if date or time - don't set segment +;AD061; jnz subst_seg_set ;AN000;yes - skip it +;AD061; mov word ptr [bx],cs ;AN000;put segment of subst parm in list + +;AD061;SUBST_SEG_SET: +;AD061; add dx,Parm_Block_Size ;AN000;point to position of next segment +;AD061; loop SET_SUBST ;AN000;keep replacing until complete +;AD061; pop cx ;AN000; + +;AD061;NO_REPLACEMENT: +;AD061; mov bx,parm_off_pos [si] ;AN000;get subst offset +;AD061; cmp bx,offset trangroup:string_ptr_2 ;AN000;this is used for double indirection +;AD061; jnz ready_to_print ;AN000;we already have address +;AD061; mov dx,string_ptr_2 ;AN000;get address in string_ptr_2 +;AD061; mov parm_off_pos [si],dx ;AN000;put proper address in table +;AD061; mov string_ptr_2_sb,si ;AN000;save block changed + + mov di,offset trangroup:subst_buffer;AN061; Get address of message subst buffer + push di ;AN061; save it + push cx ;AN061; save number of subst + +MOVE_SUBST: + push cx ;AN061;save number of subst + mov bx,si ;AN061;save start of sublist + mov cx,parm_block_size ;AN061;get size of sublist + rep movsb ;AN061;move sublist + test byte ptr [bx.$M_S_FLAG],date_type ;AN061;are we doing date/time? + jz move_subst_cont ;AN061;no - no need to reset + mov word ptr [bx.$M_S_VALUE],0 ;AN061;reset original date or time to 0 + mov word ptr [bx.$M_S_VALUE+2],0 ;AN061; + +MOVE_SUBST_CONT: ;AN061; + pop cx ;AN061;get number of subst back + loop move_subst ;AN061;move cx sublists + + pop cx ;AN061;get number of subst + push ax ;AN061;save message number + cmp Msg_Disp_Class,Util_Msg_Class ;AN061;Is this a utility message + jz CHECK_FIX ;AN061;YES - go see if substitutions + mov msg_flag,ext_msg_class ;AN061;set message flag + mov di,offset trangroup:extend_buf_ptr ;AN061; Get address of extended message block + xor ax,ax ;AN061;clear ax register + stosw ;AN061;clear out message number + stosb ;AN061;clear out subst count + +CHECK_FIX: ;AN061; + pop ax ;AN061;get message number back + pop di ;AN061;get start of sublists + mov si,di ;AN061;get into SI for msgserv + mov bx,si ;AN061;get into BX for addressing + push cx ;AN061;save number of subst + +SET_SUBST: ;AN061;store the segment of the subst + cmp word ptr [bx.$M_S_VALUE+2],0 ;AN061;was it set already? + jnz subst_seg_set ;AN061;if not 0, don't replace it + test byte ptr [bx.$M_S_FLAG],date_type ;AN061;don't replace if date or time + jnz subst_seg_set ;AN061;yes - skip it + mov word ptr [bx.$M_S_VALUE+2],cs ;AN061;set segment value + +SUBST_SEG_SET: ;AN061; + add bx,parm_block_size ;AN061;go to next sublist + loop set_subst ;AN061;loop CX times + pop cx ;AN061;get number of subst back + + mov bx,si ;AN061;get start of sublist to BX + cmp word ptr [bx.$M_S_VALUE],offset trangroup:string_ptr_2 ;AN061;are we using double indirection? + jnz ready_to_print ;AN061;no - we already have address + mov dx,string_ptr_2 ;AN061;get address in string_ptr_2 + mov word ptr [bx.$M_S_VALUE],dx ;AN061;put it into the subst block + +READY_TO_PRINT: + mov bx,Printf_Handle ;AN000;get print handle + mov dl,Msg_Cont_Flag ;AN000;set up control flag + mov dh,Msg_Disp_Class ;AN000;set up display class + mov Msg_Cont_Flag,No_Cont_Flag ;AN061;reset flags to avoid + mov Msg_Disp_Class,Util_Msg_Class ;AN061; transient reload + +;AD061; push bx ;AN026; save registers +;AD061; push cx ;AN026; +;AD061; push dx ;AN026; +;AD061; push si ;AN026; +;AD061; push di ;AN026; + push ds ;AN026; + push es ;AN026; + + + call SYSDISPMSG ;AN000;call Rod + + pop es ;AN026; restore registers + pop ds ;AN026; +;AD061; pop di ;AN026; +;AD061; pop si ;AN026; +;AD061; pop dx ;AN026; +;AD061; pop cx ;AN026; +;AD061; pop bx ;AN026; + + jnc Print_success ;AN000; everything went okay + mov print_err_flag,ax ;AN000; + +print_success: +;AD061; cmp Msg_Disp_Class,Util_Msg_Class ;AN000;Is this a utility message +;AD061; jz CHECK_FIX ;AN000;YES - go see if substitutions +;AD061; mov msg_flag,ext_msg_class ;AN022;set message flag +;AD061; mov di,offset trangroup:extend_buf_ptr ;AN000; Get address of extended message block +;AD061; xor ax,ax ;AN000;clear ax register +;AD061; stosw ;AN000;clear out message number +;AD061; stosb ;AN000;clear out subst count + +;AD061; CHECK_FIX: +;AD061; pop dx ;AN000;restore dx +;AD061; cmp cx,0 ;AN000;Any substitutions? +;AD061; jz NO_FIXUP ;AN000;No - leave + +;AD061; mov si,dx ;AN000;Reset changes so transient won't reload +;AD061; add si,Ptr_Seg_Pos ;AN000;Point to position of first segment + +;AD061;FIX_SUBST: +;AD061; mov word ptr [si],0 ;AN000;reset segment to 0 +;AD061; add si,Parm_Block_Size ;AN000;point to position of next segment +;AD061; loop FIX_SUBST ;AN000;keep replacing until complete +;AD061; cmp string_ptr_2_sb,no_subst ;AN000;was double indirection used? +;AD061; jz no_fixup ;AN000;no - we're finished +;AD061; mov si,string_ptr_2_sb ;AN000;get offset changed +;AD061; mov parm_off_pos [si],offset trangroup:string_ptr_2 ;AN000; set address back to string_ptr_2 + +;AD061;NO_FIXUP: +;AD061; mov Msg_Cont_Flag,No_Cont_Flag ;AN000;reset flags to avoid +;AD061; mov Msg_Disp_Class,Util_Msg_Class ;AN000; transient reload + pop dx ;AN061;restore dx + pop si ;AN000;restore registers + pop di ;AN000; + pop es ;AN000;restore registers + pop cx ;AN000; + pop bx ;AN000; + pop ax ;AN000; + cmp print_err_flag,0 ;AN000; if an error occurred - handle it + jnz print_err ;AN000; + + ret ;AC000; + +print_err: + push cs + pop es + cmp Printf_Handle,2 ;AN026;Print to STDERR? + jnz not_stderr ;AN026;no - continue + jmp tcommand ;AN026;Yes - hopless - just exit + +not_stderr: + mov ax,print_err_flag ;AN026;get extended error number back + mov es,[resseg] ; No, set up for error, load the +assume es:resgroup ; right error msg, and jmp to cerror. + test PipeFlag,-1 + jz go_to_error + invoke PipeOff + mov dx,offset trangroup:pipeemes_ptr + jmp print_err_exit ;AC000; + +go_to_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,ax ;AN000; get message number in control block + +PRINT_ERR_EXIT: ;AC000; + push cs + pop es + JMP CERROR + +;**************************************************************** +;* +;* ROUTINE: TSYSLOADMSG +;* +;* FUNCTION: Interface to call SYSLOADMSG to avoid duplicate +;* names since these routines are also used in the +;* resident. +;* +;* INPUT: Inputs to SYSLOADMSG +;* +;* OUTPUT: Outputs from SYSLOADMSG +;* +;**************************************************************** + + +TSYSLOADMSG PROC NEAR ;AN000; + + push bx ;AN000; + call sysloadmsg ;AN000; call routine + pop bx ;AN000; + ret ;AN000; exit + +TSYSLOADMSG ENDP ;AN000; + +;**************************************************************** +;* +;* ROUTINE: TSYSGETMSG +;* +;* FUNCTION: Interface to call SYSGETMSG to avoid duplicate +;* names since these routines are also used in the +;* resident. +;* +;* INPUT: Inputs to SYSGETMSG +;* +;* OUTPUT: Outputs from SYSGETMSG +;* +;**************************************************************** + + +TSYSGETMSG PROC NEAR ;AN000; + + push cx ;AN000; + call sysgetmsg ;AN000; call routine + pop cx ;AN000; + ret ;AN000; exit + +TSYSGETMSG ENDP ;AN000; + +MSG_SERVICES ;AC026; The message services +MSG_SERVICES ;AC026; The message services + +PRINTF_LAST LABEL WORD + +include msgdcl.inc + + +TRANCODE ENDS + END diff --git a/v4.0/src/CMD/COMMAND/TRANMSG.ASM b/v4.0/src/CMD/COMMAND/TRANMSG.ASM new file mode 100644 index 0000000..38b04ba --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TRANMSG.ASM @@ -0,0 +1,671 @@ + +;**************************************************** +;* TRANSIENT MESSAGE POINTERS & SUBSTITUTION BLOCKS * +;**************************************************** + +msg_disp_class db Util_msg_class +msg_cont_flag db No_cont_flag + +; extended error string output +; +Extend_Buf_ptr dw 0 ;AN000;set to no message +Extend_Buf_sub db 0 ;AN000;set to no substitutions + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved +Extend_Buf_off dw OFFSET TranGroup:String_ptr_2 ;AN000;offset of arg +Extend_Buf_seg dw 0 ;AN000;segment of arg + db 0 ;AN000;first subst + db Char_field_ASCIIZ ;AN000;character string + db 128 ;AN000;maximum width + db 0 ;AN000;minimum width + db blank ;AN000;pad character + +; "Duplicate file name or file not found" +; +Renerr_Ptr dw 1002 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Invalid path or file name" +; +BadCPMes_Ptr dw 1003 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Insufficient disk space" +; +NoSpace_Ptr dw 1004 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Out of environment space" +; +EnvErr_Ptr dw 1007 ;AN000;message number + db no_subst ;AN000;number of subst + +; "File creation error" +; +FulDir_Ptr dw 1008 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Batch file missing",13,10 +; +BadBat_Ptr dw 1009 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Insert disk with batch file",13,10 +; +NeedBat_Ptr dw 1010 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Bad command or file name",13,10 +; +BadNam_Ptr dw 1011 ;AN000;message number + db no_subst ;AN000;number of subst + + +; "Access denied",13,10 +; +AccDen_Ptr dw 1014 ;AN000;message number + db no_subst ;AN000;number of subst + +; "File cannot be copied onto itself",13,10 +; +OverWr_Ptr dw 1015 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Content of destination lost before copy",13,10 +; +LostErr_Ptr dw 1016 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Invalid filename or file not found",13,10 +; +InOrNot_Ptr dw 1017 ;AN000;message number + db no_subst ;AN000;number of subst + +; "%1 File(s) copied",13,10 +; +Copied_Ptr dw 1018 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:Copy_num ;AN000;offset of arg + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Right_Align+Unsgn_Bin_Word ;AN000;binary to decimal + db 9 ;AN000;maximum width + db 9 ;AN000;minimum width + db blank ;AN000;pad character + +; "%1 File(s) " +; +DirMes_Ptr dw 1019 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:Dir_num ;AN000;offset of arg + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Right_Align+Unsgn_Bin_Word ;AN000;binary to decimal + db 9 ;AN000;maximum width + db 9 ;AN000;minimum width + db blank ;AN000;pad character + +; "%1 bytes free",13,10 +; +BytMes_Ptr dw 1020 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:Bytes_Free ;AN000;offset of arg + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Right_Align+Unsgn_Bin_DWord ;AN000;long binary to decimal + db 10 ;AN000;maximum width + db 10 ;AN000;minimum width + db blank ;AN000;pad character + +; "Invalid drive specification",13,10 +; +BadDrv_Ptr dw 1021 ;AN000;message number + db no_subst ;AN000;number of subst + + +; "Code page %1 not prepared for system",13,10 +; +CP_not_set_Ptr dw 1022 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:System_cpage ;AN000;offset of arg + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Right_Align+Unsgn_Bin_Word ;AN000;binary to decimal + db 5 ;AN000;maximum width + db 1 ;AN000;minimum width + db blank ;AN000;pad character + +; "Code page %1 not prepared for all devices",13,10 +; +CP_not_all_Ptr dw 1023 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:System_cpage ;AN000;offset of arg + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Right_Align+Unsgn_Bin_Word ;AN000;binary to decimal + db 5 ;AN000;maximum width + db 1 ;AN000;minimum width + db blank ;AN000;pad character + +; "Active code page: %1",13,10 +; +CP_active_Ptr dw 1024 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:System_cpage ;AN000;offset of arg + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Right_Align+Unsgn_Bin_Word ;AN000;binary to decimal + db 5 ;AN000;maximum width + db 1 ;AN000;minimum width + db blank ;AN000;pad character + +; "NLSFUNC not installed",13,10 +; +NLSFUNC_Ptr dw 1025 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Invalid code page",13,10 +; +Inv_Code_Page dw 1026 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Current drive is no longer valid" +; +BadCurDrv dw 1027 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Press any key to continue" +; +PauseMes_Ptr dw 1028 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Label not found",13,10 +; +BadLab_Ptr dw 1029 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Syntax error",13,10 +; +SyntMes_Ptr dw 1030 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Invalid date",13,10 +; +BadDat_Ptr dw 1031 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Current date is %1 %2",13,10 +; +CurDat_Ptr dw 1032 ;AN000;message number + db 2 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:Arg_Buf ;AN000;offset of arg + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_ASCIIZ ;AN000;character string + db 3 ;AN000;maximum width + db 3 ;AN000;minimum width + db blank ;AN000;pad character + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved +CurDat_yr dw 0 ;AN000;year +CurDat_mo_day dw 0 ;AN000;month,day + db 2 ;AN000;second subst + db DATE_MDY_4 ;AN000;date + db 10 ;AN000;maximum width + db 10 ;AN000;minimum width + db blank ;AN000;pad character + + +; "SunMonTueWedThuFriSat" +; +WeekTab dw 1033 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Enter new date (%1):" +; +NewDat_Ptr dw 1034 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved +NewDat_Format dw 0 ;AN000;offset of replacement + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_ASCIIZ ;AN000;character string + db 8 ;AN000;maximum width + db 8 ;AN000;minimum width + db blank ;AN000;pad character + +; "Invalid time",13,10 +; +BadTim_Ptr dw 1035 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Current time is %1",13,10 +; +CurTim_Ptr dw 1036 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved +CurTim_hr_min dw 0 ;AN000;hours,minutes +CurTim_Sec_hn dw 0 ;AN000;seconds,hundredths + db 1 ;AN000;first subst + db Right_Align+TIME_HHMMSSHH_Cty ;AC059;time + db 12 ;AC059;maximum width + db 12 ;AC059;minimum width + db blank ;AN000;pad character + +; "Enter new time:" +; +NewTim_Ptr dw 1037 ;AN000;message number + db no_subst ;AN000;number of subst + +; ", Delete (Y/N)?",13,10 +; +Del_Y_N_Ptr dw 1038 ;AN000;message number + db no_subst ;AN000;number of subst + +; "All files in directory will be deleted!",13,10 +; "Are you sure (Y/N)?",13,10 +; +SureMes_Ptr dw 1039 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Microsoft DOS Version %1.%2",13,10 +; +VerMes_Ptr dw 1040 ;AN000;message number + db 2 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:Major_Ver_Num ;AN000;offset of arg + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Right_Align+Unsgn_Bin_Word ;AN000;binary to decimal + db 1 ;AN000;maximum width + db 1 ;AN000;minimum width + db blank ;AN000;pad character + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:Minor_Ver_Num ;AN000;offset of arg + dw 0 ;AN000;segment of arg + db 2 ;AN000;second subst + db Unsgn_Bin_Word ;AN000;binary to decimal + db 2 ;AN000;maximum width + db 2 ;AN000;minimum width + db "0" ;AN000;pad character + +; "Volume in drive %1 has no label",13,10 +; +VolMes_Ptr_2 dw 1041 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:vol_drv ;AN000;offset of drive + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_Char ;AN000;character + db 128 ;AN000;maximum width + db 1 ;AN000;minimum width + db blank ;AN000;pad character + +; "Volume in drive %1 is %2",13,10 +; +VolMes_Ptr dw 1042 ;AN000;message number + db 2 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:vol_drv ;AN000;offset of drive + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db 00000000b ;AN000;character + db 128 ;AN000;maximum width + db 1 ;AN000;minimum width + db blank ;AN000;pad character + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:CHARBUF ;AN000;offset of string + dw 0 ;AN000;segment of arg + db 2 ;AN000;second subst + db Char_field_ASCIIZ ;AN000;character string + db 128 ;AN000;maximum width + db 1 ;AN000;minimum width + db blank ;AN000;pad character + +; "Volume Serial Number is %1-%2",13,10 +; +VolSerMes_Ptr dw 1043 ;AN000;message number + db 2 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:vol_serial+2 ;AN000;offset of serial + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Right_Align+Bin_Hex_Word ;AN000;binary to hex + db 4 ;AN000;maximum width + db 4 ;AN000;minimum width + db "0" ;AN000;pad character + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:vol_serial ;AN000;offset of serial + dw 0 ;AN000;segment of arg + db 2 ;AN000;second subst + db Right_Align+Bin_Hex_Word ;AN000;binary to hex + db 4 ;AN000;maximum width + db 4 ;AN000;minimum width + db "0" ;AN000;pad character + +; "Invalid directory",13,10 +; +BadCD_Ptr dw 1044 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Unable to create directory",13,10 +; +BadMkD_Ptr dw 1045 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Invalid path, not directory,",13,10 +; "or directory not empty",13,10 +; +BadRmD_Ptr dw 1046 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Must specify ON or OFF",13,10 +; +Bad_ON_OFF_Ptr dw 1047 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Directory of %1",13,10 +; +DirHead_Ptr dw 1048 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:BWDBUF ;AN000;offset of arg + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_ASCIIZ ;AN000;character string + db 128 ;AN000;maximum width + db 0 ;AN000;minimum width + db blank ;AN000;pad character + +; "No Path",13,10 +; +NulPath_Ptr dw 1049 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Invalid drive in search path",13,10 +; +BadPMes_Ptr dw 1050 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Invalid device",13,10 +; +BadDev_Ptr dw 1051 ;AN000;message number + db no_subst ;AN000;number of subst + +; "FOR cannot be nested",13,10 +; +ForNestMes_Ptr dw 1052 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Intermediate file error during pipe",13,10 +; +PipeEMes_Ptr dw 1053 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Cannot do binary reads from a device",13,10 +; +InBDev_Ptr dw 1054 ;AN000;message number + db no_subst ;AN000;number of subst + +; "BREAK is %1",13,10 +; +CtrlcMes_Ptr dw 1055 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw 0 ;AN000;offset of on/off (new) + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_ASCIIZ ;AN000;character string + db 128 ;AN000;maximum width + db 1 ;AN000;minimum width + db blank ;AN000;pad character + +; "VERIFY is %1",13,10 +; +VeriMes_Ptr dw 1056 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw 0 ;AN000;offset of on/off (new) + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_ASCIIZ ;AN000;character string + db 128 ;AN000;maximum width + db 1 ;AN000;minimum width + db blank ;AN000;pad character + +; "ECHO is %1",13,10 +; +EchoMes_Ptr dw 1057 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw 0 ;AN000;offset of on/off (new) + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_ASCIIZ ;AN000;character string + db 128 ;AN000;maximum width + db 1 ;AN000;minimum width + db blank ;AN000;pad character + +; "off" +; +OffMes_Ptr dw 1059 ;AN000;message number + db no_subst ;AN000;number of subst + +; "on" +; +OnMes_Ptr dw 1060 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Error writing to device",13,10 +; +DevWMes_Ptr dw 1061 ;AN000;message number + db no_subst ;AN000;number of subst + +; "Invalid path",13,10 +; +Inval_Path_Ptr dw 1062 ;AN000;message number + db no_subst ;AN000;number of subst + +; unformatted string output +; +arg_Buf_Ptr dw 1063 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:Arg_Buf ;AN000;offset of arg + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_ASCIIZ ;AN000;character string + db 128 ;AN000;maximum width + db 0 ;AN000;minimum width + db blank ;AN000;pad character + +; file name output +; +File_Name_Ptr dw 1064 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:SRCBUF ;AN000;offset of arg + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_ASCIIZ ;AN000;character string + db 128 ;AN000;maximum width + db 0 ;AN000;minimum width + db blank ;AN000;pad character + +; file size output for dir +; +Disp_File_Size_Ptr dw 1065 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:File_size_low ;AN000;offset of arg + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Right_Align+Unsgn_Bin_DWord ;AN000;long binary to decimal + db 10 ;AN000;maximum width + db 10 ;AN000;minimum width + db blank ;AN000;pad character + +; unformatted string output +; %s +String_Buf_Ptr dw 1066 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:String_ptr_2 ;AN000;offset of arg + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_ASCIIZ ;AN000;character string + db 128 ;AN000;maximum width + db 0 ;AN000;minimum width + db blank ;AN000;pad character + db 0 ;AN000; + +; tab character +; +Tab_ptr dw 1067 ;AN000;message number + db no_subst ;AN000;number of subst + +; " " +; +DMes_Ptr dw 1068 ;AN000;message number + db no_subst ;AN000;number of subst + +; destructive back space +; +Dback_Ptr dw 1069 ;AN000;message number + db no_subst ;AN000;number of subst + +; carriage return / line feed +; +ACRLF_Ptr dw 1070 ;AN000;message number + db no_subst ;AN000;number of subst + +; output a single character +; +;One_Char_Buf_Ptr dw 1071 ;AN000;message number +; db 1 ;AN000;number of subst +; db parm_block_size ;AN000;size of sublist +; db 0 ;AN000;reserved +; dw OFFSET TranGroup:One_Char_Val ;AN000;offset of charcacter +; dw 0 ;AN000;segment of arg +; db 1 ;AN000;first subst +; db Char_field_Char ;AN000;character +; db 1 ;AN000;maximum width +; db 1 ;AN000;minimum width +; db blank ;AN000;pad character + +; "mm-dd-yy" +; +USADat_Ptr dw 1072 ;AN000;message number + db no_subst ;AN000;number of subst + +; "dd-mm-yy" +; +EurDat_Ptr dw 1073 ;AN000;message number + db no_subst ;AN000;number of subst + +; "yy-mm-dd" +; +JapDat_Ptr dw 1074 ;AN000;message number + db no_subst ;AN000;number of subst + +; date string for prompt +; +promptDat_Ptr dw 1075 ;AN000;message number + db 2 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved + dw OFFSET TranGroup:Arg_Buf ;AN000;offset of arg + dw 0 ;AN000;segment of arg + db 1 ;AN000;first subst + db Char_field_ASCIIZ ;AN000;character string + db 3 ;AN000;maximum width + db 3 ;AN000;minimum width + db blank ;AN000;pad character + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved +promptDat_yr dw 0 ;AN000;year +promptDat_moday dw 0 ;AN000;month,day + db 2 ;AN000;second subst + db DATE_MDY_4 ;AN000;date + db 10 ;AN000;maximum width + db 8 ;AN000;minimum width + db blank ;AN000;pad character + + +; Time for prompt +; +promTim_Ptr dw 1076 ;AN000;message number + db 1 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved +PromTim_hr_min dw 0 ;AN000;hours,minutes +PromTim_Sec_hn dw 0 ;AN000;seconds,hundredths + db 1 ;AN000;first subst + db Right_Align+TIME_HHMMSSHH_24 ;AC013;time + db 11 ;AN000;maximum width + db 11 ;AC013;minimum width + db blank ;AN000;pad character + +; Date and time for DIR +; +DirDatTim_Ptr dw 1077 ;AN000;message number + db 2 ;AN000;number of subst + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved +DirDat_yr dw 0 ;AN000;year +DirDat_mo_day dw 0 ;AN000;month,day + db 1 ;AN000;first subst + db Right_Align+DATE_MDY_2 ;AN000;date + db 10 ;AN000;maximum width + db 8 ;AN000;minimum width + db blank ;AN000;pad character + db parm_block_size ;AN000;size of sublist + db 0 ;AN000;reserved +DirTim_hr_min dw 0 ;AN000;hours,minutes +DirTim_Sec_hn dw 0 ;AN000;seconds,hundredths + db 2 ;AN000;second subst + db Right_align+TIME_HHMM_Cty ;AN000;time + db 6 ;AN000;maximum width + db 6 ;AN000;minimum width + db blank ;AN000;pad character + +; "Directory already exists" +; +MD_exists_ptr dw 1078 ;AN000;message number + db no_subst ;AN000;number of subst + +PATH_TEXT DB "PATH=" +PROMPT_TEXT DB "PROMPT=" +comspecstr db "COMSPEC=" diff --git a/v4.0/src/CMD/COMMAND/TSPC.ASM b/v4.0/src/CMD/COMMAND/TSPC.ASM new file mode 100644 index 0000000..10e5758 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TSPC.ASM @@ -0,0 +1,488 @@ + page 80,132 +; SCCSID = @(#)tspc.asm 4.1 85/09/22 +; SCCSID = @(#)tspc.asm 4.1 85/09/22 +TITLE COMMAND Transient Uninitialized DATA + + INCLUDE comsw.asm +.xlist +.xcref + INCLUDE DOSSYM.INC + INCLUDE comequ.asm + INCLUDE comseg.asm + INCLUDE EA.inc ;AN030; +.list +.cref + +; Uninitialized transient data +TRANSPACE SEGMENT PUBLIC BYTE + + PUBLIC ALLSWITCH + PUBLIC append_exec ;AN041; + PUBLIC arg + PUBLIC argbufptr + PUBLIC ARGC + PUBLIC ARG1S + PUBLIC ARG2S + PUBLIC ARGTS + PUBLIC arg_buf + PUBLIC ASCII + PUBLIC BatBuf + PUBLIC BatBufEnd + PUBLIC BatBufPos + PUBLIC BATHAND + PUBLIC BINARY + PUBLIC BITS + PUBLIC BWDBUF + PUBLIC BYTCNT + PUBLIC bytes_free + PUBLIC CFLAG + PUBLIC CHARBUF + PUBLIC CHKDRV + PUBLIC COM + PUBLIC COMBUF + PUBLIC comma + PUBLIC comptr + PUBLIC comspec_flag + PUBLIC COMSW + PUBLIC CONCAT + PUBLIC concat_xa ;AN000; + PUBLIC copy_Num + PUBLIC CPDATE + PUBLIC CPTIME + PUBLIC cpyflag + PUBLIC CURDRV + PUBLIC DATE_DAY ;AN000; + PUBLIC DATE_MONTH ;AN000; + PUBLIC DATE_OUTPUT ;AN000; + PUBLIC DATE_TYPE ;AN000; + PUBLIC DATE_YEAR ;AN000; + PUBLIC DEST + PUBLIC DESTBUF + PUBLIC DestClosed + PUBLIC DESTDIR + PUBLIC DESTFCB + PUBLIC DESTFCB2 + PUBLIC DESTHAND + PUBLIC DESTINFO + PUBLIC DESTISDEV + PUBLIC DESTISDIR + PUBLIC DESTNAME + PUBLIC DESTSIZ + PUBLIC DESTSWITCH + PUBLIC DESTTAIL + PUBLIC DESTVARS + PUBLIC DIRBUF + PUBLIC DIRCHAR + PUBLIC dirflag ;AN015; + PUBLIC Dir_Num + PUBLIC display_ioctl ;AN000; + PUBLIC display_mode ;AN000; + PUBLIC display_width ;AN000; + PUBLIC DRIVE_NUMBER ;AN000; + PUBLIC DRIVE_OUTPUT ;AN000; + PUBLIC DRIVE_TYPE ;AN000; + PUBLIC DRIVE_VALUE ;AN000; + PUBLIC ELCNT + PUBLIC ELPOS + PUBLIC EXECPATH + PUBLIC EXEC_ADDR + PUBLIC EXEFCB + PUBLIC expand_star + PUBLIC ext_entered ;AN005; + PUBLIC ext_open_off ;AN000; + PUBLIC ext_open_parms ;AN000; + PUBLIC ext_open_seg ;AN000; + PUBLIC FBUF + PUBLIC FILECNT + PUBLIC file_size_high + PUBLIC file_size_low + PUBLIC FILTYP + PUBLIC FIRSTDEST + PUBLIC FRSTSRCH + PUBLIC FULLSCR + PUBLIC GOTOLEN + PUBLIC HEADCALL + PUBLIC ID + PUBLIC IDLEN + PUBLIC IFNOTFLAG + PUBLIC if_not_count + PUBLIC INEXACT + PUBLIC INTERNATVARS + PUBLIC KPARSE + PUBLIC last_arg + PUBLIC LINCNT + PUBLIC LINLEN + PUBLIC linperpag ;AN000; + PUBLIC major_ver_num + PUBLIC MELCOPY + PUBLIC MELSTART + PUBLIC minor_ver_num + PUBLIC msg_flag ;AN022; + PUBLIC msg_numb ;AN022; + PUBLIC NOWRITE + PUBLIC NXTADD + PUBLIC objcnt + PUBLIC one_char_val + PUBLIC PARM1 + PUBLIC PARM2 + PUBLIC parse_last ;AN018; + PUBLIC PARSE1_ADDR ;AN000; + PUBLIC PARSE1_CODE ;AN000; + PUBLIC PARSE1_OUTPUT ;AN000; + PUBLIC PARSE1_SYN ;AN000; + PUBLIC PARSE1_TYPE ;AN000; + PUBLIC PATHCNT + PUBLIC pathinfo + PUBLIC PATHPOS + PUBLIC PATHSW + PUBLIC PLUS + PUBLIC plus_comma + PUBLIC print_err_flag ;AN000; + PUBLIC psep_char + PUBLIC RCH_ADDR + PUBLIC RDEOF + PUBLIC RE_INSTR + PUBLIC RESSEG + PUBLIC SCANBUF + PUBLIC SDIRBUF + PUBLIC search_best + PUBLIC search_best_buf + PUBLIC search_curdir_buf + PUBLIC search_error + PUBLIC SKPDEL + PUBLIC SOURCE + PUBLIC SPECDRV + PUBLIC SRCBUF + PUBLIC SRCHAND + PUBLIC SRCINFO + PUBLIC SRCISDEV + PUBLIC SRCISDIR + PUBLIC SRCPT + PUBLIC SRCSIZ + PUBLIC SRCTAIL + PUBLIC SRCVARS + PUBLIC srcxname + PUBLIC src_xa_seg ;AN000; + PUBLIC src_xa_size ;AN000; + PUBLIC STACK + PUBLIC STARTEL + PUBLIC string_ptr_2 +;AD061; PUBLIC string_ptr_2_sb ;AN000; + PUBLIC subst_buffer ;AN061; + PUBLIC SWITCHAR + PUBLIC system_cpage + PUBLIC TERMREAD + PUBLIC TIME_FRACTION ;AN000; + PUBLIC TIME_HOUR ;AN000; + PUBLIC TIME_MINUTES ;AN000; + PUBLIC TIME_OUTPUT ;AN000; + PUBLIC TIME_SECONDS ;AN000; + PUBLIC TIME_TYPE ;AN000; + PUBLIC TPA + PUBLIC tpbuf + PUBLIC TRANSPACEEND + PUBLIC TRAN_TPA + PUBLIC trgxname + PUBLIC UCOMBUF + PUBLIC USERDIR1 + PUBLIC vol_drv + PUBLIC vol_ioctl_buf ;AC030; + PUBLIC vol_serial ;AC030; + PUBLIC vol_label ;AC030; + PUBLIC WRITTEN + PUBLIC xa_cp_length ;AN030; + PUBLIC xa_cp_out ;AN030; + PUBLIC xa_list_attr ;AN030; + PUBLIC zflag + + IF IBM + PUBLIC ROM_CALL + PUBLIC ROM_CS + PUBLIC ROM_IP + ENDIF + + + ORG 0 +ZERO = $ +SRCXNAME DB DIRSTRLEN + 20 DUP (?) ;g buffer for name translate +TRGXNAME DB DIRSTRLEN + 20 DUP (?) ;g buffer for name translate +UCOMBUF DB COMBUFLEN+3 DUP(?) ; Raw console buffer +COMBUF DB COMBUFLEN+3 DUP(?) ; Cooked console buffer +USERDIR1 DB DIRSTRLEN+3 DUP(?) ; Storage for users current directory +EXECPATH DB COMBUFLEN+3 DUP(?) ; Path for external command +RE_INSTR DB DIRSTRLEN+3+13 DUP (?) ; path for input to redirection + +; Variables passed up from resident +HEADCALL LABEL DWORD + DW ? +RESSEG DW ? +TPA DW ? +SWITCHAR DB ? +DIRCHAR DB ? +EXEC_ADDR DD ? +RCH_ADDR DD ? +fTest DW ? +TRAN_TPA DW ? + +CHKDRV DB ? +RDEOF LABEL BYTE ; Misc flags +IFNOTFLAG LABEL BYTE +FILTYP DB ? +CURDRV DB ? +concat_xa db 0 ;AN000; flag for XA on file concatenations +CONCAT LABEL BYTE +PARM1 DB ? +ARGC LABEL BYTE +PARM2 DB ? +COMSW DW ? ; Switches between command and 1st arg +ARG1S DW ? ; Switches between 1st and 2nd arg +DESTSWITCH LABEL WORD +ARG2S DW ? ; Switches after 2nd arg +ALLSWITCH LABEL WORD +ARGTS DW ? ; ALL switches except for COMSW +CFLAG DB ? +DESTCLOSED LABEL BYTE +SPECDRV DB ? +BYTCNT DW ? ; Size of buffer between RES and TRANS +NXTADD DW ? +FRSTSRCH DB ? +LINCNT DB ? +LINLEN DB ? +FILECNT DW ? +CHARBUF DB 80 DUP (?) ;line byte character buffer for xenix write +DESTFCB2 LABEL BYTE +IDLEN DB ? +ID DB 8 DUP(?) +COM DB 3 DUP(?) +DEST DB 37 DUP(?) +DESTNAME DB 11 DUP(?) +DESTFCB LABEL BYTE +DESTDIR DB DIRSTRLEN DUP(?) ; Directory for PATH searches +GOTOLEN LABEL WORD +BWDBUF LABEL BYTE +EXEFCB LABEL WORD +DIRBUF DB DIRSTRLEN+3 DUP(?) +SDIRBUF DB 12 DUP(?) +BITS DW ? +PATHCNT DW ? +PATHPOS DW ? +PATHSW DW ? +FULLSCR DW ? +comma db 0 ;g flag set if +,, occurs +plus_comma db 0 ;g flag set if +,, occurs +dirflag db 0 ;AN015; set when pathcrunch called from DIR +parse_last dw 0 ;AN018; used to hold parsing position + +system_cpage DW 0 ;AC001; used for CHCP variable +src_XA_size DW 0 ;AN000; size of extended attributes +src_XA_seg DW 0 ;AN000; segment of extended attributes + +ext_open_parms label byte ;AN000; extended open parameter list +;emg340 ext_open_off dw offset trangroup:srcbuf ;AN000; offset of file name +ext_open_off dw ? ;AN030; offset of extended attributes +ext_open_seg dw ? ;AN000; segment of extended attributes + dw 0 ;AN000; no additional parameters + +XA_cp_out label byte ;AN030; list for one extended attribute + DW 1 ;AN030; count of entries + DB EAISBINARY ;AN030; ea_type + DW EASYSTEM ;AN030; ea_flags + DB ? ;AN030; ea_rc + DB 2 ;AN030; ea_namelen + DW 2 ;AN030; ea_valuelen + DB "CP" ;AN030; ea_name +xa_list_attr DW 0 ;AC030; code page +xa_cp_length DW $-XA_cp_out ;AN030; length of buffer + + + +arg_buf db 128 dup (?) +file_size_low dw ? ;AC000; +file_size_high dw ? ;AC000; +string_ptr_2 dw ? +;AD061;string_ptr_2_sb dw ? +copy_Num dw ? +cpyflag db ? +Dir_Num DW ? +bytes_free dw ? + dw ? +major_ver_num dw ? +minor_ver_num dw ? +one_char_val db ?,0 +vol_drv db ? + +IF IBM +ROM_CALL DB ? ; flag for rom function +ROM_IP DW ? +ROM_CS DW ? +ENDIF + +DESTVARS LABEL BYTE +DESTISDIR DB ? +DESTSIZ DB ? +DESTTAIL DW ? +DESTINFO DB ? +DESTBUF DB DIRSTRLEN + 20 DUP (?) + +DESTHAND DW ? +DESTISDEV DB ? +FIRSTDEST DB ? +MELCOPY DB ? +MELSTART DW ? + +SRCVARS LABEL BYTE +SRCISDIR DB ? +SRCSIZ DB ? +SRCTAIL DW ? +SRCINFO DB ? +SRCBUF DB DIRSTRLEN + 20 DUP (?) + +SRCHAND DW ? +SRCISDEV DB ? + +SCANBUF DB DIRSTRLEN + 20 DUP (?) + +SRCPT DW ? +INEXACT DB ? +NOWRITE DB ? +BINARY DB ? +WRITTEN DW ? +TERMREAD DB ? +ASCII DB ? +PLUS DB ? +objcnt db ? ; Used in copy +CPDATE DW ? +CPTIME DW ? +BATHAND DW ? ; Batch handle +STARTEL DW ? +ELCNT DB ? +ELPOS DB ? +SKPDEL DB ? +SOURCE DB 11 DUP(?) + +ext_entered db 0 ;AN005; + +display_ioctl db 0 ;AN000; info level + db 0 ;AN000; reserved + dw crt_ioctl_ln ;AN000; length of data + dw ? ;AN000; control flags +display_mode db ? ;AN000; display mode, colors + db 0 ;AN000; reserved + dw ? ;AN023; colors + dw ? ;AN000; display width (PELS) + dw ? ;AN000; display length (PELS) +display_width dw ? ;AN000; display width +linperpag dw linesperpage ;AN000; display length (default to linesperpage) + +vol_ioctl_buf label byte ;AN000; buffer for ioctl volume label/serial call + dw 0 ;AN000; info level +vol_serial dd 0 ;AN000; volume serial number +vol_label db 11 dup (" ") ;AN000; volume label - init to blanks + db 8 dup (" ") ;AN000; file system type + +expand_star db ? +comspec_flag db ? +msg_flag db ? ;AN022; flag set if non-utility message issued +msg_numb dw 0 ;AN022; set with extended error message issued +append_exec db 0 ;AN041; set if internal append executed +print_err_flag dw 0 ;AN000; flag set if error during sysdispmsg +subst_buffer db parm_block_size*2 dup (0);AN061; + +;;;; IF KANJI 3/3/KK +KPARSE DB ? +;;;; ENDIF 3/3/KK + +; Data declarations taken out of parse.asm + +arg arg_unit <> ; pointers, arg count, string buffer +argbufptr DW ? ; index for argv[].argpointer +tpbuf DB 128 DUP (?) ; temporary buffer +LAST_ARG DW ? ; point at which to accumulate switch info +comptr dw ? ; ptr into combuf + +; Data declarations taken out of path.asm +fbuf find_buf <> ; dma buffer for findfirst/findnext +pathinfo DW 3 DUP (?) ; ES, SI(old), and SI(new) of user path +psep_char DB ? ; '/' or '\' +search_best DB (?) ; best code, best filename so far +fname_max_len equ 13 +search_best_buf DB fname_max_len DUP (?) +search_curdir_buf DB 64 DUP (?) ; a place for CurDir info, if successful +search_error DW (?) ; address of error message to be printed + +; Data declarations taken out of tbatch.asm +if_not_count DW ? + +zflag db ? ; Used by typefil to indicate ^Z's + + DW 80H DUP(0) ; Init to 0 to make sure the linker is not fooled +STACK LABEL WORD + +INTERNATVARS internat_block <> + DB (internat_block_max - ($ - INTERNATVARS)) DUP (?) + +BatBufPos DW ? ; integer position in buffer of next byte +BatBuf DB BatLen DUP (?) +BatBufEnd DW ? + +; ***************************************************** +; EMG 4.00 +; DATA STARTING HERE WAS ADDED BY EMG FOR 4.00 +; FOR IMPLEMENTATION OF COMMON PARSE ROUTINE +; ***************************************************** +; +; COMMON PARSE OUTPUT BLOCKS +; + + +; +; Common output blocks for PARSE number, complex, or string values. +; + +PARSE1_OUTPUT LABEL BYTE ;AN000; +PARSE1_TYPE DB 0 ;AN000; type +PARSE1_CODE DB 0 ;AN000; return value +PARSE1_SYN DW 0 ;AN000; es offset of synonym +PARSE1_ADDR DD 0 ;AN000; numeric value / address + ; of string value + +; +; Common output block for PARSE date strings. +; + +DATE_OUTPUT LABEL BYTE ;AN000; +DATE_TYPE DB 0 ;AN000; type + DB 0 ;AN000; return value + DW 0 ;AN000; es offset of synonym +DATE_YEAR DW 0 ;AN000; year +DATE_MONTH DB 0 ;AN000; month +DATE_DAY DB 0 ;AN000; day + +; +; Common output block for PARSE time strings. +; + +TIME_OUTPUT LABEL BYTE ;AN000; +TIME_TYPE DB 0 ;AN000; type + DB 0 ;AN000; return value + DW 0 ;AN000; es offset of synonym +TIME_HOUR DB 0 ;AN000; hour +TIME_MINUTES DB 0 ;AN000; minutes +TIME_SECONDS DB 0 ;AN000; seconds +TIME_FRACTION DB 0 ;AN000; hundredths + +; +; Common output block for PARSE drive specifier (one based drive number). +; + +DRIVE_OUTPUT LABEL BYTE ;AN000; +DRIVE_TYPE DB 0 ;AN000; type +DRIVE_VALUE DB 0 ;AN000; return value + DW 0 ;AN000; es offset of synonym +DRIVE_NUMBER DB 0 ;AN000; drive number + DB 0,0,0 ;AN000; reserved + +TRANSPACEEND LABEL BYTE + +TRANSPACE ENDS + END diff --git a/v4.0/src/CMD/COMMAND/TUCODE.ASM b/v4.0/src/CMD/COMMAND/TUCODE.ASM new file mode 100644 index 0000000..6531c44 --- /dev/null +++ b/v4.0/src/CMD/COMMAND/TUCODE.ASM @@ -0,0 +1,520 @@ + page 80,132 +; SCCSID = @(#)tucode.asm 4.2 85/05/31 +; SCCSID = @(#)tucode.asm 4.2 85/05/31 +Title COMMAND Language midifiable Code Transient + + +.xlist +.xcref + INCLUDE dossym.inc + INCLUDE comsw.asm + INCLUDE comseg.asm + INCLUDE comequ.asm +.list +.cref + + +DATARES SEGMENT PUBLIC BYTE ;AC000; + EXTRN ECHOFLAG:BYTE +DATARES ENDS + +TRANDATA SEGMENT PUBLIC BYTE ;AC000; + EXTRN BAD_ON_OFF_ptr:word + EXTRN ctrlcmes_ptr:word + EXTRN DEL_Y_N_PTR:WORD + EXTRN ECHOMES_ptr:word + EXTRN extend_buf_ptr:word ;AC000; + EXTRN offmes_ptr:word + EXTRN onmes_ptr:word + EXTRN PARSE_BREAK:BYTE ;AN000; + EXTRN promptdat_moday:word ;AC000; + EXTRN promptdat_ptr:word ;AC000; + EXTRN promptdat_yr:word ;AC000; + EXTRN string_buf_ptr:word + EXTRN SUREMES_ptr:word + EXTRN VERIMES_ptr:BYTE + EXTRN WeekTab:word +TRANDATA ENDS + +TRANSPACE SEGMENT PUBLIC BYTE ;AC000; + EXTRN arg_buf:byte + EXTRN BWDBUF:BYTE + EXTRN DEST:BYTE + EXTRN destdir:byte + EXTRN dirchar:byte + EXTRN PARSE1_CODE:BYTE ;AN000; + EXTRN RESSEG:WORD + EXTRN string_ptr_2:word + +TRANSPACE ENDS + +TRANCODE SEGMENT PUBLIC BYTE + + EXTRN CERROR:NEAR + EXTRN CRLF2:NEAR + EXTRN extend_setup:near ;AN022; + + PUBLIC CNTRLC + PUBLIC ECHO + PUBLIC GetDate + PUBLIC NOTEST2 + PUBLIC PRINT_DATE + PUBLIC SLASHP_ERASE ;AN000; + PUBLIC VERIFY + +ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:NOTHING + +; **************************************************************** +; * +; * ROUTINE: NOTEST2 - execution of DEL/ERASE command +; * +; * FUNCTION: Delete files based on user parsed input. Prompt +; * user for Y/N if necessary. If an error occurs, +; * set up an error message and go to CERROR. +; * +; * INPUT: FCB at 5ch set up with filename(s) entered +; * Current directory set to entered directory +; * +; * OUTPUT: none +; * +; **************************************************************** +; +; ARE YOU SURE prompt when deleting *.* + +NOTEST2: + MOV CX,11 + MOV SI,FCB+1 + +AMBSPEC: + LODSB + CMP AL,'?' + JNZ ALLFIL + LOOP AMBSPEC + +ALLFIL: + CMP CX,0 + JNZ NOPRMPT + +ASKAGN: + MOV DX,OFFSET TRANGROUP:SUREMES_ptr ; "Are you sure (Y/N)?" + invoke std_printf + MOV SI,80H + MOV DX,SI + MOV WORD PTR [SI],120 ; zero length + MOV AX,(STD_CON_INPUT_FLUSH SHL 8) OR STD_CON_STRING_INPUT + INT 21H + LODSW + OR AH,AH + JZ ASKAGN + INVOKE SCANOFF + call char_in_xlat ;G Convert to upper case + retc ;AN000; return if function not supported + CMP AL,CAPITAL_N ;G + retz + CMP AL,CAPITAL_Y ;G + PUSHF + CALL CRLF2 + POPF + JNZ ASKAGN + +NOPRMPT: + MOV AH,FCB_DELETE + MOV DX,FCB + INT 21H + INC AL + jz eraerr + invoke RESTUDIR + ret ; If no error, return + +eraerr: + invoke set_ext_error_msg ;AN022; set up the extended error + push dx ;AN022; save message + invoke RESTUDIR + pop dx ;AN022; restore message + + cmp word ptr extend_buf_ptr,error_no_more_files ;AN022; convert no more files to + jnz cerrorj2 ;AN022; file not found + mov Extend_Buf_ptr,error_file_not_found ;AN000; get message number in control block + +cerrorj2: + jmp cerror + + +; **************************************************************** +; * +; * ROUTINE: SLASHP_ERASE - execution of DEL/ERASE /P +; * +; * FUNCTION: Delete files based on user parsed input. Prompt +; * user for Y/N where necessary. If an error occurs +; * set up and error message and transfer control +; * to CERROR. +; * +; * INPUT: FCB at 5ch set up with filename(s) entered +; * Current directory set to entered directory +; * +; * OUTPUT: none +; * +; **************************************************************** + +ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:NOTHING + +SLASHP_ERASE: ;AN000; entry point + invoke build_dir_string ;AN000; set up current directory string for output + mov ah,Set_DMA ;AN000; issue set dta int 21h + mov dx,offset trangroup:destdir ;AN000; use Destdir for target + int 21H ;AN000; + mov ah,Dir_Search_First ;AN000; do dir search first int 21h + mov dx,FCB ;AN000; use FCB at 5Ch for target + int 21H ;AN000; + inc al ;AN000; did an error occur + jz eraerr ;AN022; go to error exit + +delete_prompt_loop: ;AN000; + mov si,offset trangroup:destdir+1 ;AN000; set up FCB as source + mov di,offset trangroup:dest ;AN000; set up dest as target + mov al,dirchar ;AN000; store a "\" in the first char + stosb ;AN000; of DEST + invoke fcb_to_ascz ;AN000; convert filename from FCB to ASCIIZ string + +slashp_askagn: ;AN000; + call crlf2 ;AN000; print out carriage return, line feed + mov dx,offset trangroup:bwdbuf ;AN000; print out current directory string + mov bx,dx ;AN000; get string pointer in bx + cmp byte ptr [bx+3],end_of_line_out ;AN000; see if only D:\,0 + jnz not_del_root ;AN000; no continue + mov byte ptr [bx+2],end_of_line_out ;AN000; yes, get rid of \ + +Not_del_root: ;AN000; + mov string_ptr_2,dx ;AN000; + mov dx,offset trangroup:string_buf_ptr ;AN000; + invoke std_printf ;AN000; + mov dx,offset trangroup:dest ;AN000; print out file name string + mov string_ptr_2,dx ;AN000; + mov dx,offset trangroup:string_buf_ptr ;AN000; + invoke std_printf ;AN000; + mov dx,offset trangroup:Del_Y_N_Ptr ;AN000; issue ", Delete (Y/N)?" message + invoke std_printf ;AN000; + mov si,80H ;AN000; set up buffer for input + mov dx,si ;AN000; + mov word ptr [si],combuflen ;AN000; + mov ax,(std_con_input_flush shl 8) or std_con_string_input ;AN000; + int int_command ;AN000; get input from the user + lodsw ;AN000; + or ah,ah ;AN000; was a character entered? + jz slashp_askagn ;AN000; no - ask again + invoke scanoff ;AN000; scan off leading delimiters + call char_in_xlat ;AN000; yes - upper case it + retc ;AN000; return if function not supported + cmp al,capital_n ;AN000; was it no? + jz next_del_file ;AN000; yes - don't delete file + cmp al,capital_y ;AN000; was it yes? + jz delete_this_file ;AN000; yes - delete the file + jmp short slashp_askagn ;AN000; it was neither - ask again + +delete_this_file: ;AN000; + mov ah,fcb_delete ;AN000; delete the file + mov dx,offset trangroup:destdir ;AN000; use Destdir for target + int int_command ;AN000; + inc al ;AN000; did an error occur? + jnz next_del_file ;AN000; no - get next file + jmp eraerr ;AN022; go to error exit - need long jmp + +next_del_file: ;AN000; + mov ah,dir_search_next ;AN000; search for another file + mov dx,FCB ;AN000; + int int_command ;AN000; + inc al ;AN000; was a file found? + jz slash_p_exit ;AN000; no - exit + jmp delete_prompt_loop ;AN000; yes - continue (need long jump) + +slash_p_exit: + invoke get_ext_error_number ;AN022; get the extended error number + cmp ax,error_no_more_files ;AN022; was error file not found? + jz good_erase_exit ;AN022; yes - clean exit + jmp extend_setup ;AN022; go issue error message + +good_erase_exit: + invoke restudir ;AN000; we're finished - restore user's dir + call crlf2 ;AN000; print out carriage return, line feed + ret ;AN000; exit + + +;************************************************ +; ECHO, BREAK, and VERIFY commands. Check for "ON" and "OFF" + + break Echo + +assume ds:trangroup,es:trangroup + +ECHO: + CALL ON_OFF + JC DOEMES + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + JNZ ECH_OFF + OR [ECHOFLAG],1 + RET +ECH_OFF: + AND [ECHOFLAG],NOT 1 + RET + + +CERRORJ: + JMP CERROR + +; +; There was no discrenable ON or OFF after the ECHO. If there is nothing but +; delimiters on the command line, we issue the ECHO is ON/OFF message. +; + +ASSUME DS:TRANGROUP + +DOEMES: + cmp cl,0 ;AC000; was anything on the line? + jz PEcho ; just display current state. + MOV DX,82H ; Skip one char after "ECHO" + invoke CRPRINT + JMP CRLF2 + +PECHO: + MOV DS,[RESSEG] +ASSUME DS:RESGROUP + MOV BL,[ECHOFLAG] + PUSH CS + POP DS +ASSUME DS:TRANGROUP + AND BL,1 + MOV DX,OFFSET TRANGROUP:ECHOMES_ptr + JMP SHORT PYN + + break Break +assume ds:trangroup,es:trangroup + +CNTRLC: + CALL ON_OFF + MOV AX,(SET_CTRL_C_TRAPPING SHL 8) OR 1 + JC PCNTRLC + JNZ CNTRLC_OFF + MOV DL,1 + INT 21H ; Set ^C + RET + +CNTRLC_OFF: + XOR DL,DL + INT 21H ; Turn off ^C check + RET + +PCNTRLC: + CMP CL,0 ;AC000; rest of line blank? + JNZ CERRORJ ; no, oops! + +pccont: + XOR AL,AL + INT 21H + MOV BL,DL + MOV DX,OFFSET TRANGROUP:CTRLCMES_ptr + +PYN: + mov si,offset trangroup:onmes_ptr ;AC000; get ON pointer + OR BL,BL + JNZ PRINTVAL + mov si,offset trangroup:offmes_ptr ;AC000; get OFF pointer + +PRINTVAL: + push dx ;AN000; save offset of message block + mov bx,dx ;AN000; save offset value + lodsw ;AN000; get message number of on or off + mov dh,util_msg_class ;AN000; this is a utility message + invoke Tsysgetmsg ;AN000; get the address of the message + add bx,ptr_off_pos ;AN000; point to offset of ON/OFF + mov word ptr [bx],si ;AN000; put the offset in the message block + pop dx ;AN000; get message back + invoke std_printf ;AC000; go print message + mov word ptr [bx],0 ;AN000; zero out message pointer + + ret ;AN000; exit + + break Verify +assume ds:trangroup,es:trangroup + +VERIFY: + CALL ON_OFF + MOV AX,(SET_VERIFY_ON_WRITE SHL 8) OR 1 + JC PVERIFY + JNZ VER_OFF + INT 21H ; Set verify + RET + +VER_OFF: + DEC AL + INT 21H ; Turn off verify after write + RET + +PVERIFY: + CMP CL,0 ;AC000; is rest of line blank? + JNZ CERRORJ ; nope... + MOV AH,GET_VERIFY_ON_WRITE + INT 21H + MOV BL,AL + MOV DX,OFFSET TRANGROUP:VERIMES_ptr + JMP PYN + +; **************************************************************** +; * +; * ROUTINE: ON_OFF +; * +; * FUNCTION: Parse the command line for an optional ON or +; * OFF string for the BREAK, VERIFY, and ECHO +; * routines. +; * +; * INPUT: command line at offset 81H +; * PARSE_BREAK control block +; * +; * OUTPUT: If carry is clear +; * If ON is found +; * Zero flag set +; * If OFF is found +; * Zero flag clear +; * If carry set +; * If nothing on command line +; * CL set to zero +; * If error +; * CL contains error value from parse +; * +; **************************************************************** + +assume ds:trangroup,es:trangroup + +ON_OFF: + MOV SI,81h + +scan_on_off: ;AN032; scan off leading blanks & equal + lodsb ;AN032; get a char + cmp al,blank ;AN032; if whitespace + jz scan_on_off ;AN032; keep scanning + cmp al,tab_chr ;AN032; if tab + jz scan_on_off ;AN032; keep scanning + cmp al,equal_chr ;AN032; if equal char + jz parse_on_off ;AN032; start parsing + dec si ;AN032; if none of above - back up + +parse_on_off: ;AN032; and start parsing + mov di,offset trangroup:parse_break ;AN000; Get adderss of PARSE_BREAK + xor cx,cx ;AN000; clear cx,dx + xor dx,dx ;AN000; + invoke cmd_parse ;AC000; call parser + cmp ax,end_of_line ;AC000; are we at end of line? + jz BADONF ;AC000; yes, return error + cmp ax,result_no_error ;AN000; did an error occur + jz on_off_there ;AN000; no - continue + mov cx,ax ;AN000; yes - set cl to error code + jmp short BADONF ;AN000; return error + +on_off_there: + cmp parse1_code,-1 ;AN014; was a valid positional present? + jnz good_on_off ;AN014; yes - continue + mov cx,badparm_ptr ;AN014; something other than ON/OFF + jmp short BADONF ;AN014; return error + +good_on_off: ;AN014; + xor ax,ax ;AC000; set up return code for + or al,parse1_code ;AC000; ON or OFF in AX + pushf ;AN000; save flags + mov di,offset trangroup:parse_break ;AN000; Get adderss of PARSE_BREAK + xor dx,dx ;AN000; + invoke cmd_parse ;AN000; call parser + cmp ax,end_of_line ;AN000; are we at end of line? + jnz BADONF_flags ;AN000; NO, return error + popf ;AN000; restore flags + clc ;AC000; no error + jmp short on_off_end ;AN000; return to caller + +BADONF_flags: + mov cx,ax + popf + +; +; No discernable ON or OFF has been found. Put an error message pointer in DX +; and return the error +; +BADONF: + MOV DX,OFFSET TRANGROUP:BAD_ON_OFF_ptr + STC + +ON_OFF_END: + + RET + + + +;************************************************************************* +; print date + +PRINT_DATE: + PUSH ES + PUSH DI + PUSH CS + POP ES + CALL GetDate ; get date + xchg dh,dl ;AN000; switch month & day + mov promptDat_yr,cx ;AC000; put year into message control block + mov promptDat_moday,dx ;AC000; put month and day into message control block + mov dx,offset trangroup:promptDat_ptr ;AC000; set up message for output + invoke std_printf +;AD061; mov promptDat_yr,0 ;AC000; reset year, month and day +;AD061; mov promptDat_moday,0 ;AC000; pointers in control block + POP DI ;AC000; restore di,es + POP ES ;AC000; + return +; +; Do GET DATE system call and set up 3 character day of week in ARG_BUF +; for output. Date will be returned in CX,DX. +; + +GetDate: + mov di,offset trangroup:arg_buf ;AC000; target for day of week + MOV AH,GET_DATE ;AC000; get current date + INT int_command ;AC000; Get date in CX:DX + CBW ;AC000; + + push cx ;AN000; save date returned in + push dx ;AN000; CX:DX + MOV SI,AX + SHL SI,1 + ADD SI,AX ; SI=AX*3 + mov cx,si ;AN000; save si + mov ax,weektab ;AN000; get message number of weektab + mov dh,util_msg_class ;AN000; this is a utility message + push di ;AN000; save argument buffer + invoke Tsysgetmsg ;AN000; get the address of the message + pop di ;AN000; retrieve argument buffer + add si,cx ;AC000; get day of week + MOV CX,3 + REP MOVSB + mov al,end_of_line_out ;AC000; terminate the string + stosb + pop dx ;AN000; get back date + pop cx ;AN000; + + return +;g +;g This routine determines whether the character in AL is a +;g Yes or No character. On return, if AL=0, the character is +;g No, if AL=1, the character is Yes. +;g + +assume ds:trangroup + +char_in_xlat proc near + + mov dl,al ;AC000; get character into DX + xor dh,dh ;AC000; + mov ax,(getextcntry SHL 8) + 35 ;AC000; Yes/No char call + int int_command ;AC000; + + ret + +char_in_xlat endp + +TRANCODE ENDS + END diff --git a/v4.0/src/CMD/COMMAND/UINIT.ASM b/v4.0/src/CMD/COMMAND/UINIT.ASM new file mode 100644 index 0000000..8f3498b --- /dev/null +++ b/v4.0/src/CMD/COMMAND/UINIT.ASM @@ -0,0 +1,270 @@ + page 80,132 +; SCCSID = @(#)uinit.asm 4.5 85/12/04 +; SCCSID = @(#)uinit.asm 4.5 85/12/04 +TITLE COMMAND Initialization messages + +.XCREF +.XLIST +include comsw.asm +include comseg.asm +include ifequ.asm +.LIST +.CREF + +addr macro sym,name + public name + ifidn ,<> + + dw offset resgroup:sym + else + +name dw offset resgroup:sym + endif + endm + + +ENVIRONMENT SEGMENT PUBLIC PARA ;AC000; + EXTRN ECOMSPEC:BYTE +ENVIRONMENT ENDS + +TRANCODE SEGMENT PUBLIC BYTE ;AC000; + extrn Printf_init:FAR + extrn Triage_Init:FAR + extrn append_parse:FAR ;AN054; +TranCode ENDS + +INIT SEGMENT PUBLIC PARA ;AC000; + + + public icondev + public BADCSPFL + public COMSPECT + public AUTOBAT + public fslash + public bslash + public space + public PRDATTM + public INITADD + public print_add + public CHUCKENV + public scswitch + public ucasea + public ECOMLOC + public equalsign + public lcasea + public lcasez + public comspstring + public EnvSiz + public EnvMax + public initend + public trnsize + public resetenv ;AC000; + public ext_msg ;AC000; + public num_positionals + public internat_info + public parsemes_ptr + + PUBLIC triage_add + PUBLIC oldenv + PUBLIC usedenv + PUBLIC KAUTOBAT ;AN000; 3/3/KK + public eswitch ;AN018; + public dswitch ;AN018; + public init_parse ;AN054; + public old_parse_ptr ;AN057; + PUBLIC pars_msg_off ;AN060; + PUBLIC pars_msg_seg ;AN060; + +include resmsg.equ ;AC000; + + +ICONDEV LABEL BYTE + DB "/DEV/" + DB "CON",0,0,0,0,0,0 ; Room for 8 char device +BADCSPFL DB 0 +COMSPECT DB "/COMMAND.COM",0,0 +AUTOBAT DB 0,":\AUTOEXEC.BAT",0,0DH ;AC027; +KAUTOBAT DB 0,":\KAUTOEXE.BAT",0,0DH ;AC027; 3/3/KK + +PRDATTM DB -1 ;Init not to prompt for date time +INITADD DD ? +print_add LABEL DWORD + DW OFFSET TranGroup:Printf_INIT + DW 0 +triage_add LABEL DWORD + DW OFFSET TranGroup:Triage_Init + DW 0 +CHUCKENV DB 0 +;eg ECOMLOC DW OFFSET ENVIRONMENT:ECOMSPEC-10H +ECOMLOC DW OFFSET ENVIRONMENT:ECOMSPEC ;eg + +COMSPSTRING DB "COMSPEC=" +equalsign db "=" +lcasea db "a" +lcasez db "z" +fslash db "/" +bslash db "\" +space db " " +scswitch db "C" ; Single command +ucasea db "A" + +EnvSiz DW 0 ; size user wants to allocate +EnvMax DW 0 ; maximum size allowed. +oldenv DW 0 ; envirseg at initialization +usedenv DW 0 ; amount of envirseg used +PARS_MSG_OFF DW 0 ;AN060; SAVED PARSE ERROR MESSAGE OFFSET +PARS_MSG_SEG DW 0 ;AN060; SAVED PARSE ERROR MESSAGE SEGMENT + +;Do not separate the following two words. Used to call transient PARSE routine + +init_parse label dword ;AN054; +init_p DW TRANGROUP:APPEND_PARSE ;AN054; +initend DW 0 ;eg segment address of end of init + +;End of data that shouldn't be separated. + +trnsize DW 0 ;eg size of transient in paragraphs +resetenv DB 0 ;eg set if we need to setblck env at endinit +ext_msg DB 0 ;AN000; set if /MSG switch entered +eswitch db 0 ;AN018; set if /e was entered +dswitch db 0 ;AN018; set if /d was entered +parsemes_ptr dw 0 ;AN000; word to store parse error number + +; +; PARSE BLOCK FOR COMMAND +; +PUBLIC PARSE_COMMAND ;AN000; +PUBLIC COMND1_OUTPUT ;AN000; +PUBLIC COMND1_TYPE ;AN000; +PUBLIC COMND1_CODE ;AN000; +PUBLIC COMND1_SYN ;AN000; +PUBLIC COMND1_ADDR ;AN000; +PUBLIC COMMAND_F_SYN ;AN000; +PUBLIC COMMAND_P_SYN ;AN000; +PUBLIC COMMAND_C_SYN ;AN000; +PUBLIC COMMAND_D_SYN ;AN000; +PUBLIC COMMAND_E_SYN ;AN000; +PUBLIC COMMAND_M_SYN ;AN000; + +; +; The following parse control block is used for COMMAND. This block is +; used for parsing during initialization. The sytax for COMMAND is: +; COMMAND [d:][path][/P][/F][/D][/E:xxxxx][/MSG][/C executable] +; Anything on the command line after the /C switch will be passed to the +; executable command, so if /C is used, it must be specified last. The +; /MSG switch can only be specified if the /P switch is specified. +; + +ENVBIG EQU 32768 ;AN000; maximum environment size +ENVSML EQU 160 ;AN000; minimum environment size + +INTERNAT_INFO LABEL BYTE ;AN000; used for country info after parsing is completed +PARSE_COMMAND LABEL BYTE ;AN000; + DW RESGROUP:COMMAND_PARMS ;AN000; + DB 0 ;AN000; no extra delimiter + +COMMAND_PARMS LABEL BYTE ;AN000; + DB 0,1 ;AN000; 1 positional parm + DW RESGROUP:COMMAND_FILE ;AN000; + DB 6 ;AN000; 6 switches + DW RESGROUP:COMMAND_SWITCH1 ;AN000; + DW RESGROUP:COMMAND_SWITCH2 ;AN000; + DW RESGROUP:COMMAND_SWITCH3 ;AN000; + DW RESGROUP:COMMAND_SWITCH4 ;AN000; + DW RESGROUP:COMMAND_SWITCH5 ;AN000; + DW RESGROUP:COMMAND_SWITCH6 ;AN000; + DB 0 ;AN000; no keywords + +COMMAND_FILE LABEL BYTE ;AN000; + DW 0201H ;AN000; filespec - optional + DW 1 ;AN000; capitalize - file table + DW RESGROUP:COMND1_OUTPUT ;AN000; result buffer + DW RESGROUP:NO_VAL ;AN000; + DB 0 ;AN000; no keywords + +COMMAND_SWITCH1 LABEL BYTE ;AN000; + DW 0 ;AN000; no match flags + DW 2 ;AN000; capitalize by char table + DW RESGROUP:COMND1_OUTPUT ;AN000; result buffer + DW RESGROUP:NO_VAL ;AN000; + DB 1 ;AN000; 1 keyword +COMMAND_P_SYN DB "/P",0 ;AN000; /P switch + +COMMAND_SWITCH2 LABEL BYTE ;AN000; + DW 0 ;AN000; no match flags + DW 2 ;AN000; capitalize by char table + DW RESGROUP:COMND1_OUTPUT ;AN000; result buffer + DW RESGROUP:NO_VAL ;AN000; + DB 1 ;AN000; 1 keyword +COMMAND_F_SYN DB "/F",0 ;AN000; /F switch + +COMMAND_SWITCH3 LABEL BYTE ;AN000; + DW 0 ;AN000; no match flags + DW 2 ;AN000; capitalize by char table + DW RESGROUP:COMND1_OUTPUT ;AN000; result buffer + DW RESGROUP:NO_VAL ;AN000; + DB 1 ;AN000; 1 keyword +COMMAND_D_SYN DB "/D",0 ;AN000; /D switch + +COMMAND_SWITCH4 LABEL BYTE ;AN000; + DW 8000H ;AN000; numeric value - required + DW 0 ;AN000; no function flags + DW RESGROUP:COMND1_OUTPUT ;AN000; result buffer + DW RESGROUP:COMMAND_E_VAL ;AN000; pointer to value list + DB 1 ;AN000; 1 keyword +COMMAND_E_SYN DB "/E",0 ;AN000; /E switch + +COMMAND_E_VAL LABEL BYTE ;AN000; + DB 1 ;AN000; + DB 1 ;AN000; 1 range + DB 1 ;AN000; returned if result + DD ENVSML,ENVBIG ;AN000; minimum & maximum value + DB 0 ;AN000; no numeric values + DB 0 ;AN000; no string values + +COMMAND_SWITCH5 LABEL BYTE ;AN000; + DW 0 ;AN000; no match flags + DW 2 ;AN000; capitalize by char table + DW RESGROUP:COMND1_OUTPUT ;AN000; result buffer + DW RESGROUP:NO_VAL ;AN000; + DB 1 ;AN000; 1 keyword +COMMAND_C_SYN DB "/C",0 ;AN000; /C switch + +COMMAND_SWITCH6 LABEL BYTE ;AN000; + DW 0 ;AN000; no match flags + DW 2 ;AN000; capitalize by char table + DW RESGROUP:COMND1_OUTPUT ;AN000; result buffer + DW RESGROUP:NO_VAL ;AN000; + DB 1 ;AN000; 1 keyword +COMMAND_M_SYN DB "/MSG",0 ;AN000; /MSG switch + +COMND1_OUTPUT LABEL BYTE ;AN000; +COMND1_TYPE DB 0 ;AN000; type +COMND1_CODE DB 0 ;AN000; return value +COMND1_SYN DW 0 ;AN000; synonym pointer +COMND1_ADDR DD 0 ;AN000; numeric value / address + ; of string value + +NO_VAL DB 0 ;AN000; no values +num_positionals DW 0 ;AN000; counter for positionals +old_parse_ptr DW 0 ;AN057; SI position before calling parser + +.xlist +.xcref + +INCLUDE SYSMSG.INC ;AN000; get message services routine + +.list +.cref + +ASSUME DS:RESGROUP,ES:RESGROUP,CS:RESGROUP + +MSG_UTILNAME ;AN000; define utility name + +MSG_SERVICES ;AN000; include initialization messages + +include msgdcl.inc + +INIT ENDS + + END -- cgit v1.2.3