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