;- :ts=12 --------------------------------------------------------
;
;  	rm -- remove files with Oops! possibility
;
;    /|||\		  (c) Copyright 1989 by Martin J. Laubach
;   //|||\\			All rights reserved
;  ///|||\\\
;
;-----------------------------------------------------------------

	ifd CAPE
	optimon
	addsym
	objfile "rm.o"
	endc

	include "exec/types.i"
	include "exec/alerts.i"
	include "exec/libraries.i"
	include "libraries/dos.i"
	include "arp/arpbase.i"

call	macro
	ifnd	_LVO\1
	xref	_LVO\1
	endc
	jsr	_LVO\1(a6)
	endm

	xref	_LVOAlert

ScratchSiz:	equ	256
JunkSiz:	equ	80

	section	Remove,code

;---------------------------------------------------------------------------
; Try to open arp.library first. Write NoArp text if failure

main:	RESIDENT	3000

	movem.l	a0/d0,-(a7)

	move.l	4,a6
	lea	ArpN(pc),a1
	moveq	#34,d0
	call	OpenLibrary
	tst.l	d0
	bne.s	ArpOK
	lea	DosN(pc),a1
	moveq	#34,d0
	call	OpenLibrary
	tst.l	d0
	bne.s	DosOK

;-------------------------------------
; Recoverable alert if no dos.library found

alertDos:	ALERT	(AG_OpenLib!AO_DOSLib)

EFail:	moveq	#RETURN_FAIL,d0
	rts

;-------------------------------------
; Write OhAhNoArp text for user without arp.library
; Expects DOSBase in D0

DosOK:	move.l	d0,a6
	call	Output
	move.l	d0,d1
	lea	NoArp(pc),a0
	move.l	a0,d2
	moveq	#NoArpEnd-NoArp,d3
	call	Write

	move.l	a6,a1
	move.l	4,a6
	call	CloseLibrary

	bra.s	EFail

;-------------------------------------
; Arp opened ok, now parse the command line
; Expects ArpBase in D0

ArpOK:	move.l	d0,a6
	movem.l	(a7)+,a0/d0

	lea	CLIHelp(pc),a1
	lea	-4(a7),a7
	move.l	a7,a2
	lea	CLITemp(pc),a3
	call	GADS
	move.l	(a7),a5
	lea	4(a7),a7

;-------------------------------------
; Check parameters, write usage if less than one
; Expects D0 number of paramaters

	tst.l	d0
	bne.s	ParamOK
	lea	Usage(pc),a1
	call	Puts
	bra.s	EFail

;--------------------------------------------------------------------------
; Parameters ok, begin to work on them
; D0: argument count
; A5: argument vector

ParamOK:	move.l	d0,d7

	lea	-JunkSiz(a7),a7
	move.l	a7,a2

	lea	Junk(pc),a0
	move.l	a2,a1
	moveq	#JunkSiz,d0
	call	Getenv

	tst.b	(a2)
	bne.s	NoEnv

	lea	Junk(pc),a2

NoEnv:	subq.l	#1,d7

	moveq	#0,d5
	moveq	#0,d6

	lea	-ScratchSiz(a7),a7
	move.l	a7,a3
		
NextPar:	move.l	#SIGBREAKF_CTRL_C,d1
	sub.l	a1,a1
	call	CheckBreak
	tst.l	d0
	bne	BreakRcvd

	move.l	(a5)+,a4

;-------------------------------------
; Check if parameter contains | # ?
; Expects &parameter to check in A4, A3 scratch buffer

Chk4Pat:	move.l	a4,a1
;;;	moveq	#0,d1
1$:	move.b	(a1)+,d0
	beq.s	NoPattern
	cmp.b	#'?',d0
	beq.s	Pattern
	cmp.b	#'|',d0
	beq.s	Pattern
	cmp.b	#'#',d0
	bne.s	1$

;-------------------------------------
; Yes, must do pattern matching
; A4 supplied file name, A3 scratch buffer
; D6 return code, D5 return value

Pattern:	lea	-ap_SIZEOF-256(a7),a7

	move.l	#SIGBREAKF_CTRL_C,ap_BreakBits(a7)
	move.l	#256,ap_Length(a7)

	move.l	a4,d0
	move.l	a7,a0
	call	FindFirst
1$:	move.l	d0,d6
	bne.s	NoFiles

	tst.l	d5	
	bne.s	NoFiles

	lea	ap_SIZEOF(a7),a4
	bsr.s	Remove
;;;	tst.l	d0
	bne.s	2$
	moveq	#RETURN_FAIL,d5

2$:	move.l	a7,a0
	call	FindNext
	bra.s	1$

NoFiles:	tst.l	d6
	beq.s	1$
	cmp.w	#ERROR_NO_MORE_ENTRIES,d6
	beq.s	1$
	moveq	#RETURN_FAIL,d5

