
		***************************************************
		***						***
		***		     OwnDev 1.0			***
		***						***
		***************************************************
		***   © 29.3.94 by Marc Heuler (Data Design)	***
		***************************************************

		INCDIR	"Include:"
		INCLUDE	"exec/types.i"
		INCLUDE	"exec/tasks.i"
		INCLUDE	"exec/execbase.i"
		INCLUDE	"exec/libraries.i"
		INCLUDE	"dos/dosextens.i"
		INCLUDE	"_LVOExec.i"
		INCLUDE	"_LVOOwnDevUnit.i"
		INCLUDE	"_LVODos.i"

_SysBase	= 4

CALLEXE		MACRO
		move.l	_SysBase,a6
		jsr	_LVO\1(a6)
		ENDM

CALLDOS		MACRO
		move.l	_DosBase,a6
		jsr	_LVO\1(a6)
		ENDM

CALLODU		MACRO
		move.l	_ODUBase,a6
		jsr	_LVO\1(a6)
		ENDM


NAME		MACRO
		dc.b	"OwnDev"
		ENDM

VERSION		MACRO
		dc.b	"1.00"
		ENDM

DATE		MACRO
		dc.b	"29.3.94"
		ENDM

		***************************************************
		***						***
		***			Start			***
		***						***
		***************************************************

Start		bra.s	RStart

		dc.b	"$VER: "
		NAME
		dc.b	" "
		VERSION
		dc.b	" ("
		DATE
		dc.b	") © 1994 by Marc 'Nepomuk' Heuler <marc@aargh.incubus.sub.org>",0
		even

RStart		movem.l	d1-d7/a0-a6,-(a7)

		lea	_DosName(pc),a1			; Open DOS
		moveq	#33,d0
		CALLEXE	OpenLibrary
		move.l	d0,_DosBase
		beq	.Error

		move.l	4,a0				; Test Kickstart
		cmp.w	#37,LIB_VERSION(a0)
		blt	.Error_Kick

		move.l	#_Template,d1			; Get arguments
		move.l	#ARG_Device,d2
		moveq	#0,d3
		CALLDOS	ReadArgs
		move.l	d0,_Args
		beq	.Error_DOS

		***************************************************
		***						***
		***		  Parse Arguments		***
		***						***
		***************************************************

		lea	_SerialName(pc),a0		; Copy name
		lea	_Device,a1
		lea	_Owner,a2
		lea	_Name,a3
		move.l	ARG_Device(pc),d0
		beq.s	.SetName
		move.l	d0,a0
.SetName	move.b	(a0),(a1)+
		move.b	(a0),(a2)+
		move.b	(a0)+,(a3)+
		bne.s	.SetName

		move.l	ARG_Unit(pc),d0			; Copy unit
		beq.s	.SetUnit
		move.l	d0,a0
		move.l	(a0),d0
.SetUnit	move.l	d0,_Unit

		addq.l	#8,a2				; Create ID name
		clr.b	-(a2)
		addq.l	#8,a3
		clr.b	-(a3)
		move.l	_Unit,d0
		bsr	Hex

		move.l	ARG_Name(pc),d0			; Copy owner name
		beq.s	.Password
		move.l	d0,a0
		lea	_Owner,a1
.Owner		move.b	(a0)+,(a1)+
		bne.s	.Owner

.Password	lea	_Password,a1			; Copy password
		clr.b	(a1)
		move.l	ARG_Password(pc),d0
		beq.s	.NoPassword
		move.l	d0,a0
.Password_Loop	move.b	(a0)+,(a1)+
		bne.s	.Password_Loop

.NoPassword	tst.l	ARG_Disown			; Disown?
		bne	.Disown

		***************************************************
		***						***
		***		  Fire Owner Process		***
		***						***
		***************************************************

		moveq	#-1,d0
		CALLEXE	AllocSignal
		move.b	d0,_Signal
		move.l	ThisTask(a6),_Task

		move.l	#_Name,d1			; Create Owner Process
		moveq	#0,d2
		move.l	Start-4(pc),d3
		move.l	#4096,d4
		CALLDOS	CreateProc
		move.l	d0,d2
		beq	.Error_NoMem

