lock.c revision 27575
11590Srgrimes/* 21590Srgrimes * Copyright (c) 1980, 1987, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * This code is derived from software contributed to Berkeley by 61590Srgrimes * Bob Toxen. 71590Srgrimes * 81590Srgrimes * Redistribution and use in source and binary forms, with or without 91590Srgrimes * modification, are permitted provided that the following conditions 101590Srgrimes * are met: 111590Srgrimes * 1. Redistributions of source code must retain the above copyright 121590Srgrimes * notice, this list of conditions and the following disclaimer. 131590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141590Srgrimes * notice, this list of conditions and the following disclaimer in the 151590Srgrimes * documentation and/or other materials provided with the distribution. 161590Srgrimes * 3. All advertising materials mentioning features or use of this software 171590Srgrimes * must display the following acknowledgement: 181590Srgrimes * This product includes software developed by the University of 191590Srgrimes * California, Berkeley and its contributors. 201590Srgrimes * 4. Neither the name of the University nor the names of its contributors 211590Srgrimes * may be used to endorse or promote products derived from this software 221590Srgrimes * without specific prior written permission. 231590Srgrimes * 241590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 251590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 261590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 271590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 281590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 291590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 301590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 311590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 321590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 331590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 341590Srgrimes * SUCH DAMAGE. 351590Srgrimes */ 361590Srgrimes 371590Srgrimes#ifndef lint 3827575Scharnierstatic const char copyright[] = 391590Srgrimes"@(#) Copyright (c) 1980, 1987, 1993\n\ 401590Srgrimes The Regents of the University of California. All rights reserved.\n"; 411590Srgrimes#endif /* not lint */ 421590Srgrimes 431590Srgrimes#ifndef lint 4427575Scharnier#if 0 451590Srgrimesstatic char sccsid[] = "@(#)lock.c 8.1 (Berkeley) 6/6/93"; 4627575Scharnier#endif 4727575Scharnierstatic const char rcsid[] = 4827575Scharnier "$Id$"; 491590Srgrimes#endif /* not lint */ 501590Srgrimes 511590Srgrimes/* 521590Srgrimes * Lock a terminal up until the given key is entered, until the root 531590Srgrimes * password is entered, or the given interval times out. 541590Srgrimes * 551590Srgrimes * Timeout interval is by default TIMEOUT, it can be changed with 561590Srgrimes * an argument of the form -time where time is in minutes 571590Srgrimes */ 581590Srgrimes 591590Srgrimes#include <sys/param.h> 601590Srgrimes#include <sys/stat.h> 611590Srgrimes#include <sys/time.h> 621590Srgrimes#include <sys/signal.h> 6327575Scharnier#include <err.h> 6427575Scharnier#include <ctype.h> 6527575Scharnier#include <pwd.h> 661590Srgrimes#include <sgtty.h> 671590Srgrimes#include <stdio.h> 6827575Scharnier#include <stdlib.h> 691590Srgrimes#include <string.h> 7027575Scharnier#include <unistd.h> 711590Srgrimes 721590Srgrimes#define TIMEOUT 15 731590Srgrimes 741590Srgrimesvoid quit(), bye(), hi(); 7527575Scharnierstatic void usage __P((void)); 761590Srgrimes 771590Srgrimesstruct timeval timeout; 781590Srgrimesstruct timeval zerotime; 791590Srgrimesstruct sgttyb tty, ntty; 801590Srgrimeslong nexttime; /* keep the timeout time */ 8118295Srobertoint no_timeout; /* lock terminal forever */ 821590Srgrimes 831590Srgrimes/*ARGSUSED*/ 8427575Scharnierint 851590Srgrimesmain(argc, argv) 861590Srgrimes int argc; 871590Srgrimes char **argv; 881590Srgrimes{ 891590Srgrimes struct passwd *pw; 901590Srgrimes struct timeval timval; 911590Srgrimes struct itimerval ntimer, otimer; 921590Srgrimes struct tm *timp; 931590Srgrimes int ch, sectimeout, usemine; 941590Srgrimes char *ap, *mypw, *ttynam, *tzn; 951590Srgrimes char hostname[MAXHOSTNAMELEN], s[BUFSIZ], s1[BUFSIZ]; 961590Srgrimes char *crypt(), *ttyname(); 971590Srgrimes 981590Srgrimes sectimeout = TIMEOUT; 991590Srgrimes mypw = NULL; 1001590Srgrimes usemine = 0; 10118295Sroberto no_timeout = 0; 10224360Simp while ((ch = getopt(argc, argv, "npt:")) != -1) 1031590Srgrimes switch((char)ch) { 1041590Srgrimes case 't': 10527575Scharnier if ((sectimeout = atoi(optarg)) <= 0) 10627575Scharnier errx(1, "illegal timeout value"); 1071590Srgrimes break; 1081590Srgrimes case 'p': 1091590Srgrimes usemine = 1; 11027575Scharnier if (!(pw = getpwuid(getuid()))) 11127575Scharnier errx(1, "unknown uid %d", getuid()); 1121590Srgrimes mypw = strdup(pw->pw_passwd); 1131590Srgrimes break; 11418295Sroberto case 'n': 11518295Sroberto no_timeout = 1; 11618295Sroberto break; 1171590Srgrimes case '?': 1181590Srgrimes default: 11927575Scharnier usage(); 1201590Srgrimes } 1211590Srgrimes timeout.tv_sec = sectimeout * 60; 1221590Srgrimes 1231590Srgrimes setuid(getuid()); /* discard privs */ 1241590Srgrimes 1251590Srgrimes if (ioctl(0, TIOCGETP, &tty)) /* get information for header */ 1261590Srgrimes exit(1); 1271590Srgrimes gethostname(hostname, sizeof(hostname)); 12827575Scharnier if (!(ttynam = ttyname(0))) 12927575Scharnier errx(1, "not a terminal?"); 13027575Scharnier if (gettimeofday(&timval, (struct timezone *)NULL)) 13127575Scharnier err(1, "gettimeofday"); 1321590Srgrimes nexttime = timval.tv_sec + (sectimeout * 60); 1331590Srgrimes timp = localtime(&timval.tv_sec); 1341590Srgrimes ap = asctime(timp); 1351590Srgrimes tzn = timp->tm_zone; 1361590Srgrimes 1371590Srgrimes (void)signal(SIGINT, quit); 1381590Srgrimes (void)signal(SIGQUIT, quit); 1391590Srgrimes ntty = tty; ntty.sg_flags &= ~ECHO; 1401590Srgrimes (void)ioctl(0, TIOCSETP, &ntty); 1411590Srgrimes 1421590Srgrimes if (!mypw) { 1431590Srgrimes /* get key and check again */ 1441590Srgrimes (void)printf("Key: "); 1451590Srgrimes if (!fgets(s, sizeof(s), stdin) || *s == '\n') 1461590Srgrimes quit(); 1471590Srgrimes (void)printf("\nAgain: "); 1481590Srgrimes /* 1491590Srgrimes * Don't need EOF test here, if we get EOF, then s1 != s 1501590Srgrimes * and the right things will happen. 1511590Srgrimes */ 1521590Srgrimes (void)fgets(s1, sizeof(s1), stdin); 1531590Srgrimes (void)putchar('\n'); 1541590Srgrimes if (strcmp(s1, s)) { 1551590Srgrimes (void)printf("\07lock: passwords didn't match.\n"); 1561590Srgrimes ioctl(0, TIOCSETP, &tty); 1571590Srgrimes exit(1); 1581590Srgrimes } 15927575Scharnier s[0] = '\0'; 1601590Srgrimes mypw = s1; 1611590Srgrimes } 1621590Srgrimes 1631590Srgrimes /* set signal handlers */ 1641590Srgrimes (void)signal(SIGINT, hi); 1651590Srgrimes (void)signal(SIGQUIT, hi); 1661590Srgrimes (void)signal(SIGTSTP, hi); 1671590Srgrimes (void)signal(SIGALRM, bye); 1681590Srgrimes 1691590Srgrimes ntimer.it_interval = zerotime; 1701590Srgrimes ntimer.it_value = timeout; 17118295Sroberto if (!no_timeout) 17218295Sroberto setitimer(ITIMER_REAL, &ntimer, &otimer); 1731590Srgrimes 1741590Srgrimes /* header info */ 17518295Sroberto if (no_timeout) { 17618295Sroberto(void)printf("lock: %s on %s. no timeout\ntime now is %.20s%s%s", 17718295Sroberto ttynam, hostname, ap, tzn, ap + 19); 17818295Sroberto } else { 1791590Srgrimes(void)printf("lock: %s on %s. timeout in %d minutes\ntime now is %.20s%s%s", 1801590Srgrimes ttynam, hostname, sectimeout, ap, tzn, ap + 19); 18118295Sroberto } 1821590Srgrimes 1831590Srgrimes for (;;) { 1841590Srgrimes (void)printf("Key: "); 1851590Srgrimes if (!fgets(s, sizeof(s), stdin)) { 1861590Srgrimes clearerr(stdin); 1871590Srgrimes hi(); 1881590Srgrimes continue; 1891590Srgrimes } 1901590Srgrimes if (usemine) { 1911590Srgrimes s[strlen(s) - 1] = '\0'; 1921590Srgrimes if (!strcmp(mypw, crypt(s, mypw))) 1931590Srgrimes break; 1941590Srgrimes } 1951590Srgrimes else if (!strcmp(s, s1)) 1961590Srgrimes break; 1971590Srgrimes (void)printf("\07\n"); 1981590Srgrimes if (ioctl(0, TIOCGETP, &ntty)) 1991590Srgrimes exit(1); 2001590Srgrimes } 2011590Srgrimes quit(); 20227575Scharnier return(0); /* not reached */ 2031590Srgrimes} 2041590Srgrimes 20527575Scharnier 20627575Scharnierstatic void 20727575Scharnierusage() 20827575Scharnier{ 20927575Scharnier (void)fprintf(stderr, "usage: lock [-n] [-p] [-t timeout]\n"); 21027575Scharnier exit(1); 21127575Scharnier} 21227575Scharnier 2131590Srgrimesvoid 2141590Srgrimeshi() 2151590Srgrimes{ 2161590Srgrimes struct timeval timval; 2171590Srgrimes 21818295Sroberto if (!gettimeofday(&timval, (struct timezone *)NULL)) { 21918295Sroberto (void)printf("lock: type in the unlock key. "); 22018295Sroberto if (no_timeout) { 22118295Sroberto (void)putchar('\n'); 22218295Sroberto } else { 22318295Sroberto (void)printf("timeout in %ld:%ld minutes\n", 22418295Sroberto (nexttime - timval.tv_sec) / 60, 22518295Sroberto (nexttime - timval.tv_sec) % 60); 22618295Sroberto } 22718295Sroberto } 2281590Srgrimes} 2291590Srgrimes 2301590Srgrimesvoid 2311590Srgrimesquit() 2321590Srgrimes{ 2331590Srgrimes (void)putchar('\n'); 2341590Srgrimes (void)ioctl(0, TIOCSETP, &tty); 2351590Srgrimes exit(0); 2361590Srgrimes} 2371590Srgrimes 2381590Srgrimesvoid 2391590Srgrimesbye() 2401590Srgrimes{ 24118295Sroberto if (!no_timeout) { 24218295Sroberto (void)ioctl(0, TIOCSETP, &tty); 24318295Sroberto (void)printf("lock: timeout\n"); 24418295Sroberto exit(1); 24518295Sroberto } 2461590Srgrimes} 247