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