xref: /csrg-svn/usr.bin/finger/util.c (revision 38052)
137660Sbostic /*
237660Sbostic  * Copyright (c) 1989 The Regents of the University of California.
337660Sbostic  * All rights reserved.
437660Sbostic  *
537660Sbostic  * Redistribution and use in source and binary forms are permitted
637660Sbostic  * provided that the above copyright notice and this paragraph are
737660Sbostic  * duplicated in all such forms and that any documentation,
837660Sbostic  * advertising materials, and other materials related to such
937660Sbostic  * distribution and use acknowledge that the software was developed
1037660Sbostic  * by the University of California, Berkeley.  The name of the
1137660Sbostic  * University may not be used to endorse or promote products derived
1237660Sbostic  * from this software without specific prior written permission.
1337660Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1437660Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1537660Sbostic  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1637660Sbostic  */
1737660Sbostic 
1837660Sbostic #ifndef lint
19*38052Sbostic static char sccsid[] = "@(#)util.c	5.6 (Berkeley) 05/18/89";
2037660Sbostic #endif /* not lint */
2137660Sbostic 
2237660Sbostic #include <sys/param.h>
2337660Sbostic #include <sys/stat.h>
2437660Sbostic #include <sys/file.h>
2537660Sbostic #include <stdio.h>
2637660Sbostic #include <ctype.h>
2737660Sbostic #include <strings.h>
2837660Sbostic #include "finger.h"
2937660Sbostic #include "pathnames.h"
3037660Sbostic 
3137664Sedward find_idle_and_ttywrite(w)
3237664Sedward 	register WHERE *w;
3337660Sbostic {
3437660Sbostic 	extern time_t now;
3537660Sbostic 	extern int errno;
3637660Sbostic 	struct stat sb;
3737660Sbostic 	char *strerror();
3837660Sbostic 
3937664Sedward 	(void)sprintf(tbuf, "%s/%s", _PATH_DEV, w->tty);
4037660Sbostic 	if (stat(tbuf, &sb) < 0) {
4137660Sbostic 		(void)fprintf(stderr,
4237660Sbostic 		    "finger: %s: %s\n", tbuf, strerror(errno));
4337660Sbostic 		exit(1);
4437660Sbostic 	}
4537664Sedward 	w->idletime = now < sb.st_atime ? 0 : now - sb.st_atime;
4637660Sbostic 
4737660Sbostic #define	TALKABLE	0220		/* tty is writable if 220 mode */
4837664Sedward 	w->writable = ((sb.st_mode & TALKABLE) == TALKABLE);
4937660Sbostic }
5037660Sbostic 
5137660Sbostic userinfo(pn, pw)
5237660Sbostic 	register PERSON *pn;
5337660Sbostic 	register struct passwd *pw;
5437660Sbostic {
5537660Sbostic 	register char *p, *t;
5637660Sbostic 	char name[256];
5737660Sbostic 
5837660Sbostic 	pn->realname = pn->office = pn->officephone = pn->homephone = NULL;
5937660Sbostic 
6037660Sbostic 	pn->uid = pw->pw_uid;
6137660Sbostic 	pn->name = strdup(pw->pw_name);
6237660Sbostic 	pn->dir = strdup(pw->pw_dir);
6337660Sbostic 	pn->shell = strdup(pw->pw_shell);
6437660Sbostic 
6537660Sbostic 	/* why do we skip asterisks!?!? */
6637660Sbostic 	(void)strcpy(p = tbuf, pw->pw_gecos);
6737660Sbostic 	if (*p == '*')
6837660Sbostic 		++p;
6937660Sbostic 
7037660Sbostic 	/* ampersands get replaced by the login name */
7137660Sbostic 	if (!(p = strsep(p, ",")))
7237660Sbostic 		return;
7337660Sbostic 	for (t = name; *t = *p; ++p)
7437660Sbostic 		if (*t == '&') {
7537660Sbostic 			(void)strcpy(t, pw->pw_name);
7637660Sbostic 			if (islower(*t))
7737660Sbostic 				*t = toupper(*t);
7837660Sbostic 			while (*++t);
7937660Sbostic 		}
8037660Sbostic 		else
8137660Sbostic 			++t;
8237660Sbostic 	pn->realname = strdup(name);
8337660Sbostic 	pn->office = (p = strsep((char *)NULL, ",")) ? strdup(p) : NULL;
8437660Sbostic 	pn->officephone = (p = strsep((char *)NULL, ",")) ? strdup(p) : NULL;
8537660Sbostic 	pn->homephone = (p = strsep((char *)NULL, ",")) ? strdup(p) : NULL;
8637660Sbostic }
8737660Sbostic 
8837660Sbostic match(pw, user)
8937660Sbostic 	struct passwd *pw;
9037660Sbostic 	char *user;
9137660Sbostic {
9237660Sbostic 	register char *p, *t;
9337660Sbostic 	char name[256];
9437660Sbostic 
9537660Sbostic 	/* why do we skip asterisks!?!? */
9637660Sbostic 	(void)strcpy(p = tbuf, pw->pw_gecos);
9737660Sbostic 	if (*p == '*')
9837660Sbostic 		++p;
9937660Sbostic 
10037660Sbostic 	/* ampersands get replaced by the login name */
10137660Sbostic 	if (!(p = strtok(p, ",")))
10237660Sbostic 		return(0);
10337660Sbostic 	for (t = name; *t = *p; ++p)
10437660Sbostic 		if (*t == '&') {
10537660Sbostic 			(void)strcpy(t, pw->pw_name);
10637660Sbostic 			while (*++t);
10737660Sbostic 		}
10837660Sbostic 		else
10937660Sbostic 			++t;
11037660Sbostic 	for (t = name; p = strtok(t, "\t "); t = (char *)NULL)
11137660Sbostic 		if (!strcasecmp(p, user))
11237660Sbostic 			return(1);
11337660Sbostic 	return(0);
11437660Sbostic }
11537660Sbostic 
11637664Sedward enter_lastlog(pn)
11737660Sbostic 	register PERSON *pn;
11837660Sbostic {
11937664Sedward 	register WHERE *w;
12037683Sedward 	static int opened, fd;
12137660Sbostic 	struct lastlog ll;
12237664Sedward 	char doit = 0;
12337660Sbostic 	off_t lseek();
12437660Sbostic 
12537665Sbostic 	/* some systems may not maintain lastlog, don't report errors. */
12637665Sbostic 	if (!opened) {
12737664Sedward 		fd = open(_PATH_LASTLOG, O_RDONLY, 0);
12837665Sbostic 		opened = 1;
12937660Sbostic 	}
13037665Sbostic 	if (fd == -1 ||
13137665Sbostic 	    lseek(fd, (long)pn->uid * sizeof(ll), L_SET) !=
13237665Sbostic 	    (long)pn->uid * sizeof(ll) ||
13337665Sbostic 	    read(fd, (char *)&ll, sizeof(ll)) != sizeof(ll)) {
13437665Sbostic 			/* as if never logged in */
13537665Sbostic 			ll.ll_line[0] = ll.ll_host[0] = NULL;
13637665Sbostic 			ll.ll_time = 0;
13737665Sbostic 		}
13837664Sedward 	if ((w = pn->whead) == NULL)
13937664Sedward 		doit = 1;
14037683Sedward 	else if (ll.ll_time != 0) {
14137664Sedward 		/* if last login is earlier than some current login */
14237664Sedward 		for (; !doit && w != NULL; w = w->next)
14337664Sedward 			if (w->info == LOGGEDIN && w->loginat < ll.ll_time)
14437664Sedward 				doit = 1;
14537664Sedward 		/*
14637664Sedward 		 * and if it's not any of the current logins
14737664Sedward 		 * can't use time comparison because there may be a small
14837664Sedward 		 * discrepency since login calls time() twice
14937664Sedward 		 */
15037664Sedward 		for (w = pn->whead; doit && w != NULL; w = w->next)
15137664Sedward 			if (w->info == LOGGEDIN &&
15237664Sedward 			    strncmp(w->tty, ll.ll_line, UT_LINESIZE) == 0)
15337664Sedward 				doit = 0;
15437660Sbostic 	}
15537664Sedward 	if (doit) {
15637664Sedward 		w = walloc(pn);
15737664Sedward 		w->info = LASTLOG;
15837664Sedward 		bcopy(ll.ll_line, w->tty, UT_LINESIZE);
15937664Sedward 		w->tty[UT_LINESIZE] = 0;
16037664Sedward 		bcopy(ll.ll_host, w->host, UT_HOSTSIZE);
16137664Sedward 		w->host[UT_HOSTSIZE] = 0;
16237664Sedward 		w->loginat = ll.ll_time;
16337664Sedward 	}
16437660Sbostic }
16537660Sbostic 
16637664Sedward enter_where(ut, pn)
16737660Sbostic 	struct utmp *ut;
16837660Sbostic 	PERSON *pn;
16937660Sbostic {
17037664Sedward 	register WHERE *w = walloc(pn);
17137664Sedward 
17237664Sedward 	w->info = LOGGEDIN;
17337664Sedward 	bcopy(ut->ut_line, w->tty, UT_LINESIZE);
17437664Sedward 	w->tty[UT_LINESIZE] = 0;
17537664Sedward 	bcopy(ut->ut_host, w->host, UT_HOSTSIZE);
17637664Sedward 	w->host[UT_HOSTSIZE] = 0;
17737664Sedward 	w->loginat = (time_t)ut->ut_time;
17837664Sedward 	find_idle_and_ttywrite(w);
17937660Sbostic }
18037664Sedward 
18137664Sedward PERSON *
18237664Sedward enter_person(pw)
18337664Sedward 	register struct passwd *pw;
18437664Sedward {
18537664Sedward 	register PERSON *pn, **pp;
18637664Sedward 
18737664Sedward 	for (pp = htab + hash(pw->pw_name);
18837664Sedward 	     *pp != NULL && strcmp((*pp)->name, pw->pw_name) != 0;
18937664Sedward 	     pp = &(*pp)->hlink)
19037664Sedward 		;
19137664Sedward 	if ((pn = *pp) == NULL) {
19237664Sedward 		pn = palloc();
19337664Sedward 		entries++;
19437664Sedward 		if (phead == NULL)
19537664Sedward 			phead = ptail = pn;
19637664Sedward 		else {
19737664Sedward 			ptail->next = pn;
19837664Sedward 			ptail = pn;
19937664Sedward 		}
20037664Sedward 		pn->next = NULL;
20137664Sedward 		pn->hlink = NULL;
20237664Sedward 		*pp = pn;
20337664Sedward 		userinfo(pn, pw);
20437664Sedward 		pn->whead = NULL;
20537664Sedward 	}
20637664Sedward 	return(pn);
20737664Sedward }
20837664Sedward 
20937664Sedward PERSON *
21037664Sedward find_person(name)
21137664Sedward 	char *name;
21237664Sedward {
21337664Sedward 	register PERSON *pn;
21437664Sedward 
21537664Sedward 	/* name may be only UT_NAMESIZE long and not terminated */
21637664Sedward 	for (pn = htab[hash(name)];
21737664Sedward 	     pn != NULL && strncmp(pn->name, name, UT_NAMESIZE) != 0;
21837664Sedward 	     pn = pn->hlink)
21937664Sedward 		;
22037664Sedward 	return(pn);
22137664Sedward }
22237664Sedward 
22337664Sedward hash(name)
22437664Sedward 	register char *name;
22537664Sedward {
22637664Sedward 	register int h, i;
22737664Sedward 
22837664Sedward 	h = 0;
22937664Sedward 	/* name may be only UT_NAMESIZE long and not terminated */
23037664Sedward 	for (i = UT_NAMESIZE; --i >= 0 && *name;)
23137664Sedward 		h = ((h << 2 | h >> HBITS - 2) ^ *name++) & HMASK;
23237664Sedward 	return(h);
23337664Sedward }
23437664Sedward 
23537664Sedward PERSON *
23637664Sedward palloc()
23737664Sedward {
23837664Sedward 	PERSON *p;
23937664Sedward 
24037664Sedward 	if ((p = (PERSON *)malloc((u_int) sizeof(PERSON))) == NULL) {
24137664Sedward 		(void)fprintf(stderr, "finger: out of space.\n");
24237664Sedward 		exit(1);
24337664Sedward 	}
24437664Sedward 	return(p);
24537664Sedward }
24637664Sedward 
24737664Sedward WHERE *
24837664Sedward walloc(pn)
24937664Sedward 	register PERSON *pn;
25037664Sedward {
25137664Sedward 	register WHERE *w;
25237664Sedward 
25337664Sedward 	if ((w = (WHERE *)malloc((u_int) sizeof(WHERE))) == NULL) {
25437664Sedward 		(void)fprintf(stderr, "finger: out of space.\n");
25537664Sedward 		exit(1);
25637664Sedward 	}
25737664Sedward 	if (pn->whead == NULL)
25837664Sedward 		pn->whead = pn->wtail = w;
25937664Sedward 	else {
26037664Sedward 		pn->wtail->next = w;
26137664Sedward 		pn->wtail = w;
26237664Sedward 	}
26337664Sedward 	w->next = NULL;
26437664Sedward 	return(w);
26537664Sedward }
266*38052Sbostic 
267*38052Sbostic char *
268*38052Sbostic prphone(num)
269*38052Sbostic 	char *num;
270*38052Sbostic {
271*38052Sbostic 	register char *p;
272*38052Sbostic 	int len;
273*38052Sbostic 	static char pbuf[15];
274*38052Sbostic 
275*38052Sbostic 	/* don't touch anything if the user has their own formatting */
276*38052Sbostic 	for (p = num; *p; ++p)
277*38052Sbostic 		if (!isdigit(*p))
278*38052Sbostic 			return(num);
279*38052Sbostic 	len = p - num;
280*38052Sbostic 	p = pbuf;
281*38052Sbostic 	switch(len) {
282*38052Sbostic 	case 11:			/* +0-123-456-7890 */
283*38052Sbostic 		*p++ = '+';
284*38052Sbostic 		*p++ = *num++;
285*38052Sbostic 		*p++ = '-';
286*38052Sbostic 		/* FALLTHROUGH */
287*38052Sbostic 	case 10:			/* 012-345-6789 */
288*38052Sbostic 		*p++ = *num++;
289*38052Sbostic 		*p++ = *num++;
290*38052Sbostic 		*p++ = *num++;
291*38052Sbostic 		*p++ = '-';
292*38052Sbostic 		/* FALLTHROUGH */
293*38052Sbostic 	case 7:				/* 012-3456 */
294*38052Sbostic 		*p++ = *num++;
295*38052Sbostic 		*p++ = *num++;
296*38052Sbostic 		*p++ = *num++;
297*38052Sbostic 		break;
298*38052Sbostic 	case 5:				/* x0-1234 */
299*38052Sbostic 		*p++ = 'x';
300*38052Sbostic 		*p++ = *num++;
301*38052Sbostic 		break;
302*38052Sbostic 	default:
303*38052Sbostic 		return(num);
304*38052Sbostic 	}
305*38052Sbostic 	*p++ = '-';
306*38052Sbostic 	*p++ = *num++;
307*38052Sbostic 	*p++ = *num++;
308*38052Sbostic 	*p++ = *num++;
309*38052Sbostic 	*p++ = *num++;
310*38052Sbostic 	*p = '\0';
311*38052Sbostic 	return(pbuf);
312*38052Sbostic }
313