[comp.sys.hp] cnode print shuttle, C language version

usenet@cps3xx.UUCP (Usenet file owner) (08/10/89)

Here is a C language program to replace the Korn shell printer "shuttle"
posted earlier (by Tw Cook of HP, I believe).

We decided to use a program instead of a shell script mainly so we could
prevent jobs from falling into a black hole when the printer is offline.

The following program has not been exhaustively tested. Use at your own risk.
-----------------------------------------------------------------------------
/* shuttle.c ************************************************************
 *									*
 * Usage: shuttle <fifo> <printer-device>				*
 *									*
 * A kludge for HP-UX 6.5 to get around the problem of not being able	*
 * to hang spooled devices on a cnode. This program sits between a	*
 * named pipe, visible on both the server and cnode, and the printer	*
 * device. The server spools to the named pipe, and the shuttle on the	*
 * cnode takes stuff out of the pipe and throws it at the device.    	*
 *									*
 * This is still a kludge, waiting on a better solution (a distributed	*
 * spooling system) from HP. We do not handle all possible errors, and	*
 * there is no way to inform the scheduler/user of printer errors.	*
 *									*
 * We assume that Carier Detect (CD - RS232C pin 8) is wired to be 	*
 * active when the printer is accepting output. For an NEC SilentWriter	*
 * on an HP 9000/340 a cable like this works (see termio(7) and modem(7)*
 * for the gory details):						*
 *									*
 *	NEC	2	3	HP					*
 *		3	2						*
 *		7	7						*
 *		20	8						*
 *									*
 * Be sure the device has modem controls enabled, for example under	*
 * HP-UX 6.5: "/etc/mknod lp09 c 1 0x090000" for the serial port.	*
 *----------------------------------------------------------------------*
 * Modification history:						*
 *	89-08-09 original coding			John Lees	*
 *									*
 * A. H. Case Center for Computer-Aided Engineering and Manufacturing	*
 *    Michigan State University, East Lansing, Michigan 48824-1226	*
 *    manager@frith.egr.msu.edu, ...!uunet!frith!manager		*
 ************************************************************************
 */
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <termio.h>
#include <sys/ioctl.h>
#include <sys/modem.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "misc.h"

#define	BUF_SIZE	8192

extern char *strerror();
extern int errno;

void usage();

