NEW
  AUTO 3,1
			.LIST OFF
			.OP	65C02
			.OR	$2000
			.TF bin/useradd
*--------------------------------------
USER.MAX	.EQ 16
PASS.MAX	.EQ 64
*--------------------------------------
			.INB INC/MACROS.I
			.INB INC/A2OSX.I
*--------------------------------------
* Zero Page Segment, up to 32 bytes
*--------------------------------------
				.DUMMY
				.OR ZPBIN
ZS.START
ZPPWPtr			.BS 2
ZPhPW			.BS 1
ZPhStr			.BS 1
ZPbStrSecret	.BS 1
ZPStrLen		.BS 1
ZPStrMax		.BS 1
ArgIndex		.BS 1
ArgUsername		.BS 1
ZPStrPtr		.BS 2
ZPTmpPtr		.BS 2
ZS.END			.ED
*--------------------------------------
*			File Header (16 Bytes)
*--------------------------------------
CS.START		cld
				jmp (.1,x)
				.DA #$61				6502,Level 1 (65c02)
				.DA #1					BIN Layout Version 1
				.DA #0					S.PS.F.EVENT
				.DA #0
				.DA CS.END-CS.START		Code Size (without Constants)
				.DA DS.END-DS.START		Data Segment Size
				.DA #64					Stack Size
				.DA #ZS.END-ZS.START	Zero Page Size
				.DA 0
*--------------------------------------
* Relocation Table
*--------------------------------------
.1				.DA CS.INIT
				.DA CS.RUN
				.DA CS.DOEVENT		
				.DA	CS.QUIT
L.MSG.USAGE		.DA MSG.USAGE
L.MSG.ROOTPWD1	.DA MSG.ROOTPWD1
L.MSG.ROOTPWD2	.DA MSG.ROOTPWD2
L.MSG.MISMATCH	.DA MSG.MISMATCH
L.MSG.DUP		.DA MSG.DUP
L.MSG.BS		.DA MSG.BS
L.MSG.CRLF		.DA MSG.CRLF
J.CS.RUN.CheckArg
				.DA CS.RUN.CheckArg.C
				.DA CS.RUN.CheckArg.D
				.DA CS.RUN.CheckArg.P
				.DA CS.RUN.CheckArg.S
				.DA 0
*--------------------------------------
* Called once at process creation
* Put code for loading LIB here
*--------------------------------------
CS.INIT			clc
				rts
*--------------------------------------
* Called until exit with CS
* if RUN exits with CC, RN entered again
*--------------------------------------
CS.RUN			>LDYAI S.PW
				>SYSCALL getmem
				bcs .99
				
				>STYA ZPPWPtr
				stx ZPhPW
				
				>LDYAI 256
				>SYSCALL getmem
				bcs .99
				
				>STYA ZPStrPtr
				stx ZPhStr
				
				lda #0
				>PUSHA
				>PUSHW ZPPWPtr
				>SYSCALL GetPWUID
				bcc .1
				
				jmp CS.RUN.ROOT

.1				ldy #S.PW

.2				dey
				lda PW.DEFAULT,y
				sta (pData),y
				tya
				bne .2

				jsr CS.RUN.CheckArg
				bcs .9

				jsr CS.RUN.MkDir
*				bcs .99
				>LDYA pData
				>SYSCALL putpw
				bcs .99
				
				lda #0
				sec
				rts

.9				>PUSHBI 0
				>LDYA L.MSG.USAGE
				>SYSCALL printf
				lda #E.SYN
				sec
.99				rts
*--------------------------------------
CS.RUN.ROOT		ldy #0

