xref: /minix/usr.bin/finger/util.c (revision 406cdd95)
1*406cdd95SThomas Cort /*	$NetBSD: util.c,v 1.28 2009/04/12 06:18:54 lukem Exp $	*/
2*406cdd95SThomas Cort 
3*406cdd95SThomas Cort /*
4*406cdd95SThomas Cort  * Copyright (c) 1989, 1993
5*406cdd95SThomas Cort  *	The Regents of the University of California.  All rights reserved.
6*406cdd95SThomas Cort  *
7*406cdd95SThomas Cort  * This code is derived from software contributed to Berkeley by
8*406cdd95SThomas Cort  * Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
9*406cdd95SThomas Cort  *
10*406cdd95SThomas Cort  * Redistribution and use in source and binary forms, with or without
11*406cdd95SThomas Cort  * modification, are permitted provided that the following conditions
12*406cdd95SThomas Cort  * are met:
13*406cdd95SThomas Cort  * 1. Redistributions of source code must retain the above copyright
14*406cdd95SThomas Cort  *    notice, this list of conditions and the following disclaimer.
15*406cdd95SThomas Cort  * 2. Redistributions in binary form must reproduce the above copyright
16*406cdd95SThomas Cort  *    notice, this list of conditions and the following disclaimer in the
17*406cdd95SThomas Cort  *    documentation and/or other materials provided with the distribution.
18*406cdd95SThomas Cort  * 3. Neither the name of the University nor the names of its contributors
19*406cdd95SThomas Cort  *    may be used to endorse or promote products derived from this software
20*406cdd95SThomas Cort  *    without specific prior written permission.
21*406cdd95SThomas Cort  *
22*406cdd95SThomas Cort  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23*406cdd95SThomas Cort  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24*406cdd95SThomas Cort  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25*406cdd95SThomas Cort  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26*406cdd95SThomas Cort  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27*406cdd95SThomas Cort  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28*406cdd95SThomas Cort  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29*406cdd95SThomas Cort  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30*406cdd95SThomas Cort  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31*406cdd95SThomas Cort  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32*406cdd95SThomas Cort  * SUCH DAMAGE.
33*406cdd95SThomas Cort  */
34*406cdd95SThomas Cort 
35*406cdd95SThomas Cort /*
36*406cdd95SThomas Cort  * Portions Copyright (c) 1983, 1995, 1996 Eric P. Allman
37*406cdd95SThomas Cort  *
38*406cdd95SThomas Cort  * This code is derived from software contributed to Berkeley by
39*406cdd95SThomas Cort  * Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
40*406cdd95SThomas Cort  *
41*406cdd95SThomas Cort  * Redistribution and use in source and binary forms, with or without
42*406cdd95SThomas Cort  * modification, are permitted provided that the following conditions
43*406cdd95SThomas Cort  * are met:
44*406cdd95SThomas Cort  * 1. Redistributions of source code must retain the above copyright
45*406cdd95SThomas Cort  *    notice, this list of conditions and the following disclaimer.
46*406cdd95SThomas Cort  * 2. Redistributions in binary form must reproduce the above copyright
47*406cdd95SThomas Cort  *    notice, this list of conditions and the following disclaimer in the
48*406cdd95SThomas Cort  *    documentation and/or other materials provided with the distribution.
49*406cdd95SThomas Cort  * 3. All advertising materials mentioning features or use of this software
50*406cdd95SThomas Cort  *    must display the following acknowledgement:
51*406cdd95SThomas Cort  *	This product includes software developed by the University of
52*406cdd95SThomas Cort  *	California, Berkeley and its contributors.
53*406cdd95SThomas Cort  * 4. Neither the name of the University nor the names of its contributors
54*406cdd95SThomas Cort  *    may be used to endorse or promote products derived from this software
55*406cdd95SThomas Cort  *    without specific prior written permission.
56*406cdd95SThomas Cort  *
57*406cdd95SThomas Cort  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
58*406cdd95SThomas Cort  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
59*406cdd95SThomas Cort  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
60*406cdd95SThomas Cort  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
61*406cdd95SThomas Cort  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
62*406cdd95SThomas Cort  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
63*406cdd95SThomas Cort  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
64*406cdd95SThomas Cort  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
65*406cdd95SThomas Cort  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
66*406cdd95SThomas Cort  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
67*406cdd95SThomas Cort  * SUCH DAMAGE.
68*406cdd95SThomas Cort  */
69*406cdd95SThomas Cort 
70*406cdd95SThomas Cort #include <sys/cdefs.h>
71*406cdd95SThomas Cort #ifndef lint
72*406cdd95SThomas Cort #if 0
73*406cdd95SThomas Cort static char sccsid[] = "@(#)util.c	8.3 (Berkeley) 4/28/95";
74*406cdd95SThomas Cort #else
75*406cdd95SThomas Cort __RCSID("$NetBSD: util.c,v 1.28 2009/04/12 06:18:54 lukem Exp $");
76*406cdd95SThomas Cort #endif
77*406cdd95SThomas Cort #endif /* not lint */
78*406cdd95SThomas Cort 
79*406cdd95SThomas Cort #include <sys/param.h>
80*406cdd95SThomas Cort #include <sys/stat.h>
81*406cdd95SThomas Cort 
82*406cdd95SThomas Cort #include <db.h>
83*406cdd95SThomas Cort #include <ctype.h>
84*406cdd95SThomas Cort #include <err.h>
85*406cdd95SThomas Cort #include <errno.h>
86*406cdd95SThomas Cort #include <fcntl.h>
87*406cdd95SThomas Cort #include <paths.h>
88*406cdd95SThomas Cort #include <pwd.h>
89*406cdd95SThomas Cort #include <stdio.h>
90*406cdd95SThomas Cort #include <stdlib.h>
91*406cdd95SThomas Cort #include <string.h>
92*406cdd95SThomas Cort #include <unistd.h>
93*406cdd95SThomas Cort #include <utmp.h>
94*406cdd95SThomas Cort 
95*406cdd95SThomas Cort #include "utmpentry.h"
96*406cdd95SThomas Cort 
97*406cdd95SThomas Cort #include "finger.h"
98*406cdd95SThomas Cort #include "extern.h"
99*406cdd95SThomas Cort 
100*406cdd95SThomas Cort static void	 find_idle_and_ttywrite(WHERE *);
101*406cdd95SThomas Cort static void	 userinfo(PERSON *, struct passwd *);
102*406cdd95SThomas Cort static WHERE	*walloc(PERSON *);
103*406cdd95SThomas Cort 
104*406cdd95SThomas Cort int
match(struct passwd * pw,char * user)105*406cdd95SThomas Cort match(struct passwd *pw, char *user)
106*406cdd95SThomas Cort {
107*406cdd95SThomas Cort 	char *p;
108*406cdd95SThomas Cort 	char *bp, name[1024];
109*406cdd95SThomas Cort 
110*406cdd95SThomas Cort 	if (!strcasecmp(pw->pw_name, user))
111*406cdd95SThomas Cort 		return(1);
112*406cdd95SThomas Cort 
113*406cdd95SThomas Cort 	(void)strlcpy(bp = tbuf, pw->pw_gecos, sizeof(tbuf));
114*406cdd95SThomas Cort 
115*406cdd95SThomas Cort 	/* Ampersands get replaced by the login name. */
116*406cdd95SThomas Cort 	if (!(p = strsep(&bp, ",")))
117*406cdd95SThomas Cort 		return(0);
118*406cdd95SThomas Cort 
119*406cdd95SThomas Cort 	expandusername(p, pw->pw_name, name, sizeof(name));
120*406cdd95SThomas Cort 	bp = name;
121*406cdd95SThomas Cort 	while ((p = strsep(&bp, "\t ")))
122*406cdd95SThomas Cort 		if (!strcasecmp(p, user))
123*406cdd95SThomas Cort 			return(1);
124*406cdd95SThomas Cort 	return(0);
125*406cdd95SThomas Cort }
126*406cdd95SThomas Cort 
127*406cdd95SThomas Cort /* inspired by usr.sbin/sendmail/util.c::buildfname */
128*406cdd95SThomas Cort void
expandusername(const char * gecos,const char * login,char * buf,int buflen)129*406cdd95SThomas Cort expandusername(const char *gecos, const char *login, char *buf, int buflen)
130*406cdd95SThomas Cort {
131*406cdd95SThomas Cort 	const char *p;
132*406cdd95SThomas Cort 	char *bp;
133*406cdd95SThomas Cort 
134*406cdd95SThomas Cort 	/* why do we skip asterisks!?!? */
135*406cdd95SThomas Cort 	if (*gecos == '*')
136*406cdd95SThomas Cort 		gecos++;
137*406cdd95SThomas Cort 	bp = buf;
138*406cdd95SThomas Cort 
139*406cdd95SThomas Cort 	/* copy gecos, interpolating & to be full name */
140*406cdd95SThomas Cort 	for (p = gecos; *p != '\0'; p++) {
141*406cdd95SThomas Cort 		if (bp >= &buf[buflen - 1]) {
142*406cdd95SThomas Cort 			/* buffer overflow - just use login name */
143*406cdd95SThomas Cort 			snprintf(buf, buflen, "%s", login);
144*406cdd95SThomas Cort 			buf[buflen - 1] = '\0';
145*406cdd95SThomas Cort 			return;
146*406cdd95SThomas Cort 		}
147*406cdd95SThomas Cort 		if (*p == '&') {
148*406cdd95SThomas Cort 			/* interpolate full name */
149*406cdd95SThomas Cort 			snprintf(bp, buflen - (bp - buf), "%s", login);
150*406cdd95SThomas Cort 			*bp = toupper((unsigned char)*bp);
151*406cdd95SThomas Cort 			bp += strlen(bp);
152*406cdd95SThomas Cort 		}
153*406cdd95SThomas Cort 		else
154*406cdd95SThomas Cort 			*bp++ = *p;
155*406cdd95SThomas Cort 	}
156*406cdd95SThomas Cort 	*bp = '\0';
157*406cdd95SThomas Cort }
158*406cdd95SThomas Cort 
159*406cdd95SThomas Cort void
enter_lastlog(PERSON * pn)160*406cdd95SThomas Cort enter_lastlog(PERSON *pn)
161*406cdd95SThomas Cort {
162*406cdd95SThomas Cort 	WHERE *w;
163*406cdd95SThomas Cort 	static int opened, fd;
164*406cdd95SThomas Cort 	struct lastlog ll;
165*406cdd95SThomas Cort 	char doit = 0;
166*406cdd95SThomas Cort 
167*406cdd95SThomas Cort 	/* some systems may not maintain lastlog, don't report errors. */
168*406cdd95SThomas Cort 	if (!opened) {
169*406cdd95SThomas Cort 		fd = open(_PATH_LASTLOG, O_RDONLY, 0);
170*406cdd95SThomas Cort 		opened = 1;
171*406cdd95SThomas Cort 	}
172*406cdd95SThomas Cort 	if (fd == -1 ||
173*406cdd95SThomas Cort 	    lseek(fd, (off_t)pn->uid * sizeof(ll), SEEK_SET) !=
174*406cdd95SThomas Cort 	    (off_t)pn->uid * (off_t)sizeof(ll) ||
175*406cdd95SThomas Cort 	    read(fd, (char *)&ll, sizeof(ll)) != sizeof(ll)) {
176*406cdd95SThomas Cort 			/* as if never logged in */
177*406cdd95SThomas Cort 			ll.ll_line[0] = ll.ll_host[0] = '\0';
178*406cdd95SThomas Cort 			ll.ll_time = 0;
179*406cdd95SThomas Cort 		}
180*406cdd95SThomas Cort 	if ((w = pn->whead) == NULL)
181*406cdd95SThomas Cort 		doit = 1;
182*406cdd95SThomas Cort 	else if (ll.ll_time != 0) {
183*406cdd95SThomas Cort 		/* if last login is earlier than some current login */
184*406cdd95SThomas Cort 		for (; !doit && w != NULL; w = w->next)
185*406cdd95SThomas Cort 			if (w->info == LOGGEDIN && w->loginat < ll.ll_time)
186*406cdd95SThomas Cort 				doit = 1;
187*406cdd95SThomas Cort 		/*
188*406cdd95SThomas Cort 		 * and if it's not any of the current logins
189*406cdd95SThomas Cort 		 * can't use time comparison because there may be a small
190*406cdd95SThomas Cort 		 * discrepency since login calls time() twice
191*406cdd95SThomas Cort 		 */
192*406cdd95SThomas Cort 		for (w = pn->whead; doit && w != NULL; w = w->next)
193*406cdd95SThomas Cort 			if (w->info == LOGGEDIN &&
194*406cdd95SThomas Cort 			    strncmp(w->tty, ll.ll_line, UT_LINESIZE) == 0)
195*406cdd95SThomas Cort 				doit = 0;
196*406cdd95SThomas Cort 	}
197*406cdd95SThomas Cort 	if (doit) {
198*406cdd95SThomas Cort 		w = walloc(pn);
199*406cdd95SThomas Cort 		w->info = LASTLOG;
200*406cdd95SThomas Cort 		if ((w->tty = malloc(UT_LINESIZE + 1)) == NULL)
201*406cdd95SThomas Cort 			err(1, NULL);
202*406cdd95SThomas Cort 		memcpy(w->tty, ll.ll_line, UT_LINESIZE);
203*406cdd95SThomas Cort 		w->tty[UT_LINESIZE] = '\0';
204*406cdd95SThomas Cort 		if ((w->host = malloc(UT_HOSTSIZE + 1)) == NULL)
205*406cdd95SThomas Cort 			err(1, NULL);
206*406cdd95SThomas Cort 		memcpy(w->host, ll.ll_host, UT_HOSTSIZE);
207*406cdd95SThomas Cort 		w->host[UT_HOSTSIZE] = '\0';
208*406cdd95SThomas Cort 		w->loginat = ll.ll_time;
209*406cdd95SThomas Cort 	}
210*406cdd95SThomas Cort }
211*406cdd95SThomas Cort 
212*406cdd95SThomas Cort void
enter_where(struct utmpentry * ep,PERSON * pn)213*406cdd95SThomas Cort enter_where(struct utmpentry *ep, PERSON *pn)
214*406cdd95SThomas Cort {
215*406cdd95SThomas Cort 	WHERE *w = walloc(pn);
216*406cdd95SThomas Cort 
217*406cdd95SThomas Cort 	w->info = LOGGEDIN;
218*406cdd95SThomas Cort 	w->tty = ep->line;
219*406cdd95SThomas Cort 	w->host = ep->host;
220*406cdd95SThomas Cort 	w->loginat = (time_t)ep->tv.tv_sec;
221*406cdd95SThomas Cort 	find_idle_and_ttywrite(w);
222*406cdd95SThomas Cort }
223*406cdd95SThomas Cort 
224*406cdd95SThomas Cort PERSON *
enter_person(struct passwd * pw)225*406cdd95SThomas Cort enter_person(struct passwd *pw)
226*406cdd95SThomas Cort {
227*406cdd95SThomas Cort 	DBT data, key;
228*406cdd95SThomas Cort 	PERSON *pn;
229*406cdd95SThomas Cort 
230*406cdd95SThomas Cort 	if (db == NULL &&
231*406cdd95SThomas Cort 	    (db = dbopen(NULL, O_RDWR, 0, DB_BTREE, NULL)) == NULL)
232*406cdd95SThomas Cort 		err(1, NULL);
233*406cdd95SThomas Cort 
234*406cdd95SThomas Cort 	key.data = (char *)pw->pw_name;
235*406cdd95SThomas Cort 	key.size = strlen(pw->pw_name);
236*406cdd95SThomas Cort 
237*406cdd95SThomas Cort 	switch ((*db->get)(db, &key, &data, 0)) {
238*406cdd95SThomas Cort 	case 0:
239*406cdd95SThomas Cort 		memmove(&pn, data.data, sizeof pn);
240*406cdd95SThomas Cort 		return (pn);
241*406cdd95SThomas Cort 	default:
242*406cdd95SThomas Cort 	case -1:
243*406cdd95SThomas Cort 		err(1, "db get");
244*406cdd95SThomas Cort 		/* NOTREACHED */
245*406cdd95SThomas Cort 	case 1:
246*406cdd95SThomas Cort 		++entries;
247*406cdd95SThomas Cort 		pn = palloc();
248*406cdd95SThomas Cort 		userinfo(pn, pw);
249*406cdd95SThomas Cort 		pn->whead = NULL;
250*406cdd95SThomas Cort 
251*406cdd95SThomas Cort 		data.size = sizeof(PERSON *);
252*406cdd95SThomas Cort 		data.data = &pn;
253*406cdd95SThomas Cort 		if ((*db->put)(db, &key, &data, 0))
254*406cdd95SThomas Cort 			err(1, "db put");
255*406cdd95SThomas Cort 		return (pn);
256*406cdd95SThomas Cort 	}
257*406cdd95SThomas Cort }
258*406cdd95SThomas Cort 
259*406cdd95SThomas Cort PERSON *
find_person(char * name)260*406cdd95SThomas Cort find_person(char *name)
261*406cdd95SThomas Cort {
262*406cdd95SThomas Cort 	DBT data, key;
263*406cdd95SThomas Cort 	PERSON *p;
264*406cdd95SThomas Cort 
265*406cdd95SThomas Cort 	if (!db)
266*406cdd95SThomas Cort 		return(NULL);
267*406cdd95SThomas Cort 
268*406cdd95SThomas Cort 	key.data = name;
269*406cdd95SThomas Cort 	key.size = strlen(name);
270*406cdd95SThomas Cort 
271*406cdd95SThomas Cort 	if ((*db->get)(db, &key, &data, 0))
272*406cdd95SThomas Cort 		return (NULL);
273*406cdd95SThomas Cort 	memmove(&p, data.data, sizeof p);
274*406cdd95SThomas Cort 	return (p);
275*406cdd95SThomas Cort }
276*406cdd95SThomas Cort 
277*406cdd95SThomas Cort PERSON *
palloc(void)278*406cdd95SThomas Cort palloc(void)
279*406cdd95SThomas Cort {
280*406cdd95SThomas Cort 	PERSON *p;
281*406cdd95SThomas Cort 
282*406cdd95SThomas Cort 	if ((p = malloc((u_int) sizeof(PERSON))) == NULL)
283*406cdd95SThomas Cort 		err(1, NULL);
284*406cdd95SThomas Cort 	return(p);
285*406cdd95SThomas Cort }
286*406cdd95SThomas Cort 
287*406cdd95SThomas Cort static WHERE *
walloc(PERSON * pn)288*406cdd95SThomas Cort walloc(PERSON *pn)
289*406cdd95SThomas Cort {
290*406cdd95SThomas Cort 	WHERE *w;
291*406cdd95SThomas Cort 
292*406cdd95SThomas Cort 	if ((w = malloc((u_int) sizeof(WHERE))) == NULL)
293*406cdd95SThomas Cort 		err(1, NULL);
294*406cdd95SThomas Cort 	if (pn->whead == NULL)
295*406cdd95SThomas Cort 		pn->whead = pn->wtail = w;
296*406cdd95SThomas Cort 	else {
297*406cdd95SThomas Cort 		pn->wtail->next = w;
298*406cdd95SThomas Cort 		pn->wtail = w;
299*406cdd95SThomas Cort 	}
300*406cdd95SThomas Cort 	w->next = NULL;
301*406cdd95SThomas Cort 	return(w);
302*406cdd95SThomas Cort }
303*406cdd95SThomas Cort 
304*406cdd95SThomas Cort char *
prphone(char * num)305*406cdd95SThomas Cort prphone(char *num)
306*406cdd95SThomas Cort {
307*406cdd95SThomas Cort 	char *p;
308*406cdd95SThomas Cort 	int len;
309*406cdd95SThomas Cort 	static char pbuf[15];
310*406cdd95SThomas Cort 
311*406cdd95SThomas Cort 	/* don't touch anything if the user has their own formatting */
312*406cdd95SThomas Cort 	for (p = num; *p; ++p)
313*406cdd95SThomas Cort 		if (!isdigit((unsigned char)*p))
314*406cdd95SThomas Cort 			return(num);
315*406cdd95SThomas Cort 	len = p - num;
316*406cdd95SThomas Cort 	p = pbuf;
317*406cdd95SThomas Cort 	switch(len) {
318*406cdd95SThomas Cort 	case 11:			/* +0-123-456-7890 */
319*406cdd95SThomas Cort 		*p++ = '+';
320*406cdd95SThomas Cort 		*p++ = *num++;
321*406cdd95SThomas Cort 		*p++ = '-';
322*406cdd95SThomas Cort 		/* FALLTHROUGH */
323*406cdd95SThomas Cort 	case 10:			/* 012-345-6789 */
324*406cdd95SThomas Cort 		*p++ = *num++;
325*406cdd95SThomas Cort 		*p++ = *num++;
326*406cdd95SThomas Cort 		*p++ = *num++;
327*406cdd95SThomas Cort 		*p++ = '-';
328*406cdd95SThomas Cort 		/* FALLTHROUGH */
329*406cdd95SThomas Cort 	case 7:				/* 012-3456 */
330*406cdd95SThomas Cort 		*p++ = *num++;
331*406cdd95SThomas Cort 		*p++ = *num++;
332*406cdd95SThomas Cort 		*p++ = *num++;
333*406cdd95SThomas Cort 		break;
334*406cdd95SThomas Cort 	case 5:				/* x0-1234 */
335*406cdd95SThomas Cort 	case 4:				/* x1234 */
336*406cdd95SThomas Cort 		*p++ = 'x';
337*406cdd95SThomas Cort 		*p++ = *num++;
338*406cdd95SThomas Cort 		break;
339*406cdd95SThomas Cort 	default:
340*406cdd95SThomas Cort 		return(num);
341*406cdd95SThomas Cort 	}
342*406cdd95SThomas Cort 	if (len != 4) {
343*406cdd95SThomas Cort 		*p++ = '-';
344*406cdd95SThomas Cort 		*p++ = *num++;
345*406cdd95SThomas Cort 	}
346*406cdd95SThomas Cort 	*p++ = *num++;
347*406cdd95SThomas Cort 	*p++ = *num++;
348*406cdd95SThomas Cort 	*p++ = *num++;
349*406cdd95SThomas Cort 	*p = '\0';
350*406cdd95SThomas Cort 	return(pbuf);
351*406cdd95SThomas Cort }
352*406cdd95SThomas Cort 
353*406cdd95SThomas Cort static void
find_idle_and_ttywrite(WHERE * w)354*406cdd95SThomas Cort find_idle_and_ttywrite(WHERE *w)
355*406cdd95SThomas Cort {
356*406cdd95SThomas Cort 	struct stat sb;
357*406cdd95SThomas Cort 
358*406cdd95SThomas Cort 	(void)snprintf(tbuf, sizeof(tbuf), "%s/%s", _PATH_DEV, w->tty);
359*406cdd95SThomas Cort 	if (stat(tbuf, &sb) < 0) {
360*406cdd95SThomas Cort 		warn("%s", tbuf);
361*406cdd95SThomas Cort 		return;
362*406cdd95SThomas Cort 	}
363*406cdd95SThomas Cort 	w->idletime = now < sb.st_atime ? 0 : now - sb.st_atime;
364*406cdd95SThomas Cort 
365*406cdd95SThomas Cort #define	TALKABLE	0220		/* tty is writable if 220 mode */
366*406cdd95SThomas Cort 	w->writable = ((sb.st_mode & TALKABLE) == TALKABLE);
367*406cdd95SThomas Cort }
368*406cdd95SThomas Cort 
369*406cdd95SThomas Cort static void
userinfo(PERSON * pn,struct passwd * pw)370*406cdd95SThomas Cort userinfo(PERSON *pn, struct passwd *pw)
371*406cdd95SThomas Cort {
372*406cdd95SThomas Cort 	char *p;
373*406cdd95SThomas Cort 	char *bp, name[1024];
374*406cdd95SThomas Cort 	struct stat sb;
375*406cdd95SThomas Cort 
376*406cdd95SThomas Cort 	pn->realname = pn->office = pn->officephone = pn->homephone = NULL;
377*406cdd95SThomas Cort 
378*406cdd95SThomas Cort 	pn->uid = pw->pw_uid;
379*406cdd95SThomas Cort 	pn->name = strdup(pw->pw_name);
380*406cdd95SThomas Cort 	pn->dir = strdup(pw->pw_dir);
381*406cdd95SThomas Cort 	pn->shell = strdup(pw->pw_shell);
382*406cdd95SThomas Cort 
383*406cdd95SThomas Cort 	(void)strlcpy(bp = tbuf, pw->pw_gecos, sizeof(tbuf));
384*406cdd95SThomas Cort 
385*406cdd95SThomas Cort 	/* ampersands get replaced by the login name */
386*406cdd95SThomas Cort 	if (!(p = strsep(&bp, ",")))
387*406cdd95SThomas Cort 		return;
388*406cdd95SThomas Cort 	expandusername(p, pw->pw_name, name, sizeof(name));
389*406cdd95SThomas Cort 	pn->realname = strdup(name);
390*406cdd95SThomas Cort 	pn->office = ((p = strsep(&bp, ",")) && *p) ?
391*406cdd95SThomas Cort 	    strdup(p) : NULL;
392*406cdd95SThomas Cort 	pn->officephone = ((p = strsep(&bp, ",")) && *p) ?
393*406cdd95SThomas Cort 	    strdup(p) : NULL;
394*406cdd95SThomas Cort 	pn->homephone = ((p = strsep(&bp, ",")) && *p) ?
395*406cdd95SThomas Cort 	    strdup(p) : NULL;
396*406cdd95SThomas Cort 	(void)snprintf(tbuf, sizeof(tbuf), "%s/%s", _PATH_MAILDIR,
397*406cdd95SThomas Cort 	    pw->pw_name);
398*406cdd95SThomas Cort 	pn->mailrecv = -1;		/* -1 == not_valid */
399*406cdd95SThomas Cort 	if (stat(tbuf, &sb) < 0) {
400*406cdd95SThomas Cort 		if (errno != ENOENT) {
401*406cdd95SThomas Cort 			(void)fprintf(stderr,
402*406cdd95SThomas Cort 			    "finger: %s: %s\n", tbuf, strerror(errno));
403*406cdd95SThomas Cort 			return;
404*406cdd95SThomas Cort 		}
405*406cdd95SThomas Cort 	} else if (sb.st_size != 0) {
406*406cdd95SThomas Cort 		pn->mailrecv = sb.st_mtime;
407*406cdd95SThomas Cort 		pn->mailread = sb.st_atime;
408*406cdd95SThomas Cort 	}
409*406cdd95SThomas Cort }
410