;**************************************************************************
;*
;* CDD.ASM
;*
;* DESCRIPTION:
;*   This program performs the same function as MS-DOS' CD command,
;*   however it changes the drive as well as the directory.
;*
;*   usage: CDD [Drive:][Directory]
;*
;*   If neither Drive nor Directory are specified then CDD displays the
;*   current working directory.
;*
;* REVISION HISTORY:
;*
;* 18-Jun-1993  Scott A.Mintz
;*              Original
;*
;* Assembly/Linking instructions (Turbo Assembler):
;*     tasm /q /m2 cdd
;*     tlink /t cdd
;* (Generates CDD.COM)
;*
;**************************************************************************

                .MODEL  tiny

                .CODE
                org     100h

main            label   near
                mov     di,offset sPath         ; point to my buffer
                mov     si,80h                  ; point to the command line
                lodsb                           ; get byte count
                sub     ah,ah                   ;
                or      al,al                   ; is it empty
                jnz     skip_whitespace         ; z means 
                jmp     ShowCwd                 ;   just show where we are

skip_whitespace label   near
                lodsb                           ; get a byte
                cmp     al,0dh                  ; is it a CR?
                je      ShowCwd                 ;
                cmp     al,' '                  ; is it a space?
                je      skip_whitespace         ; eat it if yes
                cmp     al,09h                  ; is it a tab char?
                je      skip_whitespace         ; eat it if yes

store_path      label   near
                stosb                           ; save a char in my buffer
                cmp     al,' '                  ; is it a space 
                jle     done                    ;   or control char?
                cmp     al,'?'                  ; asking for help?
                jne     @1
                jmp     ShowUsage               ;
@1:             lodsb                           ; get a char
                jmp     store_path              ; do some more

done            label   near
                dec     di
                sub     al,al                   ; null terminate the string
                stosb
                mov     al,'$'                  ; DOS PrintString terminator
                stosb
                mov     si,offset sPath         ; point to copied path

                mov     ah,19h                  ; DOS GetDrive Command
                int     21h                     ; save it just in case
                mov     bl,al                   ;  we need to restore it

                cmp     byte ptr [si+1],':'     ; was a drive specified?
                jne     nodrive                 ;

                mov     dl,[si]                 ; get the drive letter
                or      dl,20h                  ; map to lower case
                sub     dl,'a'                  ; A=0, B=1, etc.
                mov     ah,0eh                  ; DOS SetDrive Command
                int     21h                     ;

                ; since SetDrive never fails the only way of
                ; knowing if we have a valid drive is to get
                ; the "new" drive and see if it is the one
                ; we set.

                mov     ah,19h                  ; DOS GetDrive Command
                int     21h                     ;
                cmp     al,dl                   ; same drive?
                je      chkpath                 ; yes setdrive worked

                add     dl,'a'                  ; map drive letter to ASCII
                mov     cDrive,dl               ; update the error message
                mov     dl,bl                   ; restore original drive
                mov     ah,0eh                  ; DOS SetDrive Command
                int     21h                     ; call DOS
                mov     dx,offset sBadDrive     ; show the error
                jmp     DisplayMsg

chkpath         label   near
                cmp     byte ptr [si+2],0       ; path spec'd?
                je      exit                    ; no, just change drive

nodrive         label   near
                mov     dx,si                   ; point to the path
                mov     ah,03bh                 ; DOS ChDir Command
                int     21h
                jnc     exit

                mov     dl,bl                   ; restore original drive
                mov     ah,0eh                  ; DOS SetDrive Command
                int     21h                     ;
                mov     dx,offset sBadDir1      ; show the error
                mov     ah,09h                  ; DOS PrintString Command
                int     21h
                mov     dx,si                   ; display the bad path
                mov     ah,09h                  ; DOS PrintString Command
                int     21h
                mov     dx,offset sBadDir2      ; finish up
                jmp     DisplayMsg

ShowCwd         label   near
                mov     di,offset sPath         ; point to my buffer
                mov     ah,19h                  ; DOS GetDrive Command
                int     21h                     ; A=0, B=1, etc.
                add     al,'A'                  ; map to ASCII
                stosb                           ; store the drive
                mov     al,':'                  ;
                stosb                           ; store the colon
                mov     al,'\'                  ;
                stosb                           ; store the root directory
                mov     si,di                   ; current location in buffer
                sub     dl,dl                   ; default drive
                mov     ah,47h                  ; DOS GetCWD Command
                int     21h

                mov     si,di                   ; reset the buffer pointer
find_end        label   near
                lodsb                           ; get a char
                or      al,al                   ; end of buffer?
                jne     find_end                ;

                dec     si                      ;
                mov     ax,0a0dh                ; CR-LF
                mov     di,si                   ; point to the end
                stosw                           ; store a CR-LF
                mov     al,'$'                  ;
                stosb                           ; store end of string char
                mov     dx,offset sPath         ; point to string
                jmp     DisplayMsg


exit            label   near
                mov     ax,4c00h                ; DOS Exit Pgm Command
                int     21h
                jmp     ShowCwd

ShowUsage       label   near
                mov     dx,offset sUsage        ; usage string
DisplayMsg      label   near
                mov     ah,09h                  ; DOS PrintString Command
                int     21h
                jmp     exit

                .DATA
sUsage          db      "CDD: Change Drive and Directory",13,10,10
                db      "FORMAT: CDD [Drive:][Directory]",13,10,10,"$"

sBadDir1        db      'Invalid path "$'
sBadDir2        db      8,'"',13,10,'$'
sBadDrive       db      'Invalid drive "'
cDrive          db      'a:"',13,10,'$'

sPath           db      128 dup (?)             ; current working directory

                end     main
