NEW
  AUTO 3,1
*--------------------------------------
* ZPPtr1 : UID
* TXTPTR : pName (Input)
* FORPNT : pPW (Output)
* ZPPtr3 : pDB
* USERNAME:PASSWORD:UID:GID:GECOS:HOME:SHELL\CR
* ....\CR
* \0
*--------------------------------------
PWDX.GetPWUID	lda PWD.hUsrDB
				beq PWD.GetPW.9

				jsr K.GetmemPtr
				>STYA ZPPtr3

.1				lda (ZPPtr3)
				beq PWD.GetPW.99		EOF

				ldy #0
				jsr PWD.NextString		skip USERNAME
	
				jsr PWD.NextString		skip PASSWORD
	
				jsr PWD.GetByte			get UID
				cmp ZPPtr1+1
				beq PWD.GetPW.8

				jsr PWD.NextLine
				bra .1

PWD.GetPW.8		ldx FORPNT+1
				beq  .8					Dry run, no output
				jmp PWD.Record2PW

.8				clc						a = UID
				rts

PWD.GetPW.9		lda #E.IPWDDB
				.HS 2C					BIT ABS
	
PWD.GetPW.99	lda #E.IUSR
				sec
PWD.GetPW.RTS	rts
*--------------------------------------
PWDX.GetPWName	lda PWD.hUsrDB
				beq PWD.GetPW.9

				jsr K.GetmemPtr
				>STYA ZPPtr3

				ldy #0
				jsr SHARED.TXTPTR.GetY
				beq PWD.GetPW.99

.1				lda (ZPPtr3)
				beq PWD.GetPW.99

				ldy #$ff
.2				iny
				jsr SHARED.TXTPTR.GetY
				beq .4

				cmp (ZPPtr3),y
				beq .2

.3				jsr PWD.NextLine
				bra .1

.4				lda (ZPPtr3),y
				cmp #':'
				bne .3
				
				ldx FORPNT+1
				beq .8

				jmp PWD.Record2PW

.8				iny
				jsr PWD.NextString		skip PASSWORD
				jmp PWD.GetByte			get UID
*--------------------------------------
* TXTPTR : pPW (Input)
* ZPPtr3 : pDB
*--------------------------------------
PWDX.PutPW		lda PWD.hUsrDB
				bne PWDX.PutPW.1

				ldy #S.PW.UID
				jsr SHARED.TXTPTR.GetY
				bne PWD.GetPW.RTS		Must be ROOT user

				jsr PWD.GetRecordLen
				tay
				lda #0
				>STYA PWD.UsrDBSize

				jsr K.getmem
				bcs PWD.GetPW.RTS

				>STYA ZPPtr3
				stx PWD.hUsrDB
				
				lda #0
				sta (ZPPtr3)
				
				jsr PWD.AppendRecord
				
				lda PWD.hGrpDB
				beq .2
				
				jsr K.freemem
				
.2				>LDYAI PWDX.GROUP.Size
				>STYA PWD.GrpDBSize
				jsr K.getmem
				bcs .9
				
				>STYA ZPPtr3
				stx PWD.hGrpDB
				
				ldy #PWD.GrpDBSize-1
				
.3				lda PWDX.GROUP,y
				sta (ZPPtr3),y
				dey
				bpl .3
		
				clc
.9				rts
*--------------------------------------
PWDX.PutPW.1	jsr K.GetmemPtr
				>STYA ZPPtr3

				ldy #S.PW.PASSWD
				jsr SHARED.TXTPTR.GetY
				bne .12

				jmp PWD.DeleteRecord
*--------------------------------------
.12				jsr PWD.FindRecord
				bcs .11

				lda #E.DUPUSR			user already exits.
				sec
				rts
*--------------------------------------
.11				jsr PWD.GetUID			new user, get UID
				bcs .99

				ldy #S.PW.UID
				sta CLRWRITEAUX
				sta (TXTPTR),y
				sta SETWRITEAUX

				jsr PWD.GetRecordLen

				clc
				adc PWD.UsrDBSize
				sta PWD.UsrDBSize
				tay
				
				lda #0
				adc PWD.UsrDBSize+1
				sta PWD.UsrDBSize+1
				
				jsr K.Getmem
				bcs .99
				
				>STYA ZPPtr3

				lda PWD.hUsrDB
				jsr K.GetMemPtr
				>STYA ZPPtr4

				ldy #0

