Importing usr.bin/finger

This commit is contained in:
Thomas Cort 2013-06-01 14:20:33 +00:00 committed by Lionel Sambuc
parent 92f7a4ab20
commit 406cdd95a6
16 changed files with 1790 additions and 1183 deletions

View file

@ -9,7 +9,7 @@ SUBDIR= add_route arp ash at backup basename btrace \
dd decomp16 DESCRIBE devmand devsize df dhcpd \ dd decomp16 DESCRIBE devmand devsize df dhcpd \
dhrystone diff dirname diskctl dumpcore \ dhrystone diff dirname diskctl dumpcore \
eject env expand factor fbdctl \ eject env expand factor fbdctl \
find finger fingerd fix fold format fortune fsck.mfs \ find fingerd fix fold format fortune fsck.mfs \
gcore gcov-pull getty grep hexdump host \ gcore gcov-pull getty grep hexdump host \
hostaddr id ifconfig ifdef \ hostaddr id ifconfig ifdef \
intr ipcrm ipcs irdpd isoread last \ intr ipcrm ipcs irdpd isoread last \

View file

@ -1,4 +0,0 @@
PROG= finger
MAN=
.include <bsd.prog.mk>

File diff suppressed because it is too large Load diff

View file

@ -5,7 +5,7 @@ MAN= ash.1 at.1 basename.1 \
df.1 dhrystone.1 dosdir.1 dosread.1 doswrite.1 \ df.1 dhrystone.1 dosdir.1 dosread.1 doswrite.1 \
dumpcore.1 eject.1 \ dumpcore.1 eject.1 \
env.1 expand.1 factor.1 \ env.1 expand.1 factor.1 \
finger.1 flexdoc.1 fold.1 format.1 fortune.1 \ flexdoc.1 fold.1 format.1 fortune.1 \
fsck.mfs.1 host.1 hostaddr.1 ifdef.1 \ fsck.mfs.1 host.1 hostaddr.1 ifdef.1 \
isodir.1 isoinfo.1 isoread.1 \ isodir.1 isoinfo.1 isoread.1 \
last.1 loadfont.1 loadkeys.1 logger.1 \ last.1 loadfont.1 loadkeys.1 logger.1 \

View file

