From: franklin@ug.cs.dal.ca (Steve Franklin)
Subject: THE SOURCE TO NAMEDP, A FINGER PROGRAM
Organization: Math, Stats & CS, Dalhousie University, Halifax, NS, Canada
Date: Tue, 10 Nov 1992 14:07:09 GMT

Here's the source to NAMEDP. I'm not sure if it made it to the group already.
This is the 4th time I have posted it. I think I mucked up the last time.
 Please do not mail me asking for help, unless
a) i know you
b) You can make me laugh.
   Otherwise I have no time to help you install it.
steve

# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by Scratchy <napalm@molest> on Wed Jan 15 12:32:17 1992
#
# This archive contains:
#	README		MANIFEST	Makefile	logfinger	
#	plan.c		plan.nr		
#
# Existing files will not be overwritten.
# Error checking via wc(1) will be performed.
# Error checking via sum(1) will be performed.

LANG=""; export LANG
PATH=/bin:/usr/bin:$PATH; export PATH

if sum -r </dev/null >/dev/null 2>&1
then
	sumopt='-r'
else
	sumopt=''
fi

if test -f README
then
	echo Ok to overwrite existing file README\?
	read answer
	case "$answer" in
	[yY]*)	echo Proceeding;;
	*)	echo Aborting; exit 1;;
	esac
	rm -f README
	if test -f README
	then
		echo Error: could not remove README, aborting
		exit 1
	fi
fi
echo x - README
cat >README <<'@EOF'
All I did was to put in a function that keeps track of the PID for
plan by writing it to a file called ".planpid" in your home directory.
Now you run plan in your .login, and, to kill the process when you log
out, put something like this in your .logout:

	kill `cat /home/mine/.planpid`
	rm -f /home/mine/.planpid

You have to remove the .planpid (or modify the code), because the 
program will not run if a plan is already running, which it assumes
when it finds a .planpid file already there.

