137660Sbostic /* 237660Sbostic * Copyright (c) 1989 The Regents of the University of California. 337660Sbostic * All rights reserved. 437660Sbostic * 537660Sbostic * This code is derived from software contributed to Berkeley by 637660Sbostic * Tony Nardo of the Johns Hopkins University/Applied Physics Lab. 737660Sbostic * 837660Sbostic * Redistribution and use in source and binary forms are permitted 937660Sbostic * provided that the above copyright notice and this paragraph are 1037660Sbostic * duplicated in all such forms and that any documentation, 1137660Sbostic * advertising materials, and other materials related to such 1237660Sbostic * distribution and use acknowledge that the software was developed 1337660Sbostic * by the University of California, Berkeley. The name of the 1437660Sbostic * University may not be used to endorse or promote products derived 1537660Sbostic * from this software without specific prior written permission. 1637660Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1737660Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1837660Sbostic * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1937660Sbostic */ 2037660Sbostic 2137660Sbostic #ifndef lint 22*37664Sedward static char sccsid[] = "@(#)util.c 5.2 (Berkeley) 05/07/89"; 2337660Sbostic #endif /* not lint */ 2437660Sbostic 2537660Sbostic #include <sys/param.h> 2637660Sbostic #include <sys/stat.h> 2737660Sbostic #include <sys/file.h> 2837660Sbostic #include <stdio.h> 2937660Sbostic #include <ctype.h> 3037660Sbostic #include <strings.h> 3137660Sbostic #include "finger.h" 3237660Sbostic #include "pathnames.h" 3337660Sbostic 34*37664Sedward find_idle_and_ttywrite(w) 35*37664Sedward register WHERE *w; 3637660Sbostic { 3737660Sbostic extern time_t now; 3837660Sbostic extern int errno; 3937660Sbostic struct stat sb; 4037660Sbostic char *strerror(); 4137660Sbostic 42*37664Sedward (void)sprintf(tbuf, "%s/%s", _PATH_DEV, w->tty); 4337660Sbostic if (stat(tbuf, &sb) < 0) { 4437660Sbostic (void)fprintf(stderr, 4537660Sbostic "finger: %s: %s\n", tbuf, strerror(errno)); 4637660Sbostic exit(1); 4737660Sbostic } 48*37664Sedward w->idletime = now < sb.st_atime ? 0 : now - sb.st_atime; 4937660Sbostic 5037660Sbostic #define TALKABLE 0220 /* tty is writable if 220 mode */ 51*37664Sedward w->writable = ((sb.st_mode & TALKABLE) == TALKABLE); 5237660Sbostic } 5337660Sbostic 5437660Sbostic userinfo(pn, pw) 5537660Sbostic register PERSON *pn; 5637660Sbostic register struct passwd *pw; 5737660Sbostic { 5837660Sbostic register char *p, *t; 5937660Sbostic char name[256]; 6037660Sbostic 6137660Sbostic pn->realname = pn->office = pn->officephone = pn->homephone = NULL; 6237660Sbostic 6337660Sbostic pn->uid = pw->pw_uid; 6437660Sbostic pn->name = strdup(pw->pw_name); 6537660Sbostic pn->dir = strdup(pw->pw_dir); 6637660Sbostic pn->shell = strdup(pw->pw_shell); 6737660Sbostic 6837660Sbostic /* why do we skip asterisks!?!? */ 6937660Sbostic (void)strcpy(p = tbuf, pw->pw_gecos); 7037660Sbostic if (*p == '*') 7137660Sbostic ++p; 7237660Sbostic 7337660Sbostic /* ampersands get replaced by the login name */ 7437660Sbostic if (!(p = strsep(p, ","))) 7537660Sbostic return; 7637660Sbostic for (t = name; *t = *p; ++p) 7737660Sbostic if (*t == '&') { 7837660Sbostic (void)strcpy(t, pw->pw_name); 7937660Sbostic if (islower(*t)) 8037660Sbostic *t = toupper(*t); 8137660Sbostic while (*++t); 8237660Sbostic } 8337660Sbostic else 8437660Sbostic ++t; 8537660Sbostic pn->realname = strdup(name); 8637660Sbostic pn->office = (p = strsep((char *)NULL, ",")) ? strdup(p) : NULL; 8737660Sbostic pn->officephone = (p = strsep((char *)NULL, ",")) ? strdup(p) : NULL; 8837660Sbostic pn->homephone = (p = strsep((char *)NULL, ",")) ? strdup(p) : NULL; 8937660Sbostic } 9037660Sbostic 9137660Sbostic match(pw, user) 9237660Sbostic struct passwd *pw; 9337660Sbostic char *user; 9437660Sbostic { 9537660Sbostic register char *p, *t; 9637660Sbostic char name[256]; 9737660Sbostic 9837660Sbostic /* why do we skip asterisks!?!? */ 9937660Sbostic (void)strcpy(p = tbuf, pw->pw_gecos); 10037660Sbostic if (*p == '*') 10137660Sbostic ++p; 10237660Sbostic 10337660Sbostic /* ampersands get replaced by the login name */ 10437660Sbostic if (!(p = strtok(p, ","))) 10537660Sbostic return(0); 10637660Sbostic for (t = name; *t = *p; ++p) 10737660Sbostic if (*t == '&') { 10837660Sbostic (void)strcpy(t, pw->pw_name); 10937660Sbostic while (*++t); 11037660Sbostic } 11137660Sbostic else 11237660Sbostic ++t; 11337660Sbostic for (t = name; p = strtok(t, "\t "); t = (char *)NULL) 11437660Sbostic if (!strcasecmp(p, user)) 11537660Sbostic return(1); 11637660Sbostic return(0); 11737660Sbostic } 11837660Sbostic 119*37664Sedward enter_lastlog(pn) 12037660Sbostic register PERSON *pn; 12137660Sbostic { 122*37664Sedward register WHERE *w; 12337660Sbostic static int fd; 12437660Sbostic struct lastlog ll; 125*37664Sedward char doit = 0; 12637660Sbostic off_t lseek(); 12737660Sbostic 128*37664Sedward /* 129*37664Sedward * Some systems may choose not to keep lastlog, 130*37664Sedward * so we don't report any errors. 131*37664Sedward * Not only that, we leave fd at -1 so lseek and read 132*37664Sedward * will fail and act like there were no last logins. 133*37664Sedward * Not the fastest way to do it, but what the hell. 134*37664Sedward */ 135*37664Sedward if (fd == 0) 136*37664Sedward fd = open(_PATH_LASTLOG, O_RDONLY, 0); 137*37664Sedward (void) lseek(fd, (long) (pn->uid * sizeof ll), L_SET); 138*37664Sedward if (read(fd, (char *)&ll, sizeof ll) != sizeof ll) { 139*37664Sedward /* same as never logged in */ 140*37664Sedward ll.ll_line[0] = 0; 141*37664Sedward ll.ll_host[0] = 0; 142*37664Sedward ll.ll_time = 0; 14337660Sbostic } 144*37664Sedward if ((w = pn->whead) == NULL) 145*37664Sedward doit = 1; 146*37664Sedward else { 147*37664Sedward /* if last login is earlier than some current login */ 148*37664Sedward for (; !doit && w != NULL; w = w->next) 149*37664Sedward if (w->info == LOGGEDIN && w->loginat < ll.ll_time) 150*37664Sedward doit = 1; 151*37664Sedward /* 152*37664Sedward * and if it's not any of the current logins 153*37664Sedward * can't use time comparison because there may be a small 154*37664Sedward * discrepency since login calls time() twice 155*37664Sedward */ 156*37664Sedward for (w = pn->whead; doit && w != NULL; w = w->next) 157*37664Sedward if (w->info == LOGGEDIN && 158*37664Sedward strncmp(w->tty, ll.ll_line, UT_LINESIZE) == 0) 159*37664Sedward doit = 0; 16037660Sbostic } 161*37664Sedward if (doit) { 162*37664Sedward w = walloc(pn); 163*37664Sedward w->info = LASTLOG; 164*37664Sedward bcopy(ll.ll_line, w->tty, UT_LINESIZE); 165*37664Sedward w->tty[UT_LINESIZE] = 0; 166*37664Sedward bcopy(ll.ll_host, w->host, UT_HOSTSIZE); 167*37664Sedward w->host[UT_HOSTSIZE] = 0; 168*37664Sedward w->loginat = ll.ll_time; 169*37664Sedward } 17037660Sbostic } 17137660Sbostic 172*37664Sedward enter_where(ut, pn) 17337660Sbostic struct utmp *ut; 17437660Sbostic PERSON *pn; 17537660Sbostic { 176*37664Sedward register WHERE *w = walloc(pn); 177*37664Sedward 178*37664Sedward w->info = LOGGEDIN; 179*37664Sedward bcopy(ut->ut_line, w->tty, UT_LINESIZE); 180*37664Sedward w->tty[UT_LINESIZE] = 0; 181*37664Sedward bcopy(ut->ut_host, w->host, UT_HOSTSIZE); 182*37664Sedward w->host[UT_HOSTSIZE] = 0; 183*37664Sedward w->loginat = (time_t)ut->ut_time; 184*37664Sedward find_idle_and_ttywrite(w); 18537660Sbostic } 186*37664Sedward 187*37664Sedward PERSON * 188*37664Sedward enter_person(pw) 189*37664Sedward register struct passwd *pw; 190*37664Sedward { 191*37664Sedward register PERSON *pn, **pp; 192*37664Sedward 193*37664Sedward for (pp = htab + hash(pw->pw_name); 194*37664Sedward *pp != NULL && strcmp((*pp)->name, pw->pw_name) != 0; 195*37664Sedward pp = &(*pp)->hlink) 196*37664Sedward ; 197*37664Sedward if ((pn = *pp) == NULL) { 198*37664Sedward pn = palloc(); 199*37664Sedward entries++; 200*37664Sedward if (phead == NULL) 201*37664Sedward phead = ptail = pn; 202*37664Sedward else { 203*37664Sedward ptail->next = pn; 204*37664Sedward ptail = pn; 205*37664Sedward } 206*37664Sedward pn->next = NULL; 207*37664Sedward pn->hlink = NULL; 208*37664Sedward *pp = pn; 209*37664Sedward userinfo(pn, pw); 210*37664Sedward pn->whead = NULL; 211*37664Sedward } 212*37664Sedward return(pn); 213*37664Sedward } 214*37664Sedward 215*37664Sedward PERSON * 216*37664Sedward find_person(name) 217*37664Sedward char *name; 218*37664Sedward { 219*37664Sedward register PERSON *pn; 220*37664Sedward 221*37664Sedward /* name may be only UT_NAMESIZE long and not terminated */ 222*37664Sedward for (pn = htab[hash(name)]; 223*37664Sedward pn != NULL && strncmp(pn->name, name, UT_NAMESIZE) != 0; 224*37664Sedward pn = pn->hlink) 225*37664Sedward ; 226*37664Sedward return(pn); 227*37664Sedward } 228*37664Sedward 229*37664Sedward hash(name) 230*37664Sedward register char *name; 231*37664Sedward { 232*37664Sedward register int h, i; 233*37664Sedward 234*37664Sedward h = 0; 235*37664Sedward /* name may be only UT_NAMESIZE long and not terminated */ 236*37664Sedward for (i = UT_NAMESIZE; --i >= 0 && *name;) 237*37664Sedward h = ((h << 2 | h >> HBITS - 2) ^ *name++) & HMASK; 238*37664Sedward return(h); 239*37664Sedward } 240*37664Sedward 241*37664Sedward PERSON * 242*37664Sedward palloc() 243*37664Sedward { 244*37664Sedward PERSON *p; 245*37664Sedward 246*37664Sedward if ((p = (PERSON *)malloc((u_int) sizeof(PERSON))) == NULL) { 247*37664Sedward (void)fprintf(stderr, "finger: out of space.\n"); 248*37664Sedward exit(1); 249*37664Sedward } 250*37664Sedward return(p); 251*37664Sedward } 252*37664Sedward 253*37664Sedward WHERE * 254*37664Sedward walloc(pn) 255*37664Sedward register PERSON *pn; 256*37664Sedward { 257*37664Sedward register WHERE *w; 258*37664Sedward 259*37664Sedward if ((w = (WHERE *)malloc((u_int) sizeof(WHERE))) == NULL) { 260*37664Sedward (void)fprintf(stderr, "finger: out of space.\n"); 261*37664Sedward exit(1); 262*37664Sedward } 263*37664Sedward if (pn->whead == NULL) 264*37664Sedward pn->whead = pn->wtail = w; 265*37664Sedward else { 266*37664Sedward pn->wtail->next = w; 267*37664Sedward pn->wtail = w; 268*37664Sedward } 269*37664Sedward w->next = NULL; 270*37664Sedward return(w); 271*37664Sedward } 272