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*37665Sbostic static char sccsid[] = "@(#)util.c 5.3 (Berkeley) 05/08/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 3437664Sedward find_idle_and_ttywrite(w) 3537664Sedward register WHERE *w; 3637660Sbostic { 3737660Sbostic extern time_t now; 3837660Sbostic extern int errno; 3937660Sbostic struct stat sb; 4037660Sbostic char *strerror(); 4137660Sbostic 4237664Sedward (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 } 4837664Sedward w->idletime = now < sb.st_atime ? 0 : now - sb.st_atime; 4937660Sbostic 5037660Sbostic #define TALKABLE 0220 /* tty is writable if 220 mode */ 5137664Sedward 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 11937664Sedward enter_lastlog(pn) 12037660Sbostic register PERSON *pn; 12137660Sbostic { 12237664Sedward register WHERE *w; 123*37665Sbostic static int opened; 12437660Sbostic struct lastlog ll; 125*37665Sbostic int fd; 12637664Sedward char doit = 0; 12737660Sbostic off_t lseek(); 12837660Sbostic 129*37665Sbostic /* some systems may not maintain lastlog, don't report errors. */ 130*37665Sbostic if (!opened) { 13137664Sedward fd = open(_PATH_LASTLOG, O_RDONLY, 0); 132*37665Sbostic opened = 1; 13337660Sbostic } 134*37665Sbostic if (fd == -1 || 135*37665Sbostic lseek(fd, (long)pn->uid * sizeof(ll), L_SET) != 136*37665Sbostic (long)pn->uid * sizeof(ll) || 137*37665Sbostic read(fd, (char *)&ll, sizeof(ll)) != sizeof(ll)) { 138*37665Sbostic /* as if never logged in */ 139*37665Sbostic ll.ll_line[0] = ll.ll_host[0] = NULL; 140*37665Sbostic ll.ll_time = 0; 141*37665Sbostic } 14237664Sedward if ((w = pn->whead) == NULL) 14337664Sedward doit = 1; 14437664Sedward else { 14537664Sedward /* if last login is earlier than some current login */ 14637664Sedward for (; !doit && w != NULL; w = w->next) 14737664Sedward if (w->info == LOGGEDIN && w->loginat < ll.ll_time) 14837664Sedward doit = 1; 14937664Sedward /* 15037664Sedward * and if it's not any of the current logins 15137664Sedward * can't use time comparison because there may be a small 15237664Sedward * discrepency since login calls time() twice 15337664Sedward */ 15437664Sedward for (w = pn->whead; doit && w != NULL; w = w->next) 15537664Sedward if (w->info == LOGGEDIN && 15637664Sedward strncmp(w->tty, ll.ll_line, UT_LINESIZE) == 0) 15737664Sedward doit = 0; 15837660Sbostic } 15937664Sedward if (doit) { 16037664Sedward w = walloc(pn); 16137664Sedward w->info = LASTLOG; 16237664Sedward bcopy(ll.ll_line, w->tty, UT_LINESIZE); 16337664Sedward w->tty[UT_LINESIZE] = 0; 16437664Sedward bcopy(ll.ll_host, w->host, UT_HOSTSIZE); 16537664Sedward w->host[UT_HOSTSIZE] = 0; 16637664Sedward w->loginat = ll.ll_time; 16737664Sedward } 16837660Sbostic } 16937660Sbostic 17037664Sedward enter_where(ut, pn) 17137660Sbostic struct utmp *ut; 17237660Sbostic PERSON *pn; 17337660Sbostic { 17437664Sedward register WHERE *w = walloc(pn); 17537664Sedward 17637664Sedward w->info = LOGGEDIN; 17737664Sedward bcopy(ut->ut_line, w->tty, UT_LINESIZE); 17837664Sedward w->tty[UT_LINESIZE] = 0; 17937664Sedward bcopy(ut->ut_host, w->host, UT_HOSTSIZE); 18037664Sedward w->host[UT_HOSTSIZE] = 0; 18137664Sedward w->loginat = (time_t)ut->ut_time; 18237664Sedward find_idle_and_ttywrite(w); 18337660Sbostic } 18437664Sedward 18537664Sedward PERSON * 18637664Sedward enter_person(pw) 18737664Sedward register struct passwd *pw; 18837664Sedward { 18937664Sedward register PERSON *pn, **pp; 19037664Sedward 19137664Sedward for (pp = htab + hash(pw->pw_name); 19237664Sedward *pp != NULL && strcmp((*pp)->name, pw->pw_name) != 0; 19337664Sedward pp = &(*pp)->hlink) 19437664Sedward ; 19537664Sedward if ((pn = *pp) == NULL) { 19637664Sedward pn = palloc(); 19737664Sedward entries++; 19837664Sedward if (phead == NULL) 19937664Sedward phead = ptail = pn; 20037664Sedward else { 20137664Sedward ptail->next = pn; 20237664Sedward ptail = pn; 20337664Sedward } 20437664Sedward pn->next = NULL; 20537664Sedward pn->hlink = NULL; 20637664Sedward *pp = pn; 20737664Sedward userinfo(pn, pw); 20837664Sedward pn->whead = NULL; 20937664Sedward } 21037664Sedward return(pn); 21137664Sedward } 21237664Sedward 21337664Sedward PERSON * 21437664Sedward find_person(name) 21537664Sedward char *name; 21637664Sedward { 21737664Sedward register PERSON *pn; 21837664Sedward 21937664Sedward /* name may be only UT_NAMESIZE long and not terminated */ 22037664Sedward for (pn = htab[hash(name)]; 22137664Sedward pn != NULL && strncmp(pn->name, name, UT_NAMESIZE) != 0; 22237664Sedward pn = pn->hlink) 22337664Sedward ; 22437664Sedward return(pn); 22537664Sedward } 22637664Sedward 22737664Sedward hash(name) 22837664Sedward register char *name; 22937664Sedward { 23037664Sedward register int h, i; 23137664Sedward 23237664Sedward h = 0; 23337664Sedward /* name may be only UT_NAMESIZE long and not terminated */ 23437664Sedward for (i = UT_NAMESIZE; --i >= 0 && *name;) 23537664Sedward h = ((h << 2 | h >> HBITS - 2) ^ *name++) & HMASK; 23637664Sedward return(h); 23737664Sedward } 23837664Sedward 23937664Sedward PERSON * 24037664Sedward palloc() 24137664Sedward { 24237664Sedward PERSON *p; 24337664Sedward 24437664Sedward if ((p = (PERSON *)malloc((u_int) sizeof(PERSON))) == NULL) { 24537664Sedward (void)fprintf(stderr, "finger: out of space.\n"); 24637664Sedward exit(1); 24737664Sedward } 24837664Sedward return(p); 24937664Sedward } 25037664Sedward 25137664Sedward WHERE * 25237664Sedward walloc(pn) 25337664Sedward register PERSON *pn; 25437664Sedward { 25537664Sedward register WHERE *w; 25637664Sedward 25737664Sedward if ((w = (WHERE *)malloc((u_int) sizeof(WHERE))) == NULL) { 25837664Sedward (void)fprintf(stderr, "finger: out of space.\n"); 25937664Sedward exit(1); 26037664Sedward } 26137664Sedward if (pn->whead == NULL) 26237664Sedward pn->whead = pn->wtail = w; 26337664Sedward else { 26437664Sedward pn->wtail->next = w; 26537664Sedward pn->wtail = w; 26637664Sedward } 26737664Sedward w->next = NULL; 26837664Sedward return(w); 26937664Sedward } 270