From: brummel@gshp9000.gradsch.ohio-state.edu (Karl Brummel)
Subject: HP-UX and init(1M)
Organization: The Ohio State University Graduate School
Date: Tue, 1 Sep 1992 15:56:19 GMT

Howdy netters.
I'm writing this program to hang out on a tty and wait for a file to arrive. 
I would like to have it in /etc/inittab so that it will get respawned after
each file.  This is happening on a HP 9000/832 running HP-UX 7.08.

My program waits for a file to arrive, then, fork()s and exec()s a shell
script that handles the actual printing. The standard input of the shell
script is connected to a pipe that my program spews data through.

This all works dandy from the command line.  Unfortunately, when it is run by
init(1M), it flails hard.  Things work great until the fork and exec.  Then,
/bin/sh closes the file descriptor for the terminal, and init(1M) *apparently*
thinks its child has exited and rexecutes my program, which in turn gets a byte
from the file, forks, and execs the shell script, which closes the terminal,
which causes init to run my program...eventually leading to a message from
init saying my process is respawning too rapidly.

How do I beat this?  When I change my program to run the spooler directly,
it works as long as I leave out the call that closes the terminal.  As soon as
I put it back, it flails.  This wouldn't be a problem if I could change the
program without editing /etc/inittab, killing the process, recompiling the
program, editing /etc/inittab, and then running /etc/telinit q each time I
want to change some small detail of the way the file is handled.

I have tried setsid() after the fork() to detach the child process from the
controlling terminal, but to no avail.  I need to send init(1M)
the message that it should worry about what the children of the program it
runs does with its file descriptors, or how to tell /bin/sh not to close
files.  Any ideas?  Thanks.  Please send email to brumski+@osu.edu.
Here's a chunk of the program...

char 	buffer[INSIZE],reset[20];
int	in,count,pipefd[2],writeflag,totalsize;

in=openterm("/dev/tty6p7"); /* Open the terminal, set up control flow
				and such. */
count=read(in,buffer,1); 	/* First read is blocking.  Wait for a file. */
pipe(pipefd);	/* Create a pipe. */
/* HERE'S WHERE THINGS GET UGLY. */
if (fork()==0) { /* This is the child, to become the spooler. */
	dup2(pipefd[0],0); /* Connect standard input to the pipe. */
	close(pipefd[0]);  /* These are no longer needed. */
	close(pipefd[1]);
	close(in); /* HERE'S WHERE THINGS GET *REALLY* UGLY. */
	execl("/usr/local/etc/pcprint.sh","pcprint.sh",(char *) 0);
	/* Be sure that the child exits, so if execl() fails the child will
		not continue. */
	perror("execl");
	exit(-1);
	}
close(pipefd[0]);
totalsize=spew(in,pipefd[1],count,&writeflag); /* Get the rest of the file.*?
/* If we have actually sent anything, append a reset string for the printer. */
if(writeflag) {
	getreset(reset); /* read the reset string for the printer. */
	write(pipefd[1],reset,strlen(reset));
	totalsize+=strlen(reset);
	}
account(writeflag,totalsize); /* Record the transaction. */
close(pipefd[1]);	/* Close the pipe.  Else lp will never complete. */
close(in);
return(0);
}
-- 
                      Karl Brummel -- brumski+@osu.edu
	        "Speed isn't everything...it's the ONLY thing."