xref: /csrg-svn/usr.bin/finger/util.c (revision 37664)
137660Sbostic /*
237660Sbostic  * Copyright (c) 1989 The Regents of the University of California.
337660Sbostic  * All rights reserved.
437660Sbostic  *
537660Sbostic  * This code is derived from software contributed to Berkeley by
637660Sbostic  * Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
737660Sbostic  *
837660Sbostic  * Redistribution and use in source and binary forms are permitted
937660Sbostic  * provided that the above copyright notice and this paragraph are
1037660Sbostic  * duplicated in all such forms and that any documentation,
1137660Sbostic  * advertising materials, and other materials related to such
1237660Sbostic  * distribution and use acknowledge that the software was developed
1337660Sbostic  * by the University of California, Berkeley.  The name of the
1437660Sbostic  * University may not be used to endorse or promote products derived
1537660Sbostic  * from this software without specific prior written permission.
1637660Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1737660Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1837660Sbostic  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1937660Sbostic  */
2037660Sbostic 
2137660Sbostic #ifndef lint
22*37664Sedward static char sccsid[] = "@(#)util.c	5.2 (Berkeley) 05/07/89";
2337660Sbostic #endif /* not lint */
2437660Sbostic 
2537660Sbostic #include <sys/param.h>
2637660Sbostic #include <sys/stat.h>
2737660Sbostic #include <sys/file.h>
2837660Sbostic #include <stdio.h>
2937660Sbostic #include <ctype.h>
3037660Sbostic #include <strings.h>
3137660Sbostic #include "finger.h"
3237660Sbostic #include "pathnames.h"
3337660Sbostic 
34*37664Sedward find_idle_and_ttywrite(w)
35*37664Sedward 	register WHERE *w;
3637660Sbostic {
3737660Sbostic 	extern time_t now;
3837660Sbostic 	extern int errno;
3937660Sbostic 	struct stat sb;
4037660Sbostic 	char *strerror();
4137660Sbostic 
42*37664Sedward 	(void)sprintf(tbuf, "%s/%s", _PATH_DEV, w->tty);
4337660Sbostic 	if (stat(tbuf, &sb) < 0) {
4437660Sbostic 		(void)fprintf(stderr,
4537660Sbostic 		    "finger: %s: %s\n", tbuf, strerror(errno));
4637660Sbostic 		exit(1);
4737660Sbostic 	}
48*37664Sedward 	w->idletime = now < sb.st_atime ? 0 : now - sb.st_atime;
4937660Sbostic 
5037660Sbostic #define	TALKABLE	0220		/* tty is writable if 220 mode */
51*37664Sedward 	w->writable = ((sb.st_mode & TALKABLE) == TALKABLE);
5237660Sbostic }
5337660Sbostic 
5437660Sbostic userinfo(pn, pw)
5537660Sbostic 	register PERSON *pn;
5637660Sbostic 	register struct passwd *pw;
5737660Sbostic {
5837660Sbostic 	register char *p, *t;
5937660Sbostic 	char name[256];
6037660Sbostic 
6137660Sbostic 	pn->realname = pn->office = pn->officephone = pn->homephone = NULL;
6237660Sbostic 
6337660Sbostic 	pn->uid = pw->pw_uid;
6437660Sbostic 	pn->name = strdup(pw->pw_name);
6537660Sbostic 	pn->dir = strdup(pw->pw_dir);
6637660Sbostic 	pn->shell = strdup(pw->pw_shell);
6737660Sbostic 
6837660Sbostic 	/* why do we skip asterisks!?!? */
6937660Sbostic 	(void)strcpy(p = tbuf, pw->pw_gecos);
7037660Sbostic 	if (*p == '*')
7137660Sbostic 		++p;
7237660Sbostic 
7337660Sbostic 	/* ampersands get replaced by the login name */
7437660Sbostic 	if (!(p = strsep(p, ",")))
7537660Sbostic 		return;
7637660Sbostic 	for (t = name; *t = *p; ++p)
7737660Sbostic 		if (*t == '&') {
7837660Sbostic 			(void)strcpy(t, pw->pw_name);
7937660Sbostic 			if (islower(*t))
8037660Sbostic 				*t = toupper(*t);
8137660Sbostic 			while (*++t);
8237660Sbostic 		}
8337660Sbostic 		else
8437660Sbostic 			++t;
8537660Sbostic 	pn->realname = strdup(name);
8637660Sbostic 	pn->office = (p = strsep((char *)NULL, ",")) ? strdup(p) : NULL;
8737660Sbostic 	pn->officephone = (p = strsep((char *)NULL, ",")) ? strdup(p) : NULL;
8837660Sbostic 	pn->homephone = (p = strsep((char *)NULL, ",")) ? strdup(p) : NULL;
8937660Sbostic }
9037660Sbostic 
9137660Sbostic match(pw, user)
9237660Sbostic 	struct passwd *pw;
9337660Sbostic 	char *user;
9437660Sbostic {
9537660Sbostic 	register char *p, *t;
9637660Sbostic 	char name[256];
9737660Sbostic 
9837660Sbostic 	/* why do we skip asterisks!?!? */
9937660Sbostic 	(void)strcpy(p = tbuf, pw->pw_gecos);
10037660Sbostic 	if (*p == '*')
10137660Sbostic 		++p;
10237660Sbostic 
10337660Sbostic 	/* ampersands get replaced by the login name */
10437660Sbostic 	if (!(p = strtok(p, ",")))
10537660Sbostic 		return(0);
10637660Sbostic 	for (t = name; *t = *p; ++p)
10737660Sbostic 		if (*t == '&') {
10837660Sbostic 			(void)strcpy(t, pw->pw_name);
10937660Sbostic 			while (*++t);
11037660Sbostic 		}
11137660Sbostic 		else
11237660Sbostic 			++t;
11337660Sbostic 	for (t = name; p = strtok(t, "\t "); t = (char *)NULL)
11437660Sbostic 		if (!strcasecmp(p, user))
11537660Sbostic 			return(1);
11637660Sbostic 	return(0);
11737660Sbostic }
11837660Sbostic 
119*37664Sedward enter_lastlog(pn)
12037660Sbostic 	register PERSON *pn;
12137660Sbostic {
122*37664Sedward 	register WHERE *w;
12337660Sbostic 	static int fd;
12437660Sbostic 	struct lastlog ll;
125*37664Sedward 	char doit = 0;
12637660Sbostic 	off_t lseek();
12737660Sbostic 
128*37664Sedward 	/*
129*37664Sedward 	 * Some systems may choose not to keep lastlog,
130*37664Sedward 	 * so we don't report any errors.
131*37664Sedward 	 * Not only that, we leave fd at -1 so lseek and read
132*37664Sedward 	 * will fail and act like there were no last logins.
133*37664Sedward 	 * Not the fastest way to do it, but what the hell.
134*37664Sedward 	 */
135*37664Sedward 	if (fd == 0)
136*37664Sedward 		fd = open(_PATH_LASTLOG, O_RDONLY, 0);
137*37664Sedward 	(void) lseek(fd, (long) (pn->uid * sizeof ll), L_SET);
138*37664Sedward 	if (read(fd, (char *)&ll, sizeof ll) != sizeof ll) {
139*37664Sedward 		/* same as never logged in */
140*37664Sedward 		ll.ll_line[0] = 0;
141*37664Sedward 		ll.ll_host[0] = 0;
142*37664Sedward 		ll.ll_time = 0;
14337660Sbostic 	}
144*37664Sedward 	if ((w = pn->whead) == NULL)
145*37664Sedward 		doit = 1;
146*37664Sedward 	else {
147*37664Sedward 		/* if last login is earlier than some current login */
148*37664Sedward 		for (; !doit && w != NULL; w = w->next)
149*37664Sedward 			if (w->info == LOGGEDIN && w->loginat < ll.ll_time)
150*37664Sedward 				doit = 1;
151*37664Sedward 		/*
152*37664Sedward 		 * and if it's not any of the current logins
153*37664Sedward 		 * can't use time comparison because there may be a small
154*37664Sedward 		 * discrepency since login calls time() twice
155*37664Sedward 		 */
156*37664Sedward 		for (w = pn->whead; doit && w != NULL; w = w->next)
157*37664Sedward 			if (w->info == LOGGEDIN &&
158*37664Sedward 			    strncmp(w->tty, ll.ll_line, UT_LINESIZE) == 0)
159*37664Sedward 				doit = 0;
16037660Sbostic 	}
161*37664Sedward 	if (doit) {
162*37664Sedward 		w = walloc(pn);
163*37664Sedward 		w->info = LASTLOG;
164*37664Sedward 		bcopy(ll.ll_line, w->tty, UT_LINESIZE);
165*37664Sedward 		w->tty[UT_LINESIZE] = 0;
166*37664Sedward 		bcopy(ll.ll_host, w->host, UT_HOSTSIZE);
167*37664Sedward 		w->host[UT_HOSTSIZE] = 0;
168*37664Sedward 		w->loginat = ll.ll_time;
169*37664Sedward 	}
17037660Sbostic }
17137660Sbostic 
172*37664Sedward enter_where(ut, pn)
17337660Sbostic 	struct utmp *ut;
17437660Sbostic 	PERSON *pn;
17537660Sbostic {
176*37664Sedward 	register WHERE *w = walloc(pn);
177*37664Sedward 
178*37664Sedward 	w->info = LOGGEDIN;
179*37664Sedward 	bcopy(ut->ut_line, w->tty, UT_LINESIZE);
180*37664Sedward 	w->tty[UT_LINESIZE] = 0;
181*37664Sedward 	bcopy(ut->ut_host, w->host, UT_HOSTSIZE);
182*37664Sedward 	w->host[UT_HOSTSIZE] = 0;
183*37664Sedward 	w->loginat = (time_t)ut->ut_time;
184*37664Sedward 	find_idle_and_ttywrite(w);
18537660Sbostic }
186*37664Sedward 
187*37664Sedward PERSON *
188*37664Sedward enter_person(pw)
189*37664Sedward 	register struct passwd *pw;
190*37664Sedward {
191*37664Sedward 	register PERSON *pn, **pp;
192*37664Sedward 
193*37664Sedward 	for (pp = htab + hash(pw->pw_name);
194*37664Sedward 	     *pp != NULL && strcmp((*pp)->name, pw->pw_name) != 0;
195*37664Sedward 	     pp = &(*pp)->hlink)
196*37664Sedward 		;
197*37664Sedward 	if ((pn = *pp) == NULL) {
198*37664Sedward 		pn = palloc();
199*37664Sedward 		entries++;
200*37664Sedward 		if (phead == NULL)
201*37664Sedward 			phead = ptail = pn;
202*37664Sedward 		else {
203*37664Sedward 			ptail->next = pn;
204*37664Sedward 			ptail = pn;
205*37664Sedward 		}
206*37664Sedward 		pn->next = NULL;
207*37664Sedward 		pn->hlink = NULL;
208*37664Sedward 		*pp = pn;
209*37664Sedward 		userinfo(pn, pw);
210*37664Sedward 		pn->whead = NULL;
211*37664Sedward 	}
212*37664Sedward 	return(pn);
213*37664Sedward }
214*37664Sedward 
215*37664Sedward PERSON *
216*37664Sedward find_person(name)
217*37664Sedward 	char *name;
218*37664Sedward {
219*37664Sedward 	register PERSON *pn;
220*37664Sedward 
221*37664Sedward 	/* name may be only UT_NAMESIZE long and not terminated */
222*37664Sedward 	for (pn = htab[hash(name)];
223*37664Sedward 	     pn != NULL && strncmp(pn->name, name, UT_NAMESIZE) != 0;
224*37664Sedward 	     pn = pn->hlink)
225*37664Sedward 		;
226*37664Sedward 	return(pn);
227*37664Sedward }
228*37664Sedward 
229*37664Sedward hash(name)
230*37664Sedward 	register char *name;
231*37664Sedward {
232*37664Sedward 	register int h, i;
233*37664Sedward 
234*37664Sedward 	h = 0;
235*37664Sedward 	/* name may be only UT_NAMESIZE long and not terminated */
236*37664Sedward 	for (i = UT_NAMESIZE; --i >= 0 && *name;)
237*37664Sedward 		h = ((h << 2 | h >> HBITS - 2) ^ *name++) & HMASK;
238*37664Sedward 	return(h);
239*37664Sedward }
240*37664Sedward 
241*37664Sedward PERSON *
242*37664Sedward palloc()
243*37664Sedward {
244*37664Sedward 	PERSON *p;
245*37664Sedward 
246*37664Sedward 	if ((p = (PERSON *)malloc((u_int) sizeof(PERSON))) == NULL) {
247*37664Sedward 		(void)fprintf(stderr, "finger: out of space.\n");
248*37664Sedward 		exit(1);
249*37664Sedward 	}
250*37664Sedward 	return(p);
251*37664Sedward }
252*37664Sedward 
253*37664Sedward WHERE *
254*37664Sedward walloc(pn)
255*37664Sedward 	register PERSON *pn;
256*37664Sedward {
257*37664Sedward 	register WHERE *w;
258*37664Sedward 
259*37664Sedward 	if ((w = (WHERE *)malloc((u_int) sizeof(WHERE))) == NULL) {
260*37664Sedward 		(void)fprintf(stderr, "finger: out of space.\n");
261*37664Sedward 		exit(1);
262*37664Sedward 	}
263*37664Sedward 	if (pn->whead == NULL)
264*37664Sedward 		pn->whead = pn->wtail = w;
265*37664Sedward 	else {
266*37664Sedward 		pn->wtail->next = w;
267*37664Sedward 		pn->wtail = w;
268*37664Sedward 	}
269*37664Sedward 	w->next = NULL;
270*37664Sedward 	return(w);
271*37664Sedward }
272