[comp.unix.programmer] how to put a program into a .plan file

rgs@bbt.UUCP (steinbeiser) (09/27/90)

>% /etc/mknod ~/.plan p (Assuming that any existing .plan is not there)

>Then you simply write a C program that checks the status of the file,
>to see whether someone (the fingerer) has opened it. Then simply
>write your message to the named pipe. You can do many fancy things with this.
>I know a user at our site who did something like this with his .plan, and every
>time you fingered him, it would say how many people had fingered him today,
>the weather, and even your name. And sometimes it would also finger the person
>who fingered in the first place.

Ok, how do you check the status of the file to see if it has
been open by someone else?  Its not obvious how (or if) stat() would do this.
Also, would the C program have to be running constantly in the background
someplace?


  Bob Steinbeiser			Internet - rgs%bbt@rti.rti.org
  BroadBand Technologies		Bitnet   - rgs%bbt%rti.rti.org@CUNYVM
  Research Triangle Park NC	        Usenet   - !mcnc!rti!bbt!rgs
  (919)-544-6850 X255

jik@athena.mit.edu (Jonathan I. Kamens) (09/27/90)

In article <978@bbt.UUCP>, rgs@bbt.UUCP (steinbeiser) writes:
|> Ok, how do you check the status of the file to see if it has
|> been open by someone else?  Its not obvious how (or if) stat() would do this.
|> Also, would the C program have to be running constantly in the background
|> someplace?

1. You open the pipe for write, and do a select() on it, and when you get an
   OK to write from select(), you know that someone has opened the other end.

2. Yes, it would have to be running constantly in the background someplace.

I suppose another thing you could do would be to write a program that talks
NFS, and mount it under your home directory (for kernels which support the use
of programs that speak the NFS protocol in this way), and then put a symbolic
link from your .plan into that filesystem -- when something tries to open your
.plan file, your NFS protocol program will get called and you'll be able to
claim whatever you want for the contents of the .plan file.

-- 
Jonathan Kamens			              USnail:
MIT Project Athena				11 Ashford Terrace
jik@Athena.MIT.EDU				Allston, MA  02134
Office: 617-253-8495			      Home: 617-782-0710

pfalstad@phoenix.Princeton.EDU (Paul John Falstad) (09/27/90)

In article <1990Sep26.201406.12663@athena.mit.edu> jik@athena.mit.edu (Jonathan I. Kamens) writes:
>In article <978@bbt.UUCP>, rgs@bbt.UUCP (steinbeiser) writes:
>|> Ok, how do you check the status of the file to see if it has
>|> been open by someone else?  Its not obvious how (or if) stat() would do this.
>|> Also, would the C program have to be running constantly in the background
>|> someplace?
>2. Yes, it would have to be running constantly in the background someplace.

True.  (It's process wouldn't have to be RUNNING constantly, just present
constantly.)

