don't bother reporting on mail -- it's never going to be right
[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 *
6b8910b8
KB
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16 */
17
18#ifndef lint
8577119b 19static char sccsid[] = "@(#)util.c 5.5 (Berkeley) %G%";
6b8910b8
KB
20#endif /* not lint */
21
22#include <sys/param.h>
23#include <sys/stat.h>
24#include <sys/file.h>
25#include <stdio.h>
26#include <ctype.h>
27#include <strings.h>
28#include "finger.h"
29#include "pathnames.h"
30
7619ff47
EW
31find_idle_and_ttywrite(w)
32 register WHERE *w;
6b8910b8
KB
33{
34 extern time_t now;
35 extern int errno;
36 struct stat sb;
37 char *strerror();
38
7619ff47 39 (void)sprintf(tbuf, "%s/%s", _PATH_DEV, w->tty);
6b8910b8
KB
40 if (stat(tbuf, &sb) < 0) {
41 (void)fprintf(stderr,
42 "finger: %s: %s\n", tbuf, strerror(errno));
43 exit(1);
44 }
7619ff47 45 w->idletime = now < sb.st_atime ? 0 : now - sb.st_atime;
6b8910b8
KB
46
47#define TALKABLE 0220 /* tty is writable if 220 mode */
7619ff47 48 w->writable = ((sb.st_mode & TALKABLE) == TALKABLE);
6b8910b8
KB
49}
50
51userinfo(pn, pw)
52 register PERSON *pn;
53 register struct passwd *pw;
54{
55 register char *p, *t;
56 char name[256];
57
58 pn->realname = pn->office = pn->officephone = pn->homephone = NULL;
59
60 pn->uid = pw->pw_uid;
61 pn->name = strdup(pw->pw_name);
62 pn->dir = strdup(pw->pw_dir);
63 pn->shell = strdup(pw->pw_shell);
64
65 /* why do we skip asterisks!?!? */
66 (void)strcpy(p = tbuf, pw->pw_gecos);
67 if (*p == '*')
68 ++p;
69
70 /* ampersands get replaced by the login name */
71 if (!(p = strsep(p, ",")))
72 return;
73 for (t = name; *t = *p; ++p)
74 if (*t == '&') {
75 (void)strcpy(t, pw->pw_name);
76 if (islower(*t))
77 *t = toupper(*t);
78 while (*++t);
79 }
80 else
81 ++t;
82 pn->realname = strdup(name);
83 pn->office = (p = strsep((char *)NULL, ",")) ? strdup(p) : NULL;
84 pn->officephone = (p = strsep((char *)NULL, ",")) ? strdup(p) : NULL;
85 pn->homephone = (p = strsep((char *)NULL, ",")) ? strdup(p) : NULL;
86}
87
88match(pw, user)
89 struct passwd *pw;
90 char *user;
91{
92 register char *p, *t;
93 char name[256];
94
95 /* why do we skip asterisks!?!? */
96 (void)strcpy(p = tbuf, pw->pw_gecos);
97 if (*p == '*')
98 ++p;
99
100 /* ampersands get replaced by the login name */
101 if (!(p = strtok(p, ",")))
102 return(0);
103 for (t = name; *t = *p; ++p)
104 if (*t == '&') {
105 (void)strcpy(t, pw->pw_name);
106 while (*++t);
107 }
108 else
109 ++t;
110 for (t = name; p = strtok(t, "\t "); t = (char *)NULL)
111 if (!strcasecmp(p, user))
112 return(1);
113 return(0);
114}
115
7619ff47 116enter_lastlog(pn)
6b8910b8
KB
117 register PERSON *pn;
118{
7619ff47 119 register WHERE *w;
8577119b 120 static int opened, fd;
6b8910b8 121 struct lastlog ll;
7619ff47 122 char doit = 0;
6b8910b8
KB
123 off_t lseek();
124
9fc6ea8a
KB
125 /* some systems may not maintain lastlog, don't report errors. */
126 if (!opened) {
7619ff47 127 fd = open(_PATH_LASTLOG, O_RDONLY, 0);
9fc6ea8a 128 opened = 1;
6b8910b8 129 }
9fc6ea8a
KB
130 if (fd == -1 ||
131 lseek(fd, (long)pn->uid * sizeof(ll), L_SET) !=
132 (long)pn->uid * sizeof(ll) ||
133 read(fd, (char *)&ll, sizeof(ll)) != sizeof(ll)) {
134 /* as if never logged in */
135 ll.ll_line[0] = ll.ll_host[0] = NULL;
136 ll.ll_time = 0;
137 }
7619ff47
EW
138 if ((w = pn->whead) == NULL)
139 doit = 1;
8577119b 140 else if (ll.ll_time != 0) {
7619ff47
EW
141 /* if last login is earlier than some current login */
142 for (; !doit && w != NULL; w = w->next)
143 if (w->info == LOGGEDIN && w->loginat < ll.ll_time)
144 doit = 1;
145 /*
146 * and if it's not any of the current logins
147 * can't use time comparison because there may be a small
148 * discrepency since login calls time() twice
149 */
150 for (w = pn->whead; doit && w != NULL; w = w->next)
151 if (w->info == LOGGEDIN &&
152 strncmp(w->tty, ll.ll_line, UT_LINESIZE) == 0)
153 doit = 0;
154 }
155 if (doit) {
156 w = walloc(pn);
157 w->info = LASTLOG;
158 bcopy(ll.ll_line, w->tty, UT_LINESIZE);
159 w->tty[UT_LINESIZE] = 0;
160 bcopy(ll.ll_host, w->host, UT_HOSTSIZE);
161 w->host[UT_HOSTSIZE] = 0;
162 w->loginat = ll.ll_time;
6b8910b8 163 }
6b8910b8
KB
164}
165
7619ff47 166enter_where(ut, pn)
6b8910b8
KB
167 struct utmp *ut;
168 PERSON *pn;
169{
7619ff47
EW
170 register WHERE *w = walloc(pn);
171
172 w->info = LOGGEDIN;
173 bcopy(ut->ut_line, w->tty, UT_LINESIZE);
174 w->tty[UT_LINESIZE] = 0;
175 bcopy(ut->ut_host, w->host, UT_HOSTSIZE);
176 w->host[UT_HOSTSIZE] = 0;
177 w->loginat = (time_t)ut->ut_time;
178 find_idle_and_ttywrite(w);
179}
180
181PERSON *
182enter_person(pw)
183 register struct passwd *pw;
184{
185 register PERSON *pn, **pp;
186
187 for (pp = htab + hash(pw->pw_name);
188 *pp != NULL && strcmp((*pp)->name, pw->pw_name) != 0;
189 pp = &(*pp)->hlink)
190 ;
191 if ((pn = *pp) == NULL) {
192 pn = palloc();
193 entries++;
194 if (phead == NULL)
195 phead = ptail = pn;
196 else {
197 ptail->next = pn;
198 ptail = pn;
199 }
200 pn->next = NULL;
201 pn->hlink = NULL;
202 *pp = pn;
203 userinfo(pn, pw);
204 pn->whead = NULL;
205 }
206 return(pn);
207}
208
209PERSON *
210find_person(name)
211 char *name;
212{
213 register PERSON *pn;
214
215 /* name may be only UT_NAMESIZE long and not terminated */
216 for (pn = htab[hash(name)];
217 pn != NULL && strncmp(pn->name, name, UT_NAMESIZE) != 0;
218 pn = pn->hlink)
219 ;
220 return(pn);
221}
222
223hash(name)
224 register char *name;
225{
226 register int h, i;
227
228 h = 0;
229 /* name may be only UT_NAMESIZE long and not terminated */
230 for (i = UT_NAMESIZE; --i >= 0 && *name;)
231 h = ((h << 2 | h >> HBITS - 2) ^ *name++) & HMASK;
232 return(h);
233}
234
235PERSON *
236palloc()
237{
238 PERSON *p;
239
240 if ((p = (PERSON *)malloc((u_int) sizeof(PERSON))) == NULL) {
241 (void)fprintf(stderr, "finger: out of space.\n");
242 exit(1);
243 }
244 return(p);
245}
246
247WHERE *
248walloc(pn)
249 register PERSON *pn;
250{
251 register WHERE *w;
252
253 if ((w = (WHERE *)malloc((u_int) sizeof(WHERE))) == NULL) {
254 (void)fprintf(stderr, "finger: out of space.\n");
255 exit(1);
256 }
257 if (pn->whead == NULL)
258 pn->whead = pn->wtail = w;
259 else {
260 pn->wtail->next = w;
261 pn->wtail = w;
262 }
263 w->next = NULL;
264 return(w);
6b8910b8 265}