.3				lda (ZPPtr4),y
				sta (ZPPtr3),y
				beq .4

				iny
				bne .3
				inc ZPPtr4
				inc ZPPtr3
				bra .3
				
.4				lda PWD.hUsrDB
				stx PWD.hUsrDB
				jsr K.Freemem
				
				lda PWD.hUsrDB
				jsr K.GetMemPtr
				>STYA ZPPtr3
				
				jsr PWD.AppendRecord
				
				clc
				rts

.9				lda #E.IPWDDB
				sec
.99				rts	
*--------------------------------------
PWDX.GetGRGID	lda PWD.hGrpDB
				beq PWD.GetGR.9

				jsr K.GetmemPtr
				>STYA ZPPtr3

.1				lda (ZPPtr3)
				beq PWD.GetGR.99		EOF

				ldy #0
				jsr PWD.NextString		skip USERNAME
	
				jsr PWD.GetByte			get UID
				cmp ZPPtr1+1
				beq PWD.GetGR.8

				jsr PWD.NextLine
				bra .1

PWD.GetGR.8		ldx FORPNT+1
				beq  .8					Dry run, no output
				jmp PWD.Record2GR

.8				clc						a = UID
				rts

PWD.GetGR.9		lda #E.IPWDDB
				.HS 2C					BIT ABS
	
PWD.GetGR.99	lda #E.IUSR
				sec
PWD.GetGR.RTS	rts
*--------------------------------------
PWDX.GetGRName	lda PWD.hGrpDB
				beq PWD.GetGR.9

				jsr K.GetmemPtr
				>STYA ZPPtr3

				ldy #0
				jsr SHARED.TXTPTR.GetY
				beq PWD.GetGR.99

.1				lda (ZPPtr3)
				beq PWD.GetGR.99

				ldy #$ff
.2				iny
				jsr SHARED.TXTPTR.GetY
				beq .4

				cmp (ZPPtr3),y
				beq .2

.3				jsr PWD.NextLine
				bra .1

.4				lda (ZPPtr3),y
				cmp #':'
				bne .3
				
				ldx FORPNT+1
				beq .8

				jmp PWD.Record2GR

.8				iny
				jmp PWD.GetByte			get GID
*--------------------------------------
PWDX.PutGR		lda PWD.hGrpDB
				beq PWD.GetGR.9
				
				jsr K.GetmemPtr
				>STYA ZPPtr3


				lda #E.IPWDDB
				sec
				rts
*--------------------------------------
PWDX.OpenSession
				lda PWD.hUsrDB
				beq .1
				
				lda TXTPTR+1			
				bne .3

.1				>LDYAI PWDX.ROOT.Size
				jsr K.GetMem
				bcs .9

				>STYA ZPPtr1
				
				ldy #PWDX.ROOT.Size-1
				
.2				lda PWDX.ROOT,y
				sta (ZPPtr1),y
				dey
				bpl .2

				txa
				clc
				rts

.3				jsr PWD.FindRecord
				bcs .9

				tya						Y = Name length +1
		
*				clc
				adc ZPPtr3
				sta ZPPtr4
				
				lda ZPPtr3+1
				adc #0
				sta ZPPtr4+1
				
				ldy #31

.5				jsr SHARED.FORPNT.getY
				cmp (ZPPtr4),y			Check MD5
				bne .9
				
				dey
				bpl .5

				>LDYAI 256				TODO: compute S.SESSION size
				jsr K.Getmem
				bcs .9

				>STYA ZPPtr2
				stx .8+1
				
				jsr PWD.Record2Session
				
.8				lda #$ff				SELF MODIFIED

				clc
				rts
				
				sec
.9				rts
*--------------------------------------
PWDX.CloseSession
				sec
				rts
*--------------------------------------
* PRIVATE
*--------------------------------------
PWD.GetUID		lda PWD.hUsrDB

				jsr K.GetmemPtr
				>STYA ZPPtr3

				stz .8+1
.1				lda (ZPPtr3)
				beq .8					End of DB

				ldy #0
				jsr	PWD.NextString		skip name
				jsr PWD.NextString		skip password
				jsr PWD.GetByte
				cmp .8+1
				bcc .4

				sta .8+1

.4				jsr PWD.NextLine
				bra .1

.8				lda #$ff				SELF MODIFIED
				inc
				beq .9

				clc
				rts

.9 				lda #E.IUSR
				sec
				rts
*--------------------------------------
PWD.DeleteRecord
				jsr PWD.FindRecord
				bcs .9
				