>1. You open the pipe for write, and do a select() on it, and when you get an
>   OK to write from select(), you know that someone has opened the other end.
>
>I suppose another thing you could do would be to write a program that talks
>NFS, and mount it under your home directory (for kernels which support the use
>...

Ick.  Overkill, isn't it?

open()ing a FIFO for writing blocks until someone opens it for reading,
unless you have O_NDELAY set.  Try something like this with the Bourne shell
(I'm using SunOS 4.1):

/usr/etc/mknod foofo p
while true
do
date >foofo
done &

Now typing 'cat foofo' will print the date.  Each time the background subshell
tries to open the redirection file foofo, it will block until someone opens
it for reading.  So as soon as the open(2) call returns, you know
someone is accessing foofo.  As soon as the redirection file is opened,
the shell execs 'date', which pipes the date to whatever process is
catting foofo, and exits.

If Lafontaine's elk would spurn Tom Jones, the engine must be our head, the
dining car our esophagus, the guardsvan our left lung, the kettle truck our
shins, the first class compartment the piece of skin at the nape of the neck,
and the level crossing an electric elk called Simon.

rsalz@bbn.com (Rich Salz) (09/28/90)

>>% /etc/mknod ~/.plan p (Assuming that any existing .plan is not there)

In <978@bbt.UUCP> rgs@bbt.UUCP (steinbeiser) writes:
>Ok, how do you check the status of the file to see if it has
>been open by someone else?

/*  $Revision$
**
**  A process to create dynamic .plan files.  Creates a fifo, waits for
**  someone to connect to it.  Optional first argument is the directory
**  to chdir(2) to, as in "plan ~rsalz &"; default is value of $HOME.
**
**  Right now, this just keeps a count and runs fortune.  A neat hack
**  would be to replace /usr/etc/in.fingerd with code that does a
**  getpeername()/gethostbyaddr(), and goes back to the requesting
**  host to do a finger there.
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>

#if	!defined(FD_SET)
    /* Some systems have it typedef'd wrong, so use #define. */
#define fd_set		int
#define	FD_SET(n, p)	(*(p) |= (1 << (n)))
#define	FD_CLR(n, p)	(*(p) &= ~(1 << (n)))
#define	FD_ISSET(n, p)	(*(p) & (1 << (n)))
#define	FD_ZERO(p)	(*(p) = 0)
#endif	/* !defined(FD_SET) */

extern int	errno;
extern char	*getenv();

static char	PLAN[] = ".plan";
static char	FORTUNE[] = "/usr/emacs/dist/etc/yow";
/*static char	FORTUNE[] = "/usr/games/fortune";*/


main(ac, av)
    int		ac;
    char	*av[];
{
    char	*p;
    int		Count;
    int		fd;
    FILE	*F;
    FILE	*In;
    fd_set	writers;
    char	buff[256];

    /* Go to the right directory. */
    if (ac == 2)
	p = av[1];
    else if ((p = getenv("HOME")) == NULL) {
	fprintf(stderr, "No $HOME.\n");
	exit(1);
    }
    if (chdir(p) < 0) {
	perror("Can't cd to $HOME");
	exit(1);
    }

    /* Remove any old one, create a new one. */
    if (unlink(PLAN) < 0 && errno != ENOENT) {
	perror("Can't unlink");
	exit(1);
    }
    (void)umask(0);
    if (mknod(PLAN, S_IFIFO | 0644, 0) < 0) {
	perror("Can't mknod");
	exit(1);
    }

    /* Enter the server loop. */
    for (Count = 0; ; ) {

	/* Open the fifo for writing. */
	if ((F = fopen(PLAN, "w")) == NULL) {
	    perror("Can't fopen");
	    (void)unlink(PLAN);
	    exit(1);
	}
	fd = fileno(F);

	/* Wait until someone else opens it for reading, so that we can
	 * write on it. */
	FD_ZERO(&writers);
	FD_SET(fd, &writers);
	if (select(fd + 1, (fd_set *)NULL, &writers, (fd_set *)NULL,
		(struct timeval *)NULL) < 0) {
	    if (errno != EINTR)
		perror("Can't select");
	    continue;
	}
	if (!FD_ISSET(fd, &writers))
	    /* "Can't happen" */
	    continue;

	/* Say hello to the nice stranger. */
	fprintf(F, "Well, hello there -- this is fortune #%d:\n", ++Count);
	if ((In = popen(FORTUNE, "r")) == NULL)
	    fprintf(F, "\tSorry, cookie jar is empty.\n");
	else {
	    while (fgets(buff, sizeof buff, In))
		fputs(buff, F);
	    (void)pclose(In);
	}

	/* Close it so they stop reading, and pause to make sure of it. */
	(void)fclose(F);
	(void)sleep(1);
    }

    /* NOTREACHED */
}
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (09/28/90)

In article <2867@litchi.bbn.com> rsalz@bbn.com (Rich Salz) writes:
> **  Right now, this just keeps a count and runs fortune.  A neat hack
> **  would be to replace /usr/etc/in.fingerd with code that does a
> **  getpeername()/gethostbyaddr(), and goes back to the requesting
> **  host to do a finger there.

Neat hack? It's absolutely trivial. You just run fingerd under
attachport (-r) instead of inetd, and its environment will show a REMOTE
variable with the remote host (and authenticated username if the remote
host supports RFC 931).

---Dan

jpensar@ra.abo.fi (Johan Pensar RT) (09/28/90)

In article <2867@litchi.bbn.com> rsalz@bbn.com (Rich Salz) writes:
>/*  $Revision$
>**
>**  A process to create dynamic .plan files.  Creates a fifo, waits for
>**  someone to connect to it.  Optional first argument is the directory
>**  to chdir(2) to, as in "plan ~rsalz &"; default is value of $HOME.
...

We have here a couple of machines (suns) using the same userdisks.
If I start the program on one machine, and try to finger myself from 
another, the finger program locks up. It doesn't matter if i finger
myself on the current machine, or the machine i started plan from.
eg
        aton% finger jpensar@ra
        aton% finger jpensar

both locks up if i started the program on ra. The same happens if I finger 
myself from a VAX.

It doesnt work, but I guess it doesn't matters anyway.
--------------------------------------------------------------------------
Johan Pensar                                     Email: jpensar@ra.abo.fi
Process Control Laboratory
Abo Akademi University
FINLAND 

dwex@cbnewsj.att.com (david.e.wexelblat) (09/28/90)

In article <1990Sep26.201406.12663@athena.mit.edu>, jik@athena.mit.edu (Jonathan I. Kamens) writes:
> In article <978@bbt.UUCP>, rgs@bbt.UUCP (steinbeiser) writes:
> |> Ok, how do you check the status of the file to see if it has
> |> been open by someone else?  Its not obvious how (or if) stat() would do this.
> |> Also, would the C program have to be running constantly in the background
> |> someplace?
> 
> 1. You open the pipe for write, and do a select() on it, and when you get an
>    OK to write from select(), you know that someone has opened the other end.
> 

Or, in System V, quoting from the open(2) man page:

	When opening a FIFO with O_RDONLY or O_WRONLY set:

	If O_NDELAY is set:
		[ not relevant ]

	If O_NDELAY is clear:
		An open for reading-only will block until a process
		opens the file for writing.  An open for writing-only
		will block until a process opens the file for reading.

So all you have to do is make .plan a FIFO, and have a program open
it for writing (the program will have to be in an infinite loop, though).

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
David Wexelblat             | dwex@mtgzx.att.com    | They recommended
AT&T Bell Laboratories      | ...!att!mtgzx!dwex    |    euthanasia
200 Laurel Ave - 4B-421     |                       | For nonconformists
Middletown, NJ  07748       | (201) 957-5871        |    everywhere

trt@rti.rti.org (Thomas Truscott) (09/29/90)

> >**  A process to create dynamic .plan files.  Creates a fifo, waits for
> >**  someone to connect to it.  
> 
> We have here a couple of machines (suns) using the same userdisks.
> If I start the program on one machine, and try to finger myself from 
> another, the finger program locks up. ...

That is because NFS does not support remote named pipes.
(Or if you prefer, each client gets a "non-interfering"
instance of the named pipe!)

If you want this to work I suggest you get Freedomnet,
which also supports supports remote devices, program execution, etc.

	Tom Truscott

demon@ibmpcug.co.uk (Cliff Stanford) (09/29/90)

In article <376@ra.abo.fi> jpensar@ra.abo.fi (Johan Pensar RT) writes:

>                                               The same happens if I finger 
> myself from a VAX.

	Are you sure this shouldn't have been in alt.sex :-)


-- 
Automatic Disclaimer:
The views expressed above are those of the author alone and may not
represent the views of the IBM PC User Group.
-- 
Cliff Stanford                                cms@demon.co.uk
Demon Systems Limited                         demon@ibmpcug.co.uk
42 Hendon Lane                                demon@cix.co.uk
London N3 1TT - England                       +44 81 349 0063

haozhou@acsu.buffalo.edu (hao zhou) (09/29/90)

A further question:
	Is it possible to figure out who have fingered you?

	-- Hao Zhou

-- 
Internet:haozhou@acsu.buffalo.edu BITNET:haozhou%acsu.buffalo.edu@UBVM.BITNET
UUCP: uunet!acsu.buffalo.edu!haozhou

dylan@ibmpcug.co.uk (Matthew Farwell) (09/29/90)

In article <38200@eerie.acsu.Buffalo.EDU> haozhou@acsu.buffalo.edu (hao zhou) writes:
>A further question:
>       Is it possible to figure out who have fingered you?

You could:- 

1) Search the process table looking for the keyword 'finger'. All this would
   alt this would require would just starting ps. However this method
   isn't very reliable in that it would catch other people who were
   fingering at that time + the process might not have an argv[0] of
   finger anyway.

2) Perhaps a more reliable method would be to go and get the active
   inode information from a program like pstat. (On Xenix, the option would
   be pstat -i). This gives you the device, the inode number and the uid
   of all currently active inodes. Therefore you can work out who is
   fingering you.

Dylan.
-- 
Matthew J Farwell                 | Email: dylan@ibmpcug.co.uk
The IBM PC User Group, PO Box 360,|        ...!uunet!ukc!ibmpcug!dylan
Harrow HA1 4LQ England            | CONNECT - Usenet Access in the UK!!
Phone: +44 81-863-1191            | Sun? Don't they make coffee machines?

r3jjs@VAX1.CC.UAKRON.EDU (Jeremy J Starcher) (09/30/90)

In article <38200@eerie.acsu.Buffalo.EDU> haozhou@acsu.buffalo.edu (hao zhou) writes:
>A further question:
>	Is it possible to figure out who have fingered you?
>
>	-- Hao Zhou
>
>-- 
>Internet:haozhou@acsu.buffalo.edu BITNET:haozhou%acsu.buffalo.edu@UBVM.BITNET
>UUCP: uunet!acsu.buffalo.edu!haozhou


We are doing a `w | grep finger $USER` and assuming only one person is 
fingering us at a time..  I can't rember the needed cut construct to extract
the other person's USER ID..

parker@vela.acs.oakland.edu (Jeff Parker) (09/30/90)

I have tried every suggestion that has come along and nothing seems to work!
We are running Ultrix 4.0 on several DEC products.  It is Ultrix's finger?

Thanks, this sounds like too much fun to not be able to get working.


-- 
Jeffrey D. Parker (no philosopher) | By all means marry; if you get a good wife,
INET: parker@vela.acs.oakland.edu  | you'll become happy; if you get a bad one,
BITNET: PARKER@OAKLAND             | you'll become a philosopher.      Socrates
UUCP: ...!umich!vela!amiga1!fanatic| (Or get an AMIGA - You'll be Happy!)	

lidl@eng.umd.edu (Kurt J. Lidl) (09/30/90)

Much discussion has occured as to whether or not it is possible to
make the output of "finger" be the output of a file.  The discussion
then moved on to how much of the systems resources are taken up by
sleeping on a named pipe.

It would seem to me (IMHO) that the finger program is the proper
place to fix the entire program...  This would take care of both
common situations that occur -- fingering a person that is on the
local machine, and fingering a person at a remote machine.

Is there any problem (security-wise) with having finger parse
the .plan file...  So a .plan file that contains:

|/home/elves/lidl/bin/finger-quoted

whould do an exec() on that program and then just shuffle the
output of that program back to the finger program?

I don't see any real problems here, except that a improperly
set up /usr/libexec/fingerd program that operates as root
would be a bit of a security hole.  Most version of fingerd
either try to do a setuid to "nobody" or are invoked that
way from inetd or are setuid to "nobody".

Any comments on this?  I think that the hacking needed to finger
would be minimal, to say the least.  Thanks in advance for the
discussion as to whether or not other security holes would result
from this simple modification.

Follows have been directed to alt.security...
--
/* Kurt J. Lidl (lidl@eng.umd.edu) | Unix is the answer, but only if you */
/* UUCP: uunet!eng.umd.edu!lidl    | phrase the question very carefully. */

henkf@dnlunx.pttrnl.nl (Henk Fictorie) (10/01/90)

parker@vela.acs.oakland.edu (Jeff Parker) writes:

>I have tried every suggestion that has come along and nothing seems to work!
>We are running Ultrix 4.0 on several DEC products.  It is Ultrix's finger?

Yep, in 4.0 the finger program is smart enough to sense that .plan is
a named pipe and not a 'real' file.

On saturday Ultrix 4.0 was installed on our site and since saturday
the named pipe .plan doesn't work any more with finger :-(.
Try 'cat .plan' and you will see that the construct itself does work.

>Thanks, this sounds like too much fun to not be able to get working.


>-- 
>Jeffrey D. Parker (no philosopher) | By all means marry; if you get a good wife,
>INET: parker@vela.acs.oakland.edu  | you'll become happy; if you get a bad one,
>BITNET: PARKER@OAKLAND             | you'll become a philosopher.      Socrates
>UUCP: ...!umich!vela!amiga1!fanatic| (Or get an AMIGA - You'll be Happy!)	
-- 
Henk Fictorie, PTT Research Neher Labs,    H_Fictorie@pttrnl.nl
P.O. box 421,                              ...!hp4nl!dnlunx!henkf
2260 AK Leidschendam, The Netherlands      Phone    : +31 70 3326356 

kaleb@thyme.jpl.nasa.gov (Kaleb Keithley ) (10/01/90)

In article <697@VAX1.CC.UAKRON.EDU> r3jjs@VAX1.CC.UAKRON.EDU (Jeremy J Starcher) writes:
>In article <38200@eerie.acsu.Buffalo.EDU> haozhou@acsu.buffalo.edu (hao zhou) writes:
>>A further question:
>>	Is it possible to figure out who have fingered you?
>>
>
>We are doing a `w | grep finger $USER` and assuming only one person is 
>fingering us at a time..  I can't rember the needed cut construct to extract
>the other person's USER ID..

What if the finger is the one forked by in.fingerd?

-- 
Kaleb Keithley                      Jet Propulsion Labs
kaleb@thyme.jpl.nasa.gov

Stirring up trouble again.

r3jjs@VAX1.CC.UAKRON.EDU (Jeremy J Starcher) (10/01/90)

In article <3194@vela.acs.oakland.edu> ...!umich!vela!amiga1!fanatic writes:
>I have tried every suggestion that has come along and nothing seems to work!
>We are running Ultrix 4.0 on several DEC products.  It is Ultrix's finger?
>
>Thanks, this sounds like too much fun to not be able to get working.
>
>

I am using Ultrix and have had little trouble.  The long C program worked just 
fine for use as long as it was in the background.  The shell script took
a little more care.  We would put a couple of echos or a ls within but
nothing too complex.

mikep@dirty.csc.ti.com (Michael A. Petonic) (10/02/90)

In article <1990Sep29.141154.3546@ibmpcug.co.uk> dylan@ibmpcug.co.uk (Matthew Farwell) writes:
>In article <38200@eerie.acsu.Buffalo.EDU> haozhou@acsu.buffalo.edu (hao zhou) writes:
>>A further question:
>>       Is it possible to figure out who have fingered you?
>
>You could:- 
>
>1) Search the process table looking for the keyword 'finger'. All this would
>alt this would require would just starting ps. However this method
>isn't very reliable in that it would catch other people who were
>fingering at that time + the process might not have an argv[0] of
>finger anyway.
>
>2) Perhaps a more reliable method would be to go and get the active
>inode information from a program like pstat. (On Xenix, the option would
>be pstat -i). This gives you the device, the inode number and the uid
>of all currently active inodes. Therefore you can work out who is
>fingering you.

This is assuming, of course, that the initiator of the finger command
did so on your local machine.  Don't you guys have networks??? :-)

-MikeP

epeterso@houligan.encore.com (Eric Peterson) (10/05/90)

dwex@cbnewsj.att.com (david.e.wexelblat) writes:

| Or, in System V, quoting from the open(2) man page:
| 
| 	When opening a FIFO with O_RDONLY or O_WRONLY set:
| 
| 	If O_NDELAY is clear:
| 		An open for reading-only will block until a process
| 		opens the file for writing.  An open for writing-only
| 		will block until a process opens the file for reading.
| 
| So all you have to do is make .plan a FIFO, and have a program open
| it for writing (the program will have to be in an infinite loop, though).

I've found an interesting problem ... here's my situation.

Rich's code works all fine and well, but running it from the command
line caused it to die as soon as I log off.  So I modified the program
to fork(2) and return immediately (for my convenience in starting it)
as well as to ignore SIGHUP so it would stay running after logoff.

The problem is that the program works fine while I'm logged in,
displaying only one fortune per finger.  However, when I log off and
the process is inhereted by the system, it does NOT block on the write
to the pipe, but rather performs the write and buffers the output in
the pipe.  The upshot of all this is that while I'm logged out and the
plan proc is running, huge amounts of fortunes accumulate in my .plan
FIFO.

Is this behavior normal?  Or is there a problem with my flavor of
System V?

Thanks ...

Eric
--
       Eric Peterson <> epeterson@encore.com <> uunet!encore!epeterson
   Encore Computer Corp. * Ft. Lauderdale, Florida * (305) 587-2900 x 5208
Why did Constantinople get the works? Gung'f abobql'f ohfvarff ohg gur Ghexf.

rembo@unisoft.UUCP (Tony Rems) (10/06/90)

In article <1990Sep28.154733.26346@cbnewsj.att.com> dwex@cbnewsj.att.com (david.e.wexelblat) writes:
>In article <1990Sep26.201406.12663@athena.mit.edu>, jik@athena.mit.edu (Jonathan I. Kamens) writes:
>> In article <978@bbt.UUCP>, rgs@bbt.UUCP (steinbeiser) writes:
>> |> Ok, how do you check the status of the file to see if it has
>> |> been open by someone else?  Its not obvious how (or if) stat() would do this.
>> |> Also, would the C program have to be running constantly in the background
>> |> someplace?
>> 
>> 1. You open the pipe for write, and do a select() on it, and when you get an
>>    OK to write from select(), you know that someone has opened the other end.
>> 
>
>Or, in System V, quoting from the open(2) man page:
>
>	When opening a FIFO with O_RDONLY or O_WRONLY set:
>
>	If O_NDELAY is set:
>		[ not relevant ]
>
>	If O_NDELAY is clear:
>		An open for reading-only will block until a process
>		opens the file for writing.  An open for writing-only
>		will block until a process opens the file for reading.
>
>So all you have to do is make .plan a FIFO, and have a program open
>it for writing (the program will have to be in an infinite loop, though).
>

There are a bunch of ways to handle this in C.  Doing a select is
really overkill.  The simplest way is to have a loop that looks 
something like:

	make fifo;
	loop forever;
		open FIFO for writing	/* This will block until 
					   someon opens it for reading */
		fork()
		if in child:
			exec a program
		if in parent 
			close FIFO
			wait for child;
		

I have a program called plan which takes one argument, the 
name of a program to exec as your plan.  This version inherits
your environment on the exec.  If anyone would like a copy
of the source, drop me a note.

-Tony