        page ,132
TITLE   PART5 COMMAND Transient routines.
;
;                        IBM Confidential
;                        Copyright (C) IBM Corporation 1991-1993
;                        All Rights Reserved.
;

.xlist
.xcref
        include comsw.asm
        include dossym.inc
        include syscall.inc
        include pdb.inc
        include mult.inc
        include comseg.asm
        include comequ.asm
.list
.cref

DATARES         SEGMENT PUBLIC BYTE     ;AC000;
; VCB - Delete unused variables
;       EXTRN   crit_msg_off:word       ;AC000;
;       EXTRN   crit_msg_seg:word       ;AC000;
        EXTRN   IO_SAVE:WORD
        EXTRN   OldTerm:DWORD
        EXTRN   PARENT:WORD
        EXTRN   PERMCOM:BYTE            ;AN045;
        EXTRN   RetCode:WORD
        EXTRN   SingleCom:word

        extrn   TrnLodCom1_Trap:far

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;

        extrn   NoCntry_Ptr:word        ;M045

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
        extrn   TCommand: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     short 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     21h                     ; Open new device
        JC      ISBADDEV
        MOV     BX,AX
        MOV     AX,IOCTL SHL 8
        INT     21h
        TEST    DL,80H
        JNZ     DEVISOK

CLOSEDEV:                                       ;AN007;
        MOV     AH,CLOSE                        ; Close initial handle
        INT     21h

ISBADDEV:
        MOV     DX,OFFSET TRANGROUP:BADDEV_ptr
        invoke  std_printf
        JMP     SHORT 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     21h                     ;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     21h
        PUSH    BX                              ; Save handle
        MOV     CX,3
        XOR     BX,BX

ICLLOOP:                                        ; Close basic handles
        MOV     AH,CLOSE
        INT     21h
        INC     BX
        LOOP    ICLLOOP
        POP     BX                              ; Get handle
        MOV     AH,XDUP
        INT     21h                     ; Dup it to 0
        MOV     AH,XDUP
        INT     21h                     ; Dup to 1
        MOV     AH,XDUP
        INT     21h                     ; Dup to 2
        MOV     AH,CLOSE                        ; Close initial handle
        INT     21h

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 DATARES:TrnLodCom1_Trap
        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?

        jz      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     21h
        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     21h                     ;  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     dx,offset TRANGROUP:NoCntry_Ptr ;M045

        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     21h
        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     21h
        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     21h                     ;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?
        jz      free_com                        ;AN045; no - free everything

;       We're a permanent command.
;       Unless this is a singlecom (int 2Eh), don't deallocate transient.

        cmp     [singlecom],-1          ;M034
        je      no_reset                ;M034   ;exit singlecom

        jmp     TCommand                        ;permanent command, recycle

free_com:
; VCB - Delete this since crit_msg was never set and setting is unsupported anyway
;       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;
;
;M040
; Restore user directory if the restore flag is set. RestUDir1 checks for
;this, restores user dir if flag is set and resets the flag.
;
        invoke  RestUDir1               ;restore user dir if needed ;M040
        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     21h                     ; Now running in "free" space
        POP     ES

        MOV     AH,Exit
        MOV     AL,BYTE PTR RetCode
        INT     21h


; ****************************************************************
; *
; * 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
