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