! 1 Jul 87
!
!	Written by Terry R. Lambert
!
! bbsadmin.cmd

! Administrative menu... assumes the a calling script or program... if
! none is present, then "return to main menu" option return to CLI
!
! Function:	1) Allow editing of users with lesser or equal privs
!		2) Do not allow a user with lesser privs to see user with more
!		3) Allow altering of alias, password, access mask
!		4) user may not give self or other user more privs than he
!		   already has (may only confer his own privs to other user)
!		5) user may delete privs he has, but previous ones remain in
!		   effect until next login session
!		6) If user deletes own privs, he MAY NOT re-instate them if
!		   he logs out then back in
!		7) In no case may ADMIN ADMIN record be modified at any time
!		8) Menu is limited to one user at a time
!		9) Username MAY NOT be modified, as it is key field.  If a
!		   username is to be changed, that users record should be
!		   deleted.  Alternately, the record COULD be altered by
!		   the administrator editing the userlist file.

! Name:		usrfmt
! Parameters:	string containing a user record
! Purpose:	split input string to load vars ufnam, upass, ualia, ulcou,
!		uacce; other prefs can be added as needed.
! record format:
! name ("first last")		 passwd alias		     pg ac   terminator
! ############################## ###### #################### ## #### xx
! 1234567890123456789012345678901234567890123456789012345678901234567890
proc usrfmt
	setvar x $1
	setvar ufnam trim(left(x,30))
	setvar upass trim(midstr(x,32,6))
	setvar ualia trim(midstr(x,39,20))
	setvar ulcou val(midstr(x,60,2))
	setvar uacce val(midstr(x,63,4))
endproc usrfmt

! Name:		usrlkup
! Parameters:	string of firstname,space,lastname ("FRED MEYER")
! Purpose:	Do user lookup and load vars upass, ualia, ulcou,
!		uacce; other prefs can be added as needed.
! record format:
! name ("first last")		 passwd alias		     pg ac   terminator
! ############################## ###### #################### ## #### xx
! 1234567890123456789012345678901234567890123456789012345678901234567890
proc usrlkup
	setv newuser true
	fopen 1,"userlist"
	repeat
		fread 1,x
		if trim($1)=trim(left(x,30))
			setvar upass midstr(x,32,6)
			setvar ualia midstr(x,39,20)
			setvar ulcou val(midstr(x,60,2))
			setvar uacce val(midstr(x,63,4))
			setvar newuser false
		endif
	until len(x)<1 | newuser=false
	fclose 1
endproc





do bbsio@lock "admin.lck" inuseby
if inuseby!=""
	?
	?
	? "Administration menu locked by $(inuseby)"
	?
	do bbsio@hitret
	return
endif

! This menu is reentrant, but not file-locked, therefore it should not be run
! by two processes simultaneously on multi-user systems.

setvar maxper		9		! maximum permission bits

! following arrays are dimensioned longer to accommodate option base of 0
dimstr pers		maxper+1	! permission names to use
setvar pers[1]		"Admin"
setvar pers[2]		"Sysop"
setvar pers[3]		"User2"
setvar pers[4]		"User1"
setvar pers[5]		"Ukill"
setvar pers[6]		"Dload"
setvar pers[7]		"Uload"
setvar pers[8]		"Email"
setvar pers[9]		"Regis"

dimint perm		maxper+1	! Permission masks for indexed ref.
setvar perm[1]		M_admin
setvar perm[2]		M_sysop
setvar perm[3]		M_user2
setvar perm[4]		M_user1
setvar perm[5]		M_ukill
setvar perm[6]		M_dload
setvar perm[7]		M_uload
setvar perm[8]		M_email
setvar perm[9]		M_regis

repeat
if !expert
	?
	?
	? "            [ Grapevine $(revno)             Administration Menu ]"
	?
	? "             <A> Alter a user record   <D> Delete a user record"
	? "             <L> List user records     <P> Print a user list"
	? "             <X> Exit to main menu"
