From 172540a4a29fa4c0c5f0431bb5bf5b3d08ec92c0 Mon Sep 17 00:00:00 2001 From: KatolaZ Date: Fri, 8 Feb 2019 05:13:11 +0000 Subject: New upstream version 0.17 --- .cvsignore | 1 + BUGS | 7 + ChangeLog | 133 +++++++++++++++++ MCONFIG.in | 22 +++ MRULES | 8 + Makefile | 20 +++ README | 118 +++++++++++++++ configure | 305 ++++++++++++++++++++++++++++++++++++++ finger/.cvsignore | 1 + finger/Makefile | 18 +++ finger/display.c | 179 ++++++++++++++++++++++ finger/finger.1 | 194 ++++++++++++++++++++++++ finger/finger.c | 334 +++++++++++++++++++++++++++++++++++++++++ finger/finger.h | 119 +++++++++++++++ finger/lprint.c | 361 +++++++++++++++++++++++++++++++++++++++++++++ finger/net.c | 155 +++++++++++++++++++ finger/sprint.c | 172 +++++++++++++++++++++ finger/util.c | 418 ++++++++++++++++++++++++++++++++++++++++++++++++++++ fingerd/.cvsignore | 1 + fingerd/Makefile | 18 +++ fingerd/fingerd.8 | 157 ++++++++++++++++++++ fingerd/fingerd.c | 295 ++++++++++++++++++++++++++++++++++++ fingerd/pathnames.h | 41 ++++++ version.h | 5 + 24 files changed, 3082 insertions(+) create mode 100644 .cvsignore create mode 100644 BUGS create mode 100644 ChangeLog create mode 100644 MCONFIG.in create mode 100644 MRULES create mode 100644 Makefile create mode 100644 README create mode 100755 configure create mode 100644 finger/.cvsignore create mode 100644 finger/Makefile create mode 100644 finger/display.c create mode 100644 finger/finger.1 create mode 100644 finger/finger.c create mode 100644 finger/finger.h create mode 100644 finger/lprint.c create mode 100644 finger/net.c create mode 100644 finger/sprint.c create mode 100644 finger/util.c create mode 100644 fingerd/.cvsignore create mode 100644 fingerd/Makefile create mode 100644 fingerd/fingerd.8 create mode 100644 fingerd/fingerd.c create mode 100644 fingerd/pathnames.h create mode 100644 version.h 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 .) + +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 < __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 <__conftest.c +#include +#include +#include +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 <__conftest.c +#include +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 <__conftest.c +#include +#include +#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 +#include +#include +#include +#include +#include +#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, . + */ + +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 +#include + +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 */ + 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 or a 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 +#include +#include +#include +#include +#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 +/* #include <--- unused? */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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