xref: /csrg-svn/usr.bin/finger/util.c (revision 50613)
137660Sbostic /*
237660Sbostic  * Copyright (c) 1989 The Regents of the University of California.
337660Sbostic  * All rights reserved.
437660Sbostic  *
540027Sbostic  * This code is derived from software contributed to Berkeley by
640027Sbostic  * Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
740027Sbostic  *
842731Sbostic  * %sccs.include.redist.c%
937660Sbostic  */
1037660Sbostic 
1137660Sbostic #ifndef lint
12*50613Sbostic static char sccsid[] = "@(#)util.c	5.16 (Berkeley) 07/27/91";
1337660Sbostic #endif /* not lint */
1437660Sbostic 
1537660Sbostic #include <sys/param.h>
1637660Sbostic #include <sys/stat.h>
1750596Sbostic #include <fcntl.h>
18*50613Sbostic #include <db.h>
1950596Sbostic #include <pwd.h>
2050596Sbostic #include <utmp.h>
2150596Sbostic #include <errno.h>
2250596Sbostic #include <unistd.h>
2337660Sbostic #include <stdio.h>
2437660Sbostic #include <ctype.h>
2550596Sbostic #include <stdlib.h>
2642053Sbostic #include <string.h>
2743857Sbostic #include <paths.h>
2837660Sbostic #include "finger.h"
2937660Sbostic 
3050596Sbostic static void	 find_idle_and_ttywrite __P((WHERE *));
3150596Sbostic static void	 userinfo __P((PERSON *, struct passwd *));
3250596Sbostic static WHERE	*walloc __P((PERSON *));
3350596Sbostic 
3437660Sbostic match(pw, user)
3537660Sbostic 	struct passwd *pw;
3637660Sbostic 	char *user;
3737660Sbostic {
3837660Sbostic 	register char *p, *t;
3941568Smarc 	char name[1024];
4037660Sbostic 
4137660Sbostic 	/* why do we skip asterisks!?!? */
4237660Sbostic 	(void)strcpy(p = tbuf, pw->pw_gecos);
4337660Sbostic 	if (*p == '*')
4437660Sbostic 		++p;
4537660Sbostic 
4637660Sbostic 	/* ampersands get replaced by the login name */
4737660Sbostic 	if (!(p = strtok(p, ",")))
4837660Sbostic 		return(0);
4937660Sbostic 	for (t = name; *t = *p; ++p)
5037660Sbostic 		if (*t == '&') {
5137660Sbostic 			(void)strcpy(t, pw->pw_name);
5237660Sbostic 			while (*++t);
5337660Sbostic 		}
5437660Sbostic 		else
5537660Sbostic 			++t;
5637660Sbostic 	for (t = name; p = strtok(t, "\t "); t = (char *)NULL)
5737660Sbostic 		if (!strcasecmp(p, user))
5837660Sbostic 			return(1);
5937660Sbostic 	return(0);
6037660Sbostic }
6137660Sbostic 
6250596Sbostic void
6337664Sedward enter_lastlog(pn)
6437660Sbostic 	register PERSON *pn;
6537660Sbostic {
6637664Sedward 	register WHERE *w;
6737683Sedward 	static int opened, fd;
6837660Sbostic 	struct lastlog ll;
6937664Sedward 	char doit = 0;
7037660Sbostic 
7137665Sbostic 	/* some systems may not maintain lastlog, don't report errors. */
7237665Sbostic 	if (!opened) {
7337664Sedward 		fd = open(_PATH_LASTLOG, O_RDONLY, 0);
7437665Sbostic 		opened = 1;
7537660Sbostic 	}
7637665Sbostic 	if (fd == -1 ||
7750596Sbostic 	    lseek(fd, (long)pn->uid * sizeof(ll), SEEK_SET) !=
7837665Sbostic 	    (long)pn->uid * sizeof(ll) ||
7937665Sbostic 	    read(fd, (char *)&ll, sizeof(ll)) != sizeof(ll)) {
8037665Sbostic 			/* as if never logged in */
8137665Sbostic 			ll.ll_line[0] = ll.ll_host[0] = NULL;
8237665Sbostic 			ll.ll_time = 0;
8337665Sbostic 		}
8437664Sedward 	if ((w = pn->whead) == NULL)
8537664Sedward 		doit = 1;
8637683Sedward 	else if (ll.ll_time != 0) {
8737664Sedward 		/* if last login is earlier than some current login */
8837664Sedward 		for (; !doit && w != NULL; w = w->next)
8937664Sedward 			if (w->info == LOGGEDIN && w->loginat < ll.ll_time)
9037664Sedward 				doit = 1;
9137664Sedward 		/*
9237664Sedward 		 * and if it's not any of the current logins
9337664Sedward 		 * can't use time comparison because there may be a small
9437664Sedward 		 * discrepency since login calls time() twice
9537664Sedward 		 */
9637664Sedward 		for (w = pn->whead; doit && w != NULL; w = w->next)
9737664Sedward 			if (w->info == LOGGEDIN &&
9837664Sedward 			    strncmp(w->tty, ll.ll_line, UT_LINESIZE) == 0)
9937664Sedward 				doit = 0;
10037660Sbostic 	}
10137664Sedward 	if (doit) {
10237664Sedward 		w = walloc(pn);
10337664Sedward 		w->info = LASTLOG;
10437664Sedward 		bcopy(ll.ll_line, w->tty, UT_LINESIZE);
10537664Sedward 		w->tty[UT_LINESIZE] = 0;
10637664Sedward 		bcopy(ll.ll_host, w->host, UT_HOSTSIZE);
10737664Sedward 		w->host[UT_HOSTSIZE] = 0;
10837664Sedward 		w->loginat = ll.ll_time;
10937664Sedward 	}
11037660Sbostic }
11137660Sbostic 
11250596Sbostic void
11337664Sedward enter_where(ut, pn)
11437660Sbostic 	struct utmp *ut;
11537660Sbostic 	PERSON *pn;
11637660Sbostic {
11750596Sbostic 	register WHERE *w;
11837664Sedward 
11950596Sbostic 	w = walloc(pn);
12037664Sedward 	w->info = LOGGEDIN;
12137664Sedward 	bcopy(ut->ut_line, w->tty, UT_LINESIZE);
12237664Sedward 	w->tty[UT_LINESIZE] = 0;
12337664Sedward 	bcopy(ut->ut_host, w->host, UT_HOSTSIZE);
12437664Sedward 	w->host[UT_HOSTSIZE] = 0;
12537664Sedward 	w->loginat = (time_t)ut->ut_time;
12637664Sedward 	find_idle_and_ttywrite(w);
12737660Sbostic }
12837664Sedward 
12937664Sedward PERSON *
13037664Sedward enter_person(pw)
13137664Sedward 	register struct passwd *pw;
13237664Sedward {
133*50613Sbostic 	PERSON *pn;
134*50613Sbostic 	DBT data, key;
13537664Sedward 
136*50613Sbostic 	if (db == NULL && (db = hash_open(NULL, O_RDWR, 0, NULL)) == NULL)
137*50613Sbostic 		err("%s", strerror(errno));
138*50613Sbostic 
139*50613Sbostic 	key.data = pw->pw_name;
140*50613Sbostic 	key.size = strlen(pw->pw_name);
141*50613Sbostic 
142*50613Sbostic 	switch((*db->get)(db, &key, &data, 0)) {
143*50613Sbostic 	case 0:
144*50613Sbostic 		return(*(PERSON **)data.data);
145*50613Sbostic 	default:
146*50613Sbostic 	case -1:
147*50613Sbostic 		err("db get: %s", strerror(errno));
148*50613Sbostic 		/* NOTREACHED */
149*50613Sbostic 	case 1:
150*50613Sbostic 		++entries;
15137664Sedward 		pn = palloc();
15237664Sedward 		userinfo(pn, pw);
15337664Sedward 		pn->whead = NULL;
154*50613Sbostic 
155*50613Sbostic 		data.size = sizeof(PERSON *);
156*50613Sbostic 		data.data = &pn;
157*50613Sbostic 		if ((*db->put)(db, &key, &data, R_PUT))
158*50613Sbostic 			err("%s", strerror(errno));
159*50613Sbostic 		return(pn);
16037664Sedward 	}
16137664Sedward }
16237664Sedward 
16337664Sedward PERSON *
16437664Sedward find_person(name)
16537664Sedward 	char *name;
16637664Sedward {
167*50613Sbostic 	register int cnt;
168*50613Sbostic 	DBT data, key;
169*50613Sbostic 	char buf[UT_NAMESIZE + 1];
17037664Sedward 
171*50613Sbostic 	if (!db)
172*50613Sbostic 		return(NULL);
17337664Sedward 
174*50613Sbostic 	/* Name may be only UT_NAMESIZE long and not NUL terminated. */
175*50613Sbostic 	for (cnt = 0; cnt < UT_NAMESIZE && *name; ++name, ++cnt)
176*50613Sbostic 		buf[cnt] = *name;
177*50613Sbostic 	buf[cnt] = '\0';
178*50613Sbostic 	key.data = buf;
179*50613Sbostic 	key.size = cnt;
18037664Sedward 
181*50613Sbostic 	return((*db->get)(db, &key, &data, 0) ? NULL : *(PERSON **)data.data);
18237664Sedward }
18337664Sedward 
18437664Sedward PERSON *
18537664Sedward palloc()
18637664Sedward {
18737664Sedward 	PERSON *p;
18837664Sedward 
18950596Sbostic 	if ((p = malloc((u_int) sizeof(PERSON))) == NULL)
19050596Sbostic 		err("%s", strerror(errno));
19137664Sedward 	return(p);
19237664Sedward }
19337664Sedward 
19450596Sbostic static WHERE *
19537664Sedward walloc(pn)
19637664Sedward 	register PERSON *pn;
19737664Sedward {
19837664Sedward 	register WHERE *w;
19937664Sedward 
200*50613Sbostic 	if ((w = malloc((u_int) sizeof(WHERE))) == NULL)
201*50613Sbostic 		err("%s", strerror(errno));
20237664Sedward 	if (pn->whead == NULL)
20337664Sedward 		pn->whead = pn->wtail = w;
20437664Sedward 	else {
20537664Sedward 		pn->wtail->next = w;
20637664Sedward 		pn->wtail = w;
20737664Sedward 	}
20837664Sedward 	w->next = NULL;
20937664Sedward 	return(w);
21037664Sedward }
21138052Sbostic 
21238052Sbostic char *
21338052Sbostic prphone(num)
21438052Sbostic 	char *num;
21538052Sbostic {
21638052Sbostic 	register char *p;
21738052Sbostic 	int len;
21838052Sbostic 	static char pbuf[15];
21938052Sbostic 
22038052Sbostic 	/* don't touch anything if the user has their own formatting */
22138052Sbostic 	for (p = num; *p; ++p)
22238052Sbostic 		if (!isdigit(*p))
22338052Sbostic 			return(num);
22438052Sbostic 	len = p - num;
22538052Sbostic 	p = pbuf;
22638052Sbostic 	switch(len) {
22738052Sbostic 	case 11:			/* +0-123-456-7890 */
22838052Sbostic 		*p++ = '+';
22938052Sbostic 		*p++ = *num++;
23038052Sbostic 		*p++ = '-';
23138052Sbostic 		/* FALLTHROUGH */
23238052Sbostic 	case 10:			/* 012-345-6789 */
23338052Sbostic 		*p++ = *num++;
23438052Sbostic 		*p++ = *num++;
23538052Sbostic 		*p++ = *num++;
23638052Sbostic 		*p++ = '-';
23738052Sbostic 		/* FALLTHROUGH */
23838052Sbostic 	case 7:				/* 012-3456 */
23938052Sbostic 		*p++ = *num++;
24038052Sbostic 		*p++ = *num++;
24138052Sbostic 		*p++ = *num++;
24238052Sbostic 		break;
24338052Sbostic 	case 5:				/* x0-1234 */
24438052Sbostic 		*p++ = 'x';
24538052Sbostic 		*p++ = *num++;
24638052Sbostic 		break;
24738052Sbostic 	default:
24838052Sbostic 		return(num);
24938052Sbostic 	}
25038052Sbostic 	*p++ = '-';
25138052Sbostic 	*p++ = *num++;
25238052Sbostic 	*p++ = *num++;
25338052Sbostic 	*p++ = *num++;
25438052Sbostic 	*p++ = *num++;
25538052Sbostic 	*p = '\0';
25638052Sbostic 	return(pbuf);
25738052Sbostic }
25850596Sbostic 
259*50613Sbostic static void
260*50613Sbostic find_idle_and_ttywrite(w)
261*50613Sbostic 	register WHERE *w;
262*50613Sbostic {
263*50613Sbostic 	extern time_t now;
264*50613Sbostic 	struct stat sb;
265*50613Sbostic 
266*50613Sbostic 	(void)snprintf(tbuf, sizeof(tbuf), "%s/%s", _PATH_DEV, w->tty);
267*50613Sbostic 	if (stat(tbuf, &sb) < 0) {
268*50613Sbostic 		(void)fprintf(stderr,
269*50613Sbostic 		    "finger: %s: %s\n", tbuf, strerror(errno));
270*50613Sbostic 		return;
271*50613Sbostic 	}
272*50613Sbostic 	w->idletime = now < sb.st_atime ? 0 : now - sb.st_atime;
273*50613Sbostic 
274*50613Sbostic #define	TALKABLE	0220		/* tty is writable if 220 mode */
275*50613Sbostic 	w->writable = ((sb.st_mode & TALKABLE) == TALKABLE);
276*50613Sbostic }
277*50613Sbostic 
278*50613Sbostic static void
279*50613Sbostic userinfo(pn, pw)
280*50613Sbostic 	register PERSON *pn;
281*50613Sbostic 	register struct passwd *pw;
282*50613Sbostic {
283*50613Sbostic 	register char *p, *t;
284*50613Sbostic 	char *bp, name[1024];
285*50613Sbostic 
286*50613Sbostic 	pn->realname = pn->office = pn->officephone = pn->homephone = NULL;
287*50613Sbostic 
288*50613Sbostic 	pn->uid = pw->pw_uid;
289*50613Sbostic 	pn->name = strdup(pw->pw_name);
290*50613Sbostic 	pn->dir = strdup(pw->pw_dir);
291*50613Sbostic 	pn->shell = strdup(pw->pw_shell);
292*50613Sbostic 
293*50613Sbostic 	/* why do we skip asterisks!?!? */
294*50613Sbostic 	(void)strcpy(bp = tbuf, pw->pw_gecos);
295*50613Sbostic 	if (*bp == '*')
296*50613Sbostic 		++bp;
297*50613Sbostic 
298*50613Sbostic 	/* ampersands get replaced by the login name */
299*50613Sbostic 	if (!(p = strsep(&bp, ",")))
300*50613Sbostic 		return;
301*50613Sbostic 	for (t = name; *t = *p; ++p)
302*50613Sbostic 		if (*t == '&') {
303*50613Sbostic 			(void)strcpy(t, pw->pw_name);
304*50613Sbostic 			if (islower(*t))
305*50613Sbostic 				*t = toupper(*t);
306*50613Sbostic 			while (*++t);
307*50613Sbostic 		}
308*50613Sbostic 		else
309*50613Sbostic 			++t;
310*50613Sbostic 	pn->realname = strdup(name);
311*50613Sbostic 	pn->office = ((p = strsep(&bp, ",")) && *p) ?
312*50613Sbostic 	    strdup(p) : NULL;
313*50613Sbostic 	pn->officephone = ((p = strsep(&bp, ",")) && *p) ?
314*50613Sbostic 	    strdup(p) : NULL;
315*50613Sbostic 	pn->homephone = ((p = strsep(&bp, ",")) && *p) ?
316*50613Sbostic 	    strdup(p) : NULL;
317*50613Sbostic }
318*50613Sbostic 
31950596Sbostic #if __STDC__
32050596Sbostic #include <stdarg.h>
32150596Sbostic #else
32250596Sbostic #include <varargs.h>
32350596Sbostic #endif
32450596Sbostic 
32550596Sbostic void
32650596Sbostic #if __STDC__
32750596Sbostic err(const char *fmt, ...)
32850596Sbostic #else
32950596Sbostic err(fmt, va_alist)
33050596Sbostic 	char *fmt;
33150596Sbostic 	va_dcl
33250596Sbostic #endif
33350596Sbostic {
33450596Sbostic 	va_list ap;
33550596Sbostic #if __STDC__
33650596Sbostic 	va_start(ap, fmt);
33750596Sbostic #else
33850596Sbostic 	va_start(ap);
33950596Sbostic #endif
34050596Sbostic 	(void)fprintf(stderr, "finger: ");
34150596Sbostic 	(void)vfprintf(stderr, fmt, ap);
34250596Sbostic 	va_end(ap);
34350596Sbostic 	(void)fprintf(stderr, "\n");
34450596Sbostic 	exit(1);
34550596Sbostic 	/* NOTREACHED */
34650596Sbostic }
347