diff options
Diffstat (limited to 'adv_cmds/finger')
-rw-r--r-- | adv_cmds/finger/extern.h | 68 | ||||
-rw-r--r-- | adv_cmds/finger/finger.1 | 257 | ||||
-rw-r--r-- | adv_cmds/finger/finger.c | 416 | ||||
-rw-r--r-- | adv_cmds/finger/finger.conf.5 | 91 | ||||
-rw-r--r-- | adv_cmds/finger/finger.h | 78 | ||||
-rw-r--r-- | adv_cmds/finger/lprint.c | 367 | ||||
-rw-r--r-- | adv_cmds/finger/net.c | 250 | ||||
-rw-r--r-- | adv_cmds/finger/pathnames.h | 41 | ||||
-rw-r--r-- | adv_cmds/finger/sprint.c | 187 | ||||
-rw-r--r-- | adv_cmds/finger/util.c | 419 |
10 files changed, 2174 insertions, 0 deletions
diff --git a/adv_cmds/finger/extern.h b/adv_cmds/finger/extern.h new file mode 100644 index 0000000..7b8f29c --- /dev/null +++ b/adv_cmds/finger/extern.h @@ -0,0 +1,68 @@ +/*- + * Copyright (c) 1991, 1993 + * 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. + * + * @(#)extern.h 8.2 (Berkeley) 4/28/95 + * $FreeBSD: src/usr.bin/finger/extern.h,v 1.10 2005/09/19 10:11:46 dds Exp $ + */ + +#ifndef _EXTERN_H_ +#define _EXTERN_H_ + +extern char tbuf[1024]; /* Temp buffer for anybody. */ +extern int entries; /* Number of people. */ +extern DB *db; /* Database. */ +extern int d_first; +extern sa_family_t family; +extern int gflag; +extern int lflag; +extern time_t now; +extern int oflag; +extern int pplan; /* don't show .plan/.project */ +#ifndef __APPLE__ +extern int Tflag; +#endif +extern int invoker_root; /* Invoked by root */ + +void enter_lastlog(PERSON *); +PERSON *enter_person(struct passwd *); +void enter_where(struct utmpx *, PERSON *); +PERSON *find_person(const char *); +int hide(struct passwd *); +void lflag_print(void); +int match(struct passwd *, const char *); +void netfinger(char *); +PERSON *palloc(void); +char *prphone(char *); +void sflag_print(void); +int show_text(const char *, const char *, const char *); + +#endif /* !_EXTERN_H_ */ diff --git a/adv_cmds/finger/finger.1 b/adv_cmds/finger/finger.1 new file mode 100644 index 0000000..4fbdfeb --- /dev/null +++ b/adv_cmds/finger/finger.1 @@ -0,0 +1,257 @@ +.\" 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 +.\" $FreeBSD: src/usr.bin/finger/finger.1,v 1.31 2005/09/19 10:11:46 dds Exp $ +.\" +.Dd July 17, 2004 +.Dt FINGER 1 +.Os +.Sh NAME +.Nm finger +.Nd user information lookup program +.Sh SYNOPSIS +.Nm +.Op Fl 46gklmpsho +.Op Ar user ...\& +.Op Ar user@host ...\& +.Sh DESCRIPTION +The +.Nm +utility displays information about the system users. +.Pp +Options are: +.Bl -tag -width indent +.It Fl 4 +Forces +.Nm +to use IPv4 addresses only. +.It Fl 6 +Forces +.Nm +to use IPv6 addresses only. +.It Fl g +This option restricts the gecos output to only the users' real +name. +It also has the side-effect of restricting the output +of the remote host when used in conjunction with the +.Fl h +option. +.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. +.It Fl k +Disable all use of +.Xr utmpx 5 . +.It Fl l +Produce 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 +.Pa .forward , +.Pa .plan , +.Pa .project +and +.Pa .pubkey +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. +.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 +is case insensitive. +.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. +.It Fl p +Prevent +the +.Fl l +option of +.Nm +from displaying the contents of the +.Pa .forward , +.Pa .plan , +.Pa .project +and +.Pa .pubkey +files. +.It Fl s +Display 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 o +is given, the office location and office phone number is printed +(the default). +If +.Fl h +is given, the remote host 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. +If it is an +.Dq * , +the login time indicates the time of last login. +Login time is displayed as the day name 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. +.El +.Pp +If no options are specified, +.Nm +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 +will print an entry for each user currently logged into the system. +.Pp +The +.Nm +utility 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 +.Pa .nofinger +exists in the user's home directory, +and the program is not run with superuser privileges, +.Nm +behaves as if the user in question does not exist. +.Pp +The optional +.Xr finger.conf 5 +configuration file can be used to specify aliases. +Since +.Nm +is invoked by +.Xr fingerd 8 , +aliases will work for both local and network queries. +.Sh ENVIRONMENT +The +.Nm +utility 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 . +.El +.Sh FILES +.Bl -tag -width /var/log/lastlog -compact +.It Pa /etc/finger.conf +alias definition data base +.It Pa /var/log/lastlog +last login data base +.El +.Sh SEE ALSO +.Xr chpass 1 , +.Xr w 1 , +.Xr who 1 , +.Xr finger.conf 5 , +.Xr fingerd 8 +.Rs +.%A D. Zimmerman +.%T The Finger User Information Protocol +.%R RFC 1288 +.%D December, 1991 +.Re +.Sh HISTORY +The +.Nm +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.) +.Pp +The +.Nm +utility does not recognize multibyte characters. diff --git a/adv_cmds/finger/finger.c b/adv_cmds/finger/finger.c new file mode 100644 index 0000000..0cbb887 --- /dev/null +++ b/adv_cmds/finger/finger.c @@ -0,0 +1,416 @@ +/* + * 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 <lm@rmit.edu.au> 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 const char copyright[] = +"@(#) Copyright (c) 1989, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)finger.c 8.5 (Berkeley) 5/4/95"; +#endif +#endif + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD: src/usr.bin/finger/finger.c,v 1.36 2005/09/19 10:11:46 dds Exp $"); + +/* + * 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 <sys/types.h> +#include <sys/socket.h> +#include <db.h> +#include <err.h> +#include <pwd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <utmpx.h> +#include <locale.h> + +#include "finger.h" +#include "pathnames.h" + +DB *db; +time_t now; +int entries, gflag, kflag, lflag, mflag, pplan, sflag, oflag, Tflag; +sa_family_t family = PF_UNSPEC; +int d_first = -1; +char tbuf[1024]; +int invoker_root = 0; + +static void loginlist(void); +static int option(int, char **); +static void usage(void); +static void userlist(int, char **); + +static int +option(int argc, char **argv) +{ + int ch; + + optind = 1; /* reset getopt */ + +#ifdef __APPLE__ + while ((ch = getopt(argc, argv, "46gklmpsho")) != -1) +#else + while ((ch = getopt(argc, argv, "46gklmpshoT")) != -1) +#endif + switch(ch) { + case '4': + family = AF_INET; + break; + case '6': + family = AF_INET6; + break; + case 'g': + gflag = 1; + break; + case 'k': + kflag = 1; /* keep going without utmpx */ + break; + 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; +#ifndef __APPLE__ + case 'T': + Tflag = 1; /* disable T/TCP */ + break; +#endif + case '?': + default: + usage(); + } + + return optind; +} + +static void +usage(void) +{ + (void)fprintf(stderr, + "usage: finger [-46gklmpshoT] [user ...] [user@host ...]\n"); + exit(1); +} + +int +main(int argc, char **argv) +{ + int envargc, argcnt; + char *envargv[3]; + struct passwd *pw; + static char myname[] = "finger"; + + if (getuid() == 0 || geteuid() == 0) { + invoker_root = 1; + if ((pw = getpwnam(UNPRIV_NAME)) && pw->pw_uid > 0) { + setgid(pw->pw_gid); + setuid(pw->pw_uid); + } else { + setgid(UNPRIV_UGID); + setuid(UNPRIV_UGID); + } + } + + (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] = myname; + 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(); + } + return (0); +} + +static void +loginlist(void) +{ + PERSON *pn; + DBT data, key; + struct passwd *pw; + struct utmpx *user; + int r, sflag1; + char name[_UTX_USERSIZE + 1]; + + if (kflag) + errx(1, "can't list logins without reading utmpx"); + + setutxent(); + name[_UTX_USERSIZE] = '\0'; + while ((user = getutxent()) != NULL) { + if (!user->ut_user[0] || user->ut_type != USER_PROCESS) + continue; + if ((pn = find_person(user->ut_user)) == NULL) { + bcopy(user->ut_user, name, _UTX_USERSIZE); + if ((pw = getpwnam(name)) == NULL) + continue; + if (hide(pw)) + continue; + pn = enter_person(pw); + } + enter_where(user, pn); + } + endutxent(); + if (db && lflag) + for (sflag1 = R_FIRST;; sflag1 = R_NEXT) { + PERSON *tmp; + + r = (*db->seq)(db, &key, &data, sflag1); + if (r == -1) + err(1, "db seq"); + if (r == 1) + break; + memmove(&tmp, data.data, sizeof tmp); + enter_lastlog(tmp); + } +} + +static void +userlist(int argc, char **argv) +{ + PERSON *pn; + DBT data, key; + struct utmpx *user; + struct passwd *pw; + int r, sflag1, *used, *ip; + char **ap, **nargv, **np, **p; + FILE *conf_fp; + char conf_alias[LINE_MAX]; + char *conf_realname; + int conf_length; + + 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; + + /* + * Mark any arguments beginning with '/' as invalid so that we + * don't accidently confuse them with expansions from finger.conf + */ + for (p = argv, ip = used; *p; ++p, ++ip) + if (**p == '/') { + *ip = 1; + warnx("%s: no such user", *p); + } + + /* + * Traverse the finger alias configuration file of the form + * alias:(user|alias), ignoring comment lines beginning '#'. + */ + if ((conf_fp = fopen(_PATH_FINGERCONF, "r")) != NULL) { + while(fgets(conf_alias, sizeof(conf_alias), conf_fp) != NULL) { + conf_length = strlen(conf_alias); + if (*conf_alias == '#' || conf_alias[--conf_length] != '\n') + continue; + conf_alias[conf_length] = '\0'; /* Remove trailing LF */ + if ((conf_realname = strchr(conf_alias, ':')) == NULL) + continue; + *conf_realname = '\0'; /* Replace : with NUL */ + for (p = argv; *p; ++p) { + if (strcmp(*p, conf_alias) == 0) { + if ((*p = strdup(conf_realname+1)) == NULL) { + err(1, NULL); + } + } + } + } + (void)fclose(conf_fp); + } + + /* + * Traverse the list of possible login names and check the login name + * and real name against the name specified by the user. If the name + * begins with a '/', try to read the file of that name instead of + * gathering the traditional finger information. + */ + if (mflag) + for (p = argv, ip = used; *p; ++p, ++ip) { + if (**p != '/' || *ip == 1 || !show_text("", *p, "")) { + if (((pw = getpwnam(*p)) != NULL) && !hide(pw)) + enter_person(pw); + else if (!*ip) + warnx("%s: no such user", *p); + } + } + else { + while ((pw = getpwent()) != NULL) { + for (p = argv, ip = used; *p; ++p, ++ip) + if (**p == '/' && *ip != 1 + && show_text("", *p, "")) + *ip = 1; + else 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; + + if (kflag) + return; + + /* + * Scan thru the list of users currently logged in, saving + * appropriate data whenever a match occurs. + */ + setutxent(); + while ((user = getutxent()) != NULL) { + if (!user->ut_user && user->ut_type != USER_PROCESS) + continue; + if ((pn = find_person(user->ut_user)) == NULL) + continue; + enter_where(user, pn); + } + endutxent(); + if (db) + for (sflag1 = R_FIRST;; sflag1 = R_NEXT) { + PERSON *tmp; + + r = (*db->seq)(db, &key, &data, sflag1); + if (r == -1) + err(1, "db seq"); + if (r == 1) + break; + memmove(&tmp, data.data, sizeof tmp); + enter_lastlog(tmp); + } +} diff --git a/adv_cmds/finger/finger.conf.5 b/adv_cmds/finger/finger.conf.5 new file mode 100644 index 0000000..83ebc5b --- /dev/null +++ b/adv_cmds/finger/finger.conf.5 @@ -0,0 +1,91 @@ +.\" Copyright (c) 2000 Mark Knight <markk@knigma.org> +.\" 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. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. +.\" +.\" $FreeBSD: src/usr.bin/finger/finger.conf.5,v 1.6 2005/02/09 18:04:22 ru Exp $ +.\" +.Dd August 16, 2000 +.Dt FINGER.CONF 5 +.Os +.Sh NAME +.Nm finger.conf +.Nd +.Xr finger 1 +alias configuration file +.Sh DESCRIPTION +The optional +.Nm +file is used to provide aliases that can be fingered by local +and network users. +This may be useful where a user's login name is not the same +as their preferred mail address, or for providing virtual login names +than can be fingered. +.Pp +Lines beginning with ``#'' are comments. +Other lines must consist of an +alias name and a target name separated by a colon. +A target name should be either a user, a forward +reference to another alias or the path of a world readable file. +.Pp +Where an alias points to a file, the contents of that file will be displayed +when the alias is fingered. +.Sh FILES +.Bl -tag -width /etc/finger.conf -compact +.It Pa /etc/finger.conf +.Xr finger 1 +alias definition data base +.El +.Sh EXAMPLES +.Bd -literal +# /etc/finger.conf alias definition file +# +# Format alias:(user|alias) +# +# Individual aliases +# +markk:mkn +john.smith:dev329 +john:dev329 +sue:/etc/finger/sue.txt +# +# Network status message +# +status:/usr/local/etc/status.txt +# +# Administrative redirects +# +root:admin +postmaster:admin +abuse:admin +# +# For the time being, 'sod' is sysadmin. +# +admin:sod +.Ed +.Sh SEE ALSO +.Xr finger 1 +.Sh HISTORY +Support for the +.Nm +file was submitted by Mark Knight <markk@knigma.org> and first appeared in +.Fx 4.2 . diff --git a/adv_cmds/finger/finger.h b/adv_cmds/finger/finger.h new file mode 100644 index 0000000..19b30fb --- /dev/null +++ b/adv_cmds/finger/finger.h @@ -0,0 +1,78 @@ +/* + * 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. + * + * @(#)finger.h 8.1 (Berkeley) 6/6/93 + * $FreeBSD: src/usr.bin/finger/finger.h,v 1.5 2004/03/14 06:43:34 jmallett Exp $ + */ + +#ifndef _FINGER_H_ +#define _FINGER_H_ + +typedef struct person { + uid_t uid; /* user id */ + char *dir; /* user's home directory */ + char *homephone; /* pointer to home phone no. */ + char *name; /* login name */ + char *office; /* pointer to office name */ + char *officephone; /* pointer to office phone no. */ + char *realname; /* pointer to full name */ + char *shell; /* user's shell */ + time_t mailread; /* last time mail was read */ + time_t mailrecv; /* last time mail was received */ + struct where *whead, *wtail; /* list of where user is or has been */ +} PERSON; + +enum status { LASTLOG, LOGGEDIN }; + +typedef struct where { + struct where *next; /* next place user 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[_UTX_LINESIZE+1]; /* null terminated tty line */ + char host[_UTX_HOSTSIZE+1]; /* null terminated remote host name */ +} WHERE; + +#define UNPRIV_NAME "nobody" /* Preferred privilege level */ +#define UNPRIV_UGID 32767 /* Default uid and gid */ +#define OUTPUT_MAX 100000 /* Do not keep listinging forever */ +#define TIME_LIMIT 360 /* Do not keep listinging forever */ + +#define UT_NAMESIZE 8 /* old utmp.h value */ + +#include "extern.h" + +#endif /* !_FINGER_H_ */ diff --git a/adv_cmds/finger/lprint.c b/adv_cmds/finger/lprint.c new file mode 100644 index 0000000..6e9b42d --- /dev/null +++ b/adv_cmds/finger/lprint.c @@ -0,0 +1,367 @@ +/* + * 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. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)lprint.c 8.3 (Berkeley) 4/28/95"; +#endif +#endif + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD: src/usr.bin/finger/lprint.c,v 1.25 2004/03/14 06:43:34 jmallett Exp $"); + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <ctype.h> +#include <db.h> +#include <err.h> +#include <fcntl.h> +#include <langinfo.h> +#include <paths.h> +#include <pwd.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <utmpx.h> +#include "finger.h" +#include "pathnames.h" + +#define LINE_LEN 80 +#define TAB_LEN 8 /* 8 spaces between tabs */ + +static int demi_print(char *, int); +static void lprint(PERSON *); +static void vputc(unsigned char); + +void +lflag_print(void) +{ + PERSON *pn; + 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; + 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"); + (void)show_text(pn->dir, + _PATH_PUBKEY, "Public key"); + } + } +} + +static void +lprint(PERSON *pn) +{ + struct tm *delta; + WHERE *w; + int cpr, len, maxlen; + struct tm *tp; + int oddfield; + char t[80]; + + if (d_first < 0) + d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); + /* + * 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); + + if (gflag) + goto no_gecos; + /* + * 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'); + +no_gecos: + /* + * 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) { + if (w->info == LOGGEDIN) { + tp = localtime(&w->loginat); + strftime(t, sizeof(t), + d_first ? "%a %e %b %R (%Z)" : "%a %b %e %R (%Z)", + tp); + cpr = printf("On since %s on %s", t, 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 (w->idletime != -1 && (delta->tm_yday || + delta->tm_hour || delta->tm_min)) { + cpr += printf("%-*s idle ", + maxlen - (int)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)"); + } else if (w->loginat == 0) { + cpr = printf("Never logged in."); + } else { + tp = localtime(&w->loginat); + if (now - w->loginat > 86400 * 365 / 2) { + strftime(t, sizeof(t), + d_first ? "%a %e %b %R %Y (%Z)" : + "%a %b %e %R %Y (%Z)", + tp); + } else { + strftime(t, sizeof(t), + d_first ? "%a %e %b %R (%Z)" : + "%a %b %e %R (%Z)", + tp); + } + cpr = printf("Last login %s on %s", t, w->tty); + } + 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), + d_first ? "%a %e %b %R %Y (%Z)" : + "%a %b %e %R %Y (%Z)", + tp); + printf("New mail received %s\n", t); + tp = localtime(&pn->mailread); + strftime(t, sizeof(t), + d_first ? "%a %e %b %R %Y (%Z)" : + "%a %b %e %R %Y (%Z)", + tp); + printf(" Unread since %s\n", t); + } else { + tp = localtime(&pn->mailread); + strftime(t, sizeof(t), + d_first ? "%a %e %b %R %Y (%Z)" : + "%a %b %e %R %Y (%Z)", + tp); + printf("Mail last read %s\n", t); + } +} + +static int +demi_print(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); +} + +int +show_text(const char *directory, const char *file_name, const char *header) +{ + struct stat sb; + FILE *fp; + int ch, cnt; + char *p, lastc; + int fd, nr; + + lastc = '\0'; + + (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) { + if (*header != '\0') + (void)printf("%s: ", header); + for (p = tbuf, cnt = nr; cnt--; ++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); + if (*header != '\0') + (void)printf("%s:\n", header); + while ((ch = getc(fp)) != EOF) + if (ch != '\r') + vputc(lastc = ch); + if (lastc != '\n') + (void)putchar('\n'); + (void)fclose(fp); + return(1); +} + +static void +vputc(unsigned char 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); + } +} diff --git a/adv_cmds/finger/net.c b/adv_cmds/finger/net.c new file mode 100644 index 0000000..cf0699d --- /dev/null +++ b/adv_cmds/finger/net.c @@ -0,0 +1,250 @@ +/* + * 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. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)net.c 8.4 (Berkeley) 4/28/95"; +#endif +#endif + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD: src/usr.bin/finger/net.c,v 1.23 2004/05/16 22:08:15 stefanf Exp $"); + +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/uio.h> +#include <ctype.h> +#include <db.h> +#include <err.h> +#include <netdb.h> +#include <pwd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <utmpx.h> +#include "finger.h" + +static void cleanup(int sig); +static int do_protocol(const char *name, const struct addrinfo *ai); +static void trying(const struct addrinfo *ai); + +void +netfinger(char *name) +{ + int error, multi; + char *host; + struct addrinfo *ai, *ai0; + static struct addrinfo hint; + + host = strrchr(name, '@'); + if (host == 0) + return; + *host++ = '\0'; + signal(SIGALRM, cleanup); + alarm(TIME_LIMIT); + + hint.ai_flags = AI_CANONNAME; + hint.ai_family = family; + hint.ai_socktype = SOCK_STREAM; + + error = getaddrinfo(host, "finger", &hint, &ai0); + if (error) { + warnx("%s: %s", host, gai_strerror(error)); + return; + } + + multi = (ai0->ai_next) != 0; + + /* ai_canonname may not be filled in if the user specified an IP. */ + if (ai0->ai_canonname == 0) + printf("[%s]\n", host); + else + printf("[%s]\n", ai0->ai_canonname); + + for (ai = ai0; ai != 0; ai = ai->ai_next) { + if (multi) + trying(ai); + + error = do_protocol(name, ai); + if (!error) + break; + } + alarm(0); + freeaddrinfo(ai0); +} + +static int +do_protocol(const char *name, const struct addrinfo *ai) +{ + int cnt, line_len, s; + FILE *fp; + int c, lastc; + struct iovec iov[3]; + struct msghdr msg; + static char slash_w[] = "/W "; + static char neteol[] = "\r\n"; + + s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (s < 0) { + warn("socket(%d, %d, %d)", ai->ai_family, ai->ai_socktype, + ai->ai_protocol); + return -1; + } + + msg.msg_name = (void *)ai->ai_addr; + msg.msg_namelen = ai->ai_addrlen; + 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 = slash_w; + iov[msg.msg_iovlen++].iov_len = 3; + } + /* send the name followed by <CR><LF> */ + iov[msg.msg_iovlen].iov_base = strdup(name); + iov[msg.msg_iovlen++].iov_len = strlen(name); + iov[msg.msg_iovlen].iov_base = neteol; + iov[msg.msg_iovlen++].iov_len = 2; + +#ifdef __APPLE__ + if (connect(s, ai->ai_addr, ai->ai_addrlen) < 0) { +#else + /* + * -T disables data-on-SYN: compatibility option to finger broken + * hosts. Also, the implicit-open API is broken on IPv6, so do + * the explicit connect there, too. + */ + if ((Tflag || ai->ai_addr->sa_family == AF_INET6) + && connect(s, ai->ai_addr, ai->ai_addrlen) < 0) { +#endif + warn("connect"); + close(s); + return -1; + } + + if (sendmsg(s, &msg, 0) < 0) { + warn("sendmsg"); + close(s); + return -1; + } + + /* + * 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 <CR> or a <CR> 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. + */ + lastc = 0; + if ((fp = fdopen(s, "r")) != NULL) { + cnt = 0; + line_len = 0; + while ((c = getc(fp)) != EOF) { + if (++cnt > OUTPUT_MAX) { + printf("\n\n Output truncated at %d bytes...\n", + cnt - 1); + break; + } + 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 (c != '\n' && ++line_len > _POSIX2_LINE_MAX) { + putchar('\\'); + putchar('\n'); + lastc = '\r'; + } + if (lastc == '\n' || lastc == '\r') + line_len = 0; + } + if (ferror(fp)) { + /* + * Assume that whatever it was set errno... + */ + warn("reading from network"); + } + if (lastc != '\n') + putchar('\n'); + + fclose(fp); + } + return 0; +} + +static void +trying(const struct addrinfo *ai) +{ + char buf[NI_MAXHOST]; + + if (getnameinfo(ai->ai_addr, ai->ai_addrlen, buf, sizeof buf, + (char *)0, 0, NI_NUMERICHOST) != 0) + return; /* XXX can't happen */ + + printf("Trying %s...\n", buf); +} + +void +cleanup(int sig __unused) +{ +#define ERRSTR "Timed out.\n" + write(STDERR_FILENO, ERRSTR, sizeof ERRSTR); + exit(1); +} + diff --git a/adv_cmds/finger/pathnames.h b/adv_cmds/finger/pathnames.h new file mode 100644 index 0000000..160252d --- /dev/null +++ b/adv_cmds/finger/pathnames.h @@ -0,0 +1,41 @@ +/*- + * Copyright (c) 2000 Mark Knight <markk@knigma.org> + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + * $FreeBSD: src/usr.bin/finger/pathnames.h,v 1.5 2001/07/30 16:50:47 yar Exp $ + */ + +#ifndef PATHNAMES_H + +#define _PATH_FORWARD ".forward" +#define _PATH_NOFINGER ".nofinger" +#define _PATH_PLAN ".plan" +#define _PATH_PROJECT ".project" +#define _PATH_PUBKEY ".pubkey" + +#ifndef _PATH_FINGERCONF +#define _PATH_FINGERCONF "/etc/finger.conf" +#endif /* _PATH_FINGERCONF */ + +#endif /* PATHNAMES_H */ diff --git a/adv_cmds/finger/sprint.c b/adv_cmds/finger/sprint.c new file mode 100644 index 0000000..8de1cba --- /dev/null +++ b/adv_cmds/finger/sprint.c @@ -0,0 +1,187 @@ +/* + * 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. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)sprint.c 8.3 (Berkeley) 4/28/95"; +#endif +#endif + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD: src/usr.bin/finger/sprint.c,v 1.22 2003/04/02 20:22:29 rwatson Exp $"); + +#include <sys/types.h> +#include <sys/socket.h> +#include <db.h> +#include <err.h> +#include <langinfo.h> +#include <pwd.h> +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <utmpx.h> +#include "finger.h" + +static void stimeprint(WHERE *); + +void +sflag_print(void) +{ + PERSON *pn; + WHERE *w; + int sflag, r, namelen; + char p[80]; + PERSON *tmp; + DBT data, key; + struct tm *lc; + + if (d_first < 0) + d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); + /* + * 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 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 ", (gflag) ? "" : + 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; + 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, _UTX_USERSIZE, + 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(" * "); + lc = localtime(&w->loginat); +#define SECSPERDAY 86400 +#define DAYSPERWEEK 7 +#define DAYSPERNYEAR 365 + if (now - w->loginat < SECSPERDAY * (DAYSPERWEEK - 1)) { + (void)strftime(p, sizeof(p), "%a", lc); + } else { + (void)strftime(p, sizeof(p), + d_first ? "%e %b" : "%b %e", lc); + } + (void)printf("%-6.6s", p); + if (now - w->loginat >= SECSPERDAY * DAYSPERNYEAR / 2) { + (void)strftime(p, sizeof(p), "%Y", lc); + } else { + (void)strftime(p, sizeof(p), "%R", lc); + } + (void)printf(" %-5.5s", p); +office: + if (gflag) + goto no_gecos; + if (oflag) { + if (pn->office) + (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); +no_gecos: + putchar('\n'); + } + } +} + +static void +stimeprint(WHERE *w) +{ + struct tm *delta; + + if (w->idletime == -1) { + (void)printf(" "); + return; + } + + 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); +} diff --git a/adv_cmds/finger/util.c b/adv_cmds/finger/util.c new file mode 100644 index 0000000..6e7c925 --- /dev/null +++ b/adv_cmds/finger/util.c @@ -0,0 +1,419 @@ +/* + * 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. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)util.c 8.3 (Berkeley) 4/28/95"; +#endif +#endif + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD: src/usr.bin/finger/util.c,v 1.22 2005/09/19 10:11:47 dds Exp $"); + +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <ctype.h> +#include <db.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <paths.h> +#include <pwd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <utmpx.h> +#include "finger.h" +#include "pathnames.h" + +static void find_idle_and_ttywrite(WHERE *); +static void userinfo(PERSON *, struct passwd *); +static WHERE *walloc(PERSON *); + +int +match(struct passwd *pw, const char *user) +{ + char *p, *t; + char name[1024]; + + if (!strcasecmp(pw->pw_name, user)) + return(1); + + /* + * XXX + * Why do we skip asterisks!?!? + */ + (void)strncpy(p = tbuf, pw->pw_gecos, sizeof(tbuf)); + tbuf[sizeof(tbuf) - 1] = '\0'; + if (*p == '*') + ++p; + + /* Ampersands get replaced by the login name. */ + if ((p = strtok(p, ",")) == NULL) + return(0); + + for (t = name; t < &name[sizeof(name) - 1] && (*t = *p) != '\0'; ++p) { + if (*t == '&') { + (void)strncpy(t, pw->pw_name, + sizeof(name) - (t - name)); + name[sizeof(name) - 1] = '\0'; + while (t < &name[sizeof(name) - 1] && *++t) + continue; + } else { + ++t; + } + } + *t = '\0'; + for (t = name; (p = strtok(t, "\t ")) != NULL; t = NULL) + if (!strcasecmp(p, user)) + return(1); + return(0); +} + +void +enter_lastlog(PERSON *pn) +{ + WHERE *w; + struct lastlogx l, *ll; + char doit = 0; + + if ((ll = getlastlogxbyname(pn->name, &l)) == NULL) { + bzero(&l, sizeof(l)); + ll = &l; + } + if ((w = pn->whead) == NULL) + doit = 1; + else if (ll->ll_tv.tv_sec != 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_tv.tv_sec) + doit = 1; + /* + * and if it's not any of the current logins + * can't use time comparison because there may be a small + * discrepancy 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, _UTX_LINESIZE) == 0) + doit = 0; + } + if (doit) { + w = walloc(pn); + w->info = LASTLOG; + bcopy(ll->ll_line, w->tty, _UTX_LINESIZE); + w->tty[_UTX_LINESIZE] = 0; + bcopy(ll->ll_host, w->host, _UTX_HOSTSIZE); + w->host[_UTX_HOSTSIZE] = 0; + w->loginat = ll->ll_tv.tv_sec; + } +} + +void +enter_where(struct utmpx *ut, PERSON *pn) +{ + WHERE *w; + + w = walloc(pn); + w->info = LOGGEDIN; + bcopy(ut->ut_line, w->tty, _UTX_LINESIZE); + w->tty[_UTX_LINESIZE] = 0; + bcopy(ut->ut_host, w->host, _UTX_HOSTSIZE); + w->host[_UTX_HOSTSIZE] = 0; + w->loginat = (time_t)ut->ut_tv.tv_sec; + find_idle_and_ttywrite(w); +} + +PERSON * +enter_person(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)) { + case 0: + 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, "db put"); + return (pn); + } +} + +PERSON * +find_person(const char *name) +{ + struct passwd *pw; + + int cnt; + DBT data, key; + PERSON *p; + char buf[_UTX_USERSIZE + 1]; + + if (!db) + return(NULL); + + if ((pw = getpwnam(name)) && hide(pw)) + return(NULL); + + /* Name may be only _UTX_USERSIZE long and not NUL terminated. */ + for (cnt = 0; cnt < _UTX_USERSIZE && *name; ++name, ++cnt) + buf[cnt] = *name; + buf[cnt] = '\0'; + key.data = buf; + key.size = cnt; + + if ((*db->get)(db, &key, &data, 0)) + return (NULL); + memmove(&p, data.data, sizeof p); + return (p); +} + +PERSON * +palloc(void) +{ + PERSON *p; + + if ((p = malloc(sizeof(PERSON))) == NULL) + err(1, NULL); + return(p); +} + +static WHERE * +walloc(PERSON *pn) +{ + WHERE *w; + + if ((w = malloc(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(char *num) +{ + char *p; + int len; + static char pbuf[20]; + + /* 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(WHERE *w) +{ + struct stat sb; + time_t touched; + int error; + + (void)snprintf(tbuf, sizeof(tbuf), "%s/%s", _PATH_DEV, w->tty); + + error = stat(tbuf, &sb); + if (error < 0 && errno == ENOENT) { + /* + * The terminal listed is not actually a terminal (i.e., + * ":0"). This is a failure, so we'll skip printing + * out the idle time, which is non-ideal but better + * than a bogus warning and idle time. + */ + w->idletime = -1; + return; + } else if (error < 0) { + warn("%s", tbuf); + w->idletime = -1; + return; + } + touched = sb.st_atime; + if (touched < w->loginat) { + /* tty untouched since before login */ + touched = w->loginat; + } + w->idletime = now < touched ? 0 : now - touched; + +#define TALKABLE 0220 /* tty is writable if 220 mode */ + w->writable = ((sb.st_mode & TALKABLE) == TALKABLE); +} + +static void +userinfo(PERSON *pn, struct passwd *pw) +{ + char *p, *t; + char *bp, name[1024]; + struct stat sb; + + pn->realname = pn->office = pn->officephone = pn->homephone = NULL; + + pn->uid = pw->pw_uid; + if ((pn->name = strdup(pw->pw_name)) == NULL) + err(1, "strdup failed"); + if ((pn->dir = strdup(pw->pw_dir)) == NULL) + err(1, "strdup failed"); + if ((pn->shell = strdup(pw->pw_shell)) == NULL) + err(1, "strdup failed"); + + /* why do we skip asterisks!?!? */ + (void)strncpy(bp = tbuf, pw->pw_gecos, sizeof(tbuf)); + tbuf[sizeof(tbuf) - 1] = '\0'; + if (*bp == '*') + ++bp; + + /* ampersands get replaced by the login name */ + if (!(p = strsep(&bp, ","))) + return; + for (t = name; t < &name[sizeof(name) - 1] && (*t = *p) != '\0'; ++p) { + if (*t == '&') { + (void)strncpy(t, pw->pw_name, + sizeof(name) - (t - name)); + name[sizeof(name) - 1] = '\0'; + if (islower(*t)) + *t = toupper(*t); + while (t < &name[sizeof(name) - 1] && *++t) + continue; + } else { + ++t; + } + } + *t = '\0'; + if ((pn->realname = strdup(name)) == NULL) + err(1, "strdup failed"); + 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)snprintf(tbuf, sizeof(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 ~<user>/.nofinger exists, return 1 (hide), else return 0 (nohide). + * Nobody can hide from root. + */ + +int +hide(struct passwd *pw) +{ + struct stat st; + char buf[MAXPATHLEN]; + + if (invoker_root || !pw->pw_dir) + return 0; + + snprintf(buf, sizeof(buf), "%s/%s", pw->pw_dir, _PATH_NOFINGER); + + if (stat(buf, &st) == 0) + return 1; + + return 0; +} |