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