Index: stable/2.2/usr.bin/finger/finger.1 =================================================================== --- stable/2.2/usr.bin/finger/finger.1 (revision 34250) +++ stable/2.2/usr.bin/finger/finger.1 (revision 34251) @@ -1,209 +1,221 @@ .\" Copyright (c) 1989, 1990, 1993, 1994 .\" The Regents of the University of California. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 3. All advertising materials mentioning features or use of this software .\" must display the following acknowledgement: .\" This product includes software developed by the University of .\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" @(#)finger.1 8.3 (Berkeley) 5/5/94 +.\" $Id$ .\" -.Dd May 5, 1994 +.Dd August 1, 1997 .Dt FINGER 1 .Os BSD 4 .Sh NAME .Nm finger .Nd user information lookup program .Sh SYNOPSIS .Nm finger .Op Fl lmpshoT .Op Ar user ... .Op Ar user@host ... .Sh DESCRIPTION The .Nm finger displays information about the system users. .Pp Options are: .Bl -tag -width flag .It Fl s .Nm Finger displays the user's login name, real name, terminal name and write status (as a ``*'' before the terminal name if write permission is denied), idle time, login time, and either office location and office phone number, or the remote host. If .Fl h -is given, the remote host is printed (the default.) If +is given, the remote host is printed (the default). If .Fl o is given, the office location and office phone number is printed instead. .Pp Idle time is in minutes if it is a single integer, hours and minutes if a ``:'' is present, or days if a ``d'' is present. Login time is displayed as the dayname if less than 6 days, else month, day; hours and minutes, unless more than six months ago, in which case the year is displayed rather than the hours and minutes. .Pp Unknown devices as well as nonexistent idle and login times are displayed as single asterisks. .Pp .It Fl h When used in conjunction with the .Fl s option, the name of the remote host is displayed instead of the office location and office phone. .Pp .It Fl o When used in conjunction with the .Fl s option, the office location and office phone information is displayed instead of the name of the remote host. .Pp .It Fl l Produces a multi-line format displaying all of the information described for the .Fl s option as well as the user's home directory, home phone number, login shell, mail status, and the contents of the files .Dq Pa .forward , .Dq Pa .plan and .Dq Pa .project from the user's home directory. .Pp If idle time is at least a minute and less than a day, it is presented in the form ``hh:mm''. Idle times greater than a day are presented as ``d day[s]hh:mm''. .Pp Phone numbers specified as eleven digits are printed as ``+N-NNN-NNN-NNNN''. Numbers specified as ten or seven digits are printed as the appropriate subset of that string. Numbers specified as five digits are printed as ``xN-NNNN''. Numbers specified as four digits are printed as ``xNNNN''. .Pp If write permission is denied to the device, the phrase ``(messages off)'' is appended to the line containing the device name. One entry per user is displayed with the .Fl l option; if a user is logged on multiple times, terminal information is repeated once per login. .Pp Mail status is shown as ``No Mail.'' if there is no mail at all, ``Mail last read DDD MMM ## HH:MM YYYY (TZ)'' if the person has looked at their mailbox since new mail arriving, or ``New mail received ...'', ``Unread since ...'' if they have new mail. .Pp .It Fl p Prevents the .Fl l option of .Nm finger from displaying the contents of the .Dq Pa .forward , .Dq Pa .plan and .Dq Pa .project files. .It Fl m Prevent matching of .Ar user names. .Ar User is usually a login name; however, matching will also be done on the users' real names, unless the .Fl m option is supplied. All name matching performed by .Nm finger is case insensitive. .Pp .It Fl T Disable the use of T/TCP (see .Xr ttcp 4 ). This option is needed to finger hosts with a broken TCP implementation. .El .Pp If no options are specified, .Nm finger defaults to the .Fl l style output if operands are provided, otherwise to the .Fl s style. Note that some fields may be missing, in either format, if information is not available for them. .Pp If no arguments are specified, .Nm finger will print an entry for each user currently logged into the system. .Pp .Nm Finger may be used to look up users on a remote machine. The format is to specify a .Ar user as .Dq Li user@host , or .Dq Li @host , where the default output format for the former is the .Fl l style, and the default output format for the latter is the .Fl s style. The .Fl l option is the only option that may be passed to a remote machine. .Pp If the file .Dq Pa .nofinger exists in the user's home directory, .Nm finger behaves as if the user in question does not exist. .Sh ENVIRONMENT .Nm Finger utilizes the following environment variable, if it exists: .Bl -tag -width Fl .It Ev FINGER This variable may be set with favored options to .Nm finger . .El .Sh FILES .Bl -tag -width /var/log/lastlog -compact .It Pa /var/log/lastlog last login data base .El .Sh SEE ALSO .Xr chpass 1 , .Xr w 1 , .Xr who 1 , .Xr ttcp 4 . +.Rs +.%A D. Zimmerman +.%T The Finger User Information Protocol +.%R RFC 1288 +.%D December, 1991 +.Re .Sh HISTORY The .Nm finger command appeared in .Bx 3.0 . +.Sh BUGS +The current FINGER protocol RFC requires that the client keep the connection +fully open until the server closes. This prevents the use of the optimal +three-packet T/TCP exchange. (Servers which depend on this requirement are +bogus but have nonetheless been observed in the Internet at large.) Index: stable/2.2/usr.bin/finger/finger.c =================================================================== --- stable/2.2/usr.bin/finger/finger.c (revision 34250) +++ stable/2.2/usr.bin/finger/finger.c (revision 34251) @@ -1,325 +1,335 @@ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Tony Nardo of the Johns Hopkins University/Applied Physics Lab. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Luke Mewburn added the following on 940622: * - mail status ("No Mail", "Mail read:...", or "New Mail ..., * Unread since ...".) * - 4 digit phone extensions (3210 is printed as x3210.) * - host/office toggling in short format with -h & -o. * - short day names (`Tue' printed instead of `Jun 21' if the * login time is < 6 days. */ #ifndef lint static char copyright[] = "@(#) Copyright (c) 1989, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint #if 0 -static char sccsid[] = "@(#)finger.c 8.2 (Berkeley) 9/30/93"; +static char sccsid[] = "@(#)finger.c 8.5 (Berkeley) 5/4/95"; #else static const char rcsid[] = - "$Id: finger.c,v 1.9.2.1 1997/07/03 07:12:38 charnier Exp $"; + "$Id: finger.c,v 1.9.2.2 1997/08/29 05:29:11 imp Exp $"; #endif #endif /* not lint */ /* * Finger prints out information about users. It is not portable since * certain fields (e.g. the full user name, office, and phone numbers) are * extracted from the gecos field of the passwd file which other UNIXes * may not have or may use for other things. * * There are currently two output formats; the short format is one line * per user and displays login name, tty, login time, real name, idle time, * and either remote host information (default) or office location/phone * number, depending on if -h or -o is used respectively. * The long format gives the same information (in a more legible format) as * well as home directory, shell, mail info, and .plan/.project files. */ #include -#include -#include -#include -#include + +#include #include #include +#include +#include #include #include #include +#include +#include +#include #include #include + #include "finger.h" DB *db; time_t now; int entries, lflag, mflag, pplan, sflag, oflag, Tflag; char tbuf[1024]; static void loginlist __P((void)); static void usage __P((void)); static void userlist __P((int, char **)); int option(argc, argv) int argc; char **argv; { int ch; optind = 1; /* reset getopt */ - while ((ch = getopt(argc, argv, "lmpshoT")) != -1) + while ((ch = getopt(argc, argv, "lmpshoT")) != -1) switch(ch) { case 'l': lflag = 1; /* long format */ break; case 'm': mflag = 1; /* force exact match of names */ break; case 'p': pplan = 1; /* don't show .plan/.project */ break; case 's': sflag = 1; /* short format */ break; case 'h': oflag = 0; /* remote host info */ break; case 'o': oflag = 1; /* office info */ break; case 'T': Tflag = 1; /* disable T/TCP */ break; case '?': default: usage(); } return optind; } static void usage() { (void)fprintf(stderr, "usage: finger [-lmpshoT] [login ...]\n"); exit(1); } int main(argc, argv) int argc; char **argv; { int envargc, argcnt; char *envargv[3]; (void) setlocale(LC_ALL, ""); /* remove this line to get remote host */ oflag = 1; /* default to old "office" behavior */ /* * Process environment variables followed by command line arguments. */ if ((envargv[1] = getenv("FINGER"))) { envargc = 2; envargv[0] = "finger"; envargv[2] = NULL; (void) option(envargc, envargv); } argcnt = option(argc, argv); argc -= argcnt; argv += argcnt; (void)time(&now); setpassent(1); if (!*argv) { /* * Assign explicit "small" format if no names given and -l * not selected. Force the -s BEFORE we get names so proper * screening will be done. */ if (!lflag) sflag = 1; /* if -l not explicit, force -s */ loginlist(); if (entries == 0) (void)printf("No one logged on.\n"); } else { userlist(argc, argv); /* * Assign explicit "large" format if names given and -s not * explicitly stated. Force the -l AFTER we get names so any * remote finger attempts specified won't be mishandled. */ if (!sflag) lflag = 1; /* if -s not explicit, force -l */ } if (entries) if (lflag) lflag_print(); else sflag_print(); - exit(0); + return (0); } static void loginlist() { register PERSON *pn; DBT data, key; struct passwd *pw; struct utmp user; int r, sflag; char name[UT_NAMESIZE + 1]; if (!freopen(_PATH_UTMP, "r", stdin)) err(1, "%s", _PATH_UTMP); name[UT_NAMESIZE] = '\0'; while (fread((char *)&user, sizeof(user), 1, stdin) == 1) { if (!user.ut_name[0]) continue; if ((pn = find_person(user.ut_name)) == NULL) { bcopy(user.ut_name, name, UT_NAMESIZE); if ((pw = getpwnam(name)) == NULL) continue; if (hide(pw)) continue; pn = enter_person(pw); } enter_where(&user, pn); } if (db && lflag) for (sflag = R_FIRST;; sflag = R_NEXT) { + PERSON *tmp; + r = (*db->seq)(db, &key, &data, sflag); if (r == -1) err(1, "db seq"); if (r == 1) break; - enter_lastlog(*(PERSON **)data.data); + memmove(&tmp, data.data, sizeof tmp); + enter_lastlog(tmp); } } static void userlist(argc, argv) register int argc; register char **argv; { register PERSON *pn; DBT data, key; struct utmp user; struct passwd *pw; int r, sflag, *used, *ip; char **ap, **nargv, **np, **p; if ((nargv = malloc((argc+1) * sizeof(char *))) == NULL || (used = calloc(argc, sizeof(int))) == NULL) err(1, NULL); /* Pull out all network requests. */ for (ap = p = argv, np = nargv; *p; ++p) if (index(*p, '@')) *np++ = *p; else *ap++ = *p; *np++ = NULL; *ap++ = NULL; if (!*argv) goto net; /* * Traverse the list of possible login names and check the login name * and real name against the name specified by the user. */ if (mflag) for (p = argv; *p; ++p) - if ((pw = getpwnam(*p)) && !hide(pw)) + if (((pw = getpwnam(*p)) != NULL) && !hide(pw)) enter_person(pw); else warnx("%s: no such user", *p); else { - while (pw = getpwent()) { + while ((pw = getpwent()) != NULL) { for (p = argv, ip = used; *p; ++p, ++ip) if (match(pw, *p) && !hide(pw)) { enter_person(pw); *ip = 1; } } for (p = argv, ip = used; *p; ++p, ++ip) if (!*ip) warnx("%s: no such user", *p); } /* Handle network requests. */ net: for (p = nargv; *p;) { netfinger(*p++); if (*p || entries) printf("\n"); } if (entries == 0) return; /* * Scan thru the list of users currently logged in, saving * appropriate data whenever a match occurs. */ if (!freopen(_PATH_UTMP, "r", stdin)) err(1, "%s", _PATH_UTMP); while (fread((char *)&user, sizeof(user), 1, stdin) == 1) { if (!user.ut_name[0]) continue; if ((pn = find_person(user.ut_name)) == NULL) continue; enter_where(&user, pn); } if (db) for (sflag = R_FIRST;; sflag = R_NEXT) { + PERSON *tmp; + r = (*db->seq)(db, &key, &data, sflag); if (r == -1) err(1, "db seq"); if (r == 1) break; - enter_lastlog(*(PERSON **)data.data); + memmove(&tmp, data.data, sizeof tmp); + enter_lastlog(tmp); } } Index: stable/2.2/usr.bin/finger/lprint.c =================================================================== --- stable/2.2/usr.bin/finger/lprint.c (revision 34250) +++ stable/2.2/usr.bin/finger/lprint.c (revision 34251) @@ -1,358 +1,362 @@ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Tony Nardo of the Johns Hopkins University/Applied Physics Lab. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint #if 0 -static char sccsid[] = "@(#)lprint.c 8.1 (Berkeley) 6/6/93"; +static char sccsid[] = "@(#)lprint.c 8.3 (Berkeley) 4/28/95"; #else static const char rcsid[] = - "$Id$"; + "$Id: lprint.c,v 1.5.2.1 1997/07/03 07:12:38 charnier Exp $"; #endif #endif /* not lint */ #include #include #include #include #include #include +#include #include #include -#include #include #include #include #include #include #include #include "finger.h" #define LINE_LEN 80 #define TAB_LEN 8 /* 8 spaces between tabs */ #define _PATH_FORWARD ".forward" #define _PATH_PLAN ".plan" #define _PATH_PROJECT ".project" static int demi_print __P((char *, int)); static void lprint __P((PERSON *)); static int show_text __P((char *, char *, char *)); static void vputc __P((int)); void lflag_print() { extern int pplan; register PERSON *pn; register int sflag, r; + PERSON *tmp; DBT data, key; for (sflag = R_FIRST;; sflag = R_NEXT) { r = (*db->seq)(db, &key, &data, sflag); if (r == -1) err(1, "db seq"); if (r == 1) break; - pn = *(PERSON **)data.data; + memmove(&tmp, data.data, sizeof tmp); + pn = tmp; if (sflag != R_FIRST) putchar('\n'); lprint(pn); if (!pplan) { (void)show_text(pn->dir, _PATH_FORWARD, "Mail forwarded to"); (void)show_text(pn->dir, _PATH_PROJECT, "Project"); if (!show_text(pn->dir, _PATH_PLAN, "Plan")) (void)printf("No Plan.\n"); } } } static void lprint(pn) register PERSON *pn; { extern time_t now; register struct tm *delta; register WHERE *w; register int cpr, len, maxlen; struct tm *tp; int oddfield; char *tzn; char t[80]; /* * long format -- * login name * real name * home directory * shell * office, office phone, home phone if available * mail status */ (void)printf("Login: %-15s\t\t\tName: %s\nDirectory: %-25s", pn->name, pn->realname, pn->dir); (void)printf("\tShell: %-s\n", *pn->shell ? pn->shell : _PATH_BSHELL); /* * try and print office, office phone, and home phone on one line; * if that fails, do line filling so it looks nice. */ #define OFFICE_TAG "Office" #define OFFICE_PHONE_TAG "Office Phone" oddfield = 0; if (pn->office && pn->officephone && strlen(pn->office) + strlen(pn->officephone) + sizeof(OFFICE_TAG) + 2 <= 5 * TAB_LEN) { (void)snprintf(tbuf, sizeof(tbuf), "%s: %s, %s", OFFICE_TAG, pn->office, prphone(pn->officephone)); oddfield = demi_print(tbuf, oddfield); } else { if (pn->office) { (void)snprintf(tbuf, sizeof(tbuf), "%s: %s", OFFICE_TAG, pn->office); oddfield = demi_print(tbuf, oddfield); } if (pn->officephone) { (void)snprintf(tbuf, sizeof(tbuf), "%s: %s", OFFICE_PHONE_TAG, prphone(pn->officephone)); oddfield = demi_print(tbuf, oddfield); } } if (pn->homephone) { (void)snprintf(tbuf, sizeof(tbuf), "%s: %s", "Home Phone", prphone(pn->homephone)); oddfield = demi_print(tbuf, oddfield); } if (oddfield) putchar('\n'); /* * 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 */ /* find out longest device name for this user for formatting */ for (w = pn->whead, maxlen = -1; 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: tp = localtime(&w->loginat); strftime(t, sizeof(t), "%c", tp); tzn = tp->tm_zone; cpr = printf("On since %.16s (%s) on %s", t, tzn, 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(&w->idletime); if (delta->tm_yday || delta->tm_hour || delta->tm_min) { cpr += printf("%-*s idle ", maxlen - strlen(w->tty) + 1, ","); if (delta->tm_yday > 0) { cpr += printf("%d day%s ", delta->tm_yday, delta->tm_yday == 1 ? "" : "s"); } cpr += printf("%d:%02d", delta->tm_hour, delta->tm_min); if (*w->host) { putchar(','); ++cpr; } } if (!w->writable) cpr += printf(" (messages off)"); break; case LASTLOG: if (w->loginat == 0) { (void)printf("Never logged in."); break; } tp = localtime(&w->loginat); strftime(t, sizeof(t), "%c", tp); tzn = tp->tm_zone; if (now - w->loginat > 86400 * 365 / 2) cpr = printf("Last login %.16s %.4s (%s) on %s", t, t + 20, tzn, w->tty); else cpr = printf("Last login %.16s (%s) on %s", t, tzn, w->tty); break; } if (*w->host) { if (LINE_LEN < (cpr + 6 + strlen(w->host))) (void)printf("\n "); (void)printf(" from %s", w->host); } putchar('\n'); } if (pn->mailrecv == -1) printf("No Mail.\n"); else if (pn->mailrecv > pn->mailread) { tp = localtime(&pn->mailrecv); strftime(t, sizeof(t), "%c", tp); tzn = tp->tm_zone; printf("New mail received %.16s %.4s (%s)\n", t, t + 20, tzn); tp = localtime(&pn->mailread); strftime(t, sizeof(t), "%c", tp); tzn = tp->tm_zone; printf(" Unread since %.16s %.4s (%s)\n", t, t + 20, tzn); } else { tp = localtime(&pn->mailread); strftime(t, sizeof(t), "%c", tp); tzn = tp->tm_zone; printf("Mail last read %.16s %.4s (%s)\n", t, t + 20, tzn); } } static int demi_print(str, oddfield) char *str; int oddfield; { static int lenlast; int lenthis, maxlen; lenthis = strlen(str); if (oddfield) { /* * We left off on an odd number of fields. If we haven't * crossed the midpoint of the screen, and we have room for * the next field, print it on the same line; otherwise, * print it on a new line. * * Note: we insist on having the right hand fields start * no less than 5 tabs out. */ maxlen = 5 * TAB_LEN; if (maxlen < lenlast) maxlen = lenlast; if (((((maxlen / TAB_LEN) + 1) * TAB_LEN) + lenthis) <= LINE_LEN) { while(lenlast < (4 * TAB_LEN)) { putchar('\t'); lenlast += TAB_LEN; } (void)printf("\t%s\n", str); /* force one tab */ } else { (void)printf("\n%s", str); /* go to next line */ oddfield = !oddfield; /* this'll be undone below */ } } else (void)printf("%s", str); oddfield = !oddfield; /* toggle odd/even marker */ lenlast = lenthis; return(oddfield); } static int show_text(directory, file_name, header) char *directory, *file_name, *header; { struct stat sb; register FILE *fp; register int ch, cnt, lastc; register char *p; int fd, nr; (void)snprintf(tbuf, sizeof(tbuf), "%s/%s", directory, file_name); if ((fd = open(tbuf, O_RDONLY)) < 0 || fstat(fd, &sb) || sb.st_size == 0) return(0); /* If short enough, and no newlines, show it on a single line.*/ if (sb.st_size <= LINE_LEN - strlen(header) - 5) { nr = read(fd, tbuf, sizeof(tbuf)); if (nr <= 0) { (void)close(fd); return(0); } for (p = tbuf, cnt = nr; cnt--; ++p) if (*p == '\n') break; if (cnt <= 1) { (void)printf("%s: ", header); for (p = tbuf, cnt = nr; cnt--; ++p) - vputc(lastc = *p); + if (*p != '\r') + vputc(lastc = *p); if (lastc != '\n') (void)putchar('\n'); (void)close(fd); return(1); } else (void)lseek(fd, 0L, SEEK_SET); } if ((fp = fdopen(fd, "r")) == NULL) return(0); (void)printf("%s:\n", header); while ((ch = getc(fp)) != EOF) - vputc(lastc = ch); + if (ch != '\r') + vputc(lastc = ch); if (lastc != '\n') (void)putchar('\n'); (void)fclose(fp); return(1); } static void vputc(ch) register int ch; { int meta; if (!isprint(ch) && !isascii(ch)) { (void)putchar('M'); (void)putchar('-'); ch = toascii(ch); meta = 1; } else meta = 0; if (isprint(ch) || !meta && (ch == ' ' || ch == '\t' || ch == '\n')) (void)putchar(ch); else { (void)putchar('^'); (void)putchar(ch == '\177' ? '?' : ch | 0100); } } Index: stable/2.2/usr.bin/finger/net.c =================================================================== --- stable/2.2/usr.bin/finger/net.c (revision 34250) +++ stable/2.2/usr.bin/finger/net.c (revision 34251) @@ -1,186 +1,185 @@ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Tony Nardo of the Johns Hopkins University/Applied Physics Lab. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint #if 0 -static char sccsid[] = "@(#)net.c 8.3 (Berkeley) 1/2/94"; +static char sccsid[] = "@(#)net.c 8.4 (Berkeley) 4/28/95"; #else static const char rcsid[] = - "$Id$"; + "$Id: net.c,v 1.6.2.2 1997/08/03 19:23:28 peter Exp $"; #endif #endif /* not lint */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "finger.h" void netfinger(name) char *name; { extern int lflag; extern int Tflag; register FILE *fp; - register int c; + register int c, lastc; struct in_addr defaddr; struct hostent *hp, def; struct servent *sp; struct sockaddr_in sin; int s; char *alist[1], *host; struct iovec iov[3]; struct msghdr msg; if (!(host = rindex(name, '@'))) return; *host++ = '\0'; if (isdigit(*host) && (defaddr.s_addr = inet_addr(host)) != -1) { def.h_name = host; def.h_addr_list = alist; def.h_addr = (char *)&defaddr; def.h_length = sizeof(struct in_addr); def.h_addrtype = AF_INET; def.h_aliases = 0; hp = &def; } else if (!(hp = gethostbyname(host))) { warnx("unknown host: %s", host); return; } if (!(sp = getservbyname("finger", "tcp"))) { warnx("tcp/finger: unknown service"); return; } sin.sin_family = hp->h_addrtype; bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length); sin.sin_port = sp->s_port; if ((s = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) { perror("finger: socket"); return; } /* have network connection; identify the host connected with */ (void)printf("[%s]\n", hp->h_name); msg.msg_name = (void *)&sin; msg.msg_namelen = sizeof sin; msg.msg_iov = iov; msg.msg_iovlen = 0; msg.msg_control = 0; msg.msg_controllen = 0; msg.msg_flags = 0; /* -l flag for remote fingerd */ if (lflag) { iov[msg.msg_iovlen].iov_base = "/W "; iov[msg.msg_iovlen++].iov_len = 3; } /* send the name followed by */ iov[msg.msg_iovlen].iov_base = name; iov[msg.msg_iovlen++].iov_len = strlen(name); iov[msg.msg_iovlen].iov_base = "\r\n"; iov[msg.msg_iovlen++].iov_len = 2; /* -T disables T/TCP: compatibility option to finger broken hosts */ if (Tflag && connect(s, (struct sockaddr *)&sin, sizeof (sin))) { perror("finger: connect"); return; } if (sendmsg(s, &msg, 0) < 0) { perror("finger: sendmsg"); close(s); return; } /* * Read from the remote system; once we're connected, we assume some * data. If none arrives, we hang until the user interrupts. * * If we see a or a with the high bit set, treat it as * a newline; if followed by a newline character, only output one * newline. * * Otherwise, all high bits are stripped; if it isn't printable and * it isn't a space, we can simply set the 7th bit. Every ASCII * character with bit 7 set is printable. */ - if (fp = fdopen(s, "r")) { - int lastc = '\n'; - + lastc = 0; + if ((fp = fdopen(s, "r")) != NULL) { while ((c = getc(fp)) != EOF) { if (c == 0x0d) { if (lastc == '\r') /* ^M^M - skip dupes */ continue; c = '\n'; lastc = '\r'; } else { if (!isprint(c) && !isspace(c)) { c &= 0x7f; c |= 0x40; } if (lastc != '\r' || c != '\n') lastc = c; else { lastc = '\n'; continue; } } putchar(c); } if (lastc != '\n') putchar('\n'); if (ferror(fp)) { /* * Assume that whatever it was set errno... */ perror("finger: read"); } (void)fclose(fp); } } Index: stable/2.2/usr.bin/finger/sprint.c =================================================================== --- stable/2.2/usr.bin/finger/sprint.c (revision 34250) +++ stable/2.2/usr.bin/finger/sprint.c (revision 34251) @@ -1,172 +1,174 @@ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Tony Nardo of the Johns Hopkins University/Applied Physics Lab. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint #if 0 -static char sccsid[] = "@(#)sprint.c 8.1 (Berkeley) 6/6/93"; +static char sccsid[] = "@(#)sprint.c 8.3 (Berkeley) 4/28/95"; #else static const char rcsid[] = - "$Id$"; + "$Id: sprint.c,v 1.7.2.1 1997/07/03 07:12:39 charnier Exp $"; #endif #endif /* not lint */ #include #include #include #include -#include #include +#include #include #include #include #include #include #include "finger.h" static void stimeprint __P((WHERE *)); void sflag_print() { extern time_t now; extern int oflag; register PERSON *pn; register WHERE *w; register int sflag, r, namelen; char p[80]; + PERSON *tmp; DBT data, key; /* * short format -- * login name * real name * terminal name (the XX of ttyXX) * if terminal writeable (add an '*' to the terminal name * if not) * if logged in show idle time and day logged in, else * show last login date and time. * If > 6 months, show year instead of time. * if (-o) * office location * office phone * else * remote host */ #define MAXREALNAME 20 -#define MAXHOSTNAME 20 /* in reality, hosts are never longer than 16 */ +#define MAXHOSTNAME 17 /* in reality, hosts are never longer than 16 */ (void)printf("%-*s %-*s%s %s\n", UT_NAMESIZE, "Login", MAXREALNAME, "Name", " TTY Idle Login Time", - oflag ? " Office Office Phone" : " Where"); + oflag ? " Office Phone" : " Where"); for (sflag = R_FIRST;; sflag = R_NEXT) { r = (*db->seq)(db, &key, &data, sflag); if (r == -1) err(1, "db seq"); if (r == 1) break; - pn = *(PERSON **)data.data; + memmove(&tmp, data.data, sizeof tmp); + pn = tmp; for (w = pn->whead; w != NULL; w = w->next) { namelen = MAXREALNAME; if (w->info == LOGGEDIN && !w->writable) --namelen; /* leave space before `*' */ (void)printf("%-*.*s %-*.*s", UT_NAMESIZE, UT_NAMESIZE, pn->name, MAXREALNAME, namelen, 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("%-3.3s ", (strncmp(w->tty, "tty", 3) && strncmp(w->tty, "cua", 3)) ? w->tty : w->tty + 3); else (void)printf(" "); if (w->info == LOGGEDIN) { stimeprint(w); (void)printf(" "); } else (void)printf(" * "); strftime(p, sizeof(p), "%c", localtime(&w->loginat)); #define SECSPERDAY 86400 #define DAYSPERWEEK 7 #define DAYSPERNYEAR 365 if (now - w->loginat < SECSPERDAY * (DAYSPERWEEK - 1)) (void)printf("%.3s ", p); else (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 (oflag) { if (pn->office) - (void)printf(" %-10.10s", pn->office); - else if (pn->officephone) - (void)printf(" %-10.10s", " "); - if (pn->officephone) - (void)printf(" %-.15s", - prphone(pn->officephone)); + (void)printf(" %-7.7s", pn->office); + else if (pn->officephone) + (void)printf(" %-7.7s", " "); + if (pn->officephone) + (void)printf(" %-.9s", + prphone(pn->officephone)); } else (void)printf(" %.*s", MAXHOSTNAME, w->host); putchar('\n'); } } } static void stimeprint(w) WHERE *w; { register struct tm *delta; delta = gmtime(&w->idletime); if (!delta->tm_yday) if (!delta->tm_hour) if (!delta->tm_min) (void)printf(" "); else (void)printf("%5d", delta->tm_min); else (void)printf("%2d:%02d", delta->tm_hour, delta->tm_min); else (void)printf("%4dd", delta->tm_yday); } Index: stable/2.2/usr.bin/finger/util.c =================================================================== --- stable/2.2/usr.bin/finger/util.c (revision 34250) +++ stable/2.2/usr.bin/finger/util.c (revision 34251) @@ -1,399 +1,405 @@ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Tony Nardo of the Johns Hopkins University/Applied Physics Lab. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint #if 0 -static char sccsid[] = "@(#)util.c 8.1 (Berkeley) 6/6/93"; +static char sccsid[] = "@(#)util.c 8.3 (Berkeley) 4/28/95"; #else static const char rcsid[] = - "$Id$"; + "$Id: util.c,v 1.3.6.1 1997/07/03 07:12:40 charnier Exp $"; #endif #endif /* not lint */ #include #include #include #include +#include #include #include -#include #include #include #include #include #include #include #include +#include #include "finger.h" static void find_idle_and_ttywrite __P((WHERE *)); static void userinfo __P((PERSON *, struct passwd *)); static WHERE *walloc __P((PERSON *)); int match(pw, user) struct passwd *pw; char *user; { register char *p, *t; char name[1024]; if (!strcasecmp(pw->pw_name, user)) return(1); /* * XXX * Why do we skip asterisks!?!? */ (void)strcpy(p = tbuf, pw->pw_gecos); if (*p == '*') ++p; /* Ampersands get replaced by the login name. */ if ((p = strtok(p, ",")) == NULL) return(0); - for (t = name; *t = *p; ++p) + for (t = name; (*t = *p) != '\0'; ++p) if (*t == '&') { (void)strcpy(t, pw->pw_name); while (*++t); } else ++t; - for (t = name; p = strtok(t, "\t "); t = NULL) + for (t = name; (p = strtok(t, "\t ")) != NULL; t = NULL) if (!strcasecmp(p, user)) return(1); return(0); } void enter_lastlog(pn) register PERSON *pn; { register WHERE *w; static int opened, fd; struct lastlog ll; char doit = 0; /* some systems may not maintain lastlog, don't report errors. */ if (!opened) { fd = open(_PATH_LASTLOG, O_RDONLY, 0); opened = 1; } if (fd == -1 || lseek(fd, (long)pn->uid * sizeof(ll), SEEK_SET) != (long)pn->uid * sizeof(ll) || read(fd, (char *)&ll, sizeof(ll)) != sizeof(ll)) { /* as if never logged in */ ll.ll_line[0] = ll.ll_host[0] = '\0'; ll.ll_time = 0; } if ((w = pn->whead) == NULL) doit = 1; else if (ll.ll_time != 0) { /* 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; } } void enter_where(ut, pn) struct utmp *ut; PERSON *pn; { register WHERE *w; 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; { DBT data, key; PERSON *pn; if (db == NULL && (db = dbopen(NULL, O_RDWR, 0, DB_BTREE, NULL)) == NULL) err(1, NULL); key.data = pw->pw_name; key.size = strlen(pw->pw_name); - switch((*db->get)(db, &key, &data, 0)) { + switch ((*db->get)(db, &key, &data, 0)) { case 0: - return(*(PERSON **)data.data); + memmove(&pn, data.data, sizeof pn); + return (pn); default: case -1: err(1, "db get"); /* NOTREACHED */ case 1: ++entries; pn = palloc(); userinfo(pn, pw); pn->whead = NULL; data.size = sizeof(PERSON *); data.data = &pn; if ((*db->put)(db, &key, &data, 0)) - err(1, NULL); - return(pn); + err(1, "db put"); + return (pn); } } PERSON * find_person(name) char *name; { struct passwd *pw; register int cnt; DBT data, key; + PERSON *p; char buf[UT_NAMESIZE + 1]; if (!db) return(NULL); if ((pw = getpwnam(name)) && hide(pw)) return(NULL); /* Name may be only UT_NAMESIZE long and not NUL terminated. */ for (cnt = 0; cnt < UT_NAMESIZE && *name; ++name, ++cnt) buf[cnt] = *name; buf[cnt] = '\0'; key.data = buf; key.size = cnt; - return((*db->get)(db, &key, &data, 0) ? NULL : *(PERSON **)data.data); + if ((*db->get)(db, &key, &data, 0)) + return (NULL); + memmove(&p, data.data, sizeof p); + return (p); } PERSON * palloc() { PERSON *p; if ((p = malloc((u_int) sizeof(PERSON))) == NULL) err(1, NULL); return(p); } static WHERE * walloc(pn) register PERSON *pn; { register WHERE *w; if ((w = malloc((u_int) sizeof(WHERE))) == NULL) err(1, NULL); if (pn->whead == NULL) pn->whead = pn->wtail = w; else { pn->wtail->next = w; pn->wtail = w; } w->next = NULL; return(w); } char * prphone(num) char *num; { register char *p; int len; static char pbuf[15]; /* don't touch anything if the user has their own formatting */ for (p = num; *p; ++p) if (!isdigit(*p)) return(num); len = p - num; p = pbuf; switch(len) { case 11: /* +0-123-456-7890 */ *p++ = '+'; *p++ = *num++; *p++ = '-'; /* FALLTHROUGH */ case 10: /* 012-345-6789 */ *p++ = *num++; *p++ = *num++; *p++ = *num++; *p++ = '-'; /* FALLTHROUGH */ case 7: /* 012-3456 */ *p++ = *num++; *p++ = *num++; *p++ = *num++; break; case 5: /* x0-1234 */ case 4: /* x1234 */ *p++ = 'x'; *p++ = *num++; break; default: return(num); } if (len != 4) { *p++ = '-'; *p++ = *num++; } *p++ = *num++; *p++ = *num++; *p++ = *num++; *p = '\0'; return(pbuf); } static void find_idle_and_ttywrite(w) register WHERE *w; { extern time_t now; struct stat sb; (void)snprintf(tbuf, sizeof(tbuf), "%s/%s", _PATH_DEV, w->tty); if (stat(tbuf, &sb) < 0) { - warn("%s", tbuf); + warn(tbuf); return; } w->idletime = now < sb.st_atime ? 0 : now - sb.st_atime; #define TALKABLE 0220 /* tty is writable if 220 mode */ w->writable = ((sb.st_mode & TALKABLE) == TALKABLE); } static void userinfo(pn, pw) register PERSON *pn; register struct passwd *pw; { register char *p, *t; char *bp, name[1024]; struct stat sb; pn->realname = pn->office = pn->officephone = pn->homephone = NULL; pn->uid = pw->pw_uid; pn->name = strdup(pw->pw_name); pn->dir = strdup(pw->pw_dir); pn->shell = strdup(pw->pw_shell); /* why do we skip asterisks!?!? */ (void)strcpy(bp = tbuf, pw->pw_gecos); if (*bp == '*') ++bp; /* ampersands get replaced by the login name */ if (!(p = strsep(&bp, ","))) return; - for (t = name; *t = *p; ++p) + for (t = name; (*t = *p) != '\0'; ++p) if (*t == '&') { (void)strcpy(t, pw->pw_name); if (islower(*t)) *t = toupper(*t); while (*++t); } else ++t; pn->realname = strdup(name); pn->office = ((p = strsep(&bp, ",")) && *p) ? strdup(p) : NULL; pn->officephone = ((p = strsep(&bp, ",")) && *p) ? strdup(p) : NULL; pn->homephone = ((p = strsep(&bp, ",")) && *p) ? strdup(p) : NULL; (void)sprintf(tbuf,"%s/%s", _PATH_MAILDIR, pw->pw_name); pn->mailrecv = -1; /* -1 == not_valid */ if (stat(tbuf, &sb) < 0) { if (errno != ENOENT) { warn("%s", tbuf); return; } } else if (sb.st_size != 0) { pn->mailrecv = sb.st_mtime; pn->mailread = sb.st_atime; } } /* * Is this user hiding from finger? * If ~/.nofinger exists, return 1 (hide), else return 0 (nohide). */ int hide(pw) struct passwd *pw; { char buf[MAXPATHLEN+1]; if (!pw->pw_dir) return 0; sprintf (buf, "%s/.nofinger", pw->pw_dir); if (access (buf, F_OK) == 0) return 1; return 0; }