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