.1				iny
				lda (ZPPtr3),y
				cmp #C.CR
				bne .1

				sty .3+1
				tya
				sec
				adc ZPPtr3
				sta ZPPtr4
				lda ZPPtr3+1
				adc #0
				sta ZPPtr4+1

				ldy #$ff

.2				iny
				lda (ZPPtr4),y
				sta (ZPPtr3),y
				bne .2

				lda PWD.UsrDBSize
				sec
.3				sbc #$ff				SELF MODIFIED
				sta PWD.UsrDBSize
				bcs .8

				dec PWD.UsrDBSize+1 

.8				clc
	
.9				rts
*--------------------------------------
PWD.FindRecord	lda PWD.hUsrDB
				jsr K.GetmemPtr
				
				>STYA ZPPtr3

.2				lda (ZPPtr3)
				beq .9					End of DB

				ldy #$ff

.3				iny
				jsr SHARED.TXTPTR.GetY
				beq .4

				cmp (ZPPtr3),y
				beq .3

.5				jsr PWD.NextLine
				bra .2

.4				lda (ZPPtr3),y
				cmp #':'
				bne .5

				iny						skip ":"

				clc
				rts

.9				lda #E.IUSR
				sec
				rts
*--------------------------------------
* USERNAME:PASSWORD:UID:GID:GECOS:HOME:SHELL\CR
*--------------------------------------
PWD.Record2Session
				ldy #0
				
				jsr PWD.NextString		skip USERNAME
				jsr PWD.NextString		skip PASSWORD
				jsr PWD.GetByte			get UID
				sta ZPPtr1
				
				iny
				
				jsr PWD.GetByte			get GID
				sta ZPPtr1+1
				
				iny
				
				lda #0
				ldx ZPPtr1
				bne .1

				ora #S.SESSION.P.ROOT

.1				ldx ZPPtr1+1
				bne .2
				
				ora #S.SESSION.P.SYSADMIN
				
.2				jsr SHARED.PutCharPtr2
				
				lda ZPPtr1
				jsr SHARED.PutCharPtr2	UID

				lda ZPPtr1+1
				jsr SHARED.PutCharPtr2	GID
				
				phy
				
				ldy #$ff

.3				iny
				lda (ZPPtr3),y
				cmp #':'
				beq .4
				
				jsr SHARED.PutCharPtr2
				bra .3
				
.4				lda #0				
				jsr SHARED.PutCharPtr2
				
				ply

.5				lda (ZPPtr3),y
				cmp #C.CR
				beq .8

				cmp #':'
				bne .6
	
				lda #0

.6				jsr SHARED.PutCharPtr2
				iny
				bra .5
				
.8				lda #0				
				jmp SHARED.PutCharPtr2
*--------------------------------------
PWD.Record2PW	ldy #0

				ldx #0					NAME

.1				lda (ZPPtr3),y
				iny
				cmp #':'
				beq .2

				jsr SHARED.FORPNT.PutNext
				inx
				bra .1

.2				lda #0
				jsr SHARED.FORPNT.PutNext
				inx
				cpx #S.PW.PASSWD
				bne .2

.3				lda (ZPPtr3),y
				iny
				cmp #':'
				beq .4

				jsr SHARED.FORPNT.PutNext
				inx
				bra .3

.4				lda #0
				jsr SHARED.FORPNT.PutNext
				inx
				cpx #S.PW.UID
				bne .4

				jsr PWD.GetByte			UID
				jsr SHARED.FORPNT.PutNext

				iny

				jsr PWD.GetByte			GID
				jsr SHARED.FORPNT.PutNext

				iny

				ldx #S.PW.GECOS

.5				lda (ZPPtr3),y
				iny
				cmp #':'
				beq .6
				jsr SHARED.FORPNT.PutNext
				inx
				bra .5
.6				lda #0
				jsr SHARED.FORPNT.PutNext
				inx
				cpx #S.PW.DIR
				bne .6

.7				lda (ZPPtr3),y
				iny
				cmp #':'
				beq .8
				jsr SHARED.FORPNT.PutNext
				inx
				bra .7
.8				lda #0
				jsr SHARED.FORPNT.PutNext
				inx
				cpx #S.PW.SHELL
				bne .8

.9				lda (ZPPtr3),y
				iny
				cmp #C.CR
				beq .10
				jsr SHARED.FORPNT.PutNext
				inx
				bra .9
