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