xref: /original-bsd/usr.bin/lock/lock.c (revision 69c8e3e7)
1 /*
2  * Copyright (c) 1980, 1987, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Bob Toxen.
7  *
8  * %sccs.include.redist.c%
9  */
10 
11 #ifndef lint
12 static char copyright[] =
13 "@(#) Copyright (c) 1980, 1987, 1993\n\
14 	The Regents of the University of California.  All rights reserved.\n";
15 #endif /* not lint */
16 
17 #ifndef lint
18 static char sccsid[] = "@(#)lock.c	8.1 (Berkeley) 06/06/93";
19 #endif /* not lint */
20 
21 /*
22  * Lock a terminal up until the given key is entered, until the root
23  * password is entered, or the given interval times out.
24  *
25  * Timeout interval is by default TIMEOUT, it can be changed with
26  * an argument of the form -time where time is in minutes
27  */
28 
29 #include <sys/param.h>
30 #include <sys/stat.h>
31 #include <sys/time.h>
32 #include <sys/signal.h>
33 #include <sgtty.h>
34 #include <pwd.h>
35 #include <stdio.h>
36 #include <ctype.h>
37 #include <string.h>
38 
39 #define	TIMEOUT	15
40 
41 void quit(), bye(), hi();
42 
43 struct timeval	timeout;
44 struct timeval	zerotime;
45 struct sgttyb	tty, ntty;
46 long	nexttime;			/* keep the timeout time */
47 
48 /*ARGSUSED*/
49 main(argc, argv)
50 	int argc;
51 	char **argv;
52 {
53 	extern char *optarg;
54 	extern int errno, optind;
55 	struct passwd *pw;
56 	struct timeval timval;
57 	struct itimerval ntimer, otimer;
58 	struct tm *timp;
59 	int ch, sectimeout, usemine;
60 	char *ap, *mypw, *ttynam, *tzn;
61 	char hostname[MAXHOSTNAMELEN], s[BUFSIZ], s1[BUFSIZ];
62 	char *crypt(), *ttyname();
63 
64 	sectimeout = TIMEOUT;
65 	mypw = NULL;
66 	usemine = 0;
67 	while ((ch = getopt(argc, argv, "pt:")) != EOF)
68 		switch((char)ch) {
69 		case 't':
70 			if ((sectimeout = atoi(optarg)) <= 0) {
71 				(void)fprintf(stderr,
72 				    "lock: illegal timeout value.\n");
73 				exit(1);
74 			}
75 			break;
76 		case 'p':
77 			usemine = 1;
78 			if (!(pw = getpwuid(getuid()))) {
79 				(void)fprintf(stderr,
80 				    "lock: unknown uid %d.\n", getuid());
81 				exit(1);
82 			}
83 			mypw = strdup(pw->pw_passwd);
84 			break;
85 		case '?':
86 		default:
87 			(void)fprintf(stderr,
88 			    "usage: lock [-p] [-t timeout]\n");
89 			exit(1);
90 	}
91 	timeout.tv_sec = sectimeout * 60;
92 
93 	setuid(getuid());		/* discard privs */
94 
95 	if (ioctl(0, TIOCGETP, &tty))	/* get information for header */
96 		exit(1);
97 	gethostname(hostname, sizeof(hostname));
98 	if (!(ttynam = ttyname(0))) {
99 		(void)printf("lock: not a terminal?\n");
100 		exit(1);
101 	}
102 	if (gettimeofday(&timval, (struct timezone *)NULL)) {
103 		(void)fprintf(stderr,
104 		    "lock: gettimeofday: %s\n", strerror(errno));
105 		exit(1);
106 	}
107 	nexttime = timval.tv_sec + (sectimeout * 60);
108 	timp = localtime(&timval.tv_sec);
109 	ap = asctime(timp);
110 	tzn = timp->tm_zone;
111 
112 	(void)signal(SIGINT, quit);
113 	(void)signal(SIGQUIT, quit);
114 	ntty = tty; ntty.sg_flags &= ~ECHO;
115 	(void)ioctl(0, TIOCSETP, &ntty);
116 
117 	if (!mypw) {
118 		/* get key and check again */
119 		(void)printf("Key: ");
120 		if (!fgets(s, sizeof(s), stdin) || *s == '\n')
121 			quit();
122 		(void)printf("\nAgain: ");
123 		/*
124 		 * Don't need EOF test here, if we get EOF, then s1 != s
125 		 * and the right things will happen.
126 		 */
127 		(void)fgets(s1, sizeof(s1), stdin);
128 		(void)putchar('\n');
129 		if (strcmp(s1, s)) {
130 			(void)printf("\07lock: passwords didn't match.\n");
131 			ioctl(0, TIOCSETP, &tty);
132 			exit(1);
133 		}
134 		s[0] = NULL;
135 		mypw = s1;
136 	}
137 
138 	/* set signal handlers */
139 	(void)signal(SIGINT, hi);
140 	(void)signal(SIGQUIT, hi);
141 	(void)signal(SIGTSTP, hi);
142 	(void)signal(SIGALRM, bye);
143 
144 	ntimer.it_interval = zerotime;
145 	ntimer.it_value = timeout;
146 	setitimer(ITIMER_REAL, &ntimer, &otimer);
147 
148 	/* header info */
149 (void)printf("lock: %s on %s. timeout in %d minutes\ntime now is %.20s%s%s",
150 	    ttynam, hostname, sectimeout, ap, tzn, ap + 19);
151 
152 	for (;;) {
153 		(void)printf("Key: ");
154 		if (!fgets(s, sizeof(s), stdin)) {
155 			clearerr(stdin);
156 			hi();
157 			continue;
158 		}
159 		if (usemine) {
160 			s[strlen(s) - 1] = '\0';
161 			if (!strcmp(mypw, crypt(s, mypw)))
162 				break;
163 		}
164 		else if (!strcmp(s, s1))
165 			break;
166 		(void)printf("\07\n");
167 		if (ioctl(0, TIOCGETP, &ntty))
168 			exit(1);
169 	}
170 	quit();
171 }
172 
173 void
174 hi()
175 {
176 	struct timeval timval;
177 
178 	if (!gettimeofday(&timval, (struct timezone *)NULL))
179 (void)printf("lock: type in the unlock key. timeout in %ld:%ld minutes\n",
180 	    (nexttime - timval.tv_sec) / 60, (nexttime - timval.tv_sec) % 60);
181 }
182 
183 void
184 quit()
185 {
186 	(void)putchar('\n');
187 	(void)ioctl(0, TIOCSETP, &tty);
188 	exit(0);
189 }
190 
191 void
192 bye()
193 {
194 	(void)ioctl(0, TIOCSETP, &tty);
195 	(void)printf("lock: timeout\n");
196 	exit(1);
197 }
198