.10				lda #0
				jsr SHARED.FORPNT.PutNext

				clc
				rts
*--------------------------------------
PWD.Record2GR	ldy #0

				ldx #0					NAME

.1				lda (ZPPtr3),y
				iny
				cmp #':'
				beq .2
				
				jsr SHARED.FORPNT.PutNext
				inx
				bra .1
				
.2				lda #0
				jsr SHARED.FORPNT.PutNext
				
				jsr PWD.GetByte			UID
				jsr SHARED.FORPNT.PutNext

				clc
				rts
*--------------------------------------
PWD.NextString	lda (ZPPtr3),y
				beq .8
				
				iny
				cmp #':'
				bne PWD.NextString
.8				rts
*--------------------------------------
PWD.NextLine	lda (ZPPtr3),y
				beq .8
				
				iny
				cmp #C.CR
				bne PWD.NextLine
				
				tya
				clc
				adc ZPPtr3
				sta ZPPtr3
				bcc .8
				inc ZPPtr3+1
.8				rts
*--------------------------------------
PWD.GetByte		stz .8+1

.1				lda (ZPPtr3),y
				beq .8

				cmp #C.CR
				beq .8

				cmp #':'
				beq .8

				and #$f
				pha
				lda .8+1
				asl
				asl
				clc
				adc .8+1
				asl
				sta .8+1
				pla
				clc
				adc .8+1
				sta .8+1

				iny

				bra .1

.8				lda #$ff				SELF MODIFIED

				clc
				rts
*--------------------------------------
PWD.AppendRecord
.1				lda (ZPPtr3)
				beq .8
				
				inc ZPPtr3
				bne .1
				inc ZPPtr3+1
				bra .1

.8				sec
				.HS 90					BCC
*--------------------------------------
PWD.GetRecordLen
				clc
				ldx #0
				ldy #S.PW.NAME-1

				jsr PWD.StoreString
				lda #':'
				jsr PWD.StoreChar
				ldy #S.PW.PASSWD-1

				jsr PWD.StoreString	

				lda #':'
				jsr PWD.StoreChar

				ldy #S.PW.UID
				jsr SHARED.TXTPTR.GetY
				jsr PWD.StoreByte

				lda #':'
				jsr PWD.StoreChar
				
				ldy #S.PW.GID
				jsr SHARED.TXTPTR.GetY
				jsr PWD.StoreByte
				lda #':'
				jsr PWD.StoreChar

				ldy #S.PW.GECOS-1

				jsr PWD.StoreString
				lda #':'
				jsr PWD.StoreChar

				ldy #S.PW.DIR-1

				jsr PWD.StoreString
				lda #':'
				jsr PWD.StoreChar

				ldy #S.PW.SHELL-1

				jsr PWD.StoreString
				lda #C.CR
				jsr PWD.StoreChar

				txa
PWD.GetRecordLen.RTS
				rts
*--------------------------------------
PWD.StoreString	jsr SHARED.TXTPTR.GetY
				beq PWD.GetRecordLen.RTS
				jsr PWD.StoreChar
				iny
				bra PWD.StoreString
*--------------------------------------
PWD.StoreByte	php
				phx
				jsr MATH32.A2STR10NP
				plx
				plp

				ldy #0
				
.1				lda A2osX.NumStrBuf,y
				beq PWD.GetRecordLen.RTS
				iny
				jsr PWD.StoreChar
				bra .1
*--------------------------------------
PWD.StoreChar	inx
				bcc .9					Dry run, no store
				sta (ZPPtr3)
				inc ZPPtr3
				bne .9
				inc ZPPtr3+1
.9				rts
*--------------------------------------
PWDX.ROOT		.DA #S.SESSION.P.ROOT
				.DA #0					UID
				.DA #0					GID
				.AZ "root"				NAME
				.AZ "Root User"			GECOS
				.AZ "${ROOT}root/"		DIR
				.AZ "${ROOT}bin/sh"		SHELL
PWDX.ROOT.Size	.EQ	*-PWDX.ROOT
*--------------------------------------
PWDX.GROUP		.AS "root:0"
				.DA #C.CR
				.AS "users:1"
				.DA #C.CR
				.DA #0
PWDX.GROUP.Size	.EQ *-PWDX.GROUP
*--------------------------------------
MAN
SAVE USR/SRC/SYS/KERNEL.S.PWDX
LOAD USR/SRC/SYS/KERNEL.S
ASM
