Annotation of src/usr.bin/finger/util.c, Revision 1.4
1.4 ! deraadt 1: /* $OpenBSD: util.c,v 1.3 1996/08/07 17:49:49 downsj Exp $ */
1.2 deraadt 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.4 ! deraadt 41: static char rcsid[] = "$OpenBSD: util.c,v 1.3 1996/08/07 17:49:49 downsj 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:
1.3 downsj 62: (void)sprintf(tbuf, "%s%s", _PATH_DEV, w->tty);
1.1 deraadt 63: if (stat(tbuf, &sb) < 0) {
1.3 downsj 64: /* Don't bitch about it, just handle it... */
65: w->idletime = 0;
66: w->writable = 0;
67:
1.1 deraadt 68: return;
69: }
70: w->idletime = now < sb.st_atime ? 0 : now - sb.st_atime;
71:
72: #define TALKABLE 0220 /* tty is writable if 220 mode */
73: w->writable = ((sb.st_mode & TALKABLE) == TALKABLE);
74: }
75:
76: userinfo(pn, pw)
77: register PERSON *pn;
78: register struct passwd *pw;
79: {
80: extern time_t now;
81: register char *p, *t;
82: struct stat sb;
83: extern int errno;
1.4 ! deraadt 84: char *mbp, *bp, *name;
! 85: int len;
1.1 deraadt 86:
87: pn->realname = pn->office = pn->officephone = pn->homephone = NULL;
88:
89: pn->uid = pw->pw_uid;
90: pn->name = strdup(pw->pw_name);
91: pn->dir = strdup(pw->pw_dir);
92: pn->shell = strdup(pw->pw_shell);
93:
94: /* why do we skip asterisks!?!? */
1.4 ! deraadt 95: mbp = bp = (char *)malloc(strlen(pw->pw_gecos)+1);
! 96: strcpy(bp, pw->pw_gecos);
1.1 deraadt 97: if (*bp == '*')
98: ++bp;
99:
100: /* ampersands get replaced by the login name */
1.4 ! deraadt 101: if (!(p = strsep(&bp, ","))) {
! 102: free(mbp);
1.1 deraadt 103: return;
1.4 ! deraadt 104: }
! 105: for (len = 0, t = p; *p; ++p) {
! 106: len++;
! 107: if (*p == '&')
! 108: len += strlen(pw->pw_name);
! 109: }
! 110: name = (char *)malloc(len + 1);
! 111: for (p = t, t = name; *t = *p; ++p)
1.1 deraadt 112: if (*t == '&') {
113: (void)strcpy(t, pw->pw_name);
114: if (islower(*t))
115: *t = toupper(*t);
116: while (*++t);
1.4 ! deraadt 117: } else
1.1 deraadt 118: ++t;
1.4 ! deraadt 119: *t = '\0';
1.1 deraadt 120: pn->realname = strdup(name);
121: pn->office = ((p = strsep(&bp, ",")) && *p) ?
122: strdup(p) : NULL;
123: pn->officephone = ((p = strsep(&bp, ",")) && *p) ?
124: strdup(p) : NULL;
125: pn->homephone = ((p = strsep(&bp, ",")) && *p) ?
126: strdup(p) : NULL;
127: (void)sprintf(tbuf, "%s/%s", _PATH_MAILSPOOL, pw->pw_name);
128: pn->mailrecv = -1; /* -1 == not_valid */
129: if (stat(tbuf, &sb) < 0) {
130: if (errno != ENOENT) {
131: (void)fprintf(stderr,
132: "finger: %s: %s\n", tbuf, strerror(errno));
1.4 ! deraadt 133: free(name);
! 134: free(mbp);
1.1 deraadt 135: return;
136: }
137: } else if (sb.st_size != 0) {
138: pn->mailrecv = sb.st_mtime;
139: pn->mailread = sb.st_atime;
140: }
1.4 ! deraadt 141: free(name);
! 142: free(mbp);
1.1 deraadt 143: }
144:
145: match(pw, user)
146: struct passwd *pw;
147: char *user;
148: {
149: register char *p, *t;
150: char name[1024];
151:
152: /* why do we skip asterisks!?!? */
153: (void)strcpy(p = tbuf, pw->pw_gecos);
154: if (*p == '*')
155: ++p;
156:
157: /* ampersands get replaced by the login name */
158: if (!(p = strtok(p, ",")))
159: return(0);
160: for (t = name; *t = *p; ++p)
161: if (*t == '&') {
162: (void)strcpy(t, pw->pw_name);
163: while (*++t);
164: }
165: else
166: ++t;
167: for (t = name; p = strtok(t, "\t "); t = (char *)NULL)
168: if (!strcasecmp(p, user))
169: return(1);
170: return(0);
171: }
172:
173: enter_lastlog(pn)
174: register PERSON *pn;
175: {
176: register WHERE *w;
177: static int opened, fd;
178: struct lastlog ll;
179: char doit = 0;
180:
181: /* some systems may not maintain lastlog, don't report errors. */
182: if (!opened) {
183: fd = open(_PATH_LASTLOG, O_RDONLY, 0);
184: opened = 1;
185: }
186: if (fd == -1 ||
187: lseek(fd, (off_t)(pn->uid * sizeof(ll)), SEEK_SET) !=
188: (long)pn->uid * sizeof(ll) ||
189: read(fd, (char *)&ll, sizeof(ll)) != sizeof(ll)) {
190: /* as if never logged in */
191: ll.ll_line[0] = ll.ll_host[0] = NULL;
192: ll.ll_time = 0;
193: }
194: if ((w = pn->whead) == NULL)
195: doit = 1;
196: else if (ll.ll_time != 0) {
197: /* if last login is earlier than some current login */
198: for (; !doit && w != NULL; w = w->next)
199: if (w->info == LOGGEDIN && w->loginat < ll.ll_time)
200: doit = 1;
201: /*
202: * and if it's not any of the current logins
203: * can't use time comparison because there may be a small
204: * discrepency since login calls time() twice
205: */
206: for (w = pn->whead; doit && w != NULL; w = w->next)
207: if (w->info == LOGGEDIN &&
208: strncmp(w->tty, ll.ll_line, UT_LINESIZE) == 0)
209: doit = 0;
210: }
211: if (doit) {
212: w = walloc(pn);
213: w->info = LASTLOG;
214: bcopy(ll.ll_line, w->tty, UT_LINESIZE);
215: w->tty[UT_LINESIZE] = 0;
216: bcopy(ll.ll_host, w->host, UT_HOSTSIZE);
217: w->host[UT_HOSTSIZE] = 0;
218: w->loginat = ll.ll_time;
219: }
220: }
221:
222: enter_where(ut, pn)
223: struct utmp *ut;
224: PERSON *pn;
225: {
226: register WHERE *w = walloc(pn);
227:
228: w->info = LOGGEDIN;
229: bcopy(ut->ut_line, w->tty, UT_LINESIZE);
230: w->tty[UT_LINESIZE] = 0;
231: bcopy(ut->ut_host, w->host, UT_HOSTSIZE);
232: w->host[UT_HOSTSIZE] = 0;
233: w->loginat = (time_t)ut->ut_time;
234: find_idle_and_ttywrite(w);
235: }
236:
237: PERSON *
238: enter_person(pw)
239: register struct passwd *pw;
240: {
241: register PERSON *pn, **pp;
242:
243: for (pp = htab + hash(pw->pw_name);
244: *pp != NULL && strcmp((*pp)->name, pw->pw_name) != 0;
245: pp = &(*pp)->hlink)
246: ;
247: if ((pn = *pp) == NULL) {
248: pn = palloc();
249: entries++;
250: if (phead == NULL)
251: phead = ptail = pn;
252: else {
253: ptail->next = pn;
254: ptail = pn;
255: }
256: pn->next = NULL;
257: pn->hlink = NULL;
258: *pp = pn;
259: userinfo(pn, pw);
260: pn->whead = NULL;
261: }
262: return(pn);
263: }
264:
265: PERSON *
266: find_person(name)
267: char *name;
268: {
269: register PERSON *pn;
270:
271: /* name may be only UT_NAMESIZE long and not terminated */
272: for (pn = htab[hash(name)];
273: pn != NULL && strncmp(pn->name, name, UT_NAMESIZE) != 0;
274: pn = pn->hlink)
275: ;
276: return(pn);
277: }
278:
279: hash(name)
280: register char *name;
281: {
282: register int h, i;
283:
284: h = 0;
285: /* name may be only UT_NAMESIZE long and not terminated */
286: for (i = UT_NAMESIZE; --i >= 0 && *name;)
287: h = ((h << 2 | h >> HBITS - 2) ^ *name++) & HMASK;
288: return(h);
289: }
290:
291: PERSON *
292: palloc()
293: {
294: PERSON *p;
295:
296: if ((p = (PERSON *)malloc((u_int) sizeof(PERSON))) == NULL) {
297: (void)fprintf(stderr, "finger: out of space.\n");
298: exit(1);
299: }
300: return(p);
301: }
302:
303: WHERE *
304: walloc(pn)
305: register PERSON *pn;
306: {
307: register WHERE *w;
308:
309: if ((w = (WHERE *)malloc((u_int) sizeof(WHERE))) == NULL) {
310: (void)fprintf(stderr, "finger: out of space.\n");
311: exit(1);
312: }
313: if (pn->whead == NULL)
314: pn->whead = pn->wtail = w;
315: else {
316: pn->wtail->next = w;
317: pn->wtail = w;
318: }
319: w->next = NULL;
320: return(w);
321: }
322:
323: char *
324: prphone(num)
325: char *num;
326: {
327: register char *p;
328: int len;
329: static char pbuf[15];
330:
331: /* don't touch anything if the user has their own formatting */
332: for (p = num; *p; ++p)
333: if (!isdigit(*p))
334: return(num);
335: len = p - num;
336: p = pbuf;
337: switch(len) {
338: case 11: /* +0-123-456-7890 */
339: *p++ = '+';
340: *p++ = *num++;
341: *p++ = '-';
342: /* FALLTHROUGH */
343: case 10: /* 012-345-6789 */
344: *p++ = *num++;
345: *p++ = *num++;
346: *p++ = *num++;
347: *p++ = '-';
348: /* FALLTHROUGH */
349: case 7: /* 012-3456 */
350: *p++ = *num++;
351: *p++ = *num++;
352: *p++ = *num++;
353: break;
354: case 5: /* x0-1234 */
355: case 4: /* x1234 */
356: *p++ = 'x';
357: *p++ = *num++;
358: break;
359: default:
360: return(num);
361: }
362: if (len != 4) {
363: *p++ = '-';
364: *p++ = *num++;
365: }
366: *p++ = *num++;
367: *p++ = *num++;
368: *p++ = *num++;
369: *p = '\0';
370: return(pbuf);
371: }