|
|
1.1 root 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 are permitted provided
9: * that: (1) source distributions retain this entire copyright notice and
10: * comment, and (2) distributions including binaries display the following
11: * acknowledgement: ``This product includes software developed by the
12: * University of California, Berkeley and its contributors'' in the
13: * documentation or other materials provided with the distribution and in
14: * all advertising materials mentioning features or use of this software.
15: * Neither the name of the University nor the names of its contributors may
16: * be used to endorse or promote products derived from this software without
17: * specific prior written permission.
18: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
19: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
20: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21: */
22:
23: #ifndef lint
24: static char sccsid[] = "@(#)util.c 5.13 (Berkeley) 6/24/90";
25: #endif /* not lint */
26:
27: #include <sys/param.h>
28: #include <sys/stat.h>
29: #include <sys/file.h>
30: #include <stdio.h>
31: #include <ctype.h>
32: #include <string.h>
33: #include <paths.h>
34: #include "finger.h"
35:
36: find_idle_and_ttywrite(w)
37: register WHERE *w;
38: {
39: extern time_t now;
40: extern int errno;
41: struct stat sb;
42: char *strerror();
43:
44: (void)sprintf(tbuf, "%s/%s", _PATH_DEV, w->tty);
45: if (stat(tbuf, &sb) < 0) {
46: (void)fprintf(stderr,
47: "finger: %s: %s\n", tbuf, strerror(errno));
48: exit(1);
49: }
50: w->idletime = now < sb.st_atime ? 0 : now - sb.st_atime;
51:
52: #define TALKABLE 0220 /* tty is writable if 220 mode */
53: w->writable = ((sb.st_mode & TALKABLE) == TALKABLE);
54: }
55:
56: userinfo(pn, pw)
57: register PERSON *pn;
58: register struct passwd *pw;
59: {
60: register char *p, *t;
61: char *bp, name[1024];
62:
63: pn->realname = pn->office = pn->officephone = pn->homephone = NULL;
64:
65: pn->uid = pw->pw_uid;
66: pn->name = strdup(pw->pw_name);
67: pn->dir = strdup(pw->pw_dir);
68: pn->shell = strdup(pw->pw_shell);
69:
70: /* why do we skip asterisks!?!? */
71: (void)strcpy(bp = tbuf, pw->pw_gecos);
72: if (*bp == '*')
73: ++bp;
74:
75: /* ampersands get replaced by the login name */
76: if (!(p = strsep(&bp, ",")))
77: return;
78: for (t = name; *t = *p; ++p)
79: if (*t == '&') {
80: (void)strcpy(t, pw->pw_name);
81: if (islower(*t))
82: *t = toupper(*t);
83: while (*++t);
84: }
85: else
86: ++t;
87: pn->realname = strdup(name);
88: pn->office = ((p = strsep(&bp, ",")) && *p) ?
89: strdup(p) : NULL;
90: pn->officephone = ((p = strsep(&bp, ",")) && *p) ?
91: strdup(p) : NULL;
92: pn->homephone = ((p = strsep(&bp, ",")) && *p) ?
93: strdup(p) : NULL;
94: }
95:
96: match(pw, user)
97: struct passwd *pw;
98: char *user;
99: {
100: register char *p, *t;
101: char name[1024];
102:
103: /* why do we skip asterisks!?!? */
104: (void)strcpy(p = tbuf, pw->pw_gecos);
105: if (*p == '*')
106: ++p;
107:
108: /* ampersands get replaced by the login name */
109: if (!(p = strtok(p, ",")))
110: return(0);
111: for (t = name; *t = *p; ++p)
112: if (*t == '&') {
113: (void)strcpy(t, pw->pw_name);
114: while (*++t);
115: }
116: else
117: ++t;
118: for (t = name; p = strtok(t, "\t "); t = (char *)NULL)
119: if (!strcasecmp(p, user))
120: return(1);
121: return(0);
122: }
123:
124: enter_lastlog(pn)
125: register PERSON *pn;
126: {
127: register WHERE *w;
128: static int opened, fd;
129: struct lastlog ll;
130: char doit = 0;
131: off_t lseek();
132:
133: /* some systems may not maintain lastlog, don't report errors. */
134: if (!opened) {
135: fd = open(_PATH_LASTLOG, O_RDONLY, 0);
136: opened = 1;
137: }
138: if (fd == -1 ||
139: lseek(fd, (long)pn->uid * sizeof(ll), L_SET) !=
140: (long)pn->uid * sizeof(ll) ||
141: read(fd, (char *)&ll, sizeof(ll)) != sizeof(ll)) {
142: /* as if never logged in */
143: ll.ll_line[0] = ll.ll_host[0] = NULL;
144: ll.ll_time = 0;
145: }
146: if ((w = pn->whead) == NULL)
147: doit = 1;
148: else if (ll.ll_time != 0) {
149: /* if last login is earlier than some current login */
150: for (; !doit && w != NULL; w = w->next)
151: if (w->info == LOGGEDIN && w->loginat < ll.ll_time)
152: doit = 1;
153: /*
154: * and if it's not any of the current logins
155: * can't use time comparison because there may be a small
156: * discrepency since login calls time() twice
157: */
158: for (w = pn->whead; doit && w != NULL; w = w->next)
159: if (w->info == LOGGEDIN &&
160: strncmp(w->tty, ll.ll_line, UT_LINESIZE) == 0)
161: doit = 0;
162: }
163: if (doit) {
164: w = walloc(pn);
165: w->info = LASTLOG;
166: bcopy(ll.ll_line, w->tty, UT_LINESIZE);
167: w->tty[UT_LINESIZE] = 0;
168: bcopy(ll.ll_host, w->host, UT_HOSTSIZE);
169: w->host[UT_HOSTSIZE] = 0;
170: w->loginat = ll.ll_time;
171: }
172: }
173:
174: enter_where(ut, pn)
175: struct utmp *ut;
176: PERSON *pn;
177: {
178: register WHERE *w = walloc(pn);
179:
180: w->info = LOGGEDIN;
181: bcopy(ut->ut_line, w->tty, UT_LINESIZE);
182: w->tty[UT_LINESIZE] = 0;
183: bcopy(ut->ut_host, w->host, UT_HOSTSIZE);
184: w->host[UT_HOSTSIZE] = 0;
185: w->loginat = (time_t)ut->ut_time;
186: find_idle_and_ttywrite(w);
187: }
188:
189: PERSON *
190: enter_person(pw)
191: register struct passwd *pw;
192: {
193: register PERSON *pn, **pp;
194:
195: for (pp = htab + hash(pw->pw_name);
196: *pp != NULL && strcmp((*pp)->name, pw->pw_name) != 0;
197: pp = &(*pp)->hlink)
198: ;
199: if ((pn = *pp) == NULL) {
200: pn = palloc();
201: entries++;
202: if (phead == NULL)
203: phead = ptail = pn;
204: else {
205: ptail->next = pn;
206: ptail = pn;
207: }
208: pn->next = NULL;
209: pn->hlink = NULL;
210: *pp = pn;
211: userinfo(pn, pw);
212: pn->whead = NULL;
213: }
214: return(pn);
215: }
216:
217: PERSON *
218: find_person(name)
219: char *name;
220: {
221: register PERSON *pn;
222:
223: /* name may be only UT_NAMESIZE long and not terminated */
224: for (pn = htab[hash(name)];
225: pn != NULL && strncmp(pn->name, name, UT_NAMESIZE) != 0;
226: pn = pn->hlink)
227: ;
228: return(pn);
229: }
230:
231: hash(name)
232: register char *name;
233: {
234: register int h, i;
235:
236: h = 0;
237: /* name may be only UT_NAMESIZE long and not terminated */
238: for (i = UT_NAMESIZE; --i >= 0 && *name;)
239: h = ((h << 2 | h >> HBITS - 2) ^ *name++) & HMASK;
240: return(h);
241: }
242:
243: PERSON *
244: palloc()
245: {
246: PERSON *p;
247:
248: if ((p = (PERSON *)malloc((u_int) sizeof(PERSON))) == NULL) {
249: (void)fprintf(stderr, "finger: out of space.\n");
250: exit(1);
251: }
252: return(p);
253: }
254:
255: WHERE *
256: walloc(pn)
257: register PERSON *pn;
258: {
259: register WHERE *w;
260:
261: if ((w = (WHERE *)malloc((u_int) sizeof(WHERE))) == NULL) {
262: (void)fprintf(stderr, "finger: out of space.\n");
263: exit(1);
264: }
265: if (pn->whead == NULL)
266: pn->whead = pn->wtail = w;
267: else {
268: pn->wtail->next = w;
269: pn->wtail = w;
270: }
271: w->next = NULL;
272: return(w);
273: }
274:
275: char *
276: prphone(num)
277: char *num;
278: {
279: register char *p;
280: int len;
281: static char pbuf[15];
282:
283: /* don't touch anything if the user has their own formatting */
284: for (p = num; *p; ++p)
285: if (!isdigit(*p))
286: return(num);
287: len = p - num;
288: p = pbuf;
289: switch(len) {
290: case 11: /* +0-123-456-7890 */
291: *p++ = '+';
292: *p++ = *num++;
293: *p++ = '-';
294: /* FALLTHROUGH */
295: case 10: /* 012-345-6789 */
296: *p++ = *num++;
297: *p++ = *num++;
298: *p++ = *num++;
299: *p++ = '-';
300: /* FALLTHROUGH */
301: case 7: /* 012-3456 */
302: *p++ = *num++;
303: *p++ = *num++;
304: *p++ = *num++;
305: break;
306: case 5: /* x0-1234 */
307: *p++ = 'x';
308: *p++ = *num++;
309: break;
310: default:
311: return(num);
312: }
313: *p++ = '-';
314: *p++ = *num++;
315: *p++ = *num++;
316: *p++ = *num++;
317: *p++ = *num++;
318: *p = '\0';
319: return(pbuf);
320: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.