endif
?
? "A,C,D,L,P,X: ";
repeat
	setvar count 0
	setvar goodcmd false
	setvar cmd toupper(chrin())
	switch
	case cmd="A"
	  ? "Alter a user record"
	  ?
	  ? "Enter full username: ";
	  setvar llimit 30
	  do bbsio@echoin ufnam true true
	  setvar llimit dlimit
	  ?
	  do bbsio@wlock "userlist.lck" inuseby
	  if inuseby!=""		! ut-oh; someone's really i/o'in!
	    ? "Extreme userfile activity, try again later"
	    ? "Userfile is currently locked by $(inuseby)"
	    ? 
	    do bbsio@hitret
	  else
	    do @usrlkup ufnam
	  endif
	  if inuseby!=""
	  elseif newuser
	    ? "\007Specified user does not exist"
	    ?
	    do bbsio@hitret
	  elseif trim(ufnam)="ADMIN ADMIN"
	    ? "\007You cannot alter the ADMIN user"
	    ?
	    do bbsio@hitret
	  elseif (access & uacce) != uacce
	    ? "\007You cannot alter a user with more privileges than yourself"
	    ?
	    do bbsio@hitret
	  else
	    setvar bye false
	    repeat
	      ? "Username  $(ufnam)"
	      ? "Alias     $(ualia)"
	      ? "Password  $(upass)"
	      ? "Lcount    $(ulcou)"
	      ? "Access:   ";
	      setvar cnt 1
	      setvar acs ""
	      repeat
		if (uacce & perm[cnt]) > 0
		  setvar acs acs+pers[cnt]+"  "
		else
		  setvar acs acs+"-----  "
		endif
		setvar cnt cnt+1
	      until cnt>maxper
	      ? acs
	      ?
	      ? "             <A> Alias change          <L> Linecount change"
	      ? "             <M> Access mask change    <P> Password change"
	      ? "             <S> Save changes & exit   <X> Exit, no save"
	      ?
	      ? "A,L,M,P,S,X: ";
	      setvar goodcmd false
	      setvar bye false
	      repeat
		setvar cmd toupper(chrin())
		switch
		case cmd="A"
		  ? "Alias change"
		  ?
		  ? "Enter new alias or <RETURN> for no change"
		  ?
		  ? "Current alias is: "+ualia
		  ? "    New alias is: ";
		  setvar llimit 20
		  do bbsio@echoin nalia true true
		  setvar llimit dlimit
		  if nalia!=""
		    setvar ualia nalia
		  endif
		  ?
		  setvar goodcmd true
		case cmd="L"
		  ? "Linecount change"
		  ?
		  ? "Enter new linecount (0 < x < 25) or <RETURN> for no change"
		  ?
		  ? "Current linecount is: $(ulcou)"
		  ? "    New linecount is: ";
		  setvar llimit 2
		  do bbsio@echoin nlcou true false
		  setvar llimit dlimit
		  ?
		  if val(nlcou)>0 & val(nlcou)<25
		    setvar ulcou val(nlcou)
		  else
		    ? "New linecount must be in the range 0 < x < 25"
		  endif
		  ?
		  setvar goodcmd true
		case cmd="M"
		  ? "Access mask change"
		  ?
		  ? "You may only add or remove those privileges which you yourself have"
		  ?
		  ? "Use + and - to select, SPACE to add/remove, RETURN to accept:"
		  ?
		  setvar slct 1
		  repeat
		    if slct!=1
		      setvar acs2 " "+left(acs,6+(slct-2)*7)+"<"
		    else
		      setvar acs2 "<"
		    endif
		    setvar acs2 acs2+midstr(acs,1+(slct-1)*7,5)+">"
		    if slct!=maxper
		      setvar acs2 acs2+midstr(acs,slct*7,80)
		    endif
		    ? acs2+"\r";
		    setvar cmd toupper(chrin())
		    switch
		    case cmd="+"
		      setvar slct slct+1
		      if slct>maxper
			setvar slct slct-maxper
		      endif
		    case cmd="-"
		      setvar slct slct-1
		      if slct<1
			setvar slct slct+maxper
		      endif
		    case cmd=" "
		      if (access & perm[slct]) > 0
			if (uacce & perm[slct]) > 0
			  setvar uacce (uacce & !(perm[slct]))	! on to off
			else
			  setvar uacce (uacce | perm[slct])	! off to on
			endif
		      else
			? "\007**** You do not have this privilege yourself ****\r";
			wait 1
		      endif
		      setvar cnt 1
		      setvar acs ""
		      repeat
			if (uacce & perm[cnt]) > 0
			  setvar acs acs+pers[cnt]+"  "
			else
			  setvar acs acs+"-----  "
			endif
			setvar cnt cnt+1
		      until cnt>maxper
		    endswitch
		  until cmd="\r"
		  ?
		  ?
		  setvar goodcmd true
		case cmd="P"
		  ? "Password change"
		  ?
		  ? "Enter new password or <RETURN> for no change"
		  ?
		  ? "Current password is: "+upass
		  ? "    New password is: ";
		  setvar llimit 6
		  do bbsio@echoin npass true false
		  setvar llimit dlimit
		  if npass!=""
		    setvar upass npass
		  endif
		  ?
		  setvar goodcmd true
		case cmd="S"
		  ? "Save changes & exit"
		  do bbsio@fixuser "$(ufnam)" upass ualia ulcou uacce
		  setvar bye true
		  ?
		  setvar goodcmd true
		case cmd="X"
		  ? "Exit, no save"
		  setvar bye true
		  setvar goodcmd true
		  ?
		endswitch
		if !goodcmd & !quiet
		  ? "\007";
		endif
	      until goodcmd
	    until bye
	endif
	do bbsio@unlock "userlist.lck"
	setvar goodcmd true
      case cmd="D"
	? "Delete a user record"
	  ?
	  ? "Enter full username: ";
	  setvar llimit 30
	  do bbsio@echoin ufnam true true
	  setvar llimit dlimit
	  ?
	! we can wait for lock to complete, as we are the only ones
	! who keep it locked for any amount of time, and there can
	! only be one of us.
	do bbsio@wlock "userlist.lck" inuseby
	if inuseby!=""		! ut-oh; someone's really i/o'in!
	  ? "Extreme userfile activity, try again later"
	  ? "Userfile is currently locked by $(inuseby)"
	  ? 
	  do bbsio@hitret
	else
	  do @usrlkup ufnam
	endif
	if inuseby!=""
	elseif newuser
	  ? "\007Specified user does not exist"
	  ?
	  do bbsio@hitret
	elseif trim(ufnam)="ADMIN ADMIN"
	  ? "\007You cannot alter the ADMIN user"
	  ?
	  do bbsio@hitret
	elseif (access & uacce) != uacce
	  ? "\007You cannot delete a user with more privileges than yourself"
	  ?
	  do bbsio@hitret
	else
	  ?
	  ? "Username  $(ufnam)"
	  ? "Alias     $(ualia)"
	  ? "Password  $(upass)"
	  ? "Lcount    $(ulcou)"
	  ? "Access:   ";
	  setvar cnt 1
	  setvar acs ""
	  repeat
	    if (uacce & perm[cnt]) > 0
	      setvar acs acs+pers[cnt]+"  "
	    else
	      setvar acs acs+"-----  "
	    endif
	    setvar cnt cnt+1
	  until cnt>maxper
	  ? acs
	  ?
	  ? "Delete this user... Are you sure? (Y/N) ";
	  do bbsio@yesno zap
	  ?
	  if zap
	    do bbsio@deluser "$(ufnam)"
	    if found
	      ? "User deleted."
	    else
	      ? "Error: user not removed... May have to remove manually"
	    endif
	  endif
	endif
	do bbsio@unlock "userlist.lck"
	setvar goodcmd true
      case cmd="L"
	? "List user records"
	! we can wait for lock to complete, as we are the only ones
	! who keep it locked for any amount of time, and there can
	! only be one of us.
	do bbsio@wlock "userlist.lck" inuseby
	if inuseby!=""		! ut-oh; someone's really i/o'in!
	  ? "Extreme userfile activity, try again later"
	  ? "Userfile is currently locked by $(inuseby)"
	  ? 
	  do bbsio@hitret
	else
	  ? 
	  ? "\^C to abort list"
	  ? 
	  fopen 1,"userlist"
	  freadln 1,rec		! comment line
	  setvar cout 0
	  repeat
	    freadln 1,rec
	    do @usrfmt rec
	    if (access & uacce)=uacce
	      if cout=0
		? 'Name (first last)              Passwd Alias                Pg Access'
	      endif
	      setvar cout cout+1
	      ? "$(left(rec,67))"
	      ! don't show account unless viewer has all of those privileges
	    endif
	    if cout > 20
	      setvar cout 0
	      do bbsio@hitret
	      if rval="^C"
	        setvar rec ""
	      endif
	    endif
	  until rec=""
	  fclose 1
	  do bbsio@unlock "userlist.lck"
	  if cout!=0
	    do bbsio@hitret
	  endif
	endif
	setvar goodcmd true
	case cmd="P"
	  ? "Print a user list"
	  ! we can wait for lock to complete, as we are the only ones
	  ! who keep it locked for any amount of time, and there can
	  ! only be one of us.
	  do bbsio@wlock "userlist.lck" inuseby
	  if inuseby!=""		! ut-oh; someone's really i/o'in!
	    ? "Extreme userfile activity, try again later"
	    ? "Userfile is currently locked by $(inuseby)"
	    ? 
	    do bbsio@hitret
	  else
	    printer on
	    ? 
	    ? 
	    ? 'Name (first last)              Passwd Alias                Pg Access'
	    fopen 1,"userlist"
	    freadln 1,rec		! comment line
	    repeat
	      freadln 1,rec
	      do @usrfmt rec
	      if (access & uacce)=uacce
		? "$(left(rec,67))"
		! don't show account unless viewer has all of those privileges
	      endif
	    until rec=""
	    fclose 1
	    do bbsio@unlock "userlist.lck"
	    printer close
	    ?
	    ? "Done printing."
	    do bbsio@hitret
	  endif
	  setvar goodcmd true
	case cmd="X"
	  ? "Exit to main menu"
	  ? "Exiting..."
	    do bbsio@unlock "admin.lck"
	    return 0
	endswitch
	if !goodcmd & !quiet
	  ? "\007";
	endif
      until goodcmd
until false
? "bbsadmin.cmd: fatal error... you should NEVER get this far!"
quit
