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[] = "@(#)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 50 find_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 70 userinfo(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 110 match(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 138 enter_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 188 enter_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 203 PERSON * 204 enter_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 231 PERSON * 232 find_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 245 hash(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 257 PERSON * 258 palloc() 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 269 WHERE * 270 walloc(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 289 char * 290 prphone(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 } 335