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