137660Sbostic /* 237660Sbostic * Copyright (c) 1989 The Regents of the University of California. 337660Sbostic * All rights reserved. 437660Sbostic * 537660Sbostic * Redistribution and use in source and binary forms are permitted 637660Sbostic * provided that the above copyright notice and this paragraph are 737660Sbostic * duplicated in all such forms and that any documentation, 837660Sbostic * advertising materials, and other materials related to such 937660Sbostic * distribution and use acknowledge that the software was developed 1037660Sbostic * by the University of California, Berkeley. The name of the 1137660Sbostic * University may not be used to endorse or promote products derived 1237660Sbostic * from this software without specific prior written permission. 1337660Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1437660Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1537660Sbostic * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1637660Sbostic */ 1737660Sbostic 1837660Sbostic #ifndef lint 19*37683Sedward static char sccsid[] = "@(#)util.c 5.5 (Berkeley) 05/08/89"; 2037660Sbostic #endif /* not lint */ 2137660Sbostic 2237660Sbostic #include <sys/param.h> 2337660Sbostic #include <sys/stat.h> 2437660Sbostic #include <sys/file.h> 2537660Sbostic #include <stdio.h> 2637660Sbostic #include <ctype.h> 2737660Sbostic #include <strings.h> 2837660Sbostic #include "finger.h" 2937660Sbostic #include "pathnames.h" 3037660Sbostic 3137664Sedward find_idle_and_ttywrite(w) 3237664Sedward register WHERE *w; 3337660Sbostic { 3437660Sbostic extern time_t now; 3537660Sbostic extern int errno; 3637660Sbostic struct stat sb; 3737660Sbostic char *strerror(); 3837660Sbostic 3937664Sedward (void)sprintf(tbuf, "%s/%s", _PATH_DEV, w->tty); 4037660Sbostic if (stat(tbuf, &sb) < 0) { 4137660Sbostic (void)fprintf(stderr, 4237660Sbostic "finger: %s: %s\n", tbuf, strerror(errno)); 4337660Sbostic exit(1); 4437660Sbostic } 4537664Sedward w->idletime = now < sb.st_atime ? 0 : now - sb.st_atime; 4637660Sbostic 4737660Sbostic #define TALKABLE 0220 /* tty is writable if 220 mode */ 4837664Sedward w->writable = ((sb.st_mode & TALKABLE) == TALKABLE); 4937660Sbostic } 5037660Sbostic 5137660Sbostic userinfo(pn, pw) 5237660Sbostic register PERSON *pn; 5337660Sbostic register struct passwd *pw; 5437660Sbostic { 5537660Sbostic register char *p, *t; 5637660Sbostic char name[256]; 5737660Sbostic 5837660Sbostic pn->realname = pn->office = pn->officephone = pn->homephone = NULL; 5937660Sbostic 6037660Sbostic pn->uid = pw->pw_uid; 6137660Sbostic pn->name = strdup(pw->pw_name); 6237660Sbostic pn->dir = strdup(pw->pw_dir); 6337660Sbostic pn->shell = strdup(pw->pw_shell); 6437660Sbostic 6537660Sbostic /* why do we skip asterisks!?!? */ 6637660Sbostic (void)strcpy(p = tbuf, pw->pw_gecos); 6737660Sbostic if (*p == '*') 6837660Sbostic ++p; 6937660Sbostic 7037660Sbostic /* ampersands get replaced by the login name */ 7137660Sbostic if (!(p = strsep(p, ","))) 7237660Sbostic return; 7337660Sbostic for (t = name; *t = *p; ++p) 7437660Sbostic if (*t == '&') { 7537660Sbostic (void)strcpy(t, pw->pw_name); 7637660Sbostic if (islower(*t)) 7737660Sbostic *t = toupper(*t); 7837660Sbostic while (*++t); 7937660Sbostic } 8037660Sbostic else 8137660Sbostic ++t; 8237660Sbostic pn->realname = strdup(name); 8337660Sbostic pn->office = (p = strsep((char *)NULL, ",")) ? strdup(p) : NULL; 8437660Sbostic pn->officephone = (p = strsep((char *)NULL, ",")) ? strdup(p) : NULL; 8537660Sbostic pn->homephone = (p = strsep((char *)NULL, ",")) ? strdup(p) : NULL; 8637660Sbostic } 8737660Sbostic 8837660Sbostic match(pw, user) 8937660Sbostic struct passwd *pw; 9037660Sbostic char *user; 9137660Sbostic { 9237660Sbostic register char *p, *t; 9337660Sbostic char name[256]; 9437660Sbostic 9537660Sbostic /* why do we skip asterisks!?!? */ 9637660Sbostic (void)strcpy(p = tbuf, pw->pw_gecos); 9737660Sbostic if (*p == '*') 9837660Sbostic ++p; 9937660Sbostic 10037660Sbostic /* ampersands get replaced by the login name */ 10137660Sbostic if (!(p = strtok(p, ","))) 10237660Sbostic return(0); 10337660Sbostic for (t = name; *t = *p; ++p) 10437660Sbostic if (*t == '&') { 10537660Sbostic (void)strcpy(t, pw->pw_name); 10637660Sbostic while (*++t); 10737660Sbostic } 10837660Sbostic else 10937660Sbostic ++t; 11037660Sbostic for (t = name; p = strtok(t, "\t "); t = (char *)NULL) 11137660Sbostic if (!strcasecmp(p, user)) 11237660Sbostic return(1); 11337660Sbostic return(0); 11437660Sbostic } 11537660Sbostic 11637664Sedward enter_lastlog(pn) 11737660Sbostic register PERSON *pn; 11837660Sbostic { 11937664Sedward register WHERE *w; 120*37683Sedward static int opened, fd; 12137660Sbostic struct lastlog ll; 12237664Sedward char doit = 0; 12337660Sbostic off_t lseek(); 12437660Sbostic 12537665Sbostic /* some systems may not maintain lastlog, don't report errors. */ 12637665Sbostic if (!opened) { 12737664Sedward fd = open(_PATH_LASTLOG, O_RDONLY, 0); 12837665Sbostic opened = 1; 12937660Sbostic } 13037665Sbostic if (fd == -1 || 13137665Sbostic lseek(fd, (long)pn->uid * sizeof(ll), L_SET) != 13237665Sbostic (long)pn->uid * sizeof(ll) || 13337665Sbostic read(fd, (char *)&ll, sizeof(ll)) != sizeof(ll)) { 13437665Sbostic /* as if never logged in */ 13537665Sbostic ll.ll_line[0] = ll.ll_host[0] = NULL; 13637665Sbostic ll.ll_time = 0; 13737665Sbostic } 13837664Sedward if ((w = pn->whead) == NULL) 13937664Sedward doit = 1; 140*37683Sedward else if (ll.ll_time != 0) { 14137664Sedward /* if last login is earlier than some current login */ 14237664Sedward for (; !doit && w != NULL; w = w->next) 14337664Sedward if (w->info == LOGGEDIN && w->loginat < ll.ll_time) 14437664Sedward doit = 1; 14537664Sedward /* 14637664Sedward * and if it's not any of the current logins 14737664Sedward * can't use time comparison because there may be a small 14837664Sedward * discrepency since login calls time() twice 14937664Sedward */ 15037664Sedward for (w = pn->whead; doit && w != NULL; w = w->next) 15137664Sedward if (w->info == LOGGEDIN && 15237664Sedward strncmp(w->tty, ll.ll_line, UT_LINESIZE) == 0) 15337664Sedward doit = 0; 15437660Sbostic } 15537664Sedward if (doit) { 15637664Sedward w = walloc(pn); 15737664Sedward w->info = LASTLOG; 15837664Sedward bcopy(ll.ll_line, w->tty, UT_LINESIZE); 15937664Sedward w->tty[UT_LINESIZE] = 0; 16037664Sedward bcopy(ll.ll_host, w->host, UT_HOSTSIZE); 16137664Sedward w->host[UT_HOSTSIZE] = 0; 16237664Sedward w->loginat = ll.ll_time; 16337664Sedward } 16437660Sbostic } 16537660Sbostic 16637664Sedward enter_where(ut, pn) 16737660Sbostic struct utmp *ut; 16837660Sbostic PERSON *pn; 16937660Sbostic { 17037664Sedward register WHERE *w = walloc(pn); 17137664Sedward 17237664Sedward w->info = LOGGEDIN; 17337664Sedward bcopy(ut->ut_line, w->tty, UT_LINESIZE); 17437664Sedward w->tty[UT_LINESIZE] = 0; 17537664Sedward bcopy(ut->ut_host, w->host, UT_HOSTSIZE); 17637664Sedward w->host[UT_HOSTSIZE] = 0; 17737664Sedward w->loginat = (time_t)ut->ut_time; 17837664Sedward find_idle_and_ttywrite(w); 17937660Sbostic } 18037664Sedward 18137664Sedward PERSON * 18237664Sedward enter_person(pw) 18337664Sedward register struct passwd *pw; 18437664Sedward { 18537664Sedward register PERSON *pn, **pp; 18637664Sedward 18737664Sedward for (pp = htab + hash(pw->pw_name); 18837664Sedward *pp != NULL && strcmp((*pp)->name, pw->pw_name) != 0; 18937664Sedward pp = &(*pp)->hlink) 19037664Sedward ; 19137664Sedward if ((pn = *pp) == NULL) { 19237664Sedward pn = palloc(); 19337664Sedward entries++; 19437664Sedward if (phead == NULL) 19537664Sedward phead = ptail = pn; 19637664Sedward else { 19737664Sedward ptail->next = pn; 19837664Sedward ptail = pn; 19937664Sedward } 20037664Sedward pn->next = NULL; 20137664Sedward pn->hlink = NULL; 20237664Sedward *pp = pn; 20337664Sedward userinfo(pn, pw); 20437664Sedward pn->whead = NULL; 20537664Sedward } 20637664Sedward return(pn); 20737664Sedward } 20837664Sedward 20937664Sedward PERSON * 21037664Sedward find_person(name) 21137664Sedward char *name; 21237664Sedward { 21337664Sedward register PERSON *pn; 21437664Sedward 21537664Sedward /* name may be only UT_NAMESIZE long and not terminated */ 21637664Sedward for (pn = htab[hash(name)]; 21737664Sedward pn != NULL && strncmp(pn->name, name, UT_NAMESIZE) != 0; 21837664Sedward pn = pn->hlink) 21937664Sedward ; 22037664Sedward return(pn); 22137664Sedward } 22237664Sedward 22337664Sedward hash(name) 22437664Sedward register char *name; 22537664Sedward { 22637664Sedward register int h, i; 22737664Sedward 22837664Sedward h = 0; 22937664Sedward /* name may be only UT_NAMESIZE long and not terminated */ 23037664Sedward for (i = UT_NAMESIZE; --i >= 0 && *name;) 23137664Sedward h = ((h << 2 | h >> HBITS - 2) ^ *name++) & HMASK; 23237664Sedward return(h); 23337664Sedward } 23437664Sedward 23537664Sedward PERSON * 23637664Sedward palloc() 23737664Sedward { 23837664Sedward PERSON *p; 23937664Sedward 24037664Sedward if ((p = (PERSON *)malloc((u_int) sizeof(PERSON))) == NULL) { 24137664Sedward (void)fprintf(stderr, "finger: out of space.\n"); 24237664Sedward exit(1); 24337664Sedward } 24437664Sedward return(p); 24537664Sedward } 24637664Sedward 24737664Sedward WHERE * 24837664Sedward walloc(pn) 24937664Sedward register PERSON *pn; 25037664Sedward { 25137664Sedward register WHERE *w; 25237664Sedward 25337664Sedward if ((w = (WHERE *)malloc((u_int) sizeof(WHERE))) == NULL) { 25437664Sedward (void)fprintf(stderr, "finger: out of space.\n"); 25537664Sedward exit(1); 25637664Sedward } 25737664Sedward if (pn->whead == NULL) 25837664Sedward pn->whead = pn->wtail = w; 25937664Sedward else { 26037664Sedward pn->wtail->next = w; 26137664Sedward pn->wtail = w; 26237664Sedward } 26337664Sedward w->next = NULL; 26437664Sedward return(w); 26537664Sedward } 266