home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / cpm / dirutl / cu.lbr / CU.AQM / CU.ASM
Encoding:
Assembly Source File  |  1985-04-10  |  12.6 KB  |  566 lines

  1. ;CU.ASM - A PROGRAM TO MOVE FILES FROM ONE USER NUMBER TO ANOTHER
  2. ;
  3. ;From an idea by Aubrey Hutchinson of Pompano Beach, Florida
  4. ;published in Dr. Dobbs Journal, March 1983.
  5. ;See: Dr. Dobbs Clinic, page 82.
  6. ;
  7. ;Written by:    Robert Wilcox
  8. ;        920 N. Washington
  9. ;        Owosso, MI  48867
  10. ;Date written:    2 Mar 83
  11. ;Rewritten   : 25 Mar 85 to show filenames as they are changed
  12. ;              and allow for operator to be asked before each
  13. ;              file operation.  This revision was patterned
  14. ;              after ERAQ, from which much of the code was
  15. ;              borrowed.
  16. ;
  17. ;OPERATION:       CU [dr:]FILENAME.TYPE s,d [/N]
  18. ;
  19. ;Where dr: is the drive designator (optional),
  20. ;        s is the source user number, and
  21. ;        d is the destination user number.
  22. ;        N means don't ask before changing each file.
  23. ;
  24. ;Filename.typ may be ambiguous, same as with the ERA command.
  25. ;
  26. ;EXAMPLE:
  27. ;
  28. ;                 CU *.ASM 0,3 /N
  29. ;
  30. ;This would transfer all files of type ASM from user 0 to user 3
  31. ;without asking before each transfer.
  32. ;
  33. ;CAUTION: If a file already exists in the destination user area,
  34. ;it is possible with this program to create another one with
  35. ;the same name.  Using the ERA command will then erase BOTH
  36. ;of them.
  37. ;
  38. ;NOTE: R/O files will be R/W after the transfer.
  39. ;
  40.     ORG    00100H
  41. BOOT    EQU    00000H
  42. BDOS    EQU    00005H
  43. FCB1    EQU    0005CH
  44. FCB2    EQU    0006CH
  45. ;
  46. ;CP/M FUNCTIONS
  47. CONIN    EQU    1        ; Console in function
  48. TYPE    EQU    2        ; Console type function
  49. PRINTF    EQU    9        ; Print string function
  50. STATUS    EQU    11        ; Console status function
  51. SEARCHF    EQU    17        ; Search for first file
  52. SEARCHN    EQU    18        ; Search for next file
  53. DELETE    EQU    19        ; Delete file function
  54. CDISK    EQU    25        ; Get current disk function
  55. SETDMA    EQU    26        ; Set DMA function
  56. SETFIL    EQU    30        ; Set file attributes
  57. USERF    EQU    32        ; Get/set user
  58. ;
  59. ;ASCII EQUATES
  60. CTRLC    EQU    3        ; Control - C
  61. TAB    EQU    9
  62. CR    EQU    13
  63. LF    EQU    10
  64. ESC    EQU    27
  65. ;
  66. MAXUSR:    EQU    15        ; Highest valid user - can be
  67.                 ; made higher to 'hide' files
  68. GETRDY:    LHLD    1        ; get warm start entry point
  69.     LXI    D,-654H
  70.     DAD    D        ; subtract 654h bytes
  71.     SHLD    LOCE5        ; save address for later
  72.     MOV    A,M        ; check to see that byte there
  73.     CPI    0E5H        ; is E5...
  74.     JZ    GETSET        ; jump if it's there,
  75.     LHLD    6        ; otherwise search thru
  76. FIND:    INX    H        ; memory looking for
  77.     MOV    A,H        ; the code for MVI M,E5, MVI C,xx
  78.     CPI    0        ; If H=0 we have
  79.     JZ    BAD        ;        gone too far...
  80.     MOV    A,M        ; Otherwise keep searching
  81.     CPI    36H
  82.     JNZ    FIND
  83.     INX    H
  84.     SHLD    LOCE5
  85.     MOV    A,M
  86.     CPI    0E5H
  87.     JNZ    FIND
  88.     INX    H
  89.     MOV    A,M
  90.     CPI    0EH
  91.     JZ    GETSET
  92.     JMP    FIND
  93. ;
  94. BAD:    LXI    D,BADMSG    ; print bad system msg
  95.     CALL    PRTSTR        ; and return to CCP....
  96.     RET
  97. ;
  98. GETSET:    CALL    INIT        ; Initialize terminal if needed
  99.     LDA    FCB1 + 1
  100.     CPI    ' '
  101.     JNZ    NOWGO        ; Jump if something was typed
  102.     CALL    CLRSCR        ; No file spec'd, print help msg
  103.     CALL    REVON        ;       Reverse video on
  104.     LXI    D,PGMNAM    ;       Show the program name
  105.     CALL    PRTSTR
  106.     CALL    REVOFF        ;       Reverse video off
  107.     LXI    D,HLPMSG    ;       Help message
  108.     CALL    PRTSTR
  109.     RET            ; and return to CCP
  110.  
  111. NOWGO:    LXI    H,FCB2 + 1    ; get source user #
  112.     CALL    GETNUM
  113.     JC    GOMORE        ; if ok...
  114. BADNUM:    LXI    D,BADNR        ; otherwise print bad number msg
  115.     CALL    PRTSTR        ; and return to CCP....
  116.     JMP    ABORT
  117. GOMORE:    STA    SOURCE        ; save source user #
  118.     MVI    E,0FFH        ; get current user #
  119.     MVI    C,USERF
  120.     CALL    BDOS
  121.     STA    USRNR        ; save it
  122.     LHLD    POINTR
  123.     CALL    GETNUM        ; get dest user #
  124.     JNC    BADNUM        ; quit if bad number...
  125.     STA    DEST
  126.     MOV    E,A        ; otherwise dest to E
  127.     LDA    SOURCE        ; get source # and quit if same as
  128.     CMP    E        ; dest.
  129.     JZ    BADNUM        ; otherwise...
  130.     PUSH    D
  131.     PUSH    PSW
  132.     LDA    FCB1        ; get drive designation
  133.     ANA    A
  134.     JNZ    GOTDRV
  135.     MVI    C,CDISK        ; get default drive    
  136.     CALL    BDOS        ; returns 0 for drive A
  137.     INR    A        ; fix it so 1 = drive A...
  138. GOTDRV:    ADI    '@'        ; convert drive to ASCII
  139.     STA    DRIVE        ; save it
  140.     LHLD    LOCE5        ; point to location of e5h in CCP.
  141.     POP    PSW
  142.     POP    D
  143.     MOV    M,E        ; replace the e5h with the dest user #
  144.     MOV    E,A        ; source to E for bdos call
  145.     MVI    C,USERF
  146.     CALL    BDOS        ; set user to source
  147.     LXI    H,80H
  148.     MOV    B,M
  149.     MOV    A,B
  150.     ORA    A
  151.     JZ    NOTN        ; Skip if no characters typed
  152. FINDN:    INX    H        ; else check each character
  153.     MOV    A,M
  154.     CPI    '/'        ; Was it "/"?
  155.     JNZ    FINDLP
  156.     DCR    B
  157.     JZ    NOTN
  158.     INX    H
  159.     MOV    A,M
  160.     CPI    'N'
  161.     JZ    YESN
  162. FINDLP:    DCR    B
  163.     JNZ    FINDN
  164.     JMP    NOTN
  165. YESN:    STA    NAFLG
  166. NOTN:    LXI    D,DBUF
  167.     MVI    C,SETDMA
  168.     CALL    BDOS
  169.     LXI    D,FCB1
  170.     MVI    C,SEARCHF
  171.     CALL    BDOS
  172.     INR    A
  173.     JZ    FINIS
  174. GETFN:    DCR    A        ; Adjust Accum to point to filename
  175.     ADD    A        ; A=A*32
  176.     ADD    A
  177.     ADD    A
  178.     ADD    A
  179.     ADD    A
  180.     LXI    H,DBUF        ; Point to disk buffer
  181.     MVI    D,0        ; Add in
  182.     MOV    E,A        ;  offset for
  183.     DAD    D        ;   this file
  184.     XCHG            ; DE points to filename in disk buffer
  185.     LHLD    BUFPTR        ; Point HL to buffer
  186.     MVI    C,32        ; # of bytes to move
  187. MOVE:    LDAX    D        ; Move filename from disk buffer
  188.     MOV    M,A        ;  to main buffer
  189.     INX    H
  190.     INX    D
  191.     DCR    C
  192.     JNZ    MOVE
  193.     SHLD    BUFPTR        ; Update pointer
  194.     LDA    FCOUNT        ; Add 1 to file count
  195.     INR    A
  196.     STA    FCOUNT
  197.     LXI    D,FCB1
  198.     MVI    C,SEARCHN    ; Look for more files
  199.     CALL    BDOS
  200.     INR    A
  201.     JNZ    GETFN        ; Get next filename
  202.     LXI    H,BUFFER    ; All found, point to first one
  203.     SHLD    BUFPTR
  204. ;
  205. ;SEE IF WE TYPED "/N", IF YES, SAY "^C TO QUIT"
  206.     LDA    NAFLG
  207.     CPI    'N'
  208.     JNZ    PRTFN
  209.     CALL    REVON
  210.     LXI    D,CTCMSG    ; "^C" message
  211.     CALL    PRTSTR
  212.     CALL    REVOFF
  213. ;
  214. ;PRINT THE FILE SPECS
  215. PRTFN:    CALL    CRLF
  216.     MVI    A,8        ; Print 8 char's
  217.     PUSH    H
  218.     INX    H
  219.     CALL    TYPEB
  220.     PUSH    H
  221.     MVI    E,'.'        ; Print a period
  222.     CALL    PCHAR
  223.     POP    H
  224.     MVI    A,3        ; Print file type
  225.     CALL    TYPEB
  226.     MVI    E,' '        ; And a couple of spaces
  227.     CALL    PCHAR
  228.     MVI    E,' '
  229.     CALL    PCHAR
  230.     POP    H
  231.     LXI    D,9        ; Look at
  232.     DAD    D        ;  the
  233.     MOV    A,M        ;   R/O bit
  234.     RLC
  235.     JNC    NOTRO        ; Skip if not R/O, else
  236.     MVI    A,0FFH        ;   set R/O flag
  237.     STA    ROFLG
  238. NOTRO:    INX    H        ; Look at SYS bit
  239.     MOV    A,M
  240.     RLC
  241.     JNC    NOTSYS        ; Skip if not SYS, else
  242.     MVI    A,0FFH        ;   set SYS flag
  243.     STA    SYSFLG
  244. NOTSYS:    LDA    ROFLG
  245.     MOV    B,A
  246.     LDA    SYSFLG
  247.     ORA    B
  248.     JNZ    PRTATR        ; Jump if file is R/O or SYS
  249.     MVI    E,TAB
  250.     CALL    PCHAR
  251.     JMP    ASK
  252. ;
  253. PRTATR:    MVI    E,'('        ; Print file attributes
  254.     CALL    PCHAR
  255.     LDA    ROFLG
  256.     ORA    A
  257.     JZ    SKPRO        ; Skip if not R/O
  258.     LXI    D,ROMSG        ; "R/O"
  259.     CALL    PRTSTR
  260. SKPRO:    LDA    ROFLG
  261.     ORA    A
  262.     JZ    SKPCOM        ; Don't print ',' if we didn't print 'R/O'
  263.     MVI    E,','
  264.     CALL    PCHAR
  265. SKPCOM:    LDA    SYSFLG
  266.     ORA    A
  267.     JZ    SKPSYS
  268.     LXI    D,SYSMSG    ; "SYS"
  269.     CALL    PRTSTR
  270. SKPSYS:    MVI    E,')'
  271.     CALL    PCHAR
  272. ASK:    LDA    NAFLG        ; See if must ask to change file
  273.     CPI    'N'        ; 'N' = no ask
  274.     JZ    DOIT
  275.     LXI    D,QUERY        ; Move this file?
  276.     CALL    PRTSTR
  277.     MVI    C,CONIN        ;Get response
  278.     CALL    BDOS
  279.     ANI    05FH        ; Make upper case
  280.     CPI    CTRLC        ; ^C to quit
  281.     JZ    FINIS
  282.     CPI    'Y'        ; Y to move the file
  283. DOIT:    CZ    CHANGE
  284.     MVI    C,STATUS    ; Check if anything typed
  285.     CALL    BDOS        ;   on keyboard
  286.     ANA    A
  287.     JZ    CONT        ; Continue if not, else
  288.     MVI    C,CONIN        ;   get character
  289.     CALL    BDOS
  290.     CPI    CTRLC        ; Abort if it was ^C
  291.     JZ    FINIS
  292. CONT:    MVI    A,0        ; Reset the flags
  293.     STA    ROFLG
  294.     STA    SYSFLG
  295.     LDA    FCOUNT        ; Count down
  296.     DCR    A
  297.     STA    FCOUNT
  298.     JZ    FINIS        ; If no more
  299.     LHLD    BUFPTR
  300.     LXI    D,32        ; Move to next filename
  301.     DAD    D
  302.     SHLD    BUFPTR
  303.     JMP    PRTFN
  304. ;
  305. CHANGE:    LHLD    BUFPTR        ; Get drive and
  306.     LDA    FCB1        ;  move it to buffer
  307.     MOV    M,A
  308.     LDA    ROFLG        
  309.     ORA    A        ; If not R/O
  310.     JZ    RWOK        ;  skip next, else
  311.     PUSH    H        ; Make it   
  312.     LXI    D,9             ;  R/W    
  313.     DAD    D
  314.     MOV    A,M
  315.     ANI    07FH
  316.     MOV    M,A
  317.     POP    H
  318.     PUSH    H
  319.     XCHG
  320.     MVI    C,SETFIL
  321.     CALL    BDOS
  322.     POP    H
  323. ;CHANGE THE FILE'S USER BY CALLING THE DELETE FUNCTION
  324. RWOK:    XCHG
  325.     MVI    C,DELETE
  326.     CALL    BDOS
  327.     LDA    CHGCNT
  328.     INR    A
  329.     STA    CHGCNT
  330.     RET
  331. ;
  332. ;PRINT THE NUMBER OF FILES CHANGED AND RETURN TO CCP
  333. ;(IF ABORTING, PRINT ABORT MSG FIRST)
  334. FINIS:    CPI    CTRLC
  335.     CZ    ABORT
  336.     CALL    CRLF
  337.     CALL    REVON
  338.     LDA    CHGCNT
  339.     MVI    H,0
  340.     MOV    L,A
  341.     CALL    PT3DEC        ; Print H/L as 3 decimal digits
  342.     LXI    D,REPORT    ; "FILES CHANGED "
  343.     CALL    PRTSTR
  344.     LDA    CHGCNT        ; See if any files were changed
  345.     ANA    A        ; Skip if none changed, otherwise
  346.     JZ    FINIS1        ; show 'from here to there' message
  347.     LXI    D,FRMMSG    ; "FROM "
  348.     CALL    PRTSTR
  349.     LDA    DRIVE
  350.     MOV    E,A
  351.     CALL    PCHAR
  352.     XRA    A
  353.     STA    PRTFLG
  354.     LDA    SOURCE
  355.     MVI    H,0
  356.     MOV    L,A
  357.     CALL    PT2DEC
  358.     LXI    D,TOMSG        ; " TO "
  359.     CALL    PRTSTR
  360.     LDA    DRIVE
  361.     MOV    E,A
  362.     CALL    PCHAR
  363.     XRA    A
  364.     STA    PRTFLG
  365.     LDA    DEST
  366.     MVI    H,0
  367.     MOV    L,A
  368.     CALL    PT2DEC
  369. FINIS1:    CALL    REVOFF
  370.     CALL    CRLF
  371. ;RESTORE ORIGINAL USER AND REPLACE E5 ERASE CODE
  372.     LHLD    LOCE5
  373.     MVI    M,0E5H
  374.     LDA    USRNR
  375.     MOV    E,A
  376.     MVI    C,USERF
  377.     CALL    BDOS
  378.     JMP    BOOT
  379. ;
  380. ABORT:    CALL    REVON
  381.     LXI    D,ABTMSG    ; "PROGRAM ABORTED"
  382.     CALL    PRTSTR
  383.     CALL    REVOFF
  384.     RET
  385. ;
  386. ;Print H/L as 3 decimal digits
  387. PT3DEC:    LXI    B,-100        ; Divide by 100
  388.     CALL    DIVIDE
  389.     MOV    A,E        ; Result to A
  390.     STA     PRTFLG        ; Save it for later
  391.     CPI    0        ; Suppress leading 0
  392.     JZ    PT2DEC
  393.     CALL    PRTDIG
  394. PT2DEC:    LXI    B,-10        ; Divide by 10
  395.     CALL    DIVIDE
  396.     LDA    PRTFLG        ; Have we printed a char?
  397.     ANA    A
  398.     MOV    A,E
  399.     JNZ    NOSKIP        ; Yes, then don't skip a 0
  400.     CPI    0
  401.     JZ    LSTDIG
  402. NOSKIP:    CALL    PRTDIG
  403. LSTDIG:    MOV    A,L
  404.     CALL    PRTDIG
  405.     RET
  406. ;
  407. ;GETNUM - GETS NUMBER FROM COMMAND LINE - QUITS AT NON-NUMERIC CHAR.
  408. ;         RETURNS WITH CARRY SET IF VALID USER.
  409. ;
  410. GETNUM:    MVI    E,0        ; clear accumulation
  411. GNLOOP:    MOV    A,M        ; get the character
  412.     INX    H        ; point to next one
  413.     CALL    CKNR        ; conv. to binary & check if valid #
  414.     JC    GNDONE        ; if not 0-9
  415.     MOV    D,A        ; save present digit of user #
  416.     MOV    A,E        ; get prev. accumulation
  417.     CALL    X10        ; and mult it X 10
  418.     ADD    D        ; add in present digit
  419.     MOV    E,A        ; save the accumulated value
  420.     JMP    GNLOOP        ; get next char.
  421. GNDONE:    MOV    A,E        ; retrieve the digit
  422.     CPI    MAXUSR + 1    ; see if valid - ret w/carry set if ok
  423.     SHLD    POINTR        ; remember where we left off
  424.     RET
  425. ;
  426. ;CKNR - Returns carry set if A is not a valid ASCII digit between 0 and 9
  427. ;       otherwise returns carry=0 and A converted to the binary value of
  428. ;       the digit
  429. ;
  430. CKNR:    SUI    '0'
  431.     RC
  432.     CPI    10
  433.     CMC
  434.     RET
  435. ;
  436. X10:    ADD    A        ; A=A*2
  437.     MOV    B,A
  438.     ADD    A        ; A=A*4
  439.     ADD    A        ; A=A*8
  440.     ADD    B        ; A=A*10
  441.     RET
  442. ;
  443. ;TYPE NUMBER OF CHAR'S IN B REG
  444. TYPEB:    PUSH    PSW
  445.     PUSH    H
  446.     MOV    E,M
  447.     CALL    PCHAR
  448.     POP    H
  449.     POP    PSW
  450.     INX    H
  451.     DCR    A
  452.     JNZ    TYPEB
  453.     RET
  454. ;
  455. ;Divide HL/BC, returns quotient in E, remainder in L
  456. DIVIDE:    MVI    E,0FFH
  457. DVLOOP:    INR    E
  458.     DAD    B
  459.     JC    DVLOOP
  460.     MOV    A,B
  461.     CMA
  462.     MOV    B,A
  463.     MOV    A,C
  464.     CMA
  465.     MOV    C,A
  466.     INX    B
  467.     DAD    B
  468.     RET
  469. ;
  470. ;PRINT VALUE IN ACCUM AS ASCII DIGIT
  471. PRTDIG:    ADI    030H
  472.     PUSH    H
  473.     MOV    E,A
  474.     CALL    PCHAR
  475.     POP    H
  476.     RET
  477. ;
  478. ;SEND CARRIAGE RETURN, LINEFEED TO CRT
  479. CRLF:    MVI    E,CR
  480.     CALL    PCHAR
  481.     MVI    E,LF
  482. PCHAR:    PUSH    H
  483.     MVI    C,TYPE
  484.     CALL    BDOS
  485.     POP    H
  486.     RET
  487. ;
  488. ;CLEAR CRT SCREEN
  489. CLRSCR:    LXI    D,CLSMSG
  490.     JMP    PRTSTR
  491. ;
  492. INIT:    LXI    D,NITSTR    ; Initialize CRT for reverse video
  493.     JMP    PRTSTR
  494. ;
  495. REVOFF:    LXI    D,OFFSTR    ; Reverse video off
  496.     JMP    PRTSTR
  497. ;
  498. REVON:    LXI    D,ONSTR        ; Reverse video on
  499. ;
  500. PRTSTR:    PUSH    H
  501.     PUSH    D
  502.     MVI    C,PRINTF
  503.     CALL    BDOS
  504.     POP    D
  505.     POP    H
  506.     RET
  507. ;
  508. ;VIDEO ATTRIBUTE STRINGS
  509. ; Strings for video attributes are stored here, each ending with '$'
  510. ; Initialized to null strings.  Modify as desired for your terminal.
  511. CLSMSG:    DB    '$'        ; Clear screen
  512. ONSTR:    DB    '$'        ; Reverse video start tag
  513. OFFSTR:    DB    '$'        ; Reverse video end tag
  514. NITSTR:    DB    '$'        ; Initialize scrn for reverse video
  515. ;
  516. ;MESSAGES -
  517. CTCMSG:    DB    CR,LF,TAB,'Use ^C to quit',TAB,TAB,CR,LF,'$'
  518. QUERY:    DB    TAB,'Change this file? $'
  519. ABTMSG:    DB    CR,LF,LF,'Program aborted.$'
  520. REPORT:    DB    ' files changed $'
  521. FRMMSG:    DB    'from $'
  522. TOMSG:    DB    ' to $'
  523. PGMNAM:    DB    TAB,'CU - a program to change files from one user to'
  524.     DB    ' another.',TAB,'$'
  525. HLPMSG:    DB    CR,LF,LF
  526.     DB    'ENTER:',CR,LF,LF
  527.     DB    TAB,TAB,'CU [dr:]filename.typ s,d [/N]',CR,LF,LF
  528.     DB    TAB,'dr:=drive designator (optional)',CR,LF
  529.     DB    TAB,'s=source user number (where it is now)',CR,LF
  530.     DB    TAB,'d=destination user number (where you want the file)',CR,LF
  531.     DB    TAB,'N means don''t ask before changing each file.',CR,LF
  532.     DB    TAB,'filename.typ may be ambiguous, just as in the'
  533.     DB    ' ERA command.',CR,LF,LF
  534.     DB    'EXAMPLE:',CR,LF,LF
  535.     DB    TAB,TAB,'CU *.ASM 0,3 /N',CR,LF,LF
  536.     DB    TAB,'This would transfer all files of type ASM from'
  537.     DB    ' user 0 to user 3',CR,LF
  538.     DB    TAB,'without asking before changing each file.'
  539.     DB    CR,LF,'$'
  540. BADMSG:    DB    CR,LF,'System does not match program',CR,LF,'$'
  541. BADNR:    DB    CR,LF,'Bad user number entered',CR,LF
  542.     DB    'Enter CU<CR> for help.',CR,LF,'$'
  543. ;
  544. ROMSG:    DB    'R/O$'
  545. SYSMSG:    DB    'SYS$'
  546. ;
  547. ;STORAGE AREA
  548. ;
  549. PRTFLG:    DB    0        ; Flag for decimal print routine
  550. DRIVE:    DB    'A'        ; Default drive
  551. SOURCE:    DB    0        ; temp storage for source #
  552. DEST:    DB    0        ; temp storage for destination #
  553. POINTR:    DW    0        ; pointer to next character for dest user #
  554. LOCE5:    DW    0        ; location of e5h in CCP
  555. USRNR:    DB    0        ; Current user
  556. BUFPTR:    DW    BUFFER        ; Buffer pointer storage
  557. FCOUNT:    DB    0        ; File counter storage
  558. CHGCNT:    DB    0        ; Changed file counter storage
  559. ROFLG:    DB    0        ; Read-only flag (FF=R/O)
  560. SYSFLG:    DB    0        ; SYSTEM flag (FF=SYS)
  561. NAFLG:    DB    0        ; No ask flag (0=ask)
  562. DBUF:    DS    128        ; Disk buffer
  563. BUFFER:    DB    0        ; File name storage starts here
  564. ;
  565.     END    GETRDY
  566.