If someone wanted to run multiple plans, maybe one for a .signature
and another for a .plan, the save name for the PID could be changed,
and the program compiled twice (the binary is not that big, ~40K on
the HP 425's I used), or, if someone is really motivated, they could
add a command line argument for the save name.

Sure, my modification isn't very complex, but it does what I needed
it to do, and maybe someone else can use it.

Karen	(napalm@ugcs.caltech.edu)

****  Additions by Geoff Loker ****

I have modified Tony Rems' code for plan a bit to get rid of the
necessity for hard-coding in the file name to be set up as a FIFO.
The program will now accept an optional argument that specifies the
name of the FIFO to be used.  If that argument is not set, the default
FIFO is $HOME/.plan.

In order to use this program, your O/S needs to support named pipes.
You also need to link in getopt for the changes to work.

Any executable program can be set up to run when the specified FIFO is
opened, but don't forget that the program you specify to run is being
run under your userid.

****  Original README ****

Date: Thu, 11 Apr 91 14:09:10 MST
From: Jim Armstrong <armstron@cs.arizona.edu>
Subject: RE: fingeree ...

> >About a month ago there was a sample program posted to this newsgroup that
> >set up a FIFO named pipe as your .plan file.  I modified the code to set up
> >a simple (perhaps naive) finger monitor for users on my machine.  The process
> do you still have the source for it? would you send it to me?

Here is the article which appeared in comp.unix.questions a while back.  It
contains generic code that will run any program you want whenever a certain
file is accessed (i.e. the .plan file in this case).  All you have to do is
compile it (it creates an executable called 'plan') and then to get it
running say 'plan a.out &' where a.out is some program you have written.
I don't have my program any more, but basically what I did was a ps au
within that program.  It used egrep to search for someone currently fingering
me and appended the output to a file.  To get really fancy you could then
read from that file to find out exactly who it is (all in the same program)
and print out a nice personal message to whoever is fingering you as part
of what looks to be your .plan file.  A couple of things to watch out for:
If the finger is remote, the ps au won't find anything.  Also, if two people
finger you at the same time you may run into trouble, but I didn't try
experimenting with this too much.  I also found it helpful to timestamp a
date to the file, too (I used localtime() for efficiency).  This makes it
easier to look back later at the file and see who's been fingering you and
when while you were not logged on.  It also helpful in debugging your program.

So set up this code and experiment with different programs.  Just be creative
and see what else you can do with it.  One idea I used for a while is making
it print a different quote each time.  The possibilites are endless.  Enjoy.

Jim


Article 31270 of comp.unix.questions:
From: rembo@unisoft.UUCP (Tony Rems)
Newsgroups: comp.unix.questions
Subject: Re: Finger
Date: 22 Feb 91 02:44:17 GMT
Reply-To: rembo@unisoft.UUCP (Tony Rems)
Organization: UniSoft Corporation -- UNIX R Us.

In article <37675@netnews.upenn.edu> minzhi@eniac.seas.upenn.edu (Min-Zhi Shao) writes:
>
>    When I fingered our system administrator, I got the following result:
>
>_________________________________________________________________________
>Login name: gardella  			In real life: Ed Gardella [CETS]
>Directory: /home/cets/gardella      	Shell: /usr/local/bin/bash
>On since Feb 15 19:49:04 on ttyp1 from TSTEST.SEAS.UPEN
>14 minutes Idle Time
>No unread mail
>Project: System Administrator eniac.seas.upenn.edu
>Plan:
>         Meander about until something interesting comes along.
>
>Office: 154 Moore Building           Work Phone: 898-2491
>                                     Home Phone: 387-4104
>
>I have been fingered 3 times today
>_________________________________________________________________________
>
>the .plan file in his home directory looks like:
>
>prw-r--r--  1 gardella        0 Feb 15 23:48 /home/cets/gardella/.plan
>^

As you have found out by now, I'm sure, the p means that this is 
a named pipe aka a FIFO.  If you'd like to do this yourself, here
is a little program I wrote to do it (see the comments at the
the beginning of the plan.c file for usage info):  

Here's the shar of my plan program, just cut up until it says
"cut here", and then type 'sh filename' using whatever filename
you save it as.  If you use 'plan' it will get overwritten.

The code here should compile w/o any problems on any BSD machine,
I have tried it on a Sun, Vax 750, and Pyramid 90x.  It should
also work properly on any SVR4.0 machine.  

The code is pretty heavily commented so it should be self
explanatory.  

Note that you should put a -DFILENAME="your_home_dir/.plan"
to get it to put your path in, or you can just edit the 
source and change the value of FILENAME permanently.  

If you have any problems getting it compiled, just send me mail.

Enjoy.  

-Tony

@EOF
set `sum $sumopt <README`; if test $1 -ne 65223
then
	echo ERROR: README checksum is $1 should be 65223
fi
set `wc -lwc <README`
if test $1$2$3 != 1339725668
then
	echo ERROR: wc results of README are $* should be 133 972 5668
fi

chmod 644 README

if test -f MANIFEST
then
	echo Ok to overwrite existing file MANIFEST\?
	read answer
	case "$answer" in
	[yY]*)	echo Proceeding;;
	*)	echo Aborting; exit 1;;
	esac
	rm -f MANIFEST
	if test -f MANIFEST
	then
		echo Error: could not remove MANIFEST, aborting
		exit 1
	fi
fi
echo x - MANIFEST
cat >MANIFEST <<'@EOF'
MANIFEST - This file
Makefile - The makefile
README   - Original notes, notes for first set of changes, and notes
	   for my changes
plan.c   - The program
plan.nr  - A man page
logfinger - a perl script included with the shar I got
@EOF
set `sum $sumopt <MANIFEST`; if test $1 -ne 19972
then
	echo ERROR: MANIFEST checksum is $1 should be 19972
fi
set `wc -lwc <MANIFEST`
if test $1$2$3 != 743233
then
	echo ERROR: wc results of MANIFEST are $* should be 7 43 233
fi

chmod 644 MANIFEST

if test -f Makefile
then
	echo Ok to overwrite existing file Makefile\?
	read answer
	case "$answer" in
	[yY]*)	echo Proceeding;;
	*)	echo Aborting; exit 1;;
	esac
	rm -f Makefile
	if test -f Makefile
	then
		echo Error: could not remove Makefile, aborting
		exit 1
	fi
fi
echo x - Makefile
cat >Makefile <<'@EOF'
DEST	      = /home/napalm/bin/fifo

EXTHDRS	      = /usr/include/fcntl.h \
		/usr/include/signal.h \
		/usr/include/stdio.h \
		/usr/include/sys/fcntl.h \
		/usr/include/sys/file.h \
		/usr/include/sys/stat.h \
		/usr/include/sys/sysmacros.h \
		/usr/include/sys/sysmacros.h \
		/usr/include/sys/types.h \
		/usr/include/sys/types.h

