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