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