HDRS	      =

LDFLAGS	      =

LIBS	      =

LINKER	      = cc

MAKEFILE      = Makefile

OBJS	      = plan.o

PRINT	      = pr

PROGRAM	      = plan

SRCS	      = plan.c

all:		$(PROGRAM)

$(PROGRAM):     $(OBJS) $(LIBS)
		@echo -n "Loading $(PROGRAM) ... "
		@$(LINKER) $(LDFLAGS) $(OBJS) $(LIBS) -o $(PROGRAM)
		@echo "done"

clean:;		@rm -f $(OBJS)

depend:;	@mkmf -f $(MAKEFILE) PROGRAM=$(PROGRAM) DEST=$(DEST)

index:;		@ctags -wx $(HDRS) $(SRCS)

install:	$(PROGRAM)
		@echo Installing $(PROGRAM) in $(DEST)
		@install -s $(PROGRAM) $(DEST)

print:;		@$(PRINT) $(HDRS) $(SRCS)

program:        $(PROGRAM)

tags:           $(HDRS) $(SRCS); @ctags $(HDRS) $(SRCS)

update:		$(DEST)/$(PROGRAM)

$(DEST)/$(PROGRAM): $(SRCS) $(LIBS) $(HDRS) $(EXTHDRS)
		@make -f $(MAKEFILE) DEST=$(DEST) install
###
plan.o: /usr/include/sys/types.h /usr/include/sys/sysmacros.h \
	/usr/include/sys/sysmacros.h /usr/include/sys/file.h \
	/usr/include/sys/fcntl.h /usr/include/sys/types.h \
	/usr/include/fcntl.h /usr/include/stdio.h /usr/include/sys/stat.h \
	/usr/include/signal.h
@EOF
set `sum $sumopt <Makefile`; if test $1 -ne 45642
then
	echo ERROR: Makefile checksum is $1 should be 45642
fi
set `wc -lwc <Makefile`
if test $1$2$3 != 641331401
then
	echo ERROR: wc results of Makefile are $* should be 64 133 1401
fi

chmod 644 Makefile

if test -f logfinger
then
	echo Ok to overwrite existing file logfinger\?
	read answer
	case "$answer" in
	[yY]*)	echo Proceeding;;
	*)	echo Aborting; exit 1;;
	esac
	rm -f logfinger
	if test -f logfinger
	then
		echo Error: could not remove logfinger, aborting
		exit 1
	fi
fi
echo x - logfinger
cat >logfinger <<'@EOF'
#!/usr/bin/perl -- # -*-Perl-*-

$me = "geoff";
$logfile = "/prod_10/geoff/.fingerees";
$pscommand = "ps -auw";

open(PS, "$pscommand |");
@fingers = grep(/(f\s+$me)|(finger\s+$me)/, <PS>);
close(PS);

($num) = unpack("A9", `wc -l $logfile`); # =~ s/^\s*(\d+).*\n/\1/;
printf "I have been fingered %d time", $num;
print "s" if ($num - 1);
print " today\n";
close(STDOUT);

open(LOG, ">>$logfile");
foreach $line (@fingers) {
    ($user) = $line =~ /^\s*(\S+)/;
    print LOG "$user, at ", `date`;
}

print(LOG "somebody, at ", `date`) if (! ($#fingers + 1));
close(LOG);
@EOF
set `sum $sumopt <logfinger`; if test $1 -ne 41255
then
	echo ERROR: logfinger checksum is $1 should be 41255
fi
set `wc -lwc <logfinger`
if test $1$2$3 != 2478571
then
	echo ERROR: wc results of logfinger are $* should be 24 78 571
fi

chmod 755 logfinger

if test -f plan.c
then
	echo Ok to overwrite existing file plan.c\?
	read answer
	case "$answer" in
	[yY]*)	echo Proceeding;;
	*)	echo Aborting; exit 1;;
	esac
	rm -f plan.c
	if test -f plan.c
	then
		echo Error: could not remove plan.c, aborting
		exit 1
	fi
fi
echo x - plan.c
cat >plan.c <<'@EOF'

/*	THIS IS THE UNPUBLISHED SOURCE CODE OF REMBO		*/
/*	The copyright notice above does not evidence any   	*/
/*	actual or intended publication of such source code.	*/
/*	So, use it if you like, but give me credit.		*/


/* 	Usage: plan [-f file_name] program_name			*/


