137660Sbostic /* 261995Sbostic * Copyright (c) 1989, 1993 361995Sbostic * The Regents of the University of California. All rights reserved. 437660Sbostic * 540027Sbostic * This code is derived from software contributed to Berkeley by 640027Sbostic * Tony Nardo of the Johns Hopkins University/Applied Physics Lab. 740027Sbostic * 842731Sbostic * %sccs.include.redist.c% 937660Sbostic */ 1037660Sbostic 1137660Sbostic #ifndef lint 12*69101Sbostic static char sccsid[] = "@(#)util.c 8.2 (Berkeley) 04/28/95"; 1337660Sbostic #endif /* not lint */ 1437660Sbostic 1537660Sbostic #include <sys/param.h> 1637660Sbostic #include <sys/stat.h> 1750596Sbostic #include <fcntl.h> 1850613Sbostic #include <db.h> 19*69101Sbostic #include <err.h> 2050596Sbostic #include <pwd.h> 2150596Sbostic #include <utmp.h> 2250596Sbostic #include <errno.h> 2350596Sbostic #include <unistd.h> 2437660Sbostic #include <stdio.h> 2537660Sbostic #include <ctype.h> 2650596Sbostic #include <stdlib.h> 2742053Sbostic #include <string.h> 2843857Sbostic #include <paths.h> 2937660Sbostic #include "finger.h" 3037660Sbostic 3150596Sbostic static void find_idle_and_ttywrite __P((WHERE *)); 3250596Sbostic static void userinfo __P((PERSON *, struct passwd *)); 3350596Sbostic static WHERE *walloc __P((PERSON *)); 3450596Sbostic 3551423Sbostic int 3637660Sbostic match(pw, user) 3737660Sbostic struct passwd *pw; 3837660Sbostic char *user; 3937660Sbostic { 4037660Sbostic register char *p, *t; 4141568Smarc char name[1024]; 4237660Sbostic 4352851Sbostic if (!strcasecmp(pw->pw_name, user)) 4452851Sbostic return(1); 4552851Sbostic 4652851Sbostic /* 4752851Sbostic * XXX 4852851Sbostic * Why do we skip asterisks!?!? 4952851Sbostic */ 5037660Sbostic (void)strcpy(p = tbuf, pw->pw_gecos); 5137660Sbostic if (*p == '*') 5237660Sbostic ++p; 5337660Sbostic 5452851Sbostic /* Ampersands get replaced by the login name. */ 5552851Sbostic if ((p = strtok(p, ",")) == NULL) 5637660Sbostic return(0); 5752851Sbostic 58*69101Sbostic for (t = name; (*t = *p) != '\0'; ++p) 5937660Sbostic if (*t == '&') { 6037660Sbostic (void)strcpy(t, pw->pw_name); 6137660Sbostic while (*++t); 6237660Sbostic } 6337660Sbostic else 6437660Sbostic ++t; 65*69101Sbostic for (t = name; (p = strtok(t, "\t ")) != NULL; t = NULL) 6637660Sbostic if (!strcasecmp(p, user)) 6737660Sbostic return(1); 6837660Sbostic return(0); 6937660Sbostic } 7037660Sbostic 7150596Sbostic void 7237664Sedward enter_lastlog(pn) 7337660Sbostic register PERSON *pn; 7437660Sbostic { 7537664Sedward register WHERE *w; 7637683Sedward static int opened, fd; 7737660Sbostic struct lastlog ll; 7837664Sedward char doit = 0; 7937660Sbostic 8037665Sbostic /* some systems may not maintain lastlog, don't report errors. */ 8137665Sbostic if (!opened) { 8237664Sedward fd = open(_PATH_LASTLOG, O_RDONLY, 0); 8337665Sbostic opened = 1; 8437660Sbostic } 8537665Sbostic if (fd == -1 || 8650596Sbostic lseek(fd, (long)pn->uid * sizeof(ll), SEEK_SET) != 8737665Sbostic (long)pn->uid * sizeof(ll) || 8837665Sbostic read(fd, (char *)&ll, sizeof(ll)) != sizeof(ll)) { 8937665Sbostic /* as if never logged in */ 9037665Sbostic ll.ll_line[0] = ll.ll_host[0] = NULL; 9137665Sbostic ll.ll_time = 0; 9237665Sbostic } 9337664Sedward if ((w = pn->whead) == NULL) 9437664Sedward doit = 1; 9537683Sedward else if (ll.ll_time != 0) { 9637664Sedward /* if last login is earlier than some current login */ 9737664Sedward for (; !doit && w != NULL; w = w->next) 9837664Sedward if (w->info == LOGGEDIN && w->loginat < ll.ll_time) 9937664Sedward doit = 1; 10037664Sedward /* 10137664Sedward * and if it's not any of the current logins 10237664Sedward * can't use time comparison because there may be a small 10337664Sedward * discrepency since login calls time() twice 10437664Sedward */ 10537664Sedward for (w = pn->whead; doit && w != NULL; w = w->next) 10637664Sedward if (w->info == LOGGEDIN && 10737664Sedward strncmp(w->tty, ll.ll_line, UT_LINESIZE) == 0) 10837664Sedward doit = 0; 10937660Sbostic } 11037664Sedward if (doit) { 11137664Sedward w = walloc(pn); 11237664Sedward w->info = LASTLOG; 11337664Sedward bcopy(ll.ll_line, w->tty, UT_LINESIZE); 11437664Sedward w->tty[UT_LINESIZE] = 0; 11537664Sedward bcopy(ll.ll_host, w->host, UT_HOSTSIZE); 11637664Sedward w->host[UT_HOSTSIZE] = 0; 11737664Sedward w->loginat = ll.ll_time; 11837664Sedward } 11937660Sbostic } 12037660Sbostic 12150596Sbostic void 12237664Sedward enter_where(ut, pn) 12337660Sbostic struct utmp *ut; 12437660Sbostic PERSON *pn; 12537660Sbostic { 12650596Sbostic register WHERE *w; 12737664Sedward 12850596Sbostic w = walloc(pn); 12937664Sedward w->info = LOGGEDIN; 13037664Sedward bcopy(ut->ut_line, w->tty, UT_LINESIZE); 13137664Sedward w->tty[UT_LINESIZE] = 0; 13237664Sedward bcopy(ut->ut_host, w->host, UT_HOSTSIZE); 13337664Sedward w->host[UT_HOSTSIZE] = 0; 13437664Sedward w->loginat = (time_t)ut->ut_time; 13537664Sedward find_idle_and_ttywrite(w); 13637660Sbostic } 13737664Sedward 13837664Sedward PERSON * 13937664Sedward enter_person(pw) 14037664Sedward register struct passwd *pw; 14137664Sedward { 14251423Sbostic DBT data, key; 14350613Sbostic PERSON *pn; 14437664Sedward 14551423Sbostic if (db == NULL && 14651423Sbostic (db = dbopen(NULL, O_RDWR, 0, DB_BTREE, NULL)) == NULL) 147*69101Sbostic err(1, NULL); 14850613Sbostic 14950613Sbostic key.data = pw->pw_name; 15050613Sbostic key.size = strlen(pw->pw_name); 15150613Sbostic 152*69101Sbostic switch ((*db->get)(db, &key, &data, 0)) { 15350613Sbostic case 0: 154*69101Sbostic memcpy(&pn, data.data, sizeof pn); 155*69101Sbostic return (pn); 15650613Sbostic default: 15750613Sbostic case -1: 158*69101Sbostic err(1, "db get"); 15950613Sbostic /* NOTREACHED */ 16050613Sbostic case 1: 16150613Sbostic ++entries; 16237664Sedward pn = palloc(); 16337664Sedward userinfo(pn, pw); 16437664Sedward pn->whead = NULL; 16550613Sbostic 16650613Sbostic data.size = sizeof(PERSON *); 16750613Sbostic data.data = &pn; 16851178Sbostic if ((*db->put)(db, &key, &data, 0)) 169*69101Sbostic err(1, "db put"); 170*69101Sbostic return (pn); 17137664Sedward } 17237664Sedward } 17337664Sedward 17437664Sedward PERSON * 17537664Sedward find_person(name) 17637664Sedward char *name; 17737664Sedward { 17850613Sbostic register int cnt; 17950613Sbostic DBT data, key; 180*69101Sbostic PERSON *p; 18150613Sbostic char buf[UT_NAMESIZE + 1]; 18237664Sedward 18350613Sbostic if (!db) 18450613Sbostic return(NULL); 18537664Sedward 18650613Sbostic /* Name may be only UT_NAMESIZE long and not NUL terminated. */ 18750613Sbostic for (cnt = 0; cnt < UT_NAMESIZE && *name; ++name, ++cnt) 18850613Sbostic buf[cnt] = *name; 18950613Sbostic buf[cnt] = '\0'; 19050613Sbostic key.data = buf; 19150613Sbostic key.size = cnt; 19237664Sedward 193*69101Sbostic if ((*db->get)(db, &key, &data, 0)) 194*69101Sbostic return (NULL); 195*69101Sbostic memcpy(&p, data.data, sizeof p); 196*69101Sbostic return (p); 19737664Sedward } 19837664Sedward 19937664Sedward PERSON * 20037664Sedward palloc() 20137664Sedward { 20237664Sedward PERSON *p; 20337664Sedward 20450596Sbostic if ((p = malloc((u_int) sizeof(PERSON))) == NULL) 205*69101Sbostic err(1, NULL); 20637664Sedward return(p); 20737664Sedward } 20837664Sedward 20950596Sbostic static WHERE * 21037664Sedward walloc(pn) 21137664Sedward register PERSON *pn; 21237664Sedward { 21337664Sedward register WHERE *w; 21437664Sedward 21550613Sbostic if ((w = malloc((u_int) sizeof(WHERE))) == NULL) 216*69101Sbostic err(1, NULL); 21737664Sedward if (pn->whead == NULL) 21837664Sedward pn->whead = pn->wtail = w; 21937664Sedward else { 22037664Sedward pn->wtail->next = w; 22137664Sedward pn->wtail = w; 22237664Sedward } 22337664Sedward w->next = NULL; 22437664Sedward return(w); 22537664Sedward } 22638052Sbostic 22738052Sbostic char * 22838052Sbostic prphone(num) 22938052Sbostic char *num; 23038052Sbostic { 23138052Sbostic register char *p; 23238052Sbostic int len; 23338052Sbostic static char pbuf[15]; 23438052Sbostic 23538052Sbostic /* don't touch anything if the user has their own formatting */ 23638052Sbostic for (p = num; *p; ++p) 23738052Sbostic if (!isdigit(*p)) 23838052Sbostic return(num); 23938052Sbostic len = p - num; 24038052Sbostic p = pbuf; 24138052Sbostic switch(len) { 24238052Sbostic case 11: /* +0-123-456-7890 */ 24338052Sbostic *p++ = '+'; 24438052Sbostic *p++ = *num++; 24538052Sbostic *p++ = '-'; 24638052Sbostic /* FALLTHROUGH */ 24738052Sbostic case 10: /* 012-345-6789 */ 24838052Sbostic *p++ = *num++; 24938052Sbostic *p++ = *num++; 25038052Sbostic *p++ = *num++; 25138052Sbostic *p++ = '-'; 25238052Sbostic /* FALLTHROUGH */ 25338052Sbostic case 7: /* 012-3456 */ 25438052Sbostic *p++ = *num++; 25538052Sbostic *p++ = *num++; 25638052Sbostic *p++ = *num++; 25738052Sbostic break; 25838052Sbostic case 5: /* x0-1234 */ 25938052Sbostic *p++ = 'x'; 26038052Sbostic *p++ = *num++; 26138052Sbostic break; 26238052Sbostic default: 26338052Sbostic return(num); 26438052Sbostic } 26538052Sbostic *p++ = '-'; 26638052Sbostic *p++ = *num++; 26738052Sbostic *p++ = *num++; 26838052Sbostic *p++ = *num++; 26938052Sbostic *p++ = *num++; 27038052Sbostic *p = '\0'; 27138052Sbostic return(pbuf); 27238052Sbostic } 27350596Sbostic 27450613Sbostic static void 27550613Sbostic find_idle_and_ttywrite(w) 27650613Sbostic register WHERE *w; 27750613Sbostic { 27850613Sbostic extern time_t now; 27950613Sbostic struct stat sb; 28050613Sbostic 28150613Sbostic (void)snprintf(tbuf, sizeof(tbuf), "%s/%s", _PATH_DEV, w->tty); 28250613Sbostic if (stat(tbuf, &sb) < 0) { 283*69101Sbostic warn(tbuf); 28450613Sbostic return; 28550613Sbostic } 28650613Sbostic w->idletime = now < sb.st_atime ? 0 : now - sb.st_atime; 28750613Sbostic 28850613Sbostic #define TALKABLE 0220 /* tty is writable if 220 mode */ 28950613Sbostic w->writable = ((sb.st_mode & TALKABLE) == TALKABLE); 29050613Sbostic } 29150613Sbostic 29250613Sbostic static void 29350613Sbostic userinfo(pn, pw) 29450613Sbostic register PERSON *pn; 29550613Sbostic register struct passwd *pw; 29650613Sbostic { 29750613Sbostic register char *p, *t; 29850613Sbostic char *bp, name[1024]; 29950613Sbostic 30050613Sbostic pn->realname = pn->office = pn->officephone = pn->homephone = NULL; 30150613Sbostic 30250613Sbostic pn->uid = pw->pw_uid; 30350613Sbostic pn->name = strdup(pw->pw_name); 30450613Sbostic pn->dir = strdup(pw->pw_dir); 30550613Sbostic pn->shell = strdup(pw->pw_shell); 30650613Sbostic 30750613Sbostic /* why do we skip asterisks!?!? */ 30850613Sbostic (void)strcpy(bp = tbuf, pw->pw_gecos); 30950613Sbostic if (*bp == '*') 31050613Sbostic ++bp; 31150613Sbostic 31250613Sbostic /* ampersands get replaced by the login name */ 31350613Sbostic if (!(p = strsep(&bp, ","))) 31450613Sbostic return; 315*69101Sbostic for (t = name; (*t = *p) != '\0'; ++p) 31650613Sbostic if (*t == '&') { 31750613Sbostic (void)strcpy(t, pw->pw_name); 31850613Sbostic if (islower(*t)) 31950613Sbostic *t = toupper(*t); 32050613Sbostic while (*++t); 32150613Sbostic } 32250613Sbostic else 32350613Sbostic ++t; 32450613Sbostic pn->realname = strdup(name); 32550613Sbostic pn->office = ((p = strsep(&bp, ",")) && *p) ? 32650613Sbostic strdup(p) : NULL; 32750613Sbostic pn->officephone = ((p = strsep(&bp, ",")) && *p) ? 32850613Sbostic strdup(p) : NULL; 32950613Sbostic pn->homephone = ((p = strsep(&bp, ",")) && *p) ? 33050613Sbostic strdup(p) : NULL; 33150613Sbostic } 332