1$:	move.l	a7,a0
	call	FreeAnchorChain
	lea	ap_SIZEOF+256(a7),a7

	bra.s	EndLoop

;-------------------------------------
; No, normal remove will do
; A4 File name, A3 scratch buffer
; D5 return value

NoPattern:	bsr.s	Remove
;;;	tst.l	d0
	bne.s	EndLoop

	moveq	#RETURN_FAIL,d5
	move.l	#ERROR_OBJECT_NOT_FOUND,d6

EndLoop:	tst.l	d5
	dbne.s	d7,NextPar

	lea	ScratchSiz+JunkSiz(a7),a7

;-------------------------------------
; End this program

ExitOK:	moveq	#0,d2
	move.l	d5,d0
	beq.s	Exit
	move.l	d6,d2
Exit:	call	ArpExit
	rts

;-------------------------------------
; Break received -- print "***break" and exit program
; Expects pointer to break string in A1

BreakRcvd:	call	Puts
	bra.s	ExitOK
	move.l	#ERROR_BREAK,d2
ExitFail:	moveq	#RETURN_FAIL,d0
	bra.s	Exit


RmRet:	moveq	#0,d0
	rts

;--------------------------------------------------------------------------
; Remove a file. 
; in: A4 = filename to be removed
;     A3 = 256 bytes scratch buffer area
;
; return 0 if failure, <>0 if remove succeeded

Remove:

;-------------------------------------
; Locate the complete file name
; Expects A4 filename, A3 scratch area

	move.l	a4,d1
	move.l	#ACCESS_READ,d2
	call	Lock

	move.l	d0,d3
	beq.s	Prnt
	move.l	a3,a0
	move.l	#256,d1
	call	PathName

	move.l	d3,d1
	call	UnLock

;-------------------------------------
; Print information
; Expects A3 full file name

Prnt:	tst.l	d3
	bne.s	1$

	move.l	a4,-(a7)
	lea	RemStr(pc),a0
	move.l	a7,a1
	call	Printf
	lea	4(a7),a7
	lea	Nofile(pc),a1
	call	Puts
	bra.s	RmRet

1$:	move.l	a3,-(a7)
	lea	RemStr(pc),a0
	move.l	a7,a1
	call	Printf
	lea	4(a7),a7
	
;-------------------------------------
; Isolate drive name
; Expects A3 full file name

Isolate:	move.l	a3,a0

1$:	move.b	(a0)+,d0
	cmp.b	#':',d0
	bne.s	1$
	clr.b	(a0)

;-------------------------------------
; Build path for rename
; Expects A2 "junk" dir name, A3 full file name, A4 original file name

	move.l	a3,a0
	move.l	a2,a1
	call	TackOn
	move.l	a4,a0
	call	BaseName
	move.l	d0,a1
	move.l	a3,a0
	call	TackOn

;-------------------------------------
; Munch file name so it is unique and doesn't exist
; Expects A3 full file name to move to

	moveq	#1,d4
FindEnd:	move.l	a3,a0
1$:	tst.b	(a0)+
	bne	1$
	lea	-1(a0),a0
	move.l	a0,d3
	
ChkEx:	move.l	a3,d1
	move.l	#ACCESS_READ,d2
	call	Lock
	move.l	d0,d1
	beq.s	1$
	call	UnLock

	movem.l	a2/a3/a6,-(a7)
	lea	FileFmt(pc),a0	; Format string
	move.l	d4,-(a7)
	addq.l	#1,d4
	move.l	a7,a1		; Output values
	move.l	d3,a3		; Output buffer
	move.l	4,a6
	lea	StuffChar(pc),a2
	call	RawDoFmt
	lea	4(a7),a7
	movem.l	(a7)+,a2/a3/a6

	bra.s	ChkEx

;-------------------------------------
; Now rename the file
; Expects A3 new, unique junk file name, A4 original file name

1$:	move.l	a4,d1
	move.l	a3,d2
Ren:	call	Rename
	move.l	d0,d3
	beq.s	1$
	lea	Success(pc),a1
	bra.s	2$
1$:	lea	Failed(pc),a1
2$:	call	Puts

	move.l	d3,d0
	rts

;-------------------------------------
; StuffChar, used for Sprintf style formatting

StuffChar:	move.b	d0,(a3)+
	rts

;-------------------------------------
;-------------------------------------

RemStr:	dc.b 'Removing %s...',0
FileFmt:	dc.b ';%ld',0
Success:	dc.b 'done',0
Failed:	dc.b 'failed',0
Nofile:	dc.b 'not found',0

Junk:	dc.b 'Junk',0
CLITemp:	dc.b 'FILES/'
Think:	dc.b '...',0
CLIHelp:	dc.b 'Files to remove',0
Usage:	dc.b 'Usage: rm <file> ...',0
DosN:	dc.b 'dos.library',0
ArpN:	ArpName
NoArp:	dc.b 'You need arp.library V34+'
NoArpEnd:
TestByte:	dc.b $a

	end
