summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKatolaZ <katolaz@freaknet.org>2019-02-08 05:13:11 +0000
committerKatolaZ <katolaz@freaknet.org>2019-02-08 05:13:11 +0000
commit172540a4a29fa4c0c5f0431bb5bf5b3d08ec92c0 (patch)
treeac15b0b8ae60a42ffe04b3fd37cf2fbc97b2ddd6
New upstream version 0.17upstream
-rw-r--r--.cvsignore1
-rw-r--r--BUGS7
-rw-r--r--ChangeLog133
-rw-r--r--MCONFIG.in22
-rw-r--r--MRULES8
-rw-r--r--Makefile20
-rw-r--r--README118
-rwxr-xr-xconfigure305
-rw-r--r--finger/.cvsignore1
-rw-r--r--finger/Makefile18
-rw-r--r--finger/display.c179
-rw-r--r--finger/finger.1194
-rw-r--r--finger/finger.c334
-rw-r--r--finger/finger.h119
-rw-r--r--finger/lprint.c361
-rw-r--r--finger/net.c155
-rw-r--r--finger/sprint.c172
-rw-r--r--finger/util.c418
-rw-r--r--fingerd/.cvsignore1
-rw-r--r--fingerd/Makefile18
-rw-r--r--fingerd/fingerd.8157
-rw-r--r--fingerd/fingerd.c295
-rw-r--r--fingerd/pathnames.h41
-rw-r--r--version.h5
24 files changed, 3082 insertions, 0 deletions
diff --git a/.cvsignore b/.cvsignore
new file mode 100644
index 0000000..b3bd6af
--- /dev/null
+++ b/.cvsignore
@@ -0,0 +1 @@
+MCONFIG
diff --git a/BUGS b/BUGS
new file mode 100644
index 0000000..50701e0
--- /dev/null
+++ b/BUGS
@@ -0,0 +1,7 @@
+finger:
+ - add option to issue CRs so fingerd doesn't need to fork
+ - Some nameservers hose on "", patch finger to work around it
+
+fingerd:
+ - rejection of finger forwarding should be optional
+
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..dcd957a
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,133 @@
+22-Jul-2000:
+ Document ~/.pgpkey. (Herbert Xu, herbert@gondor.apana.org.au)
+
+18-Dec-1999:
+ Add support for ~/.nofinger files.
+
+14-Dec-1999:
+ bsd-finger-0.16 is released.
+
+12-Dec-1999:
+ Withdrew -R option; finger can figure out on its own if it needs
+ to emit CRs.
+ Also, make printing of pts/* ttys work right.
+
+14-Sep-1999:
+ Rewrote output handling of finger to deal with 8-bit characters
+ correctly. Also fixed what I think was some uninitialized data
+ displaying ":0" utmp entries.
+ Backed out patch 1.15 of finger/util.c because it was completely
+ wrong. Fixed gecos processing _again_.
+ Added -R option to finger that causes it to emit CR before every
+ LF. Changed fingerd to use it. This means fingerd no longer
+ needs to fork.
+
+1-Aug-1999:
+ Complete y2k and y2038 audit.
+
+31-Jul-1999:
+ Redid makefiles/config stuff for new confgen version.
+
+23-Sep-1997:
+ fingerd should now refuse to run as root and bail if it can't find
+ "nobody".
+
+22-Sep-1997:
+ Fix finger to not destroy gethostbyname() results with
+ getservbyname().
+
+02-Aug-1997:
+ Fix fingerd to complain if it can't switch from root.
+
+12-Jun-1997:
+ bsd-finger-0.10 released.
+
+08-Jun-1997:
+ More adjustments for glibc.
+
+13-May-1997:
+ Do dynamic column width formatting in short format printout. (HJ Lu)
+
+05-Apr-1997:
+ Added configure script to generate MCONFIG.
+ glibc fixes from HJ Lu.
+ Display .pgpkey file in finger (Edward S. Marshall,
+ emarshal@common.net)
+ Better utmp handling.
+
+08-Mar-1997:
+ Split from full NetKit package.
+ Generated this change log from NetKit's.
+
+07-Mar-1997:
+ Fixed finger to reject .plans that aren't regular files. (Thomas
+ Roessler, roessler@sobolev.rhein.de)
+
+01-Feb-1997:
+ Fixed finger's timezone handling. Now gets daylight time right.
+
+29-Dec-1996
+ NetKit-0.09 released.
+ Fix doc bugs in fingerd.
+ Fingerd accepts -p as equivalent to -L for compatibility with
+ "fingerd-extlog.tar.gz".
+ Assorted alpha/glibc patches. (Erik Troan, ewt@redhat.com)
+ Assorted bug fixes from Debian. (Peter Tobias,
+ tobias@et-inf.fho-emden.de)
+ Hardened programs against DNS h_length spoofing attacks.
+ Use inet_aton() everywhere instead of inet_addr().
+ Fixed bug in finger's processing of &'s in full names that probably has
+ security implications.
+ Finger doesn't follow symlinks now.
+
+22-Aug-1996
+ NetKit-B-0.08 released.
+ fingerd uses fork instead of system for running uptime (with -w flag).
+ fingerd supports -L flag to run alternate finger client.
+ (almost) everything now compiles with lots of warnings turned on.
+ fingerd now accepts a new -u flag to reject "finger @host" queries.
+ fix bug in finger that prevented matching full names
+ (fix from James Jones <james@richland.cc.il.us>.)
+
+25-Jul-1996
+ NetKit-B-0.07A released.
+
+23-Jul-1996
+ NetKit-B-0.07 released.
+ Integrated a collection of patches that had been lurking on the net,
+ including the 256-ptys support for telnetd and passive mode ftp.
+ Major security fixes, including to fingerd, lpr, rlogin, rsh, talkd,
+ and telnetd. Do *not* use the sliplogin from earlier versions of this
+ package, either.
+ Several of the daemons support better logging.
+ Much of the code builds without libbsd.a or bsd includes.
+ Massive code cleanup. Almost everything compiles clean with gcc
+ -Wall now. rusers and rusersd do not; patches to rpcgen to fix
+ this would be appreciated if anyone feels like it.
+ New maintainer: David A. Holland, dholland@hcs.harvard.edu
+
+date not known
+ NetKit-B-0.06 released.
+ Added a missing argument in a printf to the finger source
+ code. Phil Edge
+ "finger -l" prints the standard timezone when it should print the
+ daylight savings timezone. tzname[0] is standard timezone and
+ tzname[1] is daylight savings timezone. This patch is from Phil
+ Edge. He wasn't too sure about this patch, and I haven't looked
+ into it. Anyone who really knows about this stuff? Look into
+ lprint.c in the finger source. I changed all "1 - daylight" into
+ "daylight"... You could also verify all Linux-specific changes
+ to timezone things. Other parts look also like duplicate work.
+ (Maybe even wrong...)
+
+date not known
+ NetKit-B-0.05 released.
+ Fixed finger/util.c to cope with XDM login entry in utmp (Leonard
+ Zubkoff)
+
+date not known
+ NetKit-B-0.04 released.
+
+date not known
+ NetKit-B-0.03 released.
+ Fixed fingerd to not use 'getdomainname' to get the FQDN.
diff --git a/MCONFIG.in b/MCONFIG.in
new file mode 100644
index 0000000..4c340b0
--- /dev/null
+++ b/MCONFIG.in
@@ -0,0 +1,22 @@
+# Dirs
+INSTALLROOT
+BINDIR
+SBINDIR
+MANDIR
+
+# Modes
+BINMODE
+DAEMONMODE
+MANMODE
+
+# Compiling
+ALLWARNINGS
+CC
+CFLAGS
+LDFLAGS
+LIBS
+
+# Features
+FN(snprintf)
+TYPE(socklen_t)
+
diff --git a/MRULES b/MRULES
new file mode 100644
index 0000000..2630b72
--- /dev/null
+++ b/MRULES
@@ -0,0 +1,8 @@
+# Standard compilation rules (don't use make builtins)
+
+%.o: %.c
+ $(CC) $(CFLAGS) $< -c
+
+%.o: %.cc
+ $(CC) $(CFLAGS) $< -c
+
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..f224bc3
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,20 @@
+# You can do "make SUB=blah" to make only a few, or edit here, or both
+# You can also run make directly in the subdirs you want.
+
+SUB = finger fingerd
+
+%.build:
+ (cd $(patsubst %.build, %, $@) && $(MAKE))
+
+%.install:
+ (cd $(patsubst %.install, %, $@) && $(MAKE) install)
+
+%.clean:
+ (cd $(patsubst %.clean, %, $@) && $(MAKE) clean)
+
+all: $(patsubst %, %.build, $(SUB))
+install: $(patsubst %, %.install, $(SUB))
+clean: $(patsubst %, %.clean, $(SUB))
+
+distclean: clean
+ rm -f MCONFIG
diff --git a/README b/README
new file mode 100644
index 0000000..9bbe6ab
--- /dev/null
+++ b/README
@@ -0,0 +1,118 @@
+This is bsd-finger-0.17 for Linux.
+
+This package updates bsd-finger-0.16.
+
+If you're reading this off a CD, go right away and check the net
+archives for later versions and security fixes. As of this writing the
+home site for NetKit is
+ ftp://ftp.uk.linux.org/pub/linux/Networking/netkit
+
+Contents:
+ finger Program for printing user information
+ fingerd Daemon for remote finger access
+
+Requires:
+ Working compiler, libc, and kernel.
+
+Security:
+ bsd-finger-0.17 contains no new security fixes.
+
+ bsd-finger-0.16 fixes some possible denial of service attacks
+ against fingerd.
+
+ bsd-finger-0.10 fixed a denial of service situation where
+ users' .plan or .project files are named pipes.
+
+ The NetKit-0.09 and earlier versions of this code fixed a
+ number of now well-known security problems. Please don't use
+ older versions.
+
+Note:
+ If you are using the finger daemon from this package with a
+ custom finger client, rather than the finger client in this
+ package, you will need to update your client to send carriage
+ returns (CR, or '\r' in C) before line feeds (LF, or '\n' in
+ C) if the finger client's standard output is a socket.
+
+ This is because as of bsd-finger-0.15, finger probes this
+ condition and sends CRs itself instead of expecting fingerd
+ to make an extra copy of all the data through a pipe just to
+ add CRs in.
+
+ Ignoring this circumstance and always sending LF instead of
+ CR/LF will in most cases work, but is not RFC-compliant.
+
+Installation:
+ Do "./configure --help" and decide what options you want. The
+ defaults should be suitable for most Linux systems. Then run
+ the configure script.
+
+ Do "make" to compile.
+ Then (as root) do "make install".
+
+ Save a backup copy of any mission-critical program in case the
+ new one doesn't work, and so forth. We warned you.
+
+ If you get gcc warnings from files in /usr/include, they are
+ due to problems in your libc, not netkit. (You may only see
+ them when compiling netkit because netkit turns on a lot of
+ compiler warnings.)
+
+DEC CC:
+ The DEC compiler for the Alpha is now freely available. This
+ is a much better compiler with gcc, that is, it generates much
+ better code. If you have the DEC compiler, you can explicitly
+ use the DEC compiler instead of gcc by configuring like this:
+
+ ./configure --with-c-compiler=ccc
+
+ It is known to generate spurious warnings on some files. Also,
+ some headers from some versions of glibc confuse it; that may
+ prevent netkit from working. Other problems should be reported
+ as bugs.
+
+Bugs:
+ Please make sure the header files in /usr/include match the
+ libc version installed in /lib and /usr/lib. If you have weird
+ problems this is the most likely culprit.
+
+ Also, before reporting a bug, be sure you're working with the
+ latest version.
+
+ If something doesn't compile for you, fix it and send diffs.
+ If you can't, send the compiler's error output.
+
+ If it compiles but doesn't work, send as complete a bug report as
+ you can. Patches and fixes are welcome, as long as you describe
+ adequately what they're supposed to fix. Please, one patch per
+ distinct fix. Please do NOT send the whole archive back or
+ reindent the source.
+
+ Be sure to send all correspondence in e-mail to the netkit address.
+ Postings to netnews or mailing lists will not be seen due to the
+ enormous volume. Also, anything that doesn't get filed in the bug
+ database is quite likely to end up forgotten.
+
+ Please don't report known bugs (see the BUGS file(s)) unless you
+ are including fixes. :-)
+
+ Mail should be sent to: netbug@ftp.uk.linux.org
+
+
+Early in April 2000, a hacker broke into the machine that was hosting
+the netkit bug database for me and trashed it. Unfortunately, it seems
+backups hadn't gotten done for a while, so three months of mail (since
+mid-January) was lost. So, if you sent something and didn't hear back,
+or you sent something, heard back, but the changes failed to appear in
+this release (unlikely but possible) - please resend.
+
+Please see http://www.hcs.harvard.edu/~dholland/computers/netkit.html
+if you are curious why it was so long between the 0.10 and 0.16 releases.
+
+Future plans for netkit maintenance are still up in the air, but in the
+meantime new releases will still appear from time to time. I don't have
+a whole lot of cycles to spare to work on netkit, so things are likely
+to continue to be fairly slow.
+
+David A. Holland
+23 July 2000
diff --git a/configure b/configure
new file mode 100755
index 0000000..43a79ff
--- /dev/null
+++ b/configure
@@ -0,0 +1,305 @@
+#!/bin/sh
+#
+# This file was generated by confgen version 2.
+# Do not edit.
+#
+
+PREFIX='/usr'
+#EXECPREFIX='$PREFIX'
+INSTALLROOT=''
+BINMODE='755'
+#DAEMONMODE='$BINMODE'
+MANMODE='644'
+
+while [ x$1 != x ]; do case $1 in
+
+ --help)
+ cat <<EOF
+Usage: configure [options]
+ --help Show this message
+ --with-debug Enable debugging
+ --prefix=path Prefix for location of files [/usr]
+ --exec-prefix=path Location for arch-depedent files [prefix]
+ --installroot=root Top of filesystem tree to install in [/]
+ --binmode=mode Mode for binaries [755]
+ --daemonmode=mode Mode for daemon binaries [same as binmode]
+ --manmode=mode Mode for manual pages [644]
+ --with-c-compiler=cc Program for compiling C source [guessed]
+EOF
+ exit 0;;
+ --verbose) ;;
+ --quiet) ;;
+
+ --subdir) . ../configure.defs;;
+
+ --with-debug|--debug) DEBUG=1;;
+ --prefix=*) PREFIX=`echo $1 | sed 's/^[^=]*=//'` ;;
+ --exec-prefix=*) EXECPREFIX=`echo $1 | sed 's/^[^=]*=//'` ;;
+ --installroot=*) INSTALLROOT=`echo $1 | sed 's/^[^=]*=//'` ;;
+ --binmode=*) BINMODE=`echo $1 | sed 's/^[^=]*=//'` ;;
+ --daemonmode=*) DAEMONMODE=`echo $1 | sed 's/^[^=]*=//'` ;;
+ --manmode=*) MANMODE=`echo $1 | sed 's/^[^=]*=//'` ;;
+ --with-c-compiler=*) CC=`echo $1 | sed 's/^[^=]*=//'` ;;
+ *) echo "Unrecognized option: $1"; exit 1;;
+esac
+shift
+done
+
+if [ x$EXECPREFIX = x ]; then
+ EXECPREFIX="$PREFIX"
+fi
+
+if [ x$DAEMONMODE = x ]; then
+ DAEMONMODE="$BINMODE"
+fi
+
+BINDIR="$EXECPREFIX/bin"
+SBINDIR="$EXECPREFIX/sbin"
+MANDIR="$PREFIX/man"
+
+echo "Directories: $BINDIR $SBINDIR $MANDIR "
+
+if [ x$INSTALLROOT != x ]; then
+ echo "Installing in chroot tree rooted at $INSTALLROOT"
+fi
+
+##################################################
+
+WARNINGS='-Wall -W -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Winline '
+
+cat << EOF > __conftest.c
+ int main() { int class=0; return class; }
+EOF
+
+if [ x"$CC" = x ]; then
+ echo -n 'Looking for a C compiler... '
+ for TRY in egcs gcc g++ CC c++ cc; do
+ (
+ $TRY __conftest.c -o __conftest || exit 1;
+ ./__conftest || exit 1;
+ ) >/dev/null 2>&1 || continue;
+ CC=$TRY
+ break;
+ done
+ if [ x"$CC" = x ]; then
+ echo 'failed.'
+ echo 'Cannot find a C compiler. Run configure with --with-c-compiler.'
+ rm -f __conftest*
+ exit
+ fi
+ echo "$CC"
+else
+ echo -n 'Checking if C compiler works... '
+ if (
+ $CC __conftest.c -o __conftest || exit 1
+ ./__conftest || exit 1
+ ) >/dev/null 2>&1; then
+ echo 'yes'
+ else
+ echo 'no'
+ echo 'Compiler '"$CC"' does not exist or cannot compile C; try another.'
+ rm -f __conftest*
+ exit
+ fi
+fi
+
+echo -n "Checking if $CC accepts gcc warnings... "
+if (
+ $CC $WARNINGS __conftest.c -o __conftest || exit 1
+ ) >/dev/null 2>&1; then
+ echo 'yes'
+ CC_WARNINGS=1
+else
+ echo 'no'
+fi
+
+if [ x$DEBUG = x ]; then
+ echo -n "Checking if $CC accepts -O2... "
+ if (
+ $CC -O2 __conftest.c -o __conftest
+ ) >/dev/null 2>&1; then
+ echo 'yes'
+ CFLAGS="$CFLAGS -O2"
+ else
+ echo 'no'
+ echo -n "Checking if $CC accepts -O... "
+ if (
+ $CC -O __conftest.c -o __conftest
+ ) >/dev/null 2>&1; then
+ echo 'yes'
+ CFLAGS="$CFLAGS -O"
+ else
+ echo 'no'
+ fi
+ fi
+
+else
+ echo -n "Checking if $CC accepts -g... "
+ if (
+ $CC -g __conftest.c -o __conftest
+ ) >/dev/null 2>&1; then
+ echo 'yes'
+ CFLAGS="$CFLAGS -g"
+ else
+ echo 'no'
+ fi
+
+fi
+
+LDFLAGS=
+LIBS=
+
+rm -f __conftest*
+
+##################################################
+
+echo -n 'Checking for socklen_t... '
+cat <<EOF >__conftest.c
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+int main() {
+ struct sockaddr_in sn;
+ socklen_t len = sizeof(sn);
+ getpeername(0, (struct sockaddr *)&sn, &len);
+ return 0;
+}
+
+EOF
+if (
+ $CC $CFLAGS __conftest.c -o __conftest || exit 1
+ ) >/dev/null 2>&1; then
+ echo 'yes'
+else
+ if (
+ $CC $CFLAGS -Dsocklen_t=int __conftest.c -o __conftest || exit 1
+ ) >/dev/null 2>&1; then
+ echo 'int'
+ CFLAGS="$CFLAGS -Dsocklen_t=int"
+ else
+ if (
+ $CC $CFLAGS -Dsocklen_t=size_t __conftest.c -o __conftest || exit 1
+ ) >/dev/null 2>&1; then
+ echo 'size_t'
+ CFLAGS="$CFLAGS -Dsocklen_t=size_t"
+ else
+ echo 'no'
+ echo 'Cannot work out what to use for socklen_t. Help...'
+ rm -f __conftest*
+ exit
+ fi
+ fi
+fi
+rm -f __conftest*
+
+##################################################
+
+echo -n 'Checking for snprintf declaration... '
+cat <<EOF >__conftest.c
+#include <stdio.h>
+int main() {
+ void *x = (void *)snprintf;
+ printf("%lx", (long)x);
+ return 0;
+}
+
+EOF
+if (
+ $CC $CFLAGS __conftest.c -o __conftest || exit 1
+ ) >/dev/null 2>&1; then
+ echo 'ok'
+else
+ if (
+ $CC $CFLAGS -D_GNU_SOURCE __conftest.c -o __conftest || exit 1
+ ./__conftest || exit 1
+ ) >/dev/null 2>&1; then
+ echo '-D_GNU_SOURCE'
+ CFLAGS="$CFLAGS -D_GNU_SOURCE"
+ else
+ echo 'manual'
+ CFLAGS="$CFLAGS -DDECLARE_SNPRINTF"
+ fi
+fi
+rm -f __conftest*
+
+echo -n 'Checking for snprintf implementation... '
+cat <<EOF >__conftest.c
+#include <stdio.h>
+#include <string.h>
+#ifdef DECLARE_SNPRINTF
+#ifdef __cplusplus
+extern "C"
+#endif /*__cplusplus*/
+int snprintf(char *, int, const char *, ...);
+#endif /*DECLARE_SNPRINTF*/
+int main() {
+ char buf[32];
+ snprintf(buf, 8, "%s", "1234567890");
+ if (strlen(buf)!=7) return 1;
+ return 0;
+}
+
+EOF
+if (
+ $CC $CFLAGS __conftest.c $LIBBSD -o __conftest || exit 1
+ ./__conftest || exit 1
+ ) >/dev/null 2>&1; then
+ echo 'ok'
+else
+ if (
+ $CC $CFLAGS __conftest.c -lsnprintf $LIBBSD -o __conftest || exit 1
+ ./__conftest || exit 1
+ ) >/dev/null 2>&1; then
+ echo '-lsnprintf'
+ LIBS="$LIBS -lsnprintf"
+ else
+ if (
+ $CC $CFLAGS __conftest.c -ldb $LIBBSD -o __conftest || exit 1
+ ./__conftest || exit 1
+ ) >/dev/null 2>&1; then
+ echo '-ldb'
+ LIBS="$LIBS -ldb"
+ else
+ echo 'missing'
+ echo 'This package requires snprintf.'
+ rm -f __conftest*
+ exit
+ fi
+ fi
+fi
+rm -f __conftest*
+
+##################################################
+
+## libbsd should go last in case it's broken
+if [ "x$LIBBSD" != x ]; then
+ LIBS="$LIBS $LIBBSD"
+fi
+
+echo 'Generating MCONFIG...'
+(
+ echo -n '# Generated by configure (confgen version 2) on '
+ date
+ echo '#'
+ echo
+
+ echo "BINDIR=$BINDIR"
+ echo "SBINDIR=$SBINDIR"
+ echo "MANDIR=$MANDIR"
+ echo "BINMODE=$BINMODE"
+ echo "DAEMONMODE=$DAEMONMODE"
+ echo "MANMODE=$MANMODE"
+ echo "PREFIX=$PREFIX"
+ echo "EXECPREFIX=$EXECPREFIX"
+ echo "INSTALLROOT=$INSTALLROOT"
+ echo "CC=$CC"
+ if [ x$CC_WARNINGS != x ]; then
+ CFLAGS="$CFLAGS $WARNINGS"
+ fi
+
+ echo "CFLAGS=$CFLAGS" | sed 's/= */=/'
+ echo "LDFLAGS=$LDFLAGS" | sed 's/= */=/'
+ echo "LIBS=$LIBS" | sed 's/= */=/'
+
+) > MCONFIG
+
diff --git a/finger/.cvsignore b/finger/.cvsignore
new file mode 100644
index 0000000..f9a4475
--- /dev/null
+++ b/finger/.cvsignore
@@ -0,0 +1 @@
+finger
diff --git a/finger/Makefile b/finger/Makefile
new file mode 100644
index 0000000..bec7322
--- /dev/null
+++ b/finger/Makefile
@@ -0,0 +1,18 @@
+all: finger
+
+include ../MCONFIG
+include ../MRULES
+
+finger: finger.o lprint.o net.o sprint.o util.o display.o
+ $(CC) $(LDFLAGS) $^ $(LIBS) -o $@
+
+finger.o lprint.o net.o sprint.o util.o display.o: finger.h
+finger.o: ../version.h
+
+install: finger
+ install -s -m$(BINMODE) finger $(INSTALLROOT)$(BINDIR)
+ install -m$(MANMODE) finger.1 $(INSTALLROOT)$(MANDIR)/man1
+
+clean:
+ rm -f *.o finger
+
diff --git a/finger/display.c b/finger/display.c
new file mode 100644
index 0000000..dd33c43
--- /dev/null
+++ b/finger/display.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 1989 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.
+ */
+
+#include <termios.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include "finger.h"
+
+int
+getscreenwidth(void)
+{
+
+#if defined(TIOCGWINSZ)
+ struct winsize ws;
+ if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) < 0 || ws.ws_col==0) {
+ return 80;
+ }
+ return ws.ws_col;
+
+#elif defined(TIOCGSIZE)
+ struct ttysize ts;
+ if (ioctl(STDIN_FILENO, TIOCGSIZE, &ts) < 0 || ts.ts_cols==0) {
+ return 80;
+ }
+ return ts.ts_cols;
+
+#else
+ const char *e = getenv("COLUMNS");
+ int col = e ? atoi(e) : 0;
+ if (col==0) col = 80;
+ return col;
+#endif
+}
+
+int
+is8bit(void)
+{
+ static int cache=-1;
+ struct termios tios;
+ if (cache>=0) return cache;
+
+ if (tcgetattr(STDIN_FILENO, &tios)<0) {
+ /* assume 8-bit; it's 1999 now, not 1972 */
+ cache = 1;
+ }
+ else {
+ cache = (tios.c_cflag & CSIZE)==CS8;
+ }
+ return cache;
+}
+
+/************/
+
+static int send_crs=0;
+
+void
+set_crmode(void)
+{
+ send_crs = 1;
+}
+
+static
+void
+fxputc(FILE *f, int ch)
+{
+ /* drop any sign */
+ ch = ch&0xff;
+
+ /* on 7-bit terminals, strip high bit */
+ if (!is8bit()) ch &= 0x7f;
+
+ /*
+ * Assume anything that isn't a control character is printable.
+ * We can't count on locale stuff to tell us what's printable
+ * because we might be looking at someone who uses different
+ * locale settings or is on the other side of the planet. So,
+ * strip 0-31, 127, 128-159, and 255. Note that not stripping
+ * 128-159 is asking for trouble, as 155 (M-esc) is interpreted
+ * as esc-[ by most terminals. Hopefully this won't break anyone's
+ * charset.
+ *
+ * It would be nice if we could set the terminal to display in the
+ * right charset, but we have no way to know what it is. feh.
+ */
+
+ if (((ch&0x7f) >= 32 && (ch&0x7f) != 0x7f) || ch=='\t') {
+ putc(ch, f);
+ return;
+ }
+
+ if (ch=='\n') {
+ if (send_crs) putc('\r', f);
+ putc('\n', f);
+ return;
+ }
+
+ if (ch&0x80) {
+ putc('M', f);
+ putc('-', f);
+ ch &= 0x7f;
+ }
+
+ putc('^', f);
+ if (ch==0x7f) putc('?', f);
+ else putc(ch+'@', f);
+}
+
+void
+xputc(int ch)
+{
+ fxputc(stdout, ch);
+}
+
+static void fxputs(FILE *f, const char *buf) {
+ int i;
+ for (i=0; buf[i]; i++) fxputc(f, buf[i]);
+}
+
+int xprintf(const char *fmt, ...) {
+ char buf[1024];
+ va_list ap;
+
+ va_start(ap, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+
+ fxputs(stdout, buf);
+
+ return strlen(buf);
+}
+
+int eprintf(const char *fmt, ...) {
+ char buf[1024];
+ va_list ap;
+
+ va_start(ap, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+
+ fxputs(stderr, buf);
+
+ return strlen(buf);
+}
diff --git a/finger/finger.1 b/finger/finger.1
new file mode 100644
index 0000000..553af04
--- /dev/null
+++ b/finger/finger.1
@@ -0,0 +1,194 @@
+.\" Copyright (c) 1989, 1990 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.
+.\"
+.\" from: @(#)finger.1 6.14 (Berkeley) 7/27/91
+.\" $Id: finger.1,v 1.18 2000/07/30 23:56:57 dholland Exp $
+.\"
+.Dd August 15, 1999
+.Dt FINGER 1
+.Os "Linux NetKit (0.17)"
+.Sh NAME
+.Nm finger
+.Nd user information lookup program
+.Sh SYNOPSIS
+.Nm finger
+.Op Fl lmsp
+.Op Ar user ...
+.Op Ar user@host ...
+.Sh DESCRIPTION
+The
+.Nm finger
+displays information about the system users.
+.Pp
+Options are:
+.Bl -tag -width flag
+.It Fl s
+.Nm Finger
+displays the user's login name, real name, terminal name and write
+status (as a ``*'' after the terminal name if write permission is
+denied), idle time, login time, office location and office phone
+number.
+.Pp
+Login time is displayed as month, day, hours and minutes, unless
+more than six months ago, in which case the year is displayed rather
+than the hours and minutes.
+.Pp
+Unknown devices as well as nonexistent idle and login times are
+displayed as single asterisks.
+.Pp
+.It Fl 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 .plan ,
+.Dq Pa .project ,
+.Dq Pa .pgpkey
+and
+.Dq Pa .forward
+from the user's home directory.
+.Pp
+Phone numbers specified as eleven digits are printed as ``+N-NNN-NNN-NNNN''.
+Numbers specified as ten or seven digits are printed as the appropriate
+subset of that string.
+Numbers specified as five digits are printed as ``xN-NNNN''.
+Numbers specified as four digits are printed as ``xNNNN''.
+.Pp
+If write permission is denied to the device, the phrase ``(messages off)''
+is appended to the line containing the device name.
+One entry per user is displayed with the
+.Fl l
+option; if a user is logged on multiple times, terminal information
+is repeated once per login.
+.Pp
+Mail status is shown as ``No Mail.'' if there is no mail at all,
+``Mail last read DDD MMM ## HH:MM YYYY (TZ)'' if the person has looked
+at their mailbox since new mail arriving, or ``New mail received ...'',
+`` Unread since ...'' if they have new mail.
+.Pp
+.It Fl p
+Prevents
+the
+.Fl l
+option of
+.Nm finger
+from displaying the contents of the
+.Dq Pa .plan ,
+.Dq Pa .project
+and
+.Dq Pa .pgpkey
+files.
+.It Fl m
+Prevent matching of
+.Ar user
+names.
+.Ar User
+is usually a login name; however, matching will also be done on the
+users' real names, unless the
+.Fl m
+option is supplied.
+All name matching performed by
+.Nm finger
+is case insensitive.
+.El
+.Pp
+If no options are specified,
+.Nm finger
+defaults to the
+.Fl l
+style output if operands are provided, otherwise to the
+.Fl s
+style.
+Note that some fields may be missing, in either format, if information
+is not available for them.
+.Pp
+If no arguments are specified,
+.Nm finger
+will print an entry for each user currently logged into the system.
+.Pp
+.Nm Finger
+may be used to look up users on a remote machine.
+The format is to specify a
+.Ar user
+as
+.Dq Li user@host ,
+or
+.Dq Li @host ,
+where the default output
+format for the former is the
+.Fl l
+style, and the default output format for the latter is the
+.Fl s
+style.
+The
+.Fl l
+option is the only option that may be passed to a remote machine.
+.Pp
+If standard output is a socket,
+.Nm finger
+will emit a carriage return (^M) before every linefeed (^J). This is
+for processing remote finger requests when invoked by
+.Xr fingerd 8 .
+.Sh FILES
+.Bl -tag -width mmmmmmmmmmmmmmm
+.It Pa ~/.nofinger
+If finger finds this file in a user's home directory, it will, for
+finger requests originating outside the local host, firmly deny the
+existence of that user. For this to work, the finger program, as
+started by
+.Xr fingerd 8 ,
+must be able to see the
+.Pa .nofinger
+file. This generally means that the home directory containing the file
+must have the other-users-execute bit set (o+w). See
+.Xr chmod 1 .
+If you use this feature for privacy, please test it with ``finger
+@localhost'' before relying on it, just in case.
+.It ~/.plan
+.It ~/.project
+.It ~/.pgp
+These files are printed as part of a long-format request. The
+.Pa .project
+file is limited to one line; the
+.Pa .plan
+file may be arbitrarily long.
+.El
+.Sh SEE ALSO
+.Xr chfn 1 ,
+.Xr passwd 1 ,
+.Xr w 1 ,
+.Xr who 1
+.Sh HISTORY
+The
+.Nm finger
+command appeared in
+.Bx 3.0 .
diff --git a/finger/finger.c b/finger/finger.c
new file mode 100644
index 0000000..94c3ec0
--- /dev/null
+++ b/finger/finger.c
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 1989 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.
+ */
+
+/*
+ * Mail status reporting added 931007 by Luke Mewburn, <zak@rmit.edu.au>.
+ */
+
+char copyright[] =
+ "@(#) Copyright (c) 1989 The Regents of the University of California.\n"
+ "All rights reserved.\n";
+
+/*
+ * from: @(#)finger.c 5.22 (Berkeley) 6/29/90
+ */
+char finger_rcsid[] = \
+ "$Id: finger.c,v 1.15 1999/12/18 16:41:51 dholland 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. (This is not really true any
+ * more, btw.)
+ *
+ * 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 office location/phone number. 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/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include <time.h>
+#include <getopt.h>
+#include "finger.h"
+#include "../version.h"
+
+static void loginlist(void);
+static void userlist(int argc, char *argv[]);
+
+int lflag, pplan;
+static int sflag, mflag;
+static int enable_nofinger;
+
+time_t now;
+char tbuf[TBUFLEN];
+
+PERSON *phead, *ptail; /* the linked list of all people */
+int entries; /* number of people */
+
+
+int main(int argc, char *argv[]) {
+ int ch;
+ struct sockaddr_in sin;
+ socklen_t slen = sizeof(sin);
+
+ while ((ch = getopt(argc, argv, "lmps")) != EOF) {
+ switch(ch) {
+ case 'l':
+ lflag = 1; /* long format */
+ break;
+ case 'm':
+ mflag = 1; /* do exact match of names */
+ break;
+ case 'p':
+ pplan = 1; /* don't show .plan/.project */
+ break;
+ case 's':
+ sflag = 1; /* short format */
+ break;
+ case '?':
+ case 'h':
+ default:
+ eprintf("usage: finger [-lmps] [login ...]\n");
+ return 1;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (getsockname(STDOUT_FILENO, (struct sockaddr *)&sin, &slen)==0) {
+ /*
+ * stdout is a socket. must be a network finger request,
+ * so emit CRs with our LFs at the ends of lines.
+ */
+ set_crmode();
+
+ /*
+ * Also, enable .nofinger processing.
+ */
+ enable_nofinger = 1;
+ }
+
+ /*
+ * Also check stdin for nofinger processing, because of older
+ * fingerds that make stdout a pipe for CRLF handling.
+ */
+ if (getsockname(STDIN_FILENO, (struct sockaddr *)&sin, &slen)==0) {
+ enable_nofinger = 1;
+ }
+
+ time(&now);
+
+ setpwent();
+
+ 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) {
+ xprintf("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 != 0) {
+ if (lflag) lflag_print();
+ else sflag_print();
+ }
+ return 0;
+}
+
+/* Returns 1 if .nofinger is found and enable_nofinger is set. */
+static
+int
+check_nofinger(struct passwd *pw)
+{
+ if (enable_nofinger) {
+ char path[PATH_MAX];
+ struct stat tripe;
+ snprintf(path, sizeof(path), "%s/.nofinger", pw->pw_dir);
+ if (stat(path, &tripe)==0) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static void
+loginlist(void)
+{
+ PERSON *pn;
+ struct passwd *pw;
+ struct utmp *uptr;
+ char name[UT_NAMESIZE + 1];
+
+ name[UT_NAMESIZE] = '\0';
+
+ /*
+ * if (!freopen(_PATH_UTMP, "r", stdin)) {
+ * fprintf(stderr, "finger: can't read %s.\n", _PATH_UTMP);
+ * exit(2);
+ * }
+ */
+ setutent();
+ while ((uptr = getutent())!=NULL) {
+ if (!uptr->ut_name[0])
+ continue;
+#ifdef USER_PROCESS
+ if (uptr->ut_type != USER_PROCESS) continue;
+#endif
+ if ((pn = find_person(uptr->ut_name)) == NULL) {
+ memcpy(name, uptr->ut_name, UT_NAMESIZE);
+ if ((pw = getpwnam(name)) == NULL)
+ continue;
+ if (check_nofinger(pw))
+ continue;
+ pn = enter_person(pw);
+ }
+ enter_where(uptr, pn);
+ }
+ for (pn = phead; lflag && pn != NULL; pn = pn->next)
+ enter_lastlog(pn);
+ endutent();
+}
+
+
+static void do_local(int argc, char *argv[], int *used) {
+ int i;
+ struct passwd *pw;
+
+ /*
+ * 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 (i = 0; i < argc; i++)
+ if (used[i] >= 0 && (pw = getpwnam(argv[i]))) {
+ if (!check_nofinger(pw)) {
+ enter_person(pw);
+ used[i] = 1;
+ }
+ }
+ } else for (pw = getpwent(); pw; pw = getpwent())
+ for (i = 0; i < argc; i++)
+ if (used[i] >= 0 &&
+ (!strcasecmp(pw->pw_name, argv[i]) ||
+ match(pw, argv[i]))) {
+ if (!check_nofinger(pw)) {
+ enter_person(pw);
+ used[i] = 1;
+ }
+ }
+
+ /* list errors */
+ for (i = 0; i < argc; i++)
+ if (!used[i])
+ (void)eprintf("finger: %s: no such user.\n", argv[i]);
+
+}
+
+static void
+userlist(int argc, char *argv[])
+{
+ int i;
+ PERSON *pn;
+ PERSON *nethead, **nettail;
+ struct utmp *uptr;
+ int dolocal, *used;
+
+ used = calloc(argc, sizeof(int));
+ if (!used) {
+ eprintf("finger: out of space.\n");
+ exit(1);
+ }
+
+ /* pull out all network requests */
+ for (i = 0, dolocal = 0, nettail = &nethead; i < argc; i++) {
+ if (!strchr(argv[i], '@')) {
+ dolocal = 1;
+ continue;
+ }
+ pn = palloc();
+ *nettail = pn;
+ nettail = &pn->next;
+ pn->name = argv[i];
+ used[i] = -1;
+ }
+ *nettail = NULL;
+
+ if (dolocal) do_local(argc, argv, used);
+
+ /* handle network requests */
+ for (pn = nethead; pn; pn = pn->next) {
+ netfinger(pn->name);
+ if (pn->next || entries)
+ xputc('\n');
+ }
+
+ if (entries == 0)
+ return;
+
+ /*
+ * Scan thru the list of users currently logged in, saving
+ * appropriate data whenever a match occurs.
+ */
+ /*
+ * if (!freopen(_PATH_UTMP, "r", stdin)) {
+ * (void)fprintf( stderr, "finger: can't read %s.\n", _PATH_UTMP);
+ * exit(1);
+ * }
+ */
+ setutent();
+ while ((uptr = getutent())!=NULL) {
+ if (!uptr->ut_name[0])
+ continue;
+#ifdef USER_PROCESS
+ if (uptr->ut_type != USER_PROCESS) continue;
+#endif
+ if ((pn = find_person(uptr->ut_name)) == NULL) {
+ continue;
+ }
+ enter_where(uptr, pn);
+ }
+ for (pn = phead; pn != NULL; pn = pn->next) {
+ enter_lastlog(pn);
+ }
+ endutent();
+}
diff --git a/finger/finger.h b/finger/finger.h
new file mode 100644
index 0000000..bad5244
--- /dev/null
+++ b/finger/finger.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 1989 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.
+ *
+ * from: @(#)finger.h 5.5 (Berkeley) 6/1/90
+ * $Id: finger.h,v 1.7 1999/09/14 10:51:11 dholland Exp $
+ */
+
+#include <pwd.h>
+#include <utmp.h>
+
+/*
+ * All unique persons are linked in a list headed by "head" and linkd
+ * by the "next" field, as well as kept in a hash table.
+ */
+
+typedef struct person {
+ struct person *next; /* link to next person */
+ struct person *hlink; /* link to next person in hash bucket */
+ 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 he is or has been */
+} PERSON;
+
+enum status { LASTLOG, LOGGEDIN };
+
+typedef struct where {
+ struct where *next; /* next place he is or has been */
+ enum status info; /* type/status of request */
+ short writable; /* tty is writable */
+ time_t loginat; /* time of (last) login */
+ time_t idletime; /* how long idle (if logged in) */
+ char tty[UT_LINESIZE+1]; /* null terminated tty line */
+ char host[UT_HOSTSIZE+1]; /* null terminated remote host name */
+} WHERE;
+
+extern PERSON *phead, *ptail; /* the linked list of all people */
+
+extern int entries; /* number of people */
+
+#define TBUFLEN 1024
+extern char tbuf[TBUFLEN]; /* temp buffer for anybody */
+
+extern time_t now;
+extern int lflag, pplan;
+
+PERSON *enter_person(struct passwd *);
+PERSON *find_person(const char *name);
+PERSON *palloc(void);
+WHERE *walloc(PERSON *);
+void lflag_print(void);
+void sflag_print(void);
+void enter_where(struct utmp *ut, PERSON *pn);
+void enter_lastlog(PERSON *pn);
+int match(struct passwd *pw, const char *user);
+void netfinger(const char *name);
+const char *prphone(const char *num);
+
+#ifndef DAYSPERNYEAR
+#define DAYSPERNYEAR 365
+#endif
+
+#ifndef SECSPERDAY
+#define SECSPERDAY (60 * 60 * 24)
+#endif
+
+/* turn on crnl translation on output */
+void set_crmode(void);
+
+/* Display, masking control characters and possibly doing crnl translation */
+void xputc(int ch);
+void xputs(const char *buf);
+int xprintf(const char *fmt, ...);
+
+/* Send to stderr, possibly doing crnl translation */
+int eprintf(const char *fmt, ...);
+
+/* terminal inquiries */
+int is8bit(void);
+int getscreenwidth(void);
diff --git a/finger/lprint.c b/finger/lprint.c
new file mode 100644
index 0000000..8b9069c
--- /dev/null
+++ b/finger/lprint.c
@@ -0,0 +1,361 @@
+/*
+ * Copyright (c) 1989 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.
+ */
+
+/*
+ * from: @(#)lprint.c 5.13 (Berkeley) 10/31/90
+ */
+char lprint_rcsid[] =
+ "$Id: lprint.c,v 1.11 1999/09/14 10:51:11 dholland Exp $";
+
+#include <stdio.h>
+#include <ctype.h>
+#include <paths.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "finger.h"
+
+static void lprint(PERSON *pn);
+static int demi_print(char *str, int oddfield);
+static int show_text(const char *directory, const char *file_name,
+ const char *header);
+
+#define LINE_LEN 80
+#define TAB_LEN 8 /* 8 spaces between tabs */
+#define _PATH_FORWARD ".forward"
+#define _PATH_PLAN ".plan"
+#define _PATH_PROJECT ".project"
+#define _PATH_PGPKEY ".pgpkey"
+
+void
+lflag_print(void)
+{
+ register PERSON *pn = phead;
+ while (1) {
+ lprint(pn);
+ if (!pplan) {
+ show_text(pn->dir, _PATH_PGPKEY, "PGP key:\n");
+ show_text(pn->dir, _PATH_PROJECT, "Project:\n");
+ if (!show_text(pn->dir, _PATH_PLAN, "Plan:\n")) {
+ xprintf("No Plan.\n");
+ }
+ }
+ if (!(pn = pn->next))
+ break;
+ xputc('\n');
+ }
+}
+
+static void
+lprint(PERSON *pn)
+{
+ struct tm *delta, *tp;
+ WHERE *w;
+ int cpr, len, maxlen;
+ int oddfield;
+ char timebuf[128];
+
+ /*
+ * long format --
+ * login name
+ * real name
+ * home directory
+ * shell
+ * office, office phone, home phone if available
+ */
+ xprintf("Login: %-15s\t\t\tName: %s\nDirectory: %-25s",
+ pn->name, pn->realname, pn->dir);
+ xprintf("\tShell: %-s\n", *pn->shell ? pn->shell : _PATH_BSHELL);
+
+ /*
+ * try and print office, office phone, and home phone on one line;
+ * if that fails, do line filling so it looks nice.
+ */
+#define OFFICE_TAG "Office"
+#define OFFICE_PHONE_TAG "Office Phone"
+ oddfield = 0;
+ if (pn->office && pn->officephone &&
+ strlen(pn->office) + strlen(pn->officephone) +
+ sizeof(OFFICE_TAG) + 2 <= 5 * TAB_LEN)
+ {
+ snprintf(tbuf, TBUFLEN, "%s: %s, %s", OFFICE_TAG, pn->office,
+ prphone(pn->officephone));
+ oddfield = demi_print(tbuf, oddfield);
+ }
+ else {
+ if (pn->office) {
+ snprintf(tbuf, TBUFLEN, "%s: %s", OFFICE_TAG,
+ pn->office);
+ oddfield = demi_print(tbuf, oddfield);
+ }
+ if (pn->officephone) {
+ snprintf(tbuf, TBUFLEN, "%s: %s", OFFICE_PHONE_TAG,
+ prphone(pn->officephone));
+ oddfield = demi_print(tbuf, oddfield);
+ }
+ }
+ if (pn->homephone) {
+ snprintf(tbuf, TBUFLEN, "%s: %s", "Home Phone",
+ prphone(pn->homephone));
+ oddfield = demi_print(tbuf, oddfield);
+ }
+ if (oddfield) xputc('\n');
+
+ /*
+ * long format con't: * if logged in
+ * terminal
+ * idle time
+ * if messages allowed
+ * where logged in from
+ * if not logged in
+ * when last logged in
+ */
+ /* find out longest device name for this user for formatting */
+ for (w = pn->whead, maxlen = -1; w != NULL; w = w->next)
+ if ((len = strlen(w->tty)) > maxlen)
+ maxlen = len;
+ /* find rest of entries for user */
+ for (w = pn->whead; w != NULL; w = w->next) {
+ switch (w->info) {
+ case LOGGEDIN:
+ tp = localtime(&w->loginat);
+ /*
+ * t = asctime(tp);
+ * tzset();
+ * tzn = tzname[daylight];
+ * cpr = printf("On since %.16s (%s) on %s",
+ * t, tzn, w->tty);
+ */
+ strftime(timebuf, sizeof(timebuf),
+ "%a %b %e %R (%Z)", tp);
+ cpr = xprintf("On since %s on %s", timebuf, w->tty);
+ if (*w->host) {
+ cpr += xprintf(" from %s", w->host);
+ }
+ /*
+ * idle time is tough; if have one, print a comma,
+ * then spaces to pad out the device name, then the
+ * idle time. Follow with a comma if a remote login.
+ */
+ delta = gmtime(&w->idletime);
+ if (delta->tm_yday || delta->tm_hour
+ || delta->tm_min || delta->tm_sec) {
+ if (*w->host)
+ xputc('\n');
+ cpr += xprintf("%-*s",
+ (int) (maxlen - strlen(w->tty) + 3), "");
+ if (delta->tm_yday > 0) {
+ cpr += xprintf("%d day%s ",
+ delta->tm_yday,
+ delta->tm_yday == 1 ? "" : "s");
+ }
+ if (delta->tm_hour > 0) {
+ cpr += xprintf("%d hour%s ",
+ delta->tm_hour,
+ delta->tm_hour == 1 ? "" : "s");
+ }
+ if ((delta->tm_min > 0) && !delta->tm_yday) {
+ cpr += xprintf("%d minute%s ",
+ delta->tm_min,
+ delta->tm_min == 1 ? "" : "s");
+ }
+ if ((delta->tm_sec > 0) && !delta->tm_yday
+ && !delta->tm_hour) {
+ cpr += xprintf("%d second%s ",
+ delta->tm_sec,
+ delta->tm_sec == 1 ? "" : "s");
+ }
+ cpr += xprintf("idle");
+ }
+ if (!w->writable) {
+ if (delta->tm_yday || delta->tm_hour
+ || delta->tm_min || delta->tm_sec)
+ cpr += xprintf("\n ");
+ cpr += xprintf(" (messages off)");
+ }
+ break;
+ case LASTLOG:
+ if (w->loginat == 0) {
+ (void)xprintf("Never logged in.");
+ break;
+ }
+ tp = localtime(&w->loginat);
+ /*
+ * t = asctime(tp);
+ * tzset();
+ * tzn = tzname[daylight];
+ * if(now - w->loginat > SECSPERDAY * DAYSPERNYEAR / 2)
+ * cpr =
+ * printf("Last login %.16s %.4s (%s) on %s",
+ * t, t + 20, tzn, w->tty);
+ * else
+ * cpr = printf("Last login %.16s (%s) on %s",
+ * t, tzn, w->tty);
+ */
+ if (now - w->loginat < SECSPERDAY * DAYSPERNYEAR / 2) {
+ strftime(timebuf, sizeof(timebuf),
+ "%a %b %e %R (%Z)", tp);
+ }
+ else {
+ strftime(timebuf, sizeof(timebuf),
+ "%a %b %e %R %Y (%Z)", tp);
+ }
+ cpr = xprintf("Last login %s on %s", timebuf, w->tty);
+ if (*w->host) {
+ cpr += xprintf(" from %s", w->host);
+ }
+ break;
+ }
+ xputc('\n');
+ }
+
+ /* If the user forwards mail elsewhere, tell us about it */
+ show_text(pn->dir, _PATH_FORWARD, "Mail forwarded to ");
+
+ /* Print the standard mailbox information. */
+ if (pn->mailrecv == -1)
+ xprintf("No mail.\n");
+ else if (pn->mailrecv > pn->mailread) {
+ tp = localtime(&pn->mailrecv);
+ /*
+ * t = asctime(tp);
+ * tzset();
+ * tzn = tzname[daylight];
+ * printf("New mail received %.16s %.4s (%s)\n", t,
+ * t + 20, tzn);
+ */
+ strftime(timebuf, sizeof(timebuf),
+ "%a %b %e %R %Y (%Z)", tp);
+ xprintf("New mail received %s\n", timebuf);
+ tp = localtime(&pn->mailread);
+ /*
+ * t = asctime(tp);
+ * tzset();
+ * tzn = tzname[daylight];
+ * printf(" Unread since %.16s %.4s (%s)\n", t,
+ * t + 20, tzn);
+ */
+ strftime(timebuf, sizeof(timebuf),
+ "%a %b %e %R %Y (%Z)", tp);
+ xprintf(" Unread since %s\n", timebuf);
+ } else {
+ tp = localtime(&pn->mailread);
+ /*
+ * t = asctime(tp);
+ * tzset();
+ * tzn = tzname[daylight];
+ * printf("Mail last read %.16s %.4s (%s)\n", t,
+ * t + 20, tzn);
+ */
+ strftime(timebuf, sizeof(timebuf),
+ "%a %b %e %R %Y (%Z)", tp);
+ xprintf("Mail last read %s\n", timebuf);
+ }
+}
+
+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)) {
+ xputc('\t');
+ lenlast += TAB_LEN;
+ }
+ (void)xprintf("\t%s\n", str); /* force one tab */
+ } else {
+ (void)xprintf("\n%s", str); /* go to next line */
+ oddfield = !oddfield; /* this'll be undone below */
+ }
+ } else
+ (void)xprintf("%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)
+{
+ int ch, lastc = 0, fd;
+ FILE *fp;
+ struct stat sbuf1, sbuf2;
+
+ snprintf(tbuf, TBUFLEN, "%s/%s", directory, file_name);
+
+ if (lstat(tbuf, &sbuf1) || !S_ISREG(sbuf1.st_mode)) return 0;
+ fd = open(tbuf, O_RDONLY);
+ if (fd<0) return 0;
+ if (fstat(fd, &sbuf2)) { close(fd); return 0; }
+ /* if we didn't get the same file both times, bail */
+ if (sbuf1.st_dev!=sbuf2.st_dev || sbuf1.st_ino!=sbuf2.st_ino) {
+ close(fd);
+ return 0;
+ }
+ fp = fdopen(fd, "r");
+ if (fp == NULL) { close(fd); return 0; }
+
+ xprintf("%s", header);
+ while ((ch = getc(fp)) != EOF) {
+ xputc(ch);
+ lastc = ch;
+ }
+ if (lastc != '\n') xputc('\n');
+
+ fclose(fp);
+ return 1;
+}
+
diff --git a/finger/net.c b/finger/net.c
new file mode 100644
index 0000000..d6169fa
--- /dev/null
+++ b/finger/net.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+/*static char sccsid[] = "from: @(#)net.c 5.5 (Berkeley) 6/1/90";*/
+char net_rcsid[] = "$Id: net.c,v 1.9 1999/09/14 10:51:11 dholland Exp $";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include "finger.h"
+
+void netfinger(const char *name) {
+ register FILE *fp;
+ struct in_addr defaddr;
+ register int c, sawret, ateol;
+ struct hostent *hp, def;
+ struct servent *sp;
+ struct sockaddr_in sn;
+ int s;
+ char *alist[1], *host;
+
+ host = strrchr(name, '@');
+ if (!host) return;
+ *host++ = '\0';
+
+ memset(&sn, 0, sizeof(sn));
+
+ sp = getservbyname("finger", "tcp");
+ if (!sp) {
+ eprintf("finger: tcp/finger: unknown service\n");
+ return;
+ }
+ sn.sin_port = sp->s_port;
+
+ hp = gethostbyname(host);
+ if (!hp) {
+ if (!inet_aton(host, &defaddr)) {
+ eprintf("finger: unknown host: %s\n", host);
+ return;
+ }
+ def.h_name = host;
+ def.h_addr_list = alist;
+ def.h_addr = (char *)&defaddr;
+ def.h_length = sizeof(struct in_addr);
+ def.h_addrtype = AF_INET;
+ def.h_aliases = 0;
+ hp = &def;
+ }
+ sn.sin_family = hp->h_addrtype;
+ if (hp->h_length > (int)sizeof(sn.sin_addr)) {
+ hp->h_length = sizeof(sn.sin_addr);
+ }
+ memcpy(&sn.sin_addr, hp->h_addr, hp->h_length);
+
+ if ((s = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) {
+ eprintf("finger: socket: %s\n", strerror(errno));
+ return;
+ }
+
+ /* print hostname before connecting, in case it takes a while */
+ xprintf("[%s]\n", hp->h_name);
+ if (connect(s, (struct sockaddr *)&sn, sizeof(sn)) < 0) {
+ eprintf("finger: connect: %s\n", strerror(errno));
+ close(s);
+ return;
+ }
+
+ /* -l flag for remote fingerd */
+ if (lflag) write(s, "/W ", 3);
+
+ /* send the name followed by <CR><LF> */
+ write(s, name, strlen(name));
+ 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> or a <CR> with the high bit set, treat it as
+ * a newline; if followed by a newline character, only output one
+ * newline.
+ *
+ * Text is sent to xputc() for printability analysis.
+ */
+ fp = fdopen(s, "r");
+ if (!fp) {
+ eprintf("finger: fdopen: %s\n", strerror(errno));
+ close(s);
+ return;
+ }
+
+ sawret = 0;
+ ateol = 1;
+ while ((c = getc(fp)) != EOF) {
+ c &= 0xff;
+ if (c == ('\r'|0x80) || c == ('\n'|0x80)) c &= 0x7f;
+ if (c == '\r') {
+ sawret = ateol = 1;
+ xputc('\n');
+ }
+ else if (sawret && c == '\n') {
+ sawret = 0;
+ /* don't print */
+ }
+ else {
+ if (c == '\n') ateol = 1;
+ sawret = 0;
+ xputc(c);
+ }
+ }
+ if (!ateol) xputc('\n');
+ fclose(fp);
+}
diff --git a/finger/sprint.c b/finger/sprint.c
new file mode 100644
index 0000000..cc86080
--- /dev/null
+++ b/finger/sprint.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+/*static char sccsid[] = "from: @(#)sprint.c 5.8 (Berkeley) 12/4/90";*/
+char sprint_rcsid[] = "$Id: sprint.c,v 1.10 1999/12/12 18:59:33 dholland Exp $";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "finger.h"
+
+static void stimeprint(WHERE *w);
+static int psort(const void *a, const void *b);
+static PERSON **sort(void);
+
+void sflag_print(void) {
+ register PERSON *pn;
+ register WHERE *w;
+ register char *p;
+ PERSON **list;
+ int maxlname, maxrname, space, cnt;
+
+ list = sort();
+ /*
+ * short format --
+ * login name
+ * real name
+ * terminal name
+ * 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 moths,
+ * show year instead of time.
+ * office location
+ * office phone
+ */
+
+ maxlname = maxrname = sizeof("Login ");
+ for (cnt = 0; cnt < entries; ++cnt) {
+ int l;
+ pn = list[cnt];
+ l = pn->name ? strlen(pn->name) : 1;
+ if (l > maxlname) maxlname = l;
+ l = pn->realname ? strlen(pn->realname) : 1;
+ if (l > maxrname) maxrname = l;
+ }
+ /* prevent screen overflow */
+ space = getscreenwidth() - 50;
+ if (maxlname + maxrname > space) maxrname = space - maxlname;
+
+ /* add a space if there's room */
+ if (maxlname + maxrname < space-2) { maxlname++; maxrname++; }
+
+ (void)xprintf("%-*s %-*s %s\n", maxlname, "Login", maxrname,
+ "Name", " Tty Idle Login Time Office Office Phone");
+ for (cnt = 0; cnt < entries; ++cnt) {
+ pn = list[cnt];
+ for (w = pn->whead; w != NULL; w = w->next) {
+ (void)xprintf("%-*.*s %-*.*s ", maxlname, maxlname,
+ pn->name, maxrname, maxrname,
+ pn->realname ? pn->realname : "");
+ if (!w->loginat) {
+ (void)xprintf(" * * No logins ");
+ goto office;
+ }
+ (void)xputc(w->info == LOGGEDIN && !w->writable ?
+ '*' : ' ');
+ if (*w->tty)
+ (void)xprintf("%-7.7s ", w->tty);
+ else
+ (void)xprintf(" ");
+ if (w->info == LOGGEDIN) {
+ stimeprint(w);
+ (void)xprintf(" ");
+ } else
+ (void)xprintf(" * ");
+ p = ctime(&w->loginat);
+ (void)xprintf("%.6s", p + 4);
+ if (now - w->loginat >= SECSPERDAY * DAYSPERNYEAR / 2)
+ (void)xprintf(" %.4s", p + 20);
+ else
+ (void)xprintf(" %.5s", p + 11);
+office:
+ if (w->host[0] != '\0') {
+ xprintf(" (%s)", w->host);
+ } else {
+ if (pn->office)
+ (void)xprintf(" %-10.10s", pn->office);
+ else if (pn->officephone)
+ (void)xprintf(" %-10.10s", " ");
+ if (pn->officephone)
+ (void)xprintf(" %-.14s",
+ prphone(pn->officephone));
+ }
+ xputc('\n');
+ }
+ }
+}
+
+static PERSON **sort(void) {
+ register PERSON *pn, **lp;
+ PERSON **list;
+
+ if (!(list = (PERSON **)malloc((u_int)(entries * sizeof(PERSON *))))) {
+ eprintf("finger: Out of space.\n");
+ exit(1);
+ }
+ for (lp = list, pn = phead; pn != NULL; pn = pn->next)
+ *lp++ = pn;
+ (void)qsort(list, entries, sizeof(PERSON *), psort);
+ return(list);
+}
+
+static int psort(const void *a, const void *b) {
+ const PERSON *const *p = (const PERSON *const *)a;
+ const PERSON *const *t = (const PERSON *const *)b;
+ return(strcmp((*p)->name, (*t)->name));
+}
+
+static void stimeprint(WHERE *w) {
+ register struct tm *delta;
+
+ delta = gmtime(&w->idletime);
+ if (!delta->tm_yday)
+ if (!delta->tm_hour)
+ if (!delta->tm_min)
+ (void)xprintf(" ");
+ else
+ (void)xprintf("%5d", delta->tm_min);
+ else
+ (void)xprintf("%2d:%02d",
+ delta->tm_hour, delta->tm_min);
+ else
+ (void)xprintf("%4dd", delta->tm_yday);
+}
diff --git a/finger/util.c b/finger/util.c
new file mode 100644
index 0000000..d0498a7
--- /dev/null
+++ b/finger/util.c
@@ -0,0 +1,418 @@
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+/*static char sccsid[] = "from: @(#)util.c 5.14 (Berkeley) 1/17/91";*/
+char util_rcsid[] = "$Id: util.c,v 1.18 1999/09/28 22:53:58 netbug Exp $";
+#endif /* not lint */
+
+#include <sys/types.h>
+/* #include <sys/param.h> <--- unused? */
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <paths.h>
+#include <errno.h>
+#include <lastlog.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "finger.h"
+
+#define HBITS 8 /* number of bits in hash code */
+#define HSIZE (1 << 8) /* hash table size */
+#define HMASK (HSIZE - 1) /* hash code mask */
+static PERSON *htab[HSIZE]; /* the buckets */
+
+static int hash(const char *name);
+
+static void find_idle_and_ttywrite(register WHERE *w) {
+ struct stat sb;
+
+ /* No device for X console. Utmp entry by XDM login (":0"). */
+ if (w->tty[0] == ':') {
+ w->idletime = 0; /* would be nice to have it emit ??? */
+ w->writable = 0;
+ return;
+ }
+ snprintf(tbuf, TBUFLEN, "%s/%s", _PATH_DEV, w->tty);
+ if (stat(tbuf, &sb) < 0) {
+ eprintf("finger: %s: %s\n", tbuf, strerror(errno));
+ 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;
+ struct stat sb;
+ char *bp;
+ char *rname;
+ int i, j, ct;
+ char *fields[4];
+ int nfields;
+
+ pn->uid = pw->pw_uid;
+ pn->name = strdup(pw->pw_name);
+ pn->dir = strdup(pw->pw_dir);
+ pn->shell = strdup(pw->pw_shell);
+
+ /* make a private copy of gecos to munge */
+ strncpy(tbuf, pw->pw_gecos, TBUFLEN);
+ tbuf[TBUFLEN-1] = 0; /* ensure null termination */
+ bp = tbuf;
+
+ /* why do we skip asterisks!?!? */
+ if (*bp == '*') ++bp;
+
+ /*
+ * fields[0] -> real name
+ * fields[1] -> office
+ * fields[2] -> officephone
+ * fields[3] -> homephone
+ */
+ nfields = 0;
+ for (p = strtok(bp, ","); p; p = strtok(NULL, ",")) {
+ if (*p==0) p = NULL; // skip empties
+ if (nfields < 4) fields[nfields++] = p;
+ }
+ while (nfields<4) fields[nfields++] = NULL;
+
+ if (fields[0]) {
+ /*
+ * Ampersands in gecos get replaced by the capitalized login
+ * name. This is a major nuisance and whoever thought it up
+ * should be shot.
+ */
+ p = fields[0];
+
+ /* First, count the number of ampersands. */
+ for (ct=i=0; p[i]; i++) if (p[i]=='&') ct++;
+
+ /* This tells us how much space we need to copy the name. */
+ rname = malloc(strlen(p) + ct*strlen(pw->pw_name) + 1);
+ if (!rname) {
+ eprintf("finger: Out of space.\n");
+ exit(1);
+ }
+
+ /* Now, do it */
+ for (i=j=0; p[i]; i++) {
+ if (p[i]=='&') {
+ strcpy(rname + j, pw->pw_name);
+ if (islower(rname[j])) {
+ rname[j] = toupper(rname[j]);
+ }
+ j += strlen(pw->pw_name);
+ }
+ else {
+ rname[j++] = p[i];
+ }
+ }
+ rname[j] = 0;
+
+ pn->realname = rname;
+ }
+
+ pn->office = fields[1] ? strdup(fields[1]) : NULL;
+ pn->officephone = fields[2] ? strdup(fields[2]) : NULL;
+ pn->homephone = fields[3] ? strdup(fields[3]) : NULL;
+
+ pn->mailrecv = -1; /* -1 == not_valid */
+ pn->mailread = -1; /* -1 == not_valid */
+
+ snprintf(tbuf, TBUFLEN, "%s/%s", _PATH_MAILDIR, pw->pw_name);
+ if (stat(tbuf, &sb) < 0) {
+ if (errno != ENOENT) {
+ eprintf("finger: %s: %s\n", tbuf, strerror(errno));
+ return;
+ }
+ }
+ else if (sb.st_size != 0) {
+ pn->mailrecv = sb.st_mtime;
+ pn->mailread = sb.st_atime;
+ }
+}
+
+int
+match(struct passwd *pw, const char *user)
+{
+ char *p;
+ int i, j, ct, rv=0;
+ char *rname;
+
+ strncpy(tbuf, pw->pw_gecos, TBUFLEN);
+ tbuf[TBUFLEN-1] = 0; /* guarantee null termination */
+ p = tbuf;
+
+ /* why do we skip asterisks!?!? */
+ if (*p == '*') ++p;
+
+ /* truncate the uninteresting stuff off the end of gecos */
+ p = strtok(p, ",");
+ if (!p) return 0;
+
+ /*
+ * Ampersands get replaced by the login name.
+ */
+
+ /* First, count the number of ampersands. */
+ for (ct=i=0; p[i]; i++) if (p[i]=='&') ct++;
+
+ /* This tells us how much space we need to copy the name. */
+ rname = malloc(strlen(p) + ct*strlen(pw->pw_name) + 1);
+ if (!rname) {
+ eprintf("finger: Out of space.\n");
+ exit(1);
+ }
+
+ /* Now, do it */
+ for (i=j=0; p[i]; i++) {
+ if (p[i]=='&') {
+ strcpy(rname + j, pw->pw_name);
+ if (islower(rname[j])) rname[j] = toupper(rname[j]);
+ j += strlen(pw->pw_name);
+ }
+ else {
+ rname[j++] = p[i];
+ }
+ }
+ rname[j] = 0;
+
+ for (p = strtok(rname, "\t "); p && !rv; p = strtok(NULL, "\t ")) {
+ if (!strcasecmp(p, user))
+ rv = 1;
+ }
+ free(rname);
+
+ return rv;
+}
+
+static int get_lastlog(int fd, uid_t uid, struct lastlog *ll) {
+ loff_t pos;
+ if (fd == -1) return -1;
+ pos = (long)uid * sizeof(*ll);
+ if (lseek(fd, pos, L_SET) != pos) return -1;
+ if (read(fd, ll, sizeof(*ll)) != sizeof(*ll)) return -1;
+ return 0;
+}
+
+void enter_lastlog(PERSON *pn) {
+ static int opened = 0, fd = -1;
+
+ WHERE *w;
+ struct lastlog ll;
+ int doit = 0;
+
+ /* some systems may not maintain lastlog, don't report errors. */
+ if (!opened) {
+ fd = open(_PATH_LASTLOG, O_RDONLY, 0);
+ opened = 1;
+ }
+ if (get_lastlog(fd, pn->uid, &ll)) {
+ /* as if never logged in */
+ ll.ll_line[0] = ll.ll_host[0] = '\0';
+ ll.ll_time = 0;
+ }
+
+ if ((w = pn->whead) == NULL)
+ doit = 1;
+ else if (ll.ll_time != 0) {
+ /* if last login is earlier than some current login */
+ for (; !doit && w != NULL; w = w->next)
+ if (w->info == LOGGEDIN && w->loginat < ll.ll_time)
+ doit = 1;
+ /*
+ * and if it's not any of the current logins
+ * can't use time comparison because there may be a small
+ * discrepency since login calls time() twice
+ */
+ for (w = pn->whead; doit && w != NULL; w = w->next)
+ if (w->info == LOGGEDIN &&
+ strncmp(w->tty, ll.ll_line, UT_LINESIZE) == 0)
+ doit = 0;
+ }
+ if (doit) {
+ w = walloc(pn);
+ w->info = LASTLOG;
+ bcopy(ll.ll_line, w->tty, UT_LINESIZE);
+ w->tty[UT_LINESIZE] = 0;
+ bcopy(ll.ll_host, w->host, UT_HOSTSIZE);
+ w->host[UT_HOSTSIZE] = 0;
+ w->loginat = ll.ll_time;
+ }
+}
+
+void enter_where(struct utmp *ut, PERSON *pn) {
+ register WHERE *w = walloc(pn);
+
+ w->info = LOGGEDIN;
+ bcopy(ut->ut_line, w->tty, UT_LINESIZE);
+ w->tty[UT_LINESIZE] = 0;
+ bcopy(ut->ut_host, w->host, UT_HOSTSIZE);
+ w->host[UT_HOSTSIZE] = 0;
+ w->loginat = ut->ut_time;
+ find_idle_and_ttywrite(w);
+}
+
+PERSON * enter_person(struct passwd *pw) {
+ register PERSON *pn, **pp;
+
+ for (pp = htab + hash(pw->pw_name);
+ *pp != NULL && strcmp((*pp)->name, pw->pw_name) != 0;
+ pp = &(*pp)->hlink)
+ ;
+ if ((pn = *pp) == NULL) {
+ pn = palloc();
+ entries++;
+ if (phead == NULL)
+ phead = ptail = pn;
+ else {
+ ptail->next = pn;
+ ptail = pn;
+ }
+ pn->next = NULL;
+ pn->hlink = NULL;
+ *pp = pn;
+ userinfo(pn, pw);
+ pn->whead = NULL;
+ }
+ return(pn);
+}
+
+PERSON *find_person(const char *name) {
+ register PERSON *pn;
+
+ /* name may be only UT_NAMESIZE long and not terminated */
+ for (pn = htab[hash(name)];
+ pn != NULL && strncmp(pn->name, name, UT_NAMESIZE) != 0;
+ pn = pn->hlink)
+ ;
+ return(pn);
+}
+
+static int hash(const char *name) {
+ register int h, i;
+
+ h = 0;
+ /* name may be only UT_NAMESIZE long and not terminated */
+ for (i = UT_NAMESIZE; --i >= 0 && *name;)
+ h = ((h << 2 | h >> (HBITS - 2)) ^ *name++) & HMASK;
+ return(h);
+}
+
+PERSON *palloc(void) {
+ PERSON *p;
+
+ if ((p = (PERSON *)malloc((u_int) sizeof(PERSON))) == NULL) {
+ eprintf("finger: Out of space.\n");
+ exit(1);
+ }
+ return(p);
+}
+
+WHERE *
+walloc(PERSON *pn)
+{
+ register WHERE *w;
+
+ if ((w = (WHERE *)malloc((u_int) sizeof(WHERE))) == NULL) {
+ eprintf("finger: Out of space.\n");
+ exit(1);
+ }
+ if (pn->whead == NULL)
+ pn->whead = pn->wtail = w;
+ else {
+ pn->wtail->next = w;
+ pn->wtail = w;
+ }
+ w->next = NULL;
+ return(w);
+}
+
+const char *
+prphone(const char *num)
+{
+ char *p;
+ const char *q;
+ int len;
+ static char pbuf[15];
+
+ /* don't touch anything if the user has their own formatting */
+ for (q = num; *q; ++q)
+ if (!isdigit(*q))
+ return(num);
+ len = q - 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);
+}
diff --git a/fingerd/.cvsignore b/fingerd/.cvsignore
new file mode 100644
index 0000000..c65da7b
--- /dev/null
+++ b/fingerd/.cvsignore
@@ -0,0 +1 @@
+fingerd
diff --git a/fingerd/Makefile b/fingerd/Makefile
new file mode 100644
index 0000000..6f956bc
--- /dev/null
+++ b/fingerd/Makefile
@@ -0,0 +1,18 @@
+all: fingerd
+
+include ../MCONFIG
+include ../MRULES
+
+fingerd: fingerd.o
+ $(CC) $(LDFLAGS) $^ $(LIBS) -o $@
+
+fingerd.o: pathnames.h ../version.h
+
+install: fingerd
+ install -s -m$(DAEMONMODE) fingerd $(INSTALLROOT)$(SBINDIR)/in.fingerd
+ install -m$(MANMODE) fingerd.8 $(INSTALLROOT)$(MANDIR)/man8/in.fingerd.8
+ ln -sf in.fingerd.8 $(INSTALLROOT)$(MANDIR)/man8/fingerd.8
+
+clean:
+ rm -f *.o fingerd
+
diff --git a/fingerd/fingerd.8 b/fingerd/fingerd.8
new file mode 100644
index 0000000..9daa95b
--- /dev/null
+++ b/fingerd/fingerd.8
@@ -0,0 +1,157 @@
+.\" Copyright (c) 1980, 1991 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.
+.\"
+.\" from: @(#)fingerd.8 6.4 (Berkeley) 3/16/91
+.\" $Id: fingerd.8,v 1.18 2000/07/30 23:56:57 dholland Exp $
+.\"
+.Dd August 29, 1996
+.Dt FINGERD 8
+.Os "Linux NetKit (0.17)"
+.Sh NAME
+.Nm fingerd
+.Nd remote user information server
+.Sh SYNOPSIS
+.Nm fingerd
+.Op Fl wulf
+.Op Fl pL Ar path
+.Op Fl t Ar timeout
+.Sh DESCRIPTION
+.Nm Fingerd
+is a simple daemon based on
+.%T RFC1196
+that provides an interface to the
+.Dq finger
+program at most network sites.
+The program is supposed to return a friendly,
+human-oriented status report on either the system at the moment
+or a particular person in depth.
+.Pp
+If the
+.Fl w
+option is given, remote users will get an additional
+.Dq Welcome to ...
+banner
+which also shows some informations (e.g. uptime, operating system name and
+release) about the system the
+.Nm fingerd
+is running on. Some sites may consider this a security risk as it
+gives out information that may be useful to crackers.
+.Pp
+If the
+.Fl u
+option is given, requests of the form
+.Dq finger @host
+are rejected.
+.Pp
+If the
+.Fl l
+option is given, information about requests made is logged. This
+option probably violates users' privacy and should not be used on
+multiuser boxes.
+.Pp
+If the
+.Fl f
+option is given, finger forwarding (user@host1@host2) is allowed.
+Useful behind firewalls, but probably not wise for security and
+resource reasons.
+.Pp
+The
+.Fl p
+option allows specification of an alternate location for fingerd to find
+the
+.Dq finger
+program. The
+.Fl L
+option is equivalent.
+.Pp
+The
+.Fl t
+option specifies the time to wait for a request before closing the
+connection. A value of 0 waits forever. The default is 60 seconds.
+.Pp
+Options to fingerd should be specified in
+.Pa /etc/inetd.conf .
+.Pp
+The finger protocol consists mostly of specifying command arguments.
+The
+.Xr inetd 8
+.Dq super-server
+runs
+.Nm fingerd
+for
+.Tn TCP
+requests received on port 79.
+Once connected
+.Nm fingerd
+reads a single command line
+terminated by a
+.Aq Tn CRLF
+which is passed to
+.Xr finger 1 .
+It closes its connections as soon as all output is finished.
+.Pp
+If the line is empty (i.e. just a
+.Aq Tn CRLF
+is sent) then
+.Xr finger
+returns a
+.Dq default
+report that lists all people logged into
+the system at that moment. This feature is blocked by the
+.Fl u
+option.
+.Pp
+If a user name is specified (e.g.
+.Pf eric Aq Tn CRLF )
+then the
+response lists more extended information for only that particular user,
+whether logged in or not.
+Allowable
+.Dq names
+in the command line include both
+.Dq login names
+and
+.Dq user names .
+If a name is ambiguous, all possible derivations are returned.
+.Sh SEE ALSO
+.Xr finger 1 ,
+.Xr inetd 8
+.Sh RESTRICTIONS
+Connecting directly to the server from a
+.Tn TIP
+or an equally narrow-minded
+.Tn TELNET Ns \-protocol
+user program can result
+in meaningless attempts at option negotiation being sent to the
+server, which will foul up the command line interpretation.
+.Sh HISTORY
+The finger daemon appeared in
+.Bx 4.3 .
diff --git a/fingerd/fingerd.c b/fingerd/fingerd.c
new file mode 100644
index 0000000..856d2ba
--- /dev/null
+++ b/fingerd/fingerd.c
@@ -0,0 +1,295 @@
+/*
+ * Copyright (c) 1983 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.
+ */
+
+char copyright[] =
+ "@(#) Copyright (c) 1983 The Regents of the University of California.\n"
+ "All rights reserved.\n";
+
+/*
+ * from: @(#)fingerd.c 5.6 (Berkeley) 6/1/90"
+ */
+char rcsid[] =
+ "$Id: fingerd.c,v 1.23 1999/12/12 18:46:28 dholland Exp $";
+
+#include <pwd.h>
+#include <grp.h>
+#include <netdb.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <syslog.h>
+#include <getopt.h>
+#include <netinet/in.h>
+#include <sys/utsname.h>
+#include <sys/wait.h>
+
+#include "pathnames.h"
+#include "../version.h"
+
+#define ENTRIES 50
+#define WS " \t\r\n"
+
+/* These are used in this order if the finger path compiled in doesn't work. */
+#define _ALT_PATH_FINGER_1 "/usr/local/bin/finger"
+#define _ALT_PATH_FINGER_2 "/usr/ucb/finger"
+#define _ALT_PATH_FINGER_3 "/usr/bin/finger"
+
+static
+void
+fatal(const char *msg, int use_errno, int tolog, int toclient)
+{
+ const char *err = "";
+ const char *sep = "";
+ if (use_errno) {
+ err = strerror(errno);
+ sep = ": ";
+ }
+ if (tolog) syslog(LOG_ERR, "%s%s%s\n", msg, sep, err);
+ if (toclient) fprintf(stderr, "fingerd: %s%s%s\r\n", msg, sep, err);
+ else fprintf(stderr, "fingerd: Internal error\r\n");
+ exit(1);
+}
+
+static
+void
+timeout(int sig)
+{
+ (void)sig;
+ errno = ETIMEDOUT;
+ fatal("Input timeout", 0, 1, 1);
+}
+
+
+int
+main(int argc, char *argv[])
+{
+#if 0
+ FILE *fp;
+ int p[2], ch;
+ pid_t pid;
+#endif
+ int ca;
+ const char *av[ENTRIES + 1];
+ const char **avy;
+ char *const *avx;
+ char line[1024];
+ int welcome = 0, heavylogging = 0, nouserlist = 0;
+ int patience = 60, forwarding = 0;
+ int k, nusers;
+ char *s, *t;
+ const char *fingerpath = NULL;
+ struct sockaddr_in sn;
+ socklen_t sval = sizeof(sn);
+
+
+ if (getpeername(0, (struct sockaddr *) &sn, &sval) < 0) {
+ fatal("getpeername", 1, 0, 1);
+ }
+
+ openlog("fingerd", LOG_PID, LOG_DAEMON);
+
+ if (!getuid() || !geteuid()) {
+ struct passwd *pwd = getpwnam("nobody");
+ if (pwd) {
+ initgroups(pwd->pw_name, pwd->pw_gid);
+ setgid(pwd->pw_gid);
+ setuid(pwd->pw_uid);
+ }
+ seteuid(0); /* this should fail */
+ if (!getuid() || !geteuid()) {
+ fatal("setuid: couldn't drop root", 0, 1, 0);
+ }
+ }
+ /*endpwent(); -- is it safe to put this here? */
+
+ opterr = 0;
+ while ((ca = getopt(argc, argv, "wlL:p:uft:h?")) != EOF) {
+ switch(ca) {
+ case 'w':
+ welcome = 1;
+ break;
+ case 'l':
+ heavylogging = 1;
+ break;
+ case 'L':
+ case 'p':
+ fingerpath = optarg;
+ break;
+ case 'u':
+ nouserlist = 1;
+ break;
+ case 'f':
+ forwarding = 1;
+ break;
+ case 't':
+ patience = atoi(optarg);
+ break;
+ case '?':
+ case 'h':
+ default:
+ syslog(LOG_ERR, "usage: fingerd [-wulf]"
+ "[-pL /path/finger] [-t timeout]");
+ exit(1);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ /*
+ * Hang up after a while so people can't DoS by leaving lots of
+ * open sockets about.
+ */
+ if (patience != 0) {
+ signal(SIGALRM, timeout);
+ alarm(patience);
+ }
+ if (!fgets(line, sizeof(line), stdin)) {
+ fatal("Client hung up - probable port-scan", 0, 1, 0);
+ }
+
+ if (welcome) {
+ char buf[256];
+ struct hostent *hp;
+ struct utsname utsname;
+
+ uname(&utsname);
+ gethostname(buf, sizeof(buf));
+ if ((hp = gethostbyname(buf))) {
+ /* paranoia: dns spoofing? */
+ strncpy(buf, hp->h_name, sizeof(buf));
+ buf[sizeof(buf)-1] = 0;
+ }
+ printf("\r\nWelcome to %s version %s at %s !\r\n\n",
+ utsname.sysname, utsname.release, buf);
+ fflush(stdout);
+ switch (fork()) {
+ case -1: /* fork failed, oh well */
+ break;
+ case 0: /* child */
+ execl(_PATH_UPTIME, _PATH_UPTIME, NULL);
+ _exit(1);
+ default: /* parent */
+ wait(NULL);
+ break;
+ }
+ fflush(stdout);
+ printf("\r\n");
+ fflush(stdout);
+ }
+
+ k = nusers = 0;
+ av[k++] = "finger";
+ for (s = strtok(line, WS); s && k<ENTRIES; s = strtok(NULL, WS)) {
+ /* RFC742: "/[Ww]" == "-l" */
+ if (!strncasecmp(s, "/w", 2)) memcpy(s, "-l", 2);
+ if (!forwarding) {
+ t = strchr(s, '@');
+ if (t) {
+ fprintf(stderr,
+ "fingerd: forwarding not allowed\r\n");
+ syslog(LOG_WARNING, "rejected %s\n", s);
+ exit(1);
+ }
+ }
+ if (heavylogging) {
+ if (*s=='-') syslog(LOG_INFO, "option %s\n", s);
+ else syslog(LOG_INFO, "fingered %s\n", s);
+ }
+ av[k++] = s;
+ if (*s!='-') nusers++;
+ }
+ av[k] = NULL;
+ if (nusers==0) {
+ /* finger @host */
+ if (nouserlist) {
+ syslog(LOG_WARNING, "rejected finger @host\n");
+ printf("Please supply a username\r\n");
+ return 0;
+ }
+ if (heavylogging) syslog(LOG_INFO, "fingered @host\n");
+ }
+
+/* Yay! we don't need to do this any more - finger does it for us */
+#if 0
+ if (pipe(p) < 0) {
+ fatal("pipe", 1, 1, 0);
+ }
+
+ pid = fork();
+ if (pid<0) {
+ fatal("fork", 1, 1, 0);
+ }
+ if (pid==0) {
+ /* child */
+ close(p[0]);
+ dup2(p[1], 1);
+ if (p[1]!=1) close(p[1]);
+#endif
+ /*
+ * execv() takes (char *const *), because (char const *const *)
+ * doesn't work right in C (only in C++). C9x might fix this
+ * if we're lucky. In the meantime we need to defeat the type
+ * system to avoid warnings.
+ */
+ avy = av;
+ /*avx = avy;*/
+ memcpy(&avx, &avy, sizeof(avx));
+
+ if (fingerpath) execv(fingerpath, avx);
+ execv(_PATH_FINGER, avx);
+ execv(_ALT_PATH_FINGER_1, avx);
+ execv(_ALT_PATH_FINGER_2, avx);
+ execv(_ALT_PATH_FINGER_3, avx);
+ syslog(LOG_ERR, "Finger program not found\n");
+ exit(1);
+#if 0
+ }
+ /* parent */
+ close(p[1]);
+
+ /* convert \n to \r\n. This should be an option to finger... */
+ fp = fdopen(p[0], "r");
+ if (!fp) {
+ fatal("fdopen", 1, 1, 0);
+ }
+
+ while ((ch = getc(fp)) != EOF) {
+ if (ch == '\n') putchar('\r');
+ putchar(ch);
+ }
+ return 0;
+#endif
+}
diff --git a/fingerd/pathnames.h b/fingerd/pathnames.h
new file mode 100644
index 0000000..4fa4dff
--- /dev/null
+++ b/fingerd/pathnames.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 1989 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.
+ *
+ * from: @(#)pathnames.h 5.3 (Berkeley) 6/1/90
+ * $Id: pathnames.h,v 1.3 1996/07/13 23:21:42 dholland Exp $
+ */
+
+/*
+ * These should maybe be determined at configure/install time.
+ */
+#define _PATH_FINGER "/usr/bin/finger"
+#define _PATH_UPTIME "/usr/bin/uptime"
diff --git a/version.h b/version.h
new file mode 100644
index 0000000..e78be2d
--- /dev/null
+++ b/version.h
@@ -0,0 +1,5 @@
+/*
+ * String to embed in binaries to identify package
+ */
+
+char pkg[]="$NetKit: bsd-finger-0.17 $";