/*	Description:					*/

/* 	This program takes the full pathname of an	*/
/* 	executable and runs it on a fifo in the 	*/
/*	user's home directory named .plan.  This	*/
/* 	way, when finger is executed, the output	*/
/* 	of the program goes to the fifo.		*/
	
/*	Written by:  Tony Rems 				*/

/* 	Send bugs and flames to /dev/null or 		*/
/* 	rembo@unisoft.com 				*/

/*	Modifications:					*/

/*	September 1991					*/
/*           (by Geoff Loker geoff@mdms.moore.com)	*/
/*	Modified the program so that the path to the    */
/*	.plan file is not hardcoded in.  Now any number	*/
/*	of users can use the program at the same time.	*/
/*	I also modified the program to use an optional	*/
/*	argument to specify which file to use.  The	*/
/*	default file used is still the user's .plan,	*/
/*	but this can now also be used to set up		*/
/*	.signatures or any other file the user wants.	*/

/*	Even more modifications				*/

/*	January 1992					*/
/*	      (by Karen Bruner napalm@ugcs.caltech.edu) */
/*	Added pid_deal function, so people can stick	*/
/* 	the program in their .login, and then have it	*/
/*	killed by their .logout.  Program will not	*/
/*	run if a .planpid file, the file with the PID	*/
/*	for plan, already exists in the user's home	*/
/*	directory.					*/

#include <sys/types.h>
#include <sys/file.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <signal.h>
#include <string.h>

/* Defines */
#define PERMS 0666
#define USAGE "%s [-f file_name] program_name\n"

/* Function prototypes */
void sig_handler();
int pid_deal();	

main (argc, argv)
int argc;
char *argv[];
{
        int c, fflg;
	char *file;
        extern char *optarg;
	extern int optind;
	int fd;
	int pid;
	int status;
	char *getenv(), *home, plan[256], *strcat(), *strcpy();
	int pid_check;
	
	fflg = c = 0;
	while ((c = getopt(argc, argv, "f:")) != EOF) {
	  file = optarg;
	  fflg++;
	}

/* Comment out the next line if you don't want to have PID recorded
   to file .planpid */

	pid_check = pid_deal(); /* check for .planpid, if none, write
				   .planpid */

/* Uncomment next line if you commented out previous line */

/*  pid_check = 1; */

  if (pid_check == 1)  /* execute remaining part of program if .planpid
			  does not exist, i.e., no other plan process is
			  running */
    {
	if (fflg)
	  strcpy(plan, file);
	else {
	  home = getenv("HOME");
	  strcpy(plan, home);
	  strcat(plan, "/.plan");
	}
/*	setenv("PLAN", plan, 1); */

	if ( argc != optind + 1 ) {
		fprintf (stderr, USAGE, argv[0]);
		exit(1);
	}  /* if */

/* Catch interrupts for cleanup */
	signal(SIGTERM, sig_handler);
	signal(SIGINT, sig_handler);
	signal(SIGHUP, sig_handler);

	unlink (plan);

/* Make the fifo */
	if ((mknod(plan, S_IFIFO | PERMS, 0)) < 0 ) {
		perror("mknod");
		exit(2);
	}  /* if */

	while (1) {
		if ((fd = open(plan, O_WRONLY)) < 0 ) {
			perror("open");
			exit(3);
		} /* if */

/* Once our open completes we know that someone else has
 * opened the FIFO for reading, so we can know run our 
 * program on it.  So, we fork, exec our program and
 * wait for the child to complete.
 */
		switch (pid = fork()) {
			case -1:
				perror("fork");
				exit(4);
				break;
			case 0:
/* If we're in the child, we copy our fifo to stdout */
/* and exec the program given */
				dup2(fd, 1);
				execlp(argv[optind],argv[optind],(void *)NULL);
				perror("child returned");
				exit(5);
				break;
			default:
/* If we're in the parent, we close the pipe and wait */
				close(fd);
				while (wait(&status) != pid)
					;
				break;
		} /* switch */
		sleep(2);
		close(fd);
	} /* while */
    }  /* end of my if (pid_check... */

  else
    printf("plan already running\n");

} /* main */

void sig_handler()  /* cleanup */
{
	char *plan, *getenv();
	
	plan = getenv("PLAN");

	unlink(plan);
	exit(0);
}