.Loop		move.l	#SIGBREAKF_CTRL_C,d0		; Shake hands
		move.b	_Signal(pc),d1
		bset	d1,d0
		CALLEXE	Wait
		move.b	_Signal(pc),d1
		btst	d1,d0
		bne.s	.Check
		move.l	d2,a1				; BREAK_C
		move.l	#SIGBREAKF_CTRL_C,d0
		CALLEXE	Signal
		st	_Break
		bra.s	.Loop

.Check		move.l	_Result(pc),d0			; Check result
		beq	.Cleanup
		move.l	d0,a0
		cmp.b	#7,(a0)
		beq.s	.Check_Error
		bsr	Print				; Other owner
		lea	.tx_CR(pc),a0
		bsr	Print
		moveq	#10,d0
		bra	.Cleanup

.Check_Error	addq.l	#1,a0				; ODU error
		bsr	Print
		lea	.tx_CR(pc),a0
		bsr	Print
		moveq	#20,d0
		bra	.Cleanup

		***************************************************
		***						***
		***		   Disown Device		***
		***						***
		***************************************************

.Disown		CALLEXE	Forbid				; Find owner task
		lea	_Name,a1
		CALLEXE	FindTask
		tst.l	d0
		beq	.Disown_Warn
		move.l	d0,a2				; Compare passwords
		move.l	TC_Userdata(a2),a0
		lea	_Password,a1
.Disown_Loop	move.b	(a0)+,d0
		beq.s	.Disown_Compare
		cmp.b	(a1)+,d0
		beq.s	.Disown_Loop

.Disown_Warn	CALLEXE	Permit				; Warn about something
		moveq	#5,d0
		bra	.Cleanup

.Disown_Compare	tst.b	(a1)+
		bne.s	.Disown_Warn
		move.l	a2,a1				; Free unit
		move.l	#SIGBREAKF_CTRL_C,d0
		CALLEXE	Signal
		CALLEXE	Permit

		moveq	#0,d0
		bra	.Cleanup

		***************************************************
		***						***
		***		Error Handling			***
		***						***
		***************************************************

.Error_Kick	lea	.tx_Kick(pc),a0			; Wrong Kickstart
		bsr	Print
		bra.s	.Error

.Error_NoMem	lea	.tx_NoMem(pc),a0		; Not enough memory
		bsr	Print
		bra.s	.Error

.Error_DOS	CALLDOS	IoErr				; DOS error
		move.l	d0,d1
		move.l	#.tx_Name,d2
		CALLDOS	PrintFault

.Error		moveq	#20,d0
		bra.s	.Cleanup

.tx_Name	NAME
		dc.b	0
.tx_Kick	dc.b	"You need at least Kickstart 2.04 (v37)"
.tx_CR		dc.b	$a,0
.tx_NoMem	dc.b	"Not enough memory",$a,0
		even

		***************************************************
		***						***
		***		     Cleanup			***
		***						***
		***************************************************

.Cleanup	move.l	d0,-(a7)
		move.b	_Signal(pc),d0			; Free SigBit
		beq.s	.NoSignal
		CALLEXE	FreeSignal
.NoSignal	move.l	_Args(pc),d1			; Free Args
		beq.s	.NoArgs
		CALLDOS	FreeArgs
.NoArgs		move.l	_DosBase(pc),d0			; Close DOS
		beq.s	.NoDos
		move.l	d0,a1
		CALLEXE	CloseLibrary
.NoDos		move.l	(a7)+,d0
		movem.l	(a7)+,d1-d7/a0-a6
		rts

		***************************************************
		***						***
		***		Print To StdOutput		***
		***						***
		***************************************************
		*** >>> A0	String (0-terminated)		***
		*** <<< FLAGS	BNE ERROR			***
		***************************************************

Print		movem.l	d1-d3/a0-a1,-(a7)
		move.l	_DosBase,d0
		beq.s	.Print_Skip
		move.l	a0,-(a7)
		CALLDOS	Output
		move.l	d0,d1
		move.l	(a7)+,a0
		move.l	a0,d2
