[net.sources] keyboard locking program

oscar@utcsrgv.UUCP (Oscar M. Nierstrasz) (11/23/83)

This program locks your keyboard until you type
your login password.  It catches ^Z for csh users.
Also times out after (default) 5 minutes and logs you out.
No idea how portable it is, but shouldn't be hard to convert.
Source to follow.
------------------------------------------------------------
.TH LK 1
.UC
.SH NAME
lk \- lock a terminal
.SH SYNOPSIS
.B lk 
[timeout]
.SH DESCRIPTION
.I Lk
locks your terminal until you type in your login password.
The default timeout period is 5 minutes.
This can be increased to a maximum of 15 minutes.
.PP
.I Lk
uses your real password instead of an improvised one thus
saving time and reducing embarrassment if it is forgotten.
There is no "trap-door" password.
The ^Z signal available in csh(1) is also caught by
.I lk.
.pp
In order to use
.I lk
you must have the shell variable $shellpid available in your environment.
If you are using "C" shell, put the line
.IP
setenv shellpid=$$
.PP
in your .login file.
With the Bourne shell, put the lines
.IP
shellpid=$$
.br
export shellpid
.PP
in your .profile.
.SH DIAGNOSTICS
Tells you how many minutes are left to logout time.
.br
Quits if it can't find $shellpid.
.SH BUGS
You can fool
.I lk
by providing a bogus $shellpid.
.br
Also, sigsys(2) is not very portable.
.SH AUTHOR
Oscar Nierstrasz at the University of Toronto.
.SH SEE ALSO
csh(1), sh(1), getuid(2), getpwent(3), crypt(3), environ(5), getenv(3),
ioctl(2), signal(2), sigsys(2), sigset(2), alarm(2), kill(2).
-- 

UUCP	{ ihnp4 cornell decwrl watmath uw-beaver ubc-vision sask 
		garfield qucis linus mcgill-vision }!utcsrgv!oscar
  or	{ allegra decvax duke floyd }!utzoo!utcsrgv!oscar

oscar@utcsrgv.UUCP (Oscar M. Nierstrasz) (11/23/83)

/*							*/
/*	FILE:	LK.C					*/
/*	AUTHOR:	Oscar Nierstrasz			*/
/*							*/
/*	Usage:	lk [timeout]				*/
/*							*/
/*	Locks the keyboard. 				*/
/*	Prevents idle fingers from mucking with		*/
/*	your terminal while you dash downstairs		*/
/*	to the versatec.				*/
/*							*/
/*	Lock will timeout after at most 15 minutes.	*/
/*	(Default is 5 minutes.)				*/
/*	If you put the line				*/
/*							*/
/*		setenv shellpid=$$			*/
/*							*/
/*	in your .login (with csh), lk will		*/
/*	automatically log you off upon a timeout.	*/
/*	(use export with sh -- see environ(5)		*/
/*							*/
/*	Compile with -ljobs.				*/
/*							*/


#include	<stdio.h>
#include	<sgtty.h>
#include	<signal.h>
#include	<pwd.h>

#define		TRUE		1
#define		FALSE		0
#define		MAX		100
#define		TIMEOUT		5	/* minutes */
#define		MAXTIME		15
#define		MINUTE		60
#define		SHELL		"shellpid"
#define		BELL		'\07'

struct	passwd	*getpwuid();
char	*crypt(), *getenv();
int	timeout, min=0, pid, nomsg = TRUE;

checktime(){
	int	t;

	min++;
	t = timeout - min;
	if(t <= 0)
		goodbye();
	else	fprintf(stderr, "%d minute%c to logout\n", t, (t==1)?' ':'s');
	sigset(SIGALRM, checktime); /* reset SIGALRM */
	alarm(MINUTE);
}

goodbye(){
	echo_on();
	fprintf(stderr, "Logout%c\n", BELL);
	if(pid != NULL)
		if(kill(pid, SIGKILL) != 0) /* shouldn't happen */
			fprintf(stderr, "Can't kill process %d\n", pid);
	exit(0);
}

msg(){
	if(nomsg){
		fprintf(stderr, "Keyboard locked; enter password to unlock\n");
		nomsg = FALSE;
	}
}

main(argc,argv)
	int	argc;
	char	**argv;
{
	struct	passwd	*pwptr;
	char	*shell, p[MAX], pw[MAX], *try;
	int	nullpw, locked = TRUE;

	if(argc == 1)
		timeout = TIMEOUT;
	else	if(argc == 2){
		timeout = atoi(argv[1]);
		if(timeout == 0)
			usage();
		if(timeout > MAXTIME)
			timeout = MAXTIME;
	}
	else	usage();

	if((shell = getenv(SHELL)) == NULL) {
		fprintf(stderr,
		"%cCan't find shell variable $%s\n\n", BELL, SHELL);
		fprintf(stderr,
		"In the C shell run:\n\tsetenv %s $$\n\n", SHELL);
		fprintf(stderr,
		"In the Bourne shell run:\n\t%s=$$\n\texport shellpid\n",
			SHELL);
		exit(1);
		}
	else	pid = atoi(shell); /* process id of login shell */

	sigset(SIGINT, msg);
	sigset(SIGQUIT, msg);
	sigset(SIGTSTP, msg);
	sigset(SIGALRM, checktime);
	sigset(SIGHUP, goodbye);
	echo_off();

	pwptr = getpwuid(getuid());
	strcpy(pw,pwptr->pw_passwd); /* get encrypted password */
	nullpw = strlen(pw) == 0; /* TRUE if no password */

	fprintf(stderr, "Back within %d minute%c\n", timeout,
		(timeout==1)?' ':'s');
	alarm(MINUTE);
	while(locked){
		getline(p,stdin);
		if(nullpw){
			if(strlen(p) == 0)
				locked = FALSE;
			else	printf("incorrect password\n");
		}
		else{
			try = crypt(p,pw); /* test the password */
			if(strcmp(try,pw) == 0)
				locked = FALSE;
			else	printf("incorrect password\n");
		}
	}
	echo_on();
}
getline(s,file)
	char	*s;
	FILE	*file;
{
	/*	get a line of input up to MAX characters	*/
	/*	return length of input or EOF or MAX		*/
	int	i=0;
	char	c;

	while((c=fgetc(file)) != '\n'){
		if(c == EOF){
			rewind(file);
			return(EOF);
		}
		s[i] = c;
		i++;
		if(i == MAX){
			s[i-1] = '\0';
			return(MAX);
		}
	}
	s[i] = '\0';
	return(i);
}
echo_off()
{
	struct	sgttyb	ttybuf;

	gtty(0, &ttybuf);
	ttybuf.sg_flags &= ~ECHO;
	stty(0, &ttybuf);
}
echo_on()
{
	struct	sgttyb	ttybuf;

	gtty(0, &ttybuf);
	ttybuf.sg_flags |= ECHO;
	stty(0, &ttybuf);
}
usage()
{
	printf("Usage: lk [timeout]\n");
	printf("locks keyboard until you type your password\n");
	printf("quits after timeout minutes (default 5)\n");
	exit(1);
}
-- 

UUCP	{ ihnp4 cornell decwrl watmath uw-beaver ubc-vision sask 
		garfield qucis linus mcgill-vision }!utcsrgv!oscar
  or	{ allegra decvax duke floyd }!utzoo!utcsrgv!oscar