main(argc, argv)
int  argc;
char *argv[];
    {
    char dev_buf[132], fifo_buf[BUF_SIZE], *whoami;
    int debug, dev_fd, fifo_fd, n_read, n_wrote, rs232;
    struct termio our_termio, *termio_p = &our_termio;
    mflag modem, *p_modem = &modem;

    /*
     *** Remember who we are.
     */
    whoami = argv[0];

    /*
     *** Scan "-" arguments.
     */
    argc--;
    argv++;
    while (argc  &&  argv[0][0] == '-')
         {
         switch (argv[0][1])
              {
              case 'd':      /* set debug flag */
                   debug = TRUE;
                   break;

              default:       /* ignore crud */
                   break;
              }
         argc--;
         argv++;
         } /* while */

    if (debug)
	fprintf(stderr, "%s: *** debug mode ***\n", whoami);

    /*
     *** Get the name of the FIFO and open it.
     */
    if (argc != 0)
	{
	if ((fifo_fd = open(argv[0], O_RDONLY)) < 0)
	    {
	    fprintf(stderr, "%s: Cannot open FIFO \"%s\"\n\t%s\n",
		whoami, argv[0], strerror(errno));
	    exit(1);
	    }
	argc--;
	argv++;
	}
    else
	{
	usage(whoami);
	exit(1);
	}

    /*
     *** Get the name of the printer device and set it up.
     */
    if (argc != 0)
	{
	/* Open.
	 */
	if ((dev_fd = open(argv[0], O_RDWR)) < 0)
	    {
	    fprintf(stderr, "%s: Cannot open printer device \"%s\"\n\t%s\n",
		whoami, argv[0], strerror(errno));
	    exit(1);
	    }

	/* Set up the serial port. (If the ioctl fails, we assume this is
	 * not a serial port.)
	 */
	if (ioctl(dev_fd, TCGETA, termio_p) >= 0)
	    {
	    rs232 = TRUE;
	    termio_p->c_iflag = IXON | IXANY;
	    termio_p->c_oflag = 0;
	    termio_p->c_cflag = B9600 | CS8 | CREAD;
	    termio_p->c_lflag = 0;
	    if (ioctl(dev_fd, TCSETA, termio_p) < 0)
		{
		fprintf(stderr, "%s: ioctl TCSETA on printer device \"%s\"\n\t%s\n",
		    whoami, argv[0], strerror(errno));
		exit(1);
		}
	    else
		if (debug)
		    {
		    fprintf(stderr, "c_iflag = %o\n", termio_p->c_iflag);
		    fprintf(stderr, "c_oflag = %o\n", termio_p->c_oflag);
		    fprintf(stderr, "c_cflag = %o\n", termio_p->c_cflag);
		    fprintf(stderr, "c_lflag = %o\n", termio_p->c_lflag);
		    }
	    }
	else
	    {
	    rs232 = FALSE;
	    if (debug)
		fprintf(stderr, "%s: ioctl TCGETA on printer device \"%s\"\n\t%s\n",
		    whoami, argv[0], strerror(errno));
	    }

	argc--;
	argv++;
	}
    else
	{
	usage(whoami);
	close(fifo_fd);
	exit(1);
	}

    /*
     *** Check for invalid arguments.
     */
    if (argc != 0)
	{
	fprintf(stderr, "%s: Invalid argument \"%s\"\n", whoami, argv[0]);
	close(fifo_fd);
	close(dev_fd);
	exit(1);
	}

    /*
     *** Here we loop forever checking if there is anything in the FIFO to
     *** throw at the printer.
     ***
     *** We check for a read of size zero and sleep. The read from the fifo
     *** should block, but it doesn't (without this check, the read loop
     *** placed a 45% load on our ethernet!).
     */
    FOREVER
         {
	 n_read = read(fifo_fd, fifo_buf, BUF_SIZE);

	 if (n_read < 0)	/* FIFO error */
	    {
	    fprintf(stderr, "%s: FIFO error\n\t%s\n",
		whoami, strerror(errno));
	    n_read = 0;
	    }

	 if (n_read == 0)	/* FIFO empty */
	    {
	    sleep((unsigned long)5);
	    }

	if (n_read > 0)		/* FIFO read okay */
	    {
	    /* Don't print if the printer is not available.
	     */
    dcd_check:
	    if (rs232)
		ioctl(dev_fd, MCGETA, p_modem);
	    if (!rs232  ||  (modem & MDCD))
		    {
		    n_wrote = write(dev_fd, fifo_buf, n_read);
		    if (n_wrote < 0)
			{
			fprintf(stderr, "%s: Printer device error\n\t%s\n",
			    whoami, strerror(errno));
			n_wrote = 0;
			}
		    }
	   else
		{
		if (debug)
		    fprintf(stderr, "*** no DCD %o ***\n", modem);
		sleep((unsigned long)5);
		goto dcd_check;
		}
		}
         } /* forever */

    } /* main */


void usage(whoami)
    char *whoami;
    {
    fprintf(stderr, "Usage: %s <fifo> <printer-dev>\n", whoami);
    }
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  O  - - -
 John Lees, Manager of         A. H. Case Center for Computer      OoO
  Systems & Network Services    Aided Engineering & Manufacturing  /O
			       236 Engineering Building            |
 lees@frith.egr.msu.edu        Michigan State University          (|)
 ...!uunet!frith!lees          East Lansing, MI 48824-1226         |   flower
 CompuServe 74106,1324         Phone: (517) 355-7435/6453        __|__  power