commit 37c45574181c1558bca06bc42993578dd24795d6 Author: MichaƂ Krzysztof Feiler Date: Fri Oct 12 09:45:57 2018 +0200 artful finger package: http://archive.ubuntu.com/ubuntu/pool/universe/b/bsd-finger/bsd-finger_0.17.orig.tar.bz2 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 100644 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