%TITLE  "Password for Portfolio"

; /***************************************************************
; * password.c -- simple password protection for the portfolio   *
; *                                                              *
; * Author : Alan Davis CIS:72317,3661                           *
; *                                                              *
; * Original Implementation : TurboC v2.0                        *
; * Current Implementation  : Turbo Assembler v1.0               *
; *                                                              *
; * edits                                                        *
; * 1.1  added c_break protection                                *
; * 2.0  recode in assembler, (saved 8K in exe size)             *
; ***************************************************************/
; Portions Copyright 1989 by Tom Swan

	IDEAL
	DOSSEG
	MODEL	small
	STACK	32

;----- Equates
MaxLen		EQU	10  ; length of password

cr		EQU	13  ; ascii cr
lf		EQU	10  ; ascii lf
space           EQU     32  ; ascii space

INCLUDE "DOSMACS.ASM"

	DATASEG

exitCode	db	0

Prompt          db      'Password : ',0
Usage		db	'passwd V2.0',cr,lf
		db	'Alan Davis, Oct 1990',cr,lf,lf
                db      'Usage : passwd phlugg',cr,lf
                db      'Where phlugg is the password',cr,lf
                db      'Password is limited to 10 chars',cr,lf,0

PWString	db	MaxLen DUP (?),0
UserPW          db      MaxLen DUP (?),0
blanks          db      21 DUP (space),0
cseg            dw      ?   ; saved vector 
cofs            dw      ?   ; for cbrk int 1Bh
cbseg           dw      ?   ; saved vector 
cbofs           dw      ?   ; for cbrk int 23h

INCLUDE "longjmp.inc"

Restart         jmpbuf      ; program state buffer

	CODESEG

;-----  From: Strings.obj:

        EXTRN   StrCopy:proc, StrCompare:proc, StrLength:proc

;-----  From: Strio.obj:

	EXTRN	StrReadNE:proc, StrWrite:proc, NewLine:proc, CRnoLF:proc

;-----  From : Params.obj;

        EXTRN   Getparams:proc, GetOneParam:proc, ParamCount:proc

;-----  From : Longjmp.obj

        EXTRN setjmp:proc, longjmp:proc


PROC    c_break

        mov     ax,1                ; simulated exit code for longjmp
	push    ax                 
	mov     ax,OFFSET Restart   ; stored program state
	push    ax
        call    longjmp             

        iret
ENDP    c_break

PROC    setcbrk

        push    dx
        push    es
        push    ax
        push    bx

        DOS_GetVector 01bh          ; set 1st cbrk intr
        mov     [cseg], es          ; store original
        mov     [cofs], bx          ; 1Bh handler address (bios)
        DOS_SetVector 01bh, c_break

        DOS_GetVector 023h          ; set 2nd cbrk intr
        mov     [cbseg], es         ; store original
        mov     [cbofs], bx         ; 23h handler address (dos)
        DOS_SetVector 023h, c_break

        pop     bx
        pop     ax
        pop     es
        pop     dx

        ret
ENDP    setcbrk

Start:
	mov	ax,@data        ; Set ax to data segment
	mov	es,ax           ; set es to data segment
       
        push    ds              ; save ds for getparams
        mov     ds,ax
        call    setcbrk         ; disable c_break
        pop     ds

        call    GetParams       ; Get parameters with ds = PSP

        call    ParamCount      ; Get number of parameter into dx

; check command line
        push    dx              ; Save dx on stack
        or      dx,dx           ; does dx = 0?
        jz      Help            ; Display usage
        pop     dx              ; restore number of params
        cmp     dx,1            ; Is there only 1 param?
        jne     Help            ; No, display usage

        xor     cx,cx           ; Parameter 0 (first one)
        call    GetOneParam
        mov     dx,di           ; adr string w/ ds:dx

        call    StrLength       ; is pw longer than 10 chars
        cmp     cx,MaxLen
        jg      help

        mov     si,dx               ; save password
        mov     di,OFFSET PWString
        call    StrCopy

        jmp     clearline           ; just to set setjmp target
again:
        mov     di, OFFSET Prompt   ; display prompt
        call    StrWrite

        mov     di,OFFSET UserPW    ; set adr of entered pw
        mov     cl,MaxLen           ; can only be MaxLen chars
        call    StrReadNE           ; get it, don't echo

        mov     si, OFFSET PWString ; compare the two strings
        mov     di, OFFSET UserPW
        call    StrCompare
        jne     clearline           ; if not right pw, clear line 
                                    ; and ask again
        
done:   ; pw verified, cleanup and exit

        DOS_RestoreVector 01Bh,cseg,cofs    ; restore C-break
	DOS_RestoreVector 023h,cbseg,cbofs  ; handler vectors

Exit:
	mov	ah,04Ch
	mov	al,[exitCode]
	int	21h

clearline:  ; This is where we return to on Ctrl-C

        push    ax
	mov     ax,OFFSET Restart
        push    ax
	call    setjmp
        pop ax

        call    CRnoLF
        mov     di, OFFSET blanks
        call    StrWrite
        call    CRnoLF
        jmp     again

Help:
	mov	di,OFFSET Usage
	call	StrWrite
        jmp     Exit


	END	Start
