From 7619ff47588e33444979a68d65edc1cd2472ddea Mon Sep 17 00:00:00 2001 From: Edward Wang Date: Sun, 7 May 1989 08:02:58 -0800 Subject: [PATCH] show last login time if more recent than current logins, cleaned up, speeded up, put people in hash table, separate login info from personal info SCCS-vsn: usr.bin/finger/finger.c 5.14 SCCS-vsn: usr.bin/finger/finger.h 5.2 SCCS-vsn: usr.bin/finger/lprint.c 5.2 SCCS-vsn: usr.bin/finger/sprint.c 5.2 SCCS-vsn: usr.bin/finger/util.c 5.2 --- usr/src/usr.bin/finger/finger.c | 150 ++++++++++------------------ usr/src/usr.bin/finger/finger.h | 38 +++++-- usr/src/usr.bin/finger/lprint.c | 88 +++++++--------- usr/src/usr.bin/finger/sprint.c | 85 ++++++++-------- usr/src/usr.bin/finger/util.c | 172 +++++++++++++++++++++++++++----- 5 files changed, 306 insertions(+), 227 deletions(-) diff --git a/usr/src/usr.bin/finger/finger.c b/usr/src/usr.bin/finger/finger.c index 43bc5b6e94..873190b504 100644 --- a/usr/src/usr.bin/finger/finger.c +++ b/usr/src/usr.bin/finger/finger.c @@ -25,7 +25,7 @@ char copyright[] = #endif /* not lint */ #ifndef lint -static char sccsid[] = "@(#)finger.c 5.13 (Berkeley) %G%"; +static char sccsid[] = "@(#)finger.c 5.14 (Berkeley) %G%"; #endif /* not lint */ /* @@ -47,10 +47,8 @@ static char sccsid[] = "@(#)finger.c 5.13 (Berkeley) %G%"; #include "finger.h" #include "pathnames.h" -struct utmp user; -PERSON *head; time_t now; -int entries, lflag, sflag, mflag, pplan; +int lflag, sflag, mflag, pplan; char tbuf[1024]; main(argc, argv) @@ -95,7 +93,7 @@ main(argc, argv) if (!lflag) sflag = 1; /* if -l not explicit, force -s */ loginlist(); - if (!head) + if (entries == 0) (void)printf("No one logged on.\n"); } else { userlist(argv); @@ -107,7 +105,7 @@ main(argc, argv) if (!sflag) lflag = 1; /* if -s not explicit, force -l */ } - if (head) { + if (entries != 0) { if (lflag) lflag_print(); else @@ -121,66 +119,52 @@ loginlist() register PERSON *pn; register int fd; struct passwd *pw; - char name[UT_NAMESIZE + 1], *strdup(), *malloc(); + struct utmp user; + char name[UT_NAMESIZE + 1]; if ((fd = open(_PATH_UTMP, O_RDONLY, 0)) < 0) { (void)fprintf(stderr, "finger: can't read %s.\n", _PATH_UTMP); exit(2); } name[UT_NAMESIZE] = NULL; - while(read(fd, (char *)&user, sizeof(user)) == sizeof(user)) { + while (read(fd, (char *)&user, sizeof(user)) == sizeof(user)) { if (!user.ut_name[0]) continue; - bcopy(user.ut_name, name, UT_NAMESIZE); - if (!(pw = getpwnam(name))) - continue; - if (!(pn = (PERSON *)malloc((u_int)sizeof(PERSON)))) { - (void)fprintf(stderr, "finger: out of space.\n"); - exit(1); + if ((pn = find_person(user.ut_name)) == NULL) { + bcopy(user.ut_name, name, UT_NAMESIZE); + if ((pw = getpwnam(name)) == NULL) + continue; + pn = enter_person(pw); } - ++entries; - pn->next = head; - head = pn; - utcopy(&user, pn); - userinfo(pn, pw); - find_idle_and_ttywrite(pn); - pn->info = LOGGEDIN; + enter_where(&user, pn); } (void)close(fd); + for (pn = phead; lflag && pn != NULL; pn = pn->next) + enter_lastlog(pn); } #define ARGIGNORE (char *)0x01 userlist(argv) char **argv; { - register PERSON *nethead, *p, *pn; - register struct passwd *pw; - register char **a1, **a2; - int fd, dolocal, nelem; - char **sargv, **arglist, *malloc(), *rindex(), *strcpy(); - - /* suppress duplicates while it's still easy */ - for (a1 = argv; *a1; ++a1) - for (a2 = a1 + 1; *a2; ++a2) - if (!strcasecmp(*a1, *a2)) { - *a1 = ARGIGNORE; - break; - } + register char **ap; + register PERSON *pn; + PERSON *nethead; + struct utmp user; + struct passwd *pw; + int fd, dolocal, *index(); /* pull out all network requests */ - for (sargv = argv, dolocal = 0, nethead = NULL; *argv; ++argv) { - if (!index(*argv, '@')) { + for (ap = argv, dolocal = 0, nethead = NULL; *ap != NULL; ap++) { + if (!index(*ap, '@')) { dolocal = 1; continue; } - if (!(pn = (PERSON *)malloc((u_int)sizeof(PERSON)))) { - (void)fprintf(stderr, "finger: out of space.\n"); - exit(1); - } + pn = palloc(); pn->next = nethead; nethead = pn; - pn->name = *argv; - *argv = ARGIGNORE; + pn->name = *ap; + *ap = ARGIGNORE; } if (!dolocal) @@ -188,44 +172,33 @@ userlist(argv) /* * traverse the list of possible login names and check the login name - * and real name against the name specified by the user. Possible - * speedup would be to use getpwnam(3) if mflag set -- maybe not - * worthwhile, given that the default is the mflag off. + * and real name against the name specified by the user. */ - nelem = argv - sargv + 1; - if (!(arglist = - (char **)malloc((u_int)(nelem * sizeof(char *))))) { - (void)fprintf(stderr, "finger: out of space.\n"); - exit(1); - } - bcopy((char *)sargv, (char *)arglist, nelem * sizeof(char *)); - while (pw = getpwent()) { - for (argv = sargv; *argv; ++argv) { - if (*argv == ARGIGNORE) + if (mflag) + for (ap = argv; *ap != NULL; ap++) { + if (*ap == ARGIGNORE) + continue; + if ((pw = getpwnam(*ap)) == NULL) + continue; + enter_person(pw); + *ap = ARGIGNORE; + } + else while (pw = getpwent()) + for (ap = argv; *ap != NULL; ap++) { + if (*ap == ARGIGNORE) continue; - if (strcasecmp(pw->pw_name, *argv) && - (mflag || !match(pw, *argv))) + if (strcasecmp(pw->pw_name, *ap) && !match(pw, *ap)) continue; - if (!(pn = (PERSON *)malloc((u_int)sizeof(PERSON)))) { - (void)fprintf(stderr, - "finger: out of space.\n"); - exit(1); - } - ++entries; - pn->next = head; - head = pn; - userinfo(pn, pw); - pn->info = FOUND; - arglist[argv - sargv] = ARGIGNORE; + enter_person(pw); + *ap = ARGIGNORE; /* don't break, may be listed multiple times */ } - } /* list errors */ - for (; *arglist; ++arglist) - if (*arglist != ARGIGNORE) + for (ap = argv; *ap != NULL; ap++) + if (*ap != ARGIGNORE) (void)fprintf(stderr, - "finger: %s: no such user.\n", *arglist); + "finger: %s: no such user.\n", *ap); /* handle network requests */ net: for (pn = nethead; pn; pn = pn->next) { @@ -234,7 +207,7 @@ net: for (pn = nethead; pn; pn = pn->next) { putchar('\n'); } - if (!head) + if (entries == 0) return; /* @@ -248,32 +221,11 @@ net: for (pn = nethead; pn; pn = pn->next) { while (read(fd, (char *)&user, sizeof(user)) == sizeof(user)) { if (!user.ut_name[0]) continue; - for (pn = head; pn; pn = pn->next) { - if (strncasecmp(pn->name, user.ut_name, UT_NAMESIZE)) - continue; - if (pn->info == LOGGEDIN) { - if (!(p = - (PERSON *)malloc((u_int)sizeof(PERSON)))) { - (void)fprintf(stderr, - "finger: out of space.\n"); - exit(1); - } - ++entries; - p->name = pn->name; - (void)strcpy(p->tty, pn->tty); - /* link in so finds `real' entry first! */ - p->next = pn->next; - pn->next = p; - pn = p; - } - pn->info = LOGGEDIN; - utcopy(&user, pn); - find_idle_and_ttywrite(pn); - /* don't break, may be listed multiple times... */ - } + if ((pn = find_person(user.ut_name)) == NULL) + continue; + enter_where(&user, pn); } (void)close(fd); - for (pn = head; pn; pn = pn->next) - if (pn->info == FOUND) - find_when(pn); + for (pn = phead; pn != NULL; pn = pn->next) + enter_lastlog(pn); } diff --git a/usr/src/usr.bin/finger/finger.h b/usr/src/usr.bin/finger/finger.h index c324de95b7..3b199a5277 100644 --- a/usr/src/usr.bin/finger/finger.h +++ b/usr/src/usr.bin/finger/finger.h @@ -17,20 +17,21 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * @(#)finger.h 5.1 (Berkeley) %G% + * @(#)finger.h 5.2 (Berkeley) %G% */ #include #include -enum status { PRINTED, FOUND, LOGGEDIN }; +/* + * All unique persons are linked in a list headed by "head" and linkd + * by the "next" field, as well as kept in a hash table. + */ + typedef struct person { struct person *next; /* link to next person */ - time_t loginat; /* time of (last) login */ - time_t idletime; /* how long idle (if logged in) */ + struct person *hlink; /* link to next person in hash bucket */ uid_t uid; /* user id */ - enum status info; /* type/status of request */ - short writable; /* tty is writable */ char *dir; /* user's home directory */ char *homephone; /* pointer to home phone no. */ char *name; /* login name */ @@ -38,8 +39,31 @@ typedef struct person { char *officephone; /* pointer to office phone no. */ char *realname; /* pointer to full name */ char *shell; /* user's shell */ + struct where *whead, *wtail; /* list of where he is or has been */ +} PERSON; + +enum status { LASTLOG, LOGGEDIN }; + +typedef struct where { + struct where *next; /* next place he is or has been */ + enum status info; /* type/status of request */ + short writable; /* tty is writable */ + time_t loginat; /* time of (last) login */ + time_t idletime; /* how long idle (if logged in) */ char tty[UT_LINESIZE+1]; /* null terminated tty line */ char host[UT_HOSTSIZE+1]; /* null terminated remote host name */ -} PERSON; +} WHERE; + +#define HBITS 8 /* number of bits in hash code */ +#define HSIZE (1 << 8) /* hash table size */ +#define HMASK (HSIZE - 1) /* hash code mask */ + +PERSON *htab[HSIZE]; /* the buckets */ +PERSON *phead, *ptail; /* the linked list of all people */ + +int entries; /* number of people */ + +PERSON *enter_person(), *find_person(), *palloc(); +WHERE *walloc(); extern char tbuf[1024]; /* temp buffer for anybody */ diff --git a/usr/src/usr.bin/finger/lprint.c b/usr/src/usr.bin/finger/lprint.c index d40c93caa6..284aaed6d8 100644 --- a/usr/src/usr.bin/finger/lprint.c +++ b/usr/src/usr.bin/finger/lprint.c @@ -19,7 +19,7 @@ */ #ifndef lint -static char sccsid[] = "@(#)lprint.c 5.1 (Berkeley) %G%"; +static char sccsid[] = "@(#)lprint.c 5.2 (Berkeley) %G%"; #endif /* not lint */ #include @@ -38,20 +38,13 @@ static char sccsid[] = "@(#)lprint.c 5.1 (Berkeley) %G%"; lflag_print() { - extern PERSON *head; extern int pplan; register PERSON *pn; - for (pn = head;;) { - if (pn->info == PRINTED) { - if (!(pn = pn->next)) - break; - continue; - } + for (pn = phead;;) { lprint(pn); if (!pplan) { - (void)show_text(pn->dir, _PATH_PROJECT, - "Project:"); + (void)show_text(pn->dir, _PATH_PROJECT, "Project:"); if (!show_text(pn->dir, _PATH_PLAN, "Plan:")) (void)printf("No Plan.\n"); } @@ -66,7 +59,7 @@ lprint(pn) { extern time_t now; register struct tm *delta; - register PERSON *p; + register WHERE *w; register int cpr, len, maxlen; int oddfield; time_t time(); @@ -116,34 +109,33 @@ lprint(pn) putchar('\n'); /* - * long format con't: if logged in + * long format con't: * if logged in * terminal * idle time * if messages allowed * where logged in from + * if not logged in + * when last logged in */ - if (pn->info == LOGGEDIN) { - /* find out longest device name for this user for formatting */ - for (maxlen = -1, p = pn; p; p = p->next) - if (!strcmp(p->name, pn->name) && - (len = strlen(p->tty)) > maxlen) - maxlen = len; - /* find rest of entries for user */ - for (p = pn; p; p = p->next) { - if (strcmp(p->name, pn->name)) - continue; - p->info = PRINTED; + /* find out longest device name for this user for formatting */ + for (w = pn->whead; w != NULL; w = w->next) + if ((len = strlen(w->tty)) > maxlen) + maxlen = len; + /* find rest of entries for user */ + for (w = pn->whead; w != NULL; w = w->next) { + switch (w->info) { + case LOGGEDIN: cpr = printf("On since %16.16s on %s", - ctime(&p->loginat), p->tty); + ctime(&w->loginat), w->tty); /* * idle time is tough; if have one, print a comma, * then spaces to pad out the device name, then the * idle time. Follow with a comma if a remote login. */ - delta = gmtime(&p->idletime); + delta = gmtime(&w->idletime); if (delta->tm_yday || delta->tm_hour || delta->tm_min) { cpr += printf("%-*s idle ", - maxlen - strlen(p->tty) + 1, ","); + maxlen - strlen(w->tty) + 1, ","); if (delta->tm_yday > 0) { cpr += printf("%d day%s ", delta->tm_yday, @@ -151,40 +143,32 @@ lprint(pn) } cpr += printf("%d:%02d", delta->tm_hour, delta->tm_min); - if (*p->host) { + if (*w->host) { putchar(','); ++cpr; } } - if (!p->writable) + if (!w->writable) cpr += printf(" (messages off)"); - if (*p->host) { - if (LINE_LEN < (cpr + 6 + - strlen(p->host))) { - (void)printf("\n "); - } - (void)printf(" from %s", p->host); + break; + case LASTLOG: + if (w->loginat == 0) { + (void)printf("Never logged in."); + break; } - (void)putchar('\n'); + t = ctime(&w->loginat); + if (now - w->loginat > SECSPERDAY * DAYSPERNYEAR / 2) + cpr = printf("Last login %10.10s, %4.4s on %s", + t, t + 20, w->tty); + else + cpr = printf("Last login %16.16s on %s", + t, w->tty); + break; } - } - /* - * long format con't: if not logged in - * when last logged in - */ - else if (!pn->loginat) - (void)printf("Never logged in.\n"); - else { - t = ctime(&pn->loginat); - if (now - pn->loginat > SECSPERDAY * DAYSPERNYEAR / 2) - cpr = printf("Last login %10.10s, %4.4s on %s", - t, t + 20, pn->tty); - else - cpr = printf("Last login %16.16s on %s", t, pn->tty); - if (*pn->host) { - if (LINE_LEN < (cpr + 6 + strlen(pn->host))) + if (*w->host) { + if (LINE_LEN < (cpr + 6 + strlen(w->host))) (void)printf("\n "); - (void)printf(" from %s", pn->host); + (void)printf(" from %s", w->host); } putchar('\n'); } diff --git a/usr/src/usr.bin/finger/sprint.c b/usr/src/usr.bin/finger/sprint.c index 194b13e7a7..3c5b765abb 100644 --- a/usr/src/usr.bin/finger/sprint.c +++ b/usr/src/usr.bin/finger/sprint.c @@ -19,7 +19,7 @@ */ #ifndef lint -static char sccsid[] = "@(#)sprint.c 5.1 (Berkeley) %G%"; +static char sccsid[] = "@(#)sprint.c 5.2 (Berkeley) %G%"; #endif /* not lint */ #include @@ -34,6 +34,7 @@ sflag_print() { extern time_t now; register PERSON *pn; + register WHERE *w; register int cnt; register char *p; PERSON **list, **sort(); @@ -56,47 +57,51 @@ sflag_print() */ #define MAXREALNAME 20 (void)printf("%-*s %-*s %s\n", UT_NAMESIZE, "Login", MAXREALNAME, - "Name", "Tty Idle Login Office Office Phone"); + "Name", "Tty Idle Login Office Office Phone"); for (cnt = 0; cnt < entries; ++cnt) { pn = list[cnt]; - (void)printf("%-*.*s %-*.*s ", UT_NAMESIZE, UT_NAMESIZE, - pn->name, MAXREALNAME, MAXREALNAME, - pn->realname ? pn->realname : ""); - if (!pn->loginat) { - (void)printf(" Never logged in\n"); - continue; + for (w = pn->whead; w != NULL; w = w->next) { + (void)printf("%-*.*s %-*.*s ", UT_NAMESIZE, UT_NAMESIZE, + pn->name, MAXREALNAME, MAXREALNAME, + pn->realname ? pn->realname : ""); + if (!w->loginat) { + (void)printf(" * * No logins "); + goto office; + } + (void)putchar(w->info == LOGGEDIN && !w->writable ? + '*' : ' '); + if (*w->tty) + (void)printf("%-2.2s ", + w->tty[0] != 't' || w->tty[1] != 't' || + w->tty[2] != 'y' ? w->tty : w->tty + 3); + else + (void)printf(" "); + if (w->info == LOGGEDIN) { + stimeprint(w); + (void)printf(" "); + } else + (void)printf(" * "); + p = ctime(&w->loginat); + (void)printf("%.6s", p + 4); + if (now - w->loginat >= SECSPERDAY * DAYSPERNYEAR / 2) + (void)printf(" %.4s", p + 20); + else + (void)printf(" %.5s", p + 11); +office: if (pn->office) + (void)printf(" %-11.11s", pn->office); + else if (pn->officephone) + (void)printf(" %-11.11s", " "); + if (pn->officephone) + (void)printf(" %s", pn->officephone); + putchar('\n'); } - (void)printf(pn->info == LOGGEDIN && - !pn->writable ? "*" : " "); - if (*pn->tty) - (void)printf("%-2.2s ", - pn->tty[0] != 't' || pn->tty[1] != 't' || - pn->tty[2] != 'y' ? pn->tty : pn->tty + 3); - else - (void)printf(" "); - stimeprint(pn); - p = ctime(&pn->loginat); - (void)printf(" %.6s", p + 4); - if (now - pn->loginat >= SECSPERDAY * DAYSPERNYEAR / 2) - (void)printf(" %.4s ", p + 20); - else - (void)printf(" %.5s", p + 11); - if (pn->office) - (void)printf(" %-11.11s", pn->office); - else if (pn->officephone) - (void)printf(" %-11.11s", " "); - if (pn->officephone) - (void)printf(" %s", pn->officephone); - putchar('\n'); } } PERSON ** sort() { - extern PERSON *head; - register PERSON *pn; - register int cnt; + register PERSON *pn, **lp; PERSON **list; int psort(); char *malloc(); @@ -105,8 +110,8 @@ sort() (void)fprintf(stderr, "finger: out of space.\n"); exit(1); } - for (pn = head, cnt = 0; cnt < entries; pn = pn->next) - list[cnt++] = pn; + for (lp = list, pn = phead; pn != NULL; pn = pn->next) + *lp++ = pn; (void)qsort(list, entries, sizeof(PERSON *), psort); return(list); } @@ -117,16 +122,12 @@ psort(p, t) return(strcmp((*p)->name, (*t)->name)); } -stimeprint(pn) - PERSON *pn; +stimeprint(w) + WHERE *w; { register struct tm *delta; - if (pn->info != LOGGEDIN) { - (void)printf(" "); - return; - } - delta = gmtime(&pn->idletime); + delta = gmtime(&w->idletime); if (!delta->tm_yday) if (!delta->tm_hour) if (!delta->tm_min) diff --git a/usr/src/usr.bin/finger/util.c b/usr/src/usr.bin/finger/util.c index 2663b23419..5aeebf1b7c 100644 --- a/usr/src/usr.bin/finger/util.c +++ b/usr/src/usr.bin/finger/util.c @@ -19,7 +19,7 @@ */ #ifndef lint -static char sccsid[] = "@(#)util.c 5.1 (Berkeley) %G%"; +static char sccsid[] = "@(#)util.c 5.2 (Berkeley) %G%"; #endif /* not lint */ #include @@ -31,24 +31,24 @@ static char sccsid[] = "@(#)util.c 5.1 (Berkeley) %G%"; #include "finger.h" #include "pathnames.h" -find_idle_and_ttywrite(pn) - register PERSON *pn; +find_idle_and_ttywrite(w) + register WHERE *w; { extern time_t now; extern int errno; struct stat sb; char *strerror(); - (void)sprintf(tbuf, "%s/%s", _PATH_DEV, pn->tty); + (void)sprintf(tbuf, "%s/%s", _PATH_DEV, w->tty); if (stat(tbuf, &sb) < 0) { (void)fprintf(stderr, "finger: %s: %s\n", tbuf, strerror(errno)); exit(1); } - pn->idletime = now < sb.st_atime ? 0 : now - sb.st_atime; + w->idletime = now < sb.st_atime ? 0 : now - sb.st_atime; #define TALKABLE 0220 /* tty is writable if 220 mode */ - pn->writable = ((sb.st_mode & TALKABLE) == TALKABLE); + w->writable = ((sb.st_mode & TALKABLE) == TALKABLE); } userinfo(pn, pw) @@ -116,38 +116,156 @@ match(pw, user) return(0); } -find_when(pn) +enter_lastlog(pn) register PERSON *pn; { + register WHERE *w; static int fd; struct lastlog ll; + char doit = 0; off_t lseek(); - if (!fd && (fd = open(_PATH_LASTLOG, O_RDONLY, 0)) < 0) { - (void)fprintf(stderr, - "finger: %s: open error\n", _PATH_LASTLOG); - exit(1); + /* + * Some systems may choose not to keep lastlog, + * so we don't report any errors. + * Not only that, we leave fd at -1 so lseek and read + * will fail and act like there were no last logins. + * Not the fastest way to do it, but what the hell. + */ + if (fd == 0) + fd = open(_PATH_LASTLOG, O_RDONLY, 0); + (void) lseek(fd, (long) (pn->uid * sizeof ll), L_SET); + if (read(fd, (char *)&ll, sizeof ll) != sizeof ll) { + /* same as never logged in */ + ll.ll_line[0] = 0; + ll.ll_host[0] = 0; + ll.ll_time = 0; } - (void)lseek(fd, (long)(pn->uid * (sizeof(ll))), L_SET); - if (read(fd, (char *)&ll, sizeof(ll)) != sizeof(ll)) { - (void)fprintf(stderr, - "finger: %s: read error\n", _PATH_LASTLOG); - exit(1); + if ((w = pn->whead) == NULL) + doit = 1; + else { + /* if last login is earlier than some current login */ + for (; !doit && w != NULL; w = w->next) + if (w->info == LOGGEDIN && w->loginat < ll.ll_time) + doit = 1; + /* + * and if it's not any of the current logins + * can't use time comparison because there may be a small + * discrepency since login calls time() twice + */ + for (w = pn->whead; doit && w != NULL; w = w->next) + if (w->info == LOGGEDIN && + strncmp(w->tty, ll.ll_line, UT_LINESIZE) == 0) + doit = 0; + } + if (doit) { + w = walloc(pn); + w->info = LASTLOG; + bcopy(ll.ll_line, w->tty, UT_LINESIZE); + w->tty[UT_LINESIZE] = 0; + bcopy(ll.ll_host, w->host, UT_HOSTSIZE); + w->host[UT_HOSTSIZE] = 0; + w->loginat = ll.ll_time; } - bcopy(ll.ll_line, pn->tty, UT_LINESIZE); - pn->tty[UT_LINESIZE] = NULL; - bcopy(ll.ll_host, pn->host, UT_HOSTSIZE); - pn->host[UT_HOSTSIZE] = NULL; - pn->loginat = ll.ll_time; } -utcopy(ut, pn) +enter_where(ut, pn) struct utmp *ut; PERSON *pn; { - bcopy(ut->ut_line, pn->tty, UT_LINESIZE); - pn->tty[UT_LINESIZE] = 0; - bcopy(ut->ut_host, pn->host, UT_HOSTSIZE); - pn->host[UT_HOSTSIZE] = 0; - pn->loginat = (time_t)ut->ut_time; + register WHERE *w = walloc(pn); + + w->info = LOGGEDIN; + bcopy(ut->ut_line, w->tty, UT_LINESIZE); + w->tty[UT_LINESIZE] = 0; + bcopy(ut->ut_host, w->host, UT_HOSTSIZE); + w->host[UT_HOSTSIZE] = 0; + w->loginat = (time_t)ut->ut_time; + find_idle_and_ttywrite(w); +} + +PERSON * +enter_person(pw) + register struct passwd *pw; +{ + register PERSON *pn, **pp; + + for (pp = htab + hash(pw->pw_name); + *pp != NULL && strcmp((*pp)->name, pw->pw_name) != 0; + pp = &(*pp)->hlink) + ; + if ((pn = *pp) == NULL) { + pn = palloc(); + entries++; + if (phead == NULL) + phead = ptail = pn; + else { + ptail->next = pn; + ptail = pn; + } + pn->next = NULL; + pn->hlink = NULL; + *pp = pn; + userinfo(pn, pw); + pn->whead = NULL; + } + return(pn); +} + +PERSON * +find_person(name) + char *name; +{ + register PERSON *pn; + + /* name may be only UT_NAMESIZE long and not terminated */ + for (pn = htab[hash(name)]; + pn != NULL && strncmp(pn->name, name, UT_NAMESIZE) != 0; + pn = pn->hlink) + ; + return(pn); +} + +hash(name) + register char *name; +{ + register int h, i; + + h = 0; + /* name may be only UT_NAMESIZE long and not terminated */ + for (i = UT_NAMESIZE; --i >= 0 && *name;) + h = ((h << 2 | h >> HBITS - 2) ^ *name++) & HMASK; + return(h); +} + +PERSON * +palloc() +{ + PERSON *p; + + if ((p = (PERSON *)malloc((u_int) sizeof(PERSON))) == NULL) { + (void)fprintf(stderr, "finger: out of space.\n"); + exit(1); + } + return(p); +} + +WHERE * +walloc(pn) + register PERSON *pn; +{ + register WHERE *w; + + if ((w = (WHERE *)malloc((u_int) sizeof(WHERE))) == NULL) { + (void)fprintf(stderr, "finger: out of space.\n"); + exit(1); + } + if (pn->whead == NULL) + pn->whead = pn->wtail = w; + else { + pn->wtail->next = w; + pn->wtail = w; + } + w->next = NULL; + return(w); } -- 2.20.1