.Print_Loop	tst.b	(a0)+
		bne.s	.Print_Loop
		move.l	a0,d3
		subq.l	#1,d3
		sub.l	d2,d3
		beq.s	.Print_Skip
		move.l	d3,-(a7)
		CALLDOS	Write
		sub.l	(a7)+,d0
.Print_Skip	movem.l	(a7)+,d1-d3/a0-a1
		rts


Hex		bsr.s	.Word
		swap	d0
.Word		bsr.s	.Byte
		lsr.w	#8,d0
.Byte		move.b	d0,d1
		bsr.s	.Nibble
		move.b	d1,d0
		lsr.b	#4,d0
.Nibble		and.b	#$f,d0
		add.b	#"0",d0
		cmp.b	#"9",d0
		ble.s	.Exit
		add.b	#"A"-("9"+1),d0
.Exit		move.b	d0,-(a2)
		move.b	d0,-(a3)
		rts

		***************************************************
		***						***
		***		     Variables			***
		***						***
		***************************************************

ARG_Device	dc.l	0
ARG_Unit	dc.l	0
ARG_Name	dc.l	0
ARG_Password	dc.l	0
ARG_Wait	dc.l	0
ARG_Disown	dc.l	0

_DosBase	dc.l	0

_Task		dc.l	0
_Args		dc.l	0
_Result		dc.l	0

_Break		dc.b	0
_Signal		dc.b	0
_DosName	dc.b	"dos.library",0
_SerialName	dc.b	"serial.device",0
_Template	dc.b	"DEVICE=-D,UNIT=-U/N,NAME,PW=PASSWORD/K,WAIT/S,DISOWN/S",0
		even

		***************************************************
		***						***
		***		   Child Process		***
		***						***
		***************************************************

		SECTION	Child,code

Child		move.l	4,a0
		move.l	ThisTask(a0),a0
		move.l	#_Password,TC_Userdata(a0)

		lea	.ODUName(pc),a1
		moveq	#3,d0
		CALLEXE	OpenLibrary
		move.l	d0,_ODUBase
		beq	.ODU

.Loop		lea	_Device,a0			; Attempt lock
		move.l	_Unit,d0
		lea	_Owner,a1
		moveq	#0,d1
		CALLODU	AttemptDevUnit
		move.l	d0,_Result
		beq.s	.Fine
		move.l	d0,a0
		cmp.b	#7,(a0)
		beq.s	.Signal
		moveq	#0,d0				; BREAK_C?
		moveq	#0,d1
		CALLEXE	SetSignal
		moveq	#SIGBREAKB_CTRL_C,d1
		btst	d1,d0
		bne.s	.Break
		tst.b	_Break
		bne.s	.Break
		tst.l	ARG_Wait			; Block?
		bne.s	.Loop
		bra.s	.Signal

.Break		move.l	#.tx_Break,_Result
		bra.s	.Signal

.ODU		move.l	#.tx_ODU,_Result
		bra.s	.Signal

.Fine		pea	Wait(pc)
		clr.l	Start-4				; Detach

.Signal		moveq	#0,d0				; Shake hands
		move.b	_Signal,d1
		bset	d1,d0
		move.l	_Task,a1
		CALLEXE	Signal
		rts

.ODUName	dc.b	"OwnDevUnit.library",0
.tx_Break	dc.b	7,"*** Break",0
.tx_ODU		dc.b	7,"*** You need owndevunit.library v3+",0
		even

Wait		move.l	#SIGBREAKF_CTRL_C,d0		; Wait for disown
		CALLEXE	Wait
		lea	_Device,a0
		move.l	_Unit,d0
		CALLODU	FreeDevUnit

		move.l	_ODUBase(pc),a1
		CALLEXE	CloseLibrary

		lea	.DosName(pc),a1			; Unload myself
		moveq	#37,d0
		CALLEXE	OpenLibrary
		move.l	d0,a6
		move.l	#Child-4,d1
		lsr.l	#2,d1
		jmp	_LVOUnLoadSeg(a6)

.DosName	dc.b	"dos.library",0
		even

_ODUBase	dc.l	0


		SECTION	Buffers,bss

_Unit		ds.l	1
_Device		ds.b	256
_Owner		ds.b	256
_Name		ds.b	256
_Password	ds.b	256


		END