@ -1,84 +0,0 @@
.\" Copyright (c) 1980 Regents of the University of California.
.\" All rights reserved. The Berkeley software License Agreement
.\" specifies the terms and conditions for redistribution.
.\"
.\" @(#)finger.1 6.4 (Berkeley) 5/10/86
.\"
.TH FINGER 1 "May 10, 1986"
.UC 4
.SH NAME
finger \- user information lookup program
.SH SYNOPSIS
.B finger
[
options
] name ...
.SH DESCRIPTION
By default
.B finger
lists the login name, full name, terminal name and write status
(as a `*' before the terminal name if write permission is denied),
idle time, login time, and office location and phone number
(if they are known) for each current UNIX user.
(Idle time is minutes if it is a single integer, hours and minutes if a ':'
is present, or days and hours if a 'd' is present.)
.PP
A longer format also exists and is used by
.B finger
whenever a list of people's names is given. (Account names as well as
first and last names of users are accepted.)
This format is multi-line, and includes all the information described above
as well as the user's home
directory and login shell, any plan which the person has placed in the file
.B \&.plan
in their home
directory, and the project on which they are working from the file
.B \&.project
also in the home directory.
.PP
.B Finger
may be used to lookup users on a remote machine. The format is to specify
the user as ``user@host.'' If the user name is left off, the
standard format listing is provided on the remote machine.
.PP
.B Finger
options include:
.TP
.B \-m
Match arguments only on user name.
.TP
.B \-l
Force long output format.
.TP
.B \-p
Suppress printing of the
.B \&.plan
files
.TP
.B \-s
Force short output format.
.SH FILES
.ta 2i
/etc/utmp who file
.br
/etc/passwd for users names, offices, ...
.br
/usr/adm/lastlog last login times
.br
~/.plan plans
.br
~/.project projects
.SH "SEE ALSO"
.BR chfn (1),
.BR w (1),
.BR who (1).
.SH AUTHOR
Earl T. Cohen
.SH BUGS
Only the first line of the
.B .project
file is printed.
.PP
There is no way to pass arguments to the remote machine as
.B finger
uses an internet standard port.

View file

@ -133,6 +133,7 @@
2012/10/17 12:00:00,usr.bin/col 2012/10/17 12:00:00,usr.bin/col
2012/10/17 12:00:00,usr.bin/ctags 2012/10/17 12:00:00,usr.bin/ctags
2011/09/01 13:37:33,usr.bin/du 2011/09/01 13:37:33,usr.bin/du
2013/05/31 12:00:00,usr.bin/finger
2013/03/22 12:00:00,usr.bin/from 2013/03/22 12:00:00,usr.bin/from
2013/04/05 12:00:00,usr.bin/ftp 2013/04/05 12:00:00,usr.bin/ftp
2013/03/18 12:00:00,usr.bin/head 2013/03/18 12:00:00,usr.bin/head

View file

@ -9,7 +9,7 @@ SUBDIR= \
cal chpass cksum \ cal chpass cksum \
col ctags \ col ctags \
du \ du \
\ finger \
from ftp \ from ftp \
genassym getopt head \ genassym getopt head \
indent infocmp join \ indent infocmp join \

18
usr.bin/finger/Makefile Normal file
View file

@ -0,0 +1,18 @@
# $NetBSD: Makefile,v 1.11 2007/05/28 12:06:26 tls Exp $
# from: @(#)Makefile 8.1 (Berkeley) 6/6/93
.include <bsd.own.mk>
USE_FORT?= yes # network client
PROG= finger
SRCS= finger.c lprint.c net.c sprint.c util.c utmpentry.c
.PATH.c: ${NETBSDSRCDIR}/usr.bin/who
CPPFLAGS+=-I${NETBSDSRCDIR}/usr.bin/who -DSUPPORT_UTMPX -DSUPPORT_UTMP
.if (${USE_INET6} != "no")
CPPFLAGS+=-DINET6
.endif
.include <bsd.prog.mk>

57
usr.bin/finger/extern.h Normal file
View file

@ -0,0 +1,57 @@
/* $NetBSD: extern.h,v 1.10 2006/01/04 01:17:54 perry Exp $ */
/*-
* 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. 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
*/
extern time_t now; /* Current time. */
extern char tbuf[1024]; /* Temp buffer for anybody. */
extern int entries; /* Number of people. */
extern DB *db; /* Database. */
extern int lflag;
extern int oflag;
extern int gflag;
extern int eightflag;
extern int pplan;
void enter_lastlog(PERSON *);
PERSON *enter_person(struct passwd *);
void enter_where(struct utmpentry *, PERSON *);
void expandusername(const char *, const char *, char *, int);
PERSON *find_person(char *);
int hash(char *);
void lflag_print(void);
int match(struct passwd *, char *);
void netfinger(char *);
PERSON *palloc(void);
char *prphone(char *);
int psort(const void *, const void *);
void sflag_print(void);
PERSON **sort(void);

213
usr.bin/finger/finger.1 Normal file
View file

@ -0,0 +1,213 @@
.\" $NetBSD: finger.1,v 1.16 2012/06/10 17:45:59 dholland Exp $
.\"
.\" 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. 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.
.\"
.\" from: @(#)finger.1 8.3 (Berkeley) 5/5/94
.\"
.Dd June 10, 2012
.Dt FINGER 1
.Os
.Sh NAME
.Nm finger
.Nd user information lookup program
.Sh SYNOPSIS
.Nm
.Op Fl 8ghlmops
.Op Ar user ...
.Op Ar user@host ...
.Sh DESCRIPTION
The
.Nm
displays information about the system users.
.Pp
Options are:
.Bl -tag -width flag
.It Fl 8
Pass through 8-bit data.
This option is intended for enabling 8-bit
data output in the
.Xr fingerd 8
service.
Using this from the command line is
.Em dangerous ,
as the output data may include control characters for your terminal.
.It Fl g
This option restricts the gecos output to only the users' real names.
.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 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
.Dq hh:mm .
Idle times greater than a day are presented as
.Dq d day[s]hh:mm .
.Pp
Phone numbers specified as eleven digits are printed as
.Dq +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
.Dq xN-NNNN .
Numbers specified as four digits are printed as
.Dq xNNNN .
.Pp
If write permission is denied to the device, the phrase
.Dq (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
.Dq \&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
.Dq New mail received ... ,
.Dq 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.
This is the default.
.It Fl p
Prevents
the
.Fl l
option of
.Nm
from displaying the contents of the
.Dq Pa .forward ,
.Dq Pa .plan
and
.Dq Pa .project
files.
.It Fl s
.Nm
displays the user's login name, real name, terminal name and write
status (as a
.Dq *
after 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 is printed.
If
.Fl o
is given, the office location and phone number is printed instead
(the default).
.Pp
Idle time is in minutes if it is a single integer, hours and minutes
if a
.Dq \&:
is present, or days if a
.Dq d
is present.
Login time is displayed as the dayname if less than six 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
.Nm
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.
.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
.Sh HISTORY
The
.Nm
command appeared in
.Bx 3.0 .

301
usr.bin/finger/finger.c Normal file
View file

@ -0,0 +1,301 @@
/* $NetBSD: finger.c,v 1.29 2009/04/12 06:18:54 lukem Exp $ */
/*
* 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. 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 <lukem@NetBSD.org> added the following on 961121:
* - 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.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1989, 1993\
The Regents of the University of California. All rights reserved.");
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "@(#)finger.c 8.5 (Berkeley) 5/4/95";
#else
__RCSID("$NetBSD: finger.c,v 1.29 2009/04/12 06:18:54 lukem 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 <sys/param.h>
#include <db.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <locale.h>
#include <langinfo.h>
#include "utmpentry.h"
#include "finger.h"
#include "extern.h"
DB *db;
time_t now;
int entries, gflag, lflag, mflag, oflag, sflag, eightflag, pplan;
char tbuf[1024];
struct utmpentry *ehead;
static void loginlist(void);
static void userlist(int, char **);
int main(int, char **);
int
main(int argc, char **argv)
{
int ch;
/* Allow user's locale settings to affect character output. */
setlocale(LC_CTYPE, "");
/*
* Reset back to the C locale, unless we are using a known
* single-byte 8-bit locale.
*/
if (strncmp(nl_langinfo(CODESET), "ISO8859-", 8))
setlocale(LC_CTYPE, "C");
oflag = 1; /* default to old "office" behavior */
while ((ch = getopt(argc, argv, "lmpshog8")) != -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 'g':
gflag = 1; /* no gecos info, besides name */
break;
case '8':
eightflag = 1; /* 8-bit pass-through */
break;
case '?':
default:
(void)fprintf(stderr,
"usage: finger [-lmpshog8] [login ...]\n");
exit(1);
}
argc -= optind;
argv += optind;
(void)time(&now);
setpassent(1);
entries = getutentries(NULL, &ehead);
if (argc == 0) {
/*
* 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;
int r, seqflag;
struct utmpentry *ep;
for (ep = ehead; ep; ep = ep->next) {
if ((pn = find_person(ep->name)) == NULL) {
if ((pw = getpwnam(ep->name)) == NULL)
continue;
pn = enter_person(pw);
}
enter_where(ep, pn);
}
if (db && lflag)
for (seqflag = R_FIRST;; seqflag = R_NEXT) {
PERSON *tmp;
r = (*db->seq)(db, &key, &data, seqflag);
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 passwd *pw;
int r, seqflag, *used, *ip;
char **ap, **nargv, **np, **p;
struct utmpentry *ep;
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 (strchr(*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)) != NULL)
enter_person(pw);
else
warnx("%s: no such user", *p);
} else {
while ((pw = getpwent()) != NULL)
for (p = argv, ip = used; *p; ++p, ++ip)
if (match(pw, *p)) {
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 (entries == 0)
goto done;
/*
* Scan thru the list of users currently logged in, saving
* appropriate data whenever a match occurs.
*/
for (ep = ehead; ep; ep = ep->next) {
if ((pn = find_person(ep->name)) == NULL)
continue;
enter_where(ep, pn);
}
if (db != NULL)
for (seqflag = R_FIRST;; seqflag = R_NEXT) {
PERSON *tmp;
r = (*db->seq)(db, &key, &data, seqflag);
if (r == -1)
err(1, "db seq");
if (r == 1)
break;
memmove(&tmp, data.data, sizeof tmp);
enter_lastlog(tmp);
}
done:
free(nargv);
free(used);
}

67
usr.bin/finger/finger.h Normal file
View file

@ -0,0 +1,67 @@
/* $NetBSD: finger.h,v 1.10 2007/05/05 16:55:17 christos Exp $ */
/*
* 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. 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.
*
* from: @(#)finger.h 8.1 (Berkeley) 6/6/93
*/
/*
* All unique persons are linked in a list headed by "head" and linkd
* by the "next" field, as well as kept in a hash table.
*/
typedef struct person {
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 read */
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; /* tty line */
char *host; /* remote host name */
} WHERE;

389
usr.bin/finger/lprint.c Normal file
View file

@ -0,0 +1,389 @@
/* $NetBSD: lprint.c,v 1.23 2013/01/18 22:10:31 christos Exp $ */
/*
* 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. 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.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)lprint.c 8.3 (Berkeley) 4/28/95";
#else
__RCSID( "$NetBSD: lprint.c,v 1.23 2013/01/18 22:10:31 christos Exp $");
#endif
#endif /* not lint */
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
#include <tzfile.h>
#include <db.h>
#include <err.h>
#include <pwd.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include <paths.h>
#include <vis.h>
#include "utmpentry.h"
#include "finger.h"
#include "extern.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(const char *, int);
static void lprint(PERSON *);
static int show_text(const char *, const char *, const char *);
static void vputc(int);
#ifdef __SVR4
#define TIMEZONE(a) tzname[0]
#else
#define TIMEZONE(a) (a)->tm_zone
#endif
void
lflag_print(void)
{
PERSON *pn;
int sflag, r;
PERSON *tmp;
DBT data, key;
if (db == NULL)
return;
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");
}
}
}
static size_t
visify(char *buf, size_t blen, const char *str)
{
int len = strnvisx(buf, blen, str, strlen(str), VIS_WHITE|VIS_CSTYLE);
if (len == -1) {
buf[0] = '\0';
return 0;
}
return len;
}
static void
fmt_time(char *buf, size_t blen, time_t ti, time_t n)
{
struct tm *tp = localtime(&ti);
if (tp != NULL) {
char *t = asctime(tp);
char *tzn = TIMEZONE(tp);
if (n == (time_t)-1 ||
n - ti > SECSPERDAY * DAYSPERNYEAR / 2)
snprintf(buf, blen, "%.16s %.4s (%s)", t, t + 20, tzn);
else
snprintf(buf, blen, "%.16s (%s)", t, tzn);
} else
snprintf(buf, blen, "[*bad time 0x%llx*]", (long long)ti);
}
/*
* 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.
*/
static int
print_idle(time_t t, int maxlen, size_t hostlen, size_t ttylen) {
int cpr;
struct tm *delta = gmtime(&t);
if (delta == NULL)
return printf("Bad idle 0x%llx", (long long)t);
if (delta->tm_yday == 0 && delta->tm_hour == 0 && delta->tm_min == 0)
return 0;
cpr = printf("%-*s idle ", (int)(maxlen - ttylen + 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 (hostlen) {
putchar(',');
++cpr;
}
return cpr;
}
static void
lprint(PERSON *pn)
{
WHERE *w;
int cpr, len, maxlen;
int oddfield;
char timebuf[128], ttybuf[64], hostbuf[512];
size_t ttylen, hostlen;
cpr = 0;
/*
* 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(timebuf, sizeof(timebuf), "%s: %s, %s",
OFFICE_TAG, pn->office, prphone(pn->officephone));
oddfield = demi_print(timebuf, oddfield);
} else {
if (pn->office) {
(void)snprintf(timebuf, sizeof(timebuf), "%s: %s",
OFFICE_TAG, pn->office);
oddfield = demi_print(timebuf, oddfield);
}
if (pn->officephone) {
(void)snprintf(timebuf, sizeof(timebuf), "%s: %s",
OFFICE_PHONE_TAG, prphone(pn->officephone));
oddfield = demi_print(timebuf, oddfield);
}
}
if (pn->homephone) {
(void)snprintf(timebuf, sizeof(timebuf), "%s: %s", "Home Phone",
prphone(pn->homephone));
oddfield = demi_print(timebuf, 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) {
visify(ttybuf, sizeof(ttybuf), w->tty);
if ((len = strlen(ttybuf)) > maxlen)
maxlen = len;
}
/* find rest of entries for user */
for (w = pn->whead; w != NULL; w = w->next) {
ttylen = visify(ttybuf, sizeof(ttybuf), w->tty);
hostlen = visify(hostbuf, sizeof(hostbuf), w->host);
switch (w->info) {
case LOGGEDIN:
fmt_time(timebuf, sizeof(timebuf), w->loginat, -1);
cpr = printf("On since %s on %s", timebuf, ttybuf);
cpr += print_idle(w->idletime, maxlen, hostlen,
ttylen);
if (!w->writable)
cpr += printf(" (messages off)");
break;
case LASTLOG:
if (w->loginat == 0) {
(void)printf("Never logged in.");
break;
}
fmt_time(timebuf, sizeof(timebuf), w->loginat, now);
cpr = printf("Last login %s on %s", timebuf, ttybuf);
break;
}
if (hostlen) {
if (LINE_LEN < (cpr + 6 + hostlen))
(void)printf("\n ");
(void)printf(" from %s", hostbuf);
}
putchar('\n');
}
if (pn->mailrecv == -1)
printf("No Mail.\n");
else if (pn->mailrecv > pn->mailread) {
fmt_time(timebuf, sizeof(timebuf), pn->mailrecv, -1);
printf("New mail received %s\n", timebuf);
fmt_time(timebuf, sizeof(timebuf), pn->mailread, -1);
printf(" Unread since %s\n", timebuf);
} else {
fmt_time(timebuf, sizeof(timebuf), pn->mailread, -1);
printf("Mail last read %s\n", timebuf);
}
}
static int
demi_print(const 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(const char *directory, const char *file_name, const char *header)
{
struct stat sb;
FILE *fp;
int ch, cnt, lastc;
char *p;
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 <= (off_t)(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 = (unsigned char)*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 (lastc != '\n')
(void)putchar('\n');
(void)fclose(fp);
return(1);
}
static void
vputc(int ch)
{
char visout[5], *s2;
if (eightflag || isprint(ch) || isspace(ch)) {
(void)putchar(ch);
return;
}
ch = toascii(ch);
vis(visout, ch, VIS_SAFE|VIS_NOSLASH, 0);
for (s2 = visout; *s2; s2++)
(void)putchar(*s2);
}

159
usr.bin/finger/net.c Normal file
View file

@ -0,0 +1,159 @@
/* $NetBSD: net.c,v 1.23 2009/04/12 06:18:54 lukem Exp $ */
/*
* 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. 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.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)net.c 8.4 (Berkeley) 4/28/95";
#else
__RCSID("$NetBSD: net.c,v 1.23 2009/04/12 06:18:54 lukem Exp $");
#endif
#endif /* not lint */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <time.h>
#include <db.h>
#include <unistd.h>
#include <pwd.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <err.h>
#include "utmpentry.h"
#include "finger.h"
#include "extern.h"
void
netfinger(char *name)
{
FILE *fp;
int c, lastc;
int s;
char *host;
struct addrinfo hints, *res, *res0;
int error;
const char *emsg = NULL;
lastc = 0;
if (!(host = strrchr(name, '@')))
return;
*host++ = '\0';
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_CANONNAME;
error = getaddrinfo(host, "finger", &hints, &res0);
if (error) {
warnx("%s: %s", gai_strerror(error), host);
return;
}
s = -1;
for (res = res0; res; res = res->ai_next) {
s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (s < 0) {
emsg = "socket";
continue;
}
if (connect(s, res->ai_addr, res->ai_addrlen)) {
close(s);
s = -1;
emsg = "connect";
continue;
}
break;
}
if (s < 0) {
if (emsg != NULL)
warn("%s", emsg);
return;
}
/* have network connection; identify the host connected with */
(void)printf("[%s]\n", res0->ai_canonname ? res0->ai_canonname : host);
/* -l flag for remote fingerd */
if (lflag)
write(s, "/W ", 3);
/* send the name followed by <CR><LF> */
(void)write(s, name, strlen(name));
(void)write(s, "\r\n", 2);
/*
* 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> followed by a newline character, only output
* one newline.
*
* If a character isn't printable and it isn't a space, we strip the
* 8th bit and set the 7th bit. Every ASCII character with bit 7 set
* is printable.
*/
if ((fp = fdopen(s, "r")) != NULL)
while ((c = getc(fp)) != EOF) {
if (c == '\r') {
if (lastc == '\r') /* ^M^M - skip dupes */
continue;
c = '\n';
lastc = '\r';
} else {
if (!(eightflag || 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');
(void)fclose(fp);
}

173
usr.bin/finger/sprint.c Normal file
View file

@ -0,0 +1,173 @@
/* $NetBSD: sprint.c,v 1.17 2006/01/04 01:17:54 perry Exp $ */
/*
* 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. 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.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)sprint.c 8.3 (Berkeley) 4/28/95";
#else
__RCSID("$NetBSD: sprint.c,v 1.17 2006/01/04 01:17:54 perry Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <time.h>
#include <tzfile.h>
#include <db.h>
#include <err.h>
#include <pwd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "utmpentry.h"
#include "finger.h"
#include "extern.h"
static void stimeprint(WHERE *);
void
sflag_print(void)
{
PERSON *pn;
WHERE *w;
int sflag, r;
char *p;
PERSON *tmp;
DBT data, key;
if (db == NULL)
return;
/*
* short format --
* login name
* real name
* terminal name
* if terminal writable (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 < 6 days,
* show day name instead of month & day.
* if -h given
* remote host
* else if -o given (overriding -h) (default)
* office location
* office phone
*/
#define MAXREALNAME 18
(void)printf("%-*s %-*s %s %s\n", maxname, "Login", MAXREALNAME,
"Name", " Tty Idle Login Time ", (gflag) ? "" :
(oflag) ? "Office 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) {
(void)printf("%-*.*s %-*.*s ", (int)maxname,
(int)maxname,
pn->name, MAXREALNAME, MAXREALNAME,
pn->realname ? pn->realname : "");
if (!w->loginat) {
(void)printf(" * * No logins ");
goto office;
}
(void)putchar(w->info == LOGGEDIN && !w->writable ?
'*' : ' ');
if (*w->tty)
(void)printf("%-7.7s ", w->tty);
else
(void)printf(" ");
if (w->info == LOGGEDIN) {
stimeprint(w);
(void)printf(" ");
} else
(void)printf(" * ");
p = ctime(&w->loginat);
if (now - w->loginat < SECSPERDAY * (DAYSPERWEEK - 1))
(void)printf("%.3s %-8.5s", p, p + 11);
else if (now - w->loginat
< SECSPERDAY * DAYSPERNYEAR / 2)
(void)printf("%.6s %-5.5s", p + 4, p + 11);
else
(void)printf("%.6s %-5.4s", p + 4, p + 20);
office:
if (gflag)
goto no_gecos;
putchar(' ');
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));
} else
(void)printf("%.*s", MAXHOSTNAMELEN, w->host);
no_gecos:
putchar('\n');
}
}
}
static void
stimeprint(WHERE *w)
{
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);
}

409
usr.bin/finger/util.c Normal file
View file

@ -0,0 +1,409 @@
/* $NetBSD: util.c,v 1.28 2009/04/12 06:18:54 lukem Exp $ */
/*
* 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. 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.
*/
/*
* Portions Copyright (c) 1983, 1995, 1996 Eric P. Allman
*
* 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.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)util.c 8.3 (Berkeley) 4/28/95";
#else
__RCSID("$NetBSD: util.c,v 1.28 2009/04/12 06:18:54 lukem Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/stat.h>
#include <db.h>
#include <ctype.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 <utmp.h>
#include "utmpentry.h"
#include "finger.h"
#include "extern.h"
static void find_idle_and_ttywrite(WHERE *);
static void userinfo(PERSON *, struct passwd *);
static WHERE *walloc(PERSON *);
int
match(struct passwd *pw, char *user)
{
char *p;
char *bp, name[1024];
if (!strcasecmp(pw->pw_name, user))
return(1);
(void)strlcpy(bp = tbuf, pw->pw_gecos, sizeof(tbuf));
/* Ampersands get replaced by the login name. */
if (!(p = strsep(&bp, ",")))
return(0);
expandusername(p, pw->pw_name, name, sizeof(name));
bp = name;
while ((p = strsep(&bp, "\t ")))
if (!strcasecmp(p, user))
return(1);
return(0);
}
/* inspired by usr.sbin/sendmail/util.c::buildfname */
void
expandusername(const char *gecos, const char *login, char *buf, int buflen)
{
const char *p;
char *bp;
/* why do we skip asterisks!?!? */
if (*gecos == '*')
gecos++;
bp = buf;
/* copy gecos, interpolating & to be full name */
for (p = gecos; *p != '\0'; p++) {
if (bp >= &buf[buflen - 1]) {
/* buffer overflow - just use login name */
snprintf(buf, buflen, "%s", login);
buf[buflen - 1] = '\0';
return;
}
if (*p == '&') {
/* interpolate full name */
snprintf(bp, buflen - (bp - buf), "%s", login);
*bp = toupper((unsigned char)*bp);
bp += strlen(bp);
}
else
*bp++ = *p;
}
*bp = '\0';
}
void
enter_lastlog(PERSON *pn)
{
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, (off_t)pn->uid * sizeof(ll), SEEK_SET) !=
(off_t)pn->uid * (off_t)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;
if ((w->tty = malloc(UT_LINESIZE + 1)) == NULL)
err(1, NULL);
memcpy(w->tty, ll.ll_line, UT_LINESIZE);
w->tty[UT_LINESIZE] = '\0';
if ((w->host = malloc(UT_HOSTSIZE + 1)) == NULL)
err(1, NULL);
memcpy(w->host, ll.ll_host, UT_HOSTSIZE);
w->host[UT_HOSTSIZE] = '\0';
w->loginat = ll.ll_time;
}
}
void
enter_where(struct utmpentry *ep, PERSON *pn)
{
WHERE *w = walloc(pn);
w->info = LOGGEDIN;
w->tty = ep->line;
w->host = ep->host;
w->loginat = (time_t)ep->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 = (char *)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(char *name)
{
DBT data, key;
PERSON *p;
if (!db)
return(NULL);
key.data = name;
key.size = strlen(name);
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((u_int) sizeof(PERSON))) == NULL)
err(1, NULL);
return(p);
}
static WHERE *
walloc(PERSON *pn)
{
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(char *num)
{
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((unsigned char)*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;
(void)snprintf(tbuf, sizeof(tbuf), "%s/%s", _PATH_DEV, w->tty);
if (stat(tbuf, &sb) < 0) {
warn("%s", 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(PERSON *pn, struct passwd *pw)
{
char *p;
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);
(void)strlcpy(bp = tbuf, pw->pw_gecos, sizeof(tbuf));
/* ampersands get replaced by the login name */
if (!(p = strsep(&bp, ",")))
return;
expandusername(p, pw->pw_name, name, sizeof(name));
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)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) {
(void)fprintf(stderr,
"finger: %s: %s\n", tbuf, strerror(errno));
return;
}
} else if (sb.st_size != 0) {
pn->mailrecv = sb.st_mtime;
pn->mailread = sb.st_atime;
}
}