int pid_deal()	/* function for recording pid and making sure process
		   isn't already running */
{
  char savepid[100];	/* string for file name */
  FILE *sp;
  int checker;		/* return value:  0 if .planpid exists, and
			   program shouldn't be run, 1 if not */
  char *home;

  home = getenv("HOME");		/* put save name for file */
  strcpy(savepid, home);		/* in savepid */
  strcat(savepid, "/.planpid");

  if ((sp = fopen(savepid, "r")) != NULL) /* test for existence of 
					     .planpid by trying to open
					     the file for reading */
    checker = 0; 	/* return a zero if read was successful, i.e.,
			   file already exists */
	
  else
    checker = 1;	/* file doesn't exist, return a 1 to execute
			   the rest of the program */
  fclose(sp);

  if (checker == 1)
    {
      sp = fopen(savepid, "w");
      fprintf(sp, "%d", getpid()); 	/* puts PID for plan into file */
      fclose(sp);
    }

  return checker;
} 
@EOF
set `sum $sumopt <plan.c`; if test $1 -ne 51212
then
	echo ERROR: plan.c checksum is $1 should be 51212
fi
set `wc -lwc <plan.c`
if test $1$2$3 != 2088235034
then
	echo ERROR: wc results of plan.c are $* should be 208 823 5034
fi

chmod 644 plan.c

if test -f plan.nr
then
	echo Ok to overwrite existing file plan.nr\?
	read answer
	case "$answer" in
	[yY]*)	echo Proceeding;;
	*)	echo Aborting; exit 1;;
	esac
	rm -f plan.nr
	if test -f plan.nr
	then
		echo Error: could not remove plan.nr, aborting
		exit 1
	fi
fi
echo x - plan.nr
cat >plan.nr <<'@EOF'
.TH PLAN L "\*(V)" "4BSD"
.SH NAME
plan - run an executable when a specified FIFO is opened
.SH SYNOPSIS
.B plan
[
.BR -f file
]
.B executable
.SH DESCRIPTION
.I plan
takes the name of an executable program and runs it on a FIFO that
is specified on the command line or on a FIFO in the user's home directory
named .plan.  Whenever the FIFO is accessed, the output of the executable
program goes to the FIFO.  It also writes the PID of plan to a file, so
the process can be killed during logout, and it checks for the existence
of this file to make sure plan isn't already running.
.SH OPTIONS
.TP
.B \-f file_name
The \fB\-f flag causes \fIplan\fR to set up the specified \fBfile_name\fR
as a FIFO rather than the default \fB$HOME/.plan\fR.
.PP
Some sample uses of \fIplan\fR would be:
.TP
.B plan /usr/games/fortune &
This will display a randomly selected fortune as the contents of
your .plan file whenever you are fingered.
.TP
.B plan -f ~/.signature ~/bin/gensig &
This will run the program gensig whenever your .signature file is accessed,
allowing you to change your .signature whenever you post.
.TP
.B plan ~/bin/logfinger &
This will run the program logfinger whenever your .plan file is accessed,
and you can log all instances of people fingering you.
.SH AUTHOR
Tony Rems (rembo@unisoft.com)
.PP
Modifications by Geoff Loker (geoff@mdms.moore.com)
More modifications by Karen Bruner (napalm@ugcs.caltech.edu)
.SH BUGS
Your system must support named pipes in order for this to work.
@EOF
set `sum $sumopt <plan.nr`; if test $1 -ne 57204
then
	echo ERROR: plan.nr checksum is $1 should be 57204
fi
set `wc -lwc <plan.nr`
if test $1$2$3 != 432551495
then
	echo ERROR: wc results of plan.nr are $* should be 43 255 1495
fi

chmod 644 plan.nr

exit 0
--

Wed Jan 15 12:50:58 PST 1992

Thirty-two footsteps leading to the room where the paint doesn't wanna dry.


-- 
aasdSteveFranklin-Subliminal Psychology Major.ks;dlasBlueJaysRULEkasdfeahsdbfl
sd;lfaswoq[eBuyMeAQuadra!!!mbnZMXCNdfsba;KdSPAMiuroqiyetIBMSuxiweuryth'ewr;mxn
qpuepriuPartyOneqtuj;,n.,xnc,kjasFlameMeNot!;lkj;lkgkjd;askElvisLivesjhfquweru
zx.cfranklin@ug.cs.dal.ca,sk;t;lrut[Superboy@ac.dal.cav.zx,Physics!eq3rwkh;oHA