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.CRLF		.DA MSG.CRLF
L.MSG.BS		.DA MSG.BS
*L.ROOT			.DA ROOT
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
			
				>PUSHW pData
				>SYSCALL PutPW
				bcs .99
				
				lda #0
				sec
				rts

.9				>PUSHW L.MSG.USAGE
				>PUSHBI 0
				>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

				>PUSHW L.MSG.ROOTPWD1
				>PUSHBI 0
				>SYSCALL PrintF
				bcs .90
				jsr CS.RUN.GetStr
				bcs .90

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

				>PUSHW ZPStrPtr
				>PUSHW ZPStrPtr
				>SYSCALL MD5
				>PUSHW ZPStrPtr
				>PUSHEA.G PW+S.PW.PASSWD
				>SYSCALL StrCmp
				bcs .99
				
*				jsr CS.RUN.TEST

				>PUSHW pData
				>SYSCALL PutPW
				
*				jsr CS.RUN.TEST
				
				bcs .9
				
				lda #0
				sec
.9				rts

.99				>PUSHW L.MSG.MISMATCH
				>PUSHBI 0
				>SYSCALL PrintF
				lda #E.SYN
				sec
				rts
*--------------------------------------
*CS.RUN.TEST		php
*				pha
*				>PUSHW L.ROOT
*				>PUSHWI 0
*				>SYSCALL GetEnv
*				phx
*				>SYSCALL PutS
*				pla
*				>SYSCALL FreeMem
*				pla
*				plp
*				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
				
				>PUSHW L.MSG.BS
				>PUSHBI 0
				>SYSCALL PrintF
				bra .1
.8				ldy ZPStrLen
				lda #0
				sta (ZPStrPtr),y
				
				>PUSHW L.MSG.CRLF
				>PUSHBI 0
				>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

				lda ArgIndex
				sta ArgUsername
				>SYSCALL ArgV
				>PUSHYA
				>PUSHW ZPPWPtr
				>SYSCALL GetPWName
				bcc .9
				
				bra CS.RUN.CheckArg
				
.8				lda ArgUsername			
				beq CS.RUN.CheckArg.9
				clc
				rts
				
.9				lda #E.DUPUSR
				sec
				rts
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	>PUSHEA.G S.PW.DIR
				>PUSHWI S.STAT.MODE.RO+S.STAT.MODE.RG+S.STAT.MODE.FU
				>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"
MSG.CRLF		.AZ "\r\n"			
MSG.BS			.DA #C.BS,#C.SPACE,#C.BS,#0
MSG.ROOTPWD1	.AZ "\r\nPlease enter ROOT password : "
MSG.ROOTPWD2	.AZ "\r\nPlease retype ROOT password : "
MSG.MISMATCH	.AZ "\r\nPasswords mismatch...\r\n"
*--------------------------------------
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
*--------------------------------------
*ROOT			.AZ "ROOT"
*--------------------------------------
* Per Process DATA segment
*--------------------------------------
				.DUMMY
				.OR 0
DS.START		
PW				.BS S.PW
DS.END			.ED
*--------------------------------------
MAN
SAVE usr/src/bin/useradd.s
ASM
