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