.1				lda PW.ROOT,y
				sta (pData),y			PW
				iny
				cpy #S.PW
				bne .1

				sec
				ror ZPbStrSecret
				lda #127
				sta ZPStrMax

				>PUSHBI 0
				>LDYA L.MSG.ROOTPWD1
				>SYSCALL printf
				bcs .90
				jsr CS.RUN.GetStr
				bcs .90

				>PUSHW ZPStrPtr
				>PUSHEA.G PW+S.PW.PASSWD
				>SYSCALL MD5
				>PUSHBI 0
				>LDYA L.MSG.ROOTPWD2
				>SYSCALL printf
				bcs .9
				jsr CS.RUN.GetStr
.90				bcs .9

				>PUSHW ZPStrPtr
				>PUSHW ZPStrPtr
				>SYSCALL MD5
				>PUSHW ZPStrPtr
				>LEA.G PW+S.PW.PASSWD
				>SYSCALL strcmp
				bcs .99
				
				>LDYA pData
				>SYSCALL putpw
				bcs .9
				
				lda #0
				sec
.9				rts
.99				>PUSHBI 0
				>LDYA L.MSG.MISMATCH
				>SYSCALL printf
				lda #E.SYN
				sec
				rts
*--------------------------------------
CS.RUN.GetStr	stz ZPStrLen

.1				>SYSCALL getchar
				bcs .9
				cmp #C.SPACE
				bcc .2
				ldy ZPStrLen
				cpy ZPStrMax
				beq .1
				sta (ZPStrPtr),y
				iny
				sty ZPStrLen
				bit ZPbStrSecret
				bmi .1
				>SYSCALL putchar
				bra .1

.2				cmp #3					Ctrl-C
				beq .9

				cmp #C.CR
				beq .8
				cmp #C.BS
				bne .1
				ldy ZPStrLen
				beq .1
				dec ZPStrLen
				bit ZPbStrSecret
				bmi .1
				>PUSHBI 0
				>LDYA L.MSG.BS
				>SYSCALL printf
				bra .1
.8				ldy ZPStrLen
				lda #0
				sta (ZPStrPtr),y
				>PUSHBI 0
				>LDYA L.MSG.CRLF
				>SYSCALL printf
.9				rts	
*--------------------------------------
CS.RUN.CheckArg	inc ArgIndex
				lda ArgIndex
				>SYSCALL ArgV
				bcs .8
				>STYA ZPStrPtr
				lda (ZPStrPtr)
				cmp #'-'
				bne .4
				
				ldy #1
				lda (ZPStrPtr),y

				ldx #OptionCnt-1
				
.2				cmp OptionList,x
				beq .3
				dex
				bpl .2

				lda #E.SYN
				sec
				rts
				
.3				txa
				and #$fe
				tax
				jmp (J.CS.RUN.CheckArg,x)

.4				lda ArgUsername
				bne CS.RUN.CheckArg.9
				lda pData
				clc
				adc #S.PW.DIR+11
				sta ZPTmpPtr
				lda pData+1
				adc /S.PW.DIR+11
				sta ZPTmpPtr+1
				ldy #0
.5				lda (ZPStrPtr),y
				sta (pData),y
				sta (ZPTmpPtr),y
				beq .6
				iny 
				cpy #16
				bne .5
				bra CS.RUN.CheckArg.9
.6				lda #'/'
				sta (ZPTmpPtr),y

				>PUSHW ZPPWPtr
				lda ArgIndex
				sta ArgUsername
				>SYSCALL ArgV

				>SYSCALL GetPWName
				bcc .9
				bra CS.RUN.CheckArg
.8				lda ArgUsername			
				beq CS.RUN.CheckArg.9
				clc
				rts
.9				>PUSHBI 0
				>LDYA L.MSG.DUP
				>SYSCALL printf	
CS.RUN.CheckArg.9
				lda #E.SYN
				sec
				rts
*--------------------------------------
CS.RUN.CheckArg.P
				inc ArgIndex
				lda ArgIndex
				>SYSCALL ArgV
				bcs CS.RUN.CheckArg.9
				>PUSHYA
				>PUSHEA.G S.PW.PASSWD
				>SYSCALL MD5
				jmp CS.RUN.CheckArg
*--------------------------------------
CS.RUN.CheckArg.C
				inc ArgIndex
				lda ArgIndex
				>SYSCALL ArgV
				bcs CS.RUN.CheckArg.9
				ldx #S.PW.GECOS
				bra CS.RUN.CheckArg.Next
*--------------------------------------
CS.RUN.CheckArg.D
				inc ArgIndex
				lda ArgIndex
				>SYSCALL ArgV
				bcs CS.RUN.CheckArg.9
				ldx #S.PW.DIR
				bra CS.RUN.CheckArg.Next
*--------------------------------------
CS.RUN.CheckArg.S
				inc ArgIndex
				lda ArgIndex
				>SYSCALL ArgV
				bcs CS.RUN.CheckArg.9
				ldx #S.PW.SHELL
CS.RUN.CheckArg.Next
				>STYA ZPStrPtr
*				clc
				txa
				adc pData
				sta ZPTmpPtr
				lda pData+1
				adc #0
				sta ZPTmpPtr+1
				ldy #$ff
.1				iny
				lda (ZPStrPtr),y
				sta (ZPTmpPtr),y
				beq .8
				cpy #64
				bne .1
				lda #0
				sta (ZPTmpPtr),y
.8				jmp CS.RUN.CheckArg
*--------------------------------------
CS.RUN.MkDir	>LEA.G S.PW.DIR
				>SYSCALL MKDir

				rts
*--------------------------------------
* Called if option S.PS.F.EVENT enabled in Header
* Timer Event : every 10th seconds
*--------------------------------------
CS.DOEVENT		sec
				rts
*--------------------------------------
* Called once, when RUN exited with CS
* Put code for unloading LIB here
*--------------------------------------
CS.QUIT			lda ZPhStr
				beq .1
				>SYSCALL freemem
.1				lda ZPhPW
				beq .2
				>SYSCALL freemem
.2				clc
				rts
*--------------------------------------
CS.END
*--------------------------------------
OptionList		.AS "CcDdPpSs"
OptionCnt		.EQ *-OptionList
*--------------------------------------
* Initialized DATA
*--------------------------------------
MSG.USAGE		.AS "Usage : USERADD username\r\n"
				.AS "   -c : Comment (GECOS)\r\n"
				.AS "   -d : Home Directory\r\n"
				.AS "   -p : Password\r\n"
				.AS "   -s : Shell\r\n"
MSG.CRLF		.AZ "\r\n"			
MSG.ROOTPWD1	.AZ "\r\nPlease enter ROOT password : "
MSG.ROOTPWD2	.AZ "\r\nPlease retype ROOT password : "
MSG.MISMATCH	.AZ "\r\nPasswords mismatch...\r\n"
MSG.DUP			.AZ "\r\nDuplicate username...\r\n"
MSG.BS			.DA #C.BS,#C.SPACE,#C.BS,#0
*--------------------------------------
PW.ROOT			.AS "root"
				.BS 17-4
				.AZ "d41d8cd98f00b204e9800998ecf8427e"
				.DA #0					UID
				.DA #0					GID
				.AS "Root User"
				.BS 65-9
				.AS "${ROOT}root/"
				.BS 65-12
				.AS "${ROOT}bin/sh"
				.BS 65-13
*--------------------------------------
PW.DEFAULT		.BS 17					NAME
				.AZ "d41d8cd98f00b204e9800998ecf8427e"
				.DA #0					UID
				.DA #1					GID
				.BS 65					GECOS
				.AS "${ROOT}usr/"
				.BS 65-11
				.AS "${ROOT}bin/sh"
				.BS 65-13
*--------------------------------------
* Per Process DATA segment
*--------------------------------------
				.DUMMY
				.OR 0
DS.START		
PW				.BS S.PW
DS.END
				.ED
*--------------------------------------
MAN
SAVE USR/SRC/BIN/USERADD.S
ASM
