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