home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-02-01 | 56.5 KB | 1,393 lines |
- Newsgroups: comp.sources.unix
- From: sir-alan!ispin!lbartz@iuvax.cs.indiana.edu (Larry Bartz)
- Subject: v25i118: Indianapolis Standard Printer Interface for Networked printers, Part07/15
- Sender: sources-moderator@pa.dec.com
- Approved: vixie@pa.dec.com
-
- Submitted-By: sir-alan!ispin!lbartz@iuvax.cs.indiana.edu (Larry Bartz)
- Posting-Number: Volume 25, Issue 118
- Archive-Name: ispin/part07
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 7 (of 15)."
- # Contents: ISPIN/src/ISPIN.c.aa ISPIN/doc/TECH.doc
- # ISPIN/doc/OLD-DOCS/README.beta.1 ISPIN/doc/OLD-DOCS/rel_1.2.fixes
- # ISPIN/misc/ISPIT.dr/ispit.sh
- # Wrapped by socrates@indy6 on Tue Jan 28 15:26:48 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'ISPIN/src/ISPIN.c.aa' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'ISPIN/src/ISPIN.c.aa'\"
- else
- echo shar: Extracting \"'ISPIN/src/ISPIN.c.aa'\" \(38857 characters\)
- sed "s/^X//" >'ISPIN/src/ISPIN.c.aa' <<'END_OF_FILE'
- X/****************************************************************************/
- X/* ISPIN */
- X/* */
- X/* Indianapolis Standard Printer Interface (for Network printers) */
- X/****************************************************************************/
- X/* */
- X/* Copyright (C) 1991 */
- X/* Larry Bartz */
- X/* Internal Revenue Service */
- X/* Indianapolis District Office */
- X/* */
- X/* This program is free software; you can redistribute it and/or modify */
- X/* it under the terms of the GNU General Public License as published by */
- X/* the Free Software Foundation, version 1. */
- X/* */
- X/* This program is distributed in the hope that it will be useful, */
- X/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
- X/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
- X/* GNU General Public License for more details. */
- X/* */
- X/* You should have received a copy of the GNU General Public License */
- X/* along with this program; if not, write to the Free Software */
- X/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
- X/* */
- X/****************************************************************************/
- X/* */
- X/* COMMENTS */
- X/* */
- X/* See common.h and ispin.h */
- X/* */
- X/****************************************************************************/
- X/* */
- X/* DEFINES */
- X/* */
- X/* #define DEBUG */
- X/* */
- X/****************************************************************************/
- X/* */
- X/* INCLUDES */
- X/* */
- X#include "../h/common.h"
- X#include "../h/ispin.h"
- X/* */
- X/* */
- X/* */
- X/****************************************************************************/
- X/* */
- X/* DATA TYPES, VARIABLES, ETC */
- X/* */
- X/* See common.h and ispin.h */
- X/* */
- X/****************************************************************************/
- X/* */
- X/* */
- X/* */
- Xmain(argc,argv)
- Xint argc;
- Xchar *argv[];
- X
- X{
- X
- X#ifdef DEBUG
- X /* format an error message */
- X time(&tloc);
- X nowtime = (struct tm *)localtime(&tloc);
- X time_str = asctime(nowtime);
- X strcpy(errmsg,"ISPIN: getting started. time:\n");
- X strcat(errmsg," ");
- X strcat(errmsg,time_str);
- X strcat(errmsg,"\n");
- X if((logfile = fopen(LOGFILE,"a+")) != NULL)
- X {
- X fprintf(logfile,errmsg);
- X fclose(logfile);
- X }
- X#endif
- X
- X
- X
- X/* take care of the signals */
- X signal(SIGINT, SIG_IGN); /* ignore "interrupt" signal <DEL> */
- X signal(SIGHUP, SIG_IGN); /* ignore "hang up" signal */
- X /*************************************/
- X /* Ignore SIGHUP until setuptty(). */
- X /* We don't want some unknown tty to */
- X /* HUP us. When we get to setuptty(),*/
- X /* we'll do a setpgrp() to make this */
- X /* proc the grp leader. The next tty */
- X /* we open will become the control */
- X /* terminal. Then we'll re-enable */
- X /* SIGHUP with action my_error(). */
- X /* This will enable us to intelli- */
- X /* gently loop if the printer HUPs. */
- X /* We're sure no other process group */
- X /* will have the tty as its control */
- X /* terminal because IQUEUER won't let*/
- X /* us have it until the previous */
- X /* ISPIN is finished with it. */
- X /* This little procedure is the */
- X /* reason it's SO CRITICAL that none */
- X /* of the ttys which may be used by */
- X /* ISPIN may be made known to the na-*/
- X /* tive queuer via lpadmin (LP) or */
- X /* /usr/spool/queuer/config (NQ). If */
- X /* either dqueuer (NQ) or lp (LP) */
- X /* knew about the tty we want to use,*/
- X /* they would assume it as their own */
- X /* control terminal, thus possibly */
- X /* ruining any chance we might have */
- X /* had to choose our own. */
- X /*************************************/
- X signal(SIGQUIT, SIG_IGN); /* ignore "quit" signal */
- X signal(SIGALRM, SIG_IGN);
- X signal(SIGTERM, my_error);
- X#ifdef NQ
- X signal(SIGRES, SIG_IGN); /* ignore "restart" signal */
- X signal(SIGBACK, SIG_IGN); /* ignore "back-up" signal */
- X signal(SIGSTOP, my_error); /* trap "stop" signal */
- X#endif
- X
- X /* Assign an initial value to GO_dev string, so log messages which use */
- X /* it make sense. Also so we don't dump core trying to strcat from a */
- X /* memory address which is undefined. 05/09/90 LSB */
- X sprintf(GO_dev,"undefined");
- X
- X /* format a default error message */
- X time(&tloc);
- X nowtime = (struct tm *)localtime(&tloc);
- X time_str = asctime(nowtime);
- X strcpy(errmsg,"ISPIN: undefined error. time:\n");
- X strcat(errmsg," ");
- X strcat(errmsg,time_str);
- X strcat(errmsg,"\n");
- X
- X/* Parse the arguments. */
- X/* */
- X/* If NQ, dqueuer will invoke the backend with file descriptors and options. */
- X/* See backend(M) of Zeus 3.21 Reference Manual. */
- X/* */
- X/* If LP, lp will invoke the backend with printer name, id, user, title, */
- X/* copies, options, file(s). The backend's standard input is /dev/null. */
- X/* Standard out and standard error are both directed to the printer. */
- X/* See discussion of lp interface programs in your System V UNIX box's */
- X/* administration manual (such as pages LP4-15 through LP4-18 of AT&T */
- X/* 3B2 Administration Manual). */
- X/* */
- X/* The two parse functions will each fill the same global variables, so that */
- X/* we may consider the program somewhat homogenous after this point. */
- X/* */
- X#ifdef NQ
- X parse_NQ(argc,argv);
- X if(no_input)
- X {
- X /* format an error message */
- X time(&tloc);
- X nowtime = (struct tm *)localtime(&tloc);
- X time_str = asctime(nowtime);
- X
- X sprintf(errmsg,"ISPIN: printer %s no input file to print.\n",dest);
- X sprintf(errmsg2," USER: %s\n",from);
- X strcat(errmsg,errmsg2);
- X sprintf(errmsg2," TIME: %s\n",time_str);
- X strcat(errmsg,errmsg2);
- X
- X /* call the error routine, never come back */
- X my_error(MYERR);
- X }
- X#else
- X parse_LP(argc,argv);
- X#endif
- X
- X#ifdef DEBUG
- X /* format an error message */
- X time(&tloc);
- X nowtime = (struct tm *)localtime(&tloc);
- X time_str = asctime(nowtime);
- X sprintf(errmsg,"ISPIN: printer %s passed parse_LP. time:\n",dest);
- X strcat(errmsg," ");
- X strcat(errmsg,time_str);
- X strcat(errmsg,"\n");
- X if((logfile = fopen(LOGFILE,"a+")) != NULL)
- X {
- X fprintf(logfile,errmsg);
- X fclose(logfile);
- X }
- X#endif
- X
- X
- X/* read the table to get network connection info */
- X status = read_tbl();
- X if(status == 1)
- X {
- X /* format an error message */
- X time(&tloc);
- X nowtime = (struct tm *)localtime(&tloc);
- X time_str = asctime(nowtime);
- X
- X sprintf(errmsg,"ISPIN: printer %s not in rtab.\n",dest);
- X sprintf(errmsg2," USER: %s\n",from);
- X strcat(errmsg,errmsg2);
- X if(usr_addr)
- X {
- X sprintf(errmsg2," ADDR: %s\n",usr_strng);
- X strcat(errmsg,errmsg2);
- X }
- X#ifdef NQ
- X sprintf(errmsg2," FILE: %s\n",fyle);
- X#else
- X sprintf(errmsg2," FILE: %s\n",fyles[0]);
- X#endif
- X strcat(errmsg,errmsg2);
- X sprintf(errmsg2," TIME: %s\n",time_str);
- X strcat(errmsg,errmsg2);
- X
- X /* call the error routine, never come back */
- X my_error(MYERR);
- X }
- X
- X#ifdef DEBUG
- X /* format an error message */
- X time(&tloc);
- X nowtime = (struct tm *)localtime(&tloc);
- X time_str = asctime(nowtime);
- X sprintf(errmsg,"ISPIN: printer %s passed read_tbl. time:\n",dest);
- X strcat(errmsg," ");
- X strcat(errmsg,time_str);
- X strcat(errmsg,"\n");
- X if((logfile = fopen(LOGFILE,"a+")) != NULL)
- X {
- X fprintf(logfile,errmsg);
- X fclose(logfile);
- X }
- X#endif
- X
- X
- X /* otherwise, okay. proceed */
- X
- X/* open the communication fifos */
- X open_fifos();
- X
- X#ifdef DEBUG
- X /* format an error message */
- X time(&tloc);
- X nowtime = (struct tm *)localtime(&tloc);
- X time_str = asctime(nowtime);
- X sprintf(errmsg,"ISPIN: printer %s passed open_fifos. time:\n",dest);
- X strcat(errmsg," ");
- X strcat(errmsg,time_str);
- X strcat(errmsg,"\n");
- X if((logfile = fopen(LOGFILE,"a+")) != NULL)
- X {
- X fprintf(logfile,errmsg);
- X fclose(logfile);
- X }
- X#endif
- X
- X
- X/* Notify the secondary queuer of our existence. Wait for goahead. */
- X notify(HERE);
- X
- X#ifdef DEBUG
- X /* format an error message */
- X time(&tloc);
- X nowtime = (struct tm *)localtime(&tloc);
- X time_str = asctime(nowtime);
- X sprintf(errmsg,"ISPIN: printer %s passed notify. time:\n",dest);
- X strcat(errmsg," ");
- X strcat(errmsg,time_str);
- X strcat(errmsg,"\n");
- X if((logfile = fopen(LOGFILE,"a+")) != NULL)
- X {
- X fprintf(logfile,errmsg);
- X fclose(logfile);
- X }
- X#endif
- X
- X/* This is where we re-commence if we have to loop. */
- X/* Changed to setjmp/longjmp style. No! It is NOT the same as a GOTO! */
- X/* The longjmp back to here is in the again() function. */
- X/* 07/27/90 LSB */
- XSETJMP(agayn);
- X
- X/* Secure and set up the output device. */
- X setuptty();
- X
- X
- X#ifdef DEBUG
- X /* format an error message */
- X time(&tloc);
- X nowtime = (struct tm *)localtime(&tloc);
- X time_str = asctime(nowtime);
- X sprintf(errmsg,"ISPIN: printer %s passed setuptty. time:\n",dest);
- X strcat(errmsg," ");
- X strcat(errmsg,time_str);
- X strcat(errmsg,"\n");
- X strcat(errmsg,GO_dev);
- X strcat(errmsg,"\n");
- X if((logfile = fopen(LOGFILE,"a+")) != NULL)
- X {
- X fprintf(logfile,errmsg);
- X fclose(logfile);
- X }
- X#endif
- X
- X/* Negotiate the network connection. If we can't get through, error out */
- X/* down there. */
- X negotiate();
- X
- X
- X#ifdef DEBUG
- X /* format an error message */
- X time(&tloc);
- X nowtime = (struct tm *)localtime(&tloc);
- X time_str = asctime(nowtime);
- X sprintf(errmsg,"ISPIN: printer %s passed negotiate. time:\n",dest);
- X strcat(errmsg," ");
- X strcat(errmsg,time_str);
- X strcat(errmsg,"\n");
- X strcat(errmsg,GO_dev);
- X strcat(errmsg,"\n");
- X if((logfile = fopen(LOGFILE,"a+")) != NULL)
- X {
- X fprintf(logfile,errmsg);
- X fclose(logfile);
- X }
- X#endif
- X
- X/* Do the job. Send from the input file to the output file. */
- X/* do a loop here in the LP case for each output file */
- X#ifdef NQ
- X i_stream = fdopen(RFFD,"r");
- X if(i_stream != NULL)
- X {
- X do_it();
- X fclose(i_stream);
- X close(RFFD);
- X }
- X else
- X {
- X /* format an error message */
- X time(&tloc);
- X nowtime = (struct tm *)localtime(&tloc);
- X time_str = asctime(nowtime);
- X
- X sprintf(errmsg,"ISPIN: printer: %s file %s: %s.\n",dest,fyle,sys_errlist[errno]);
- X sprintf(errmsg2," USER: %s\n",from);
- X strcat(errmsg,errmsg2);
- X if(usr_addr)
- X {
- X sprintf(errmsg2," ADDR: %s\n",usr_strng);
- X strcat(errmsg,errmsg2);
- X }
- X sprintf(errmsg2," FILE: %s\n",fyle);
- X strcat(errmsg,errmsg2);
- X if(port_open == 1)
- X {
- X sprintf(errmsg2," DEV: %s\n",GO_dev);
- X strcat(errmsg,errmsg2);
- X }
- X sprintf(errmsg2," TIME: %s\n",time_str);
- X strcat(errmsg,errmsg2);
- X
- X /* call the error routine, never come back */
- X my_error(SYSERR);
- X }
- X#else
- X
- X while(numfiles > 0)
- X {
- X
- X --numfiles;
- X
- X
- X if((i_stream = fopen(fyles[numfiles],"r")) != NULL)
- X {
- X
- X
- X do_it();
- X fclose(i_stream);
- X }
- X else
- X {
- X /* format an error message */
- X time(&tloc);
- X nowtime = (struct tm *)localtime(&tloc);
- X time_str = asctime(nowtime);
- X
- X sprintf(errmsg,"ISPIN: printer: %s file %s: %s.\n",dest,fyles[numfiles],sys_errlist[errno]);
- X sprintf(errmsg2," USER: %s\n",from);
- X strcat(errmsg,errmsg2);
- X if(usr_addr)
- X {
- X sprintf(errmsg2," ADDR: %s\n",usr_strng);
- X strcat(errmsg,errmsg2);
- X }
- X sprintf(errmsg2," FILE: %s\n",fyles[numfiles]);
- X strcat(errmsg,errmsg2);
- X if(port_open == 1)
- X {
- X sprintf(errmsg2," DEV: %s\n",GO_dev);
- X strcat(errmsg,errmsg2);
- X }
- X sprintf(errmsg2," TIME: %s\n",time_str);
- X strcat(errmsg,errmsg2);
- X
- X /* Call the error routine, but come back. */
- X /* We don't want to bomb off the whole thing just because */
- X /* one of possibly many files might not exist. */
- X
- X /* However, we'll save errno to use later when we exit, */
- X /* so that lpsched will know we encountered a problem. */
- X /* This will permit the "-m" flag of lp to work properly, */
- X /* notifying the user that his request was not entirely */
- X /* successful. 05/09/90 LSB */
- X /* We have to make sure savd_errno won't have the same */
- X /* value as other "reason"s we pass to my_exit(). */
- X savd_errno = (errno + 255);
- X
- X ret_val = my_error(NO_EXIT);
- X }
- X }
- X
- X#endif
- X
- X#ifdef DEBUG
- X /* format an error message */
- X time(&tloc);
- X nowtime = (struct tm *)localtime(&tloc);
- X time_str = asctime(nowtime);
- X sprintf(errmsg,"ISPIN: printer %s passed do_it. time:\n",dest);
- X strcat(errmsg," ");
- X strcat(errmsg,time_str);
- X strcat(errmsg,"\n");
- X strcat(errmsg,GO_dev);
- X strcat(errmsg,"\n");
- X if((logfile = fopen(LOGFILE,"a+")) != NULL)
- X {
- X fprintf(logfile,errmsg);
- X fclose(logfile);
- X }
- X#endif
- X
- X
- X/* all done */
- X if(port_open == 1)
- X {
- X stayt = DISCONNECTING;
- X ret_val = quit_net();
- X }
- X my_exit(0);
- X
- X}
- X
- X
- X
- X#ifdef NQ
- X/****************************************************************************/
- X/* parse_NQ author = loftin, hacker = bartz 073088 */
- X/****************************************************************************/
- X/* */
- X/* subroutine to get options passed to spooler backend */
- X/* */
- X/****************************************************************************/
- X/* */
- X/* description - */
- X/* This subroutine scans and stores-off the arguments passed to the */
- X/* backend (i.e., argv[]) by dqueuer(M). */
- X/* */
- X/* how invoked - parse_NQ(argc, argv) */
- X/* int argc; */
- X/* char *argv[]; */
- X/* */
- X/* inputs - none */
- X/* */
- X/* outputs - none */
- X/* */
- X/* subroutines (in addition to standard C) - none */
- X/* */
- X/* comments - */
- X/* Freely given by Mark Loftin, this routine was originally named */
- X/* "getoptns". Adapted for use with ISPIN by Larry Bartz. */
- X/* */
- X/* This backend recognizes one flag and argument in addition */
- X/* to those passed to it by dqueuer. The "-P" flag and its */
- X/* argument (que:dev) MUST be included in the config file, as */
- X/* shown below. */
- X/* */
- X/* Queue descriptor */
- X/* Comment */
- X/* Device descriptor */
- X/* Comment */
- X/* Device descriptor */
- X/* */
- X/* */
- X/* */
- X/* Qremote,R,N,F */
- X/* # GAR-1, Gary, IN POD, Qume 11/55 */
- X/* DGAR-1,R,/dev/tty15,/usr/spool/queuer/ISPI/ISPIN -P GAR-1 */
- X/* # LAF-1, Lafayette, IN POD, Centronics LW855 */
- X/* DLAF-1,R,/dev/tty15,/usr/spool/queuer/ISPI/ISPIN -P LAF-1 */
- X/* */
- X/* */
- X/* */
- X/* See Zeus Reference Manual "backend(M)", and Zilog Systems */
- X/* Administrator Manual (for ZEUS 3.21) 7.2.3, "Configuration */
- X/* File Description." */
- X/* */
- X/* */
- X/* */
- X/****************************************************************************/
- X
- Xparse_NQ(argc, argv)
- Xint argc;
- Xchar *argv[];
- X
- X{
- X register int x; /* general purpose index register */
- X extern short optind; /* \ used to get */
- X extern char *optarg; /* > options and */
- X short opt; /* / arguments */
- X
- X
- X while ((opt=getopt(argc, argv, "Bf:c:P:F:s:t:d:b")) != EOF)
- X {
- X switch(opt)
- X {
- X case 'B':
- X no_input = 1;
- X break;
- X case 'f':
- X fyle = optarg;
- X /* we will only get one file from dqueuer */
- X break;
- X case 'c':
- X sscanf(optarg, "%d", &prtimes);
- X break;
- X case 'P':
- X dest = optarg;
- X break;
- X case 'F':
- X from = optarg;
- X break;
- X case 's':
- X sptime = optarg;
- X break;
- X case 't':
- X title = optarg;
- X break;
- X case 'd':
- X usr_strng = optarg;
- X ++usr_addr;
- X break;
- X case 'b':
- X banner = 1;
- X break;
- X case '?':
- X default:
- X break;
- X }
- X }
- X
- X
- X /* Since we're choosing our output file from the specifications given */
- X /* in rtab, we don't want the file descriptor dqueuer passed to us. */
- X
- X close(SFFD);
- X
- X /* Since we have chosen not to update the status file, close it. */
- X
- X close(STATUSFD);
- X
- X return(0);
- X}
- X#endif
- X
- X
- X
- X
- X
- X#ifdef LP
- X/****************************************************************************/
- X/* parse_LP author = bartz 073088 */
- X/****************************************************************************/
- X/* */
- X/* subroutine to parse options passed to spooler backend */
- X/* */
- X/****************************************************************************/
- X/* */
- X/* description - */
- X/* This subroutine scans and stores-off the arguments passed to the */
- X/* backend (i.e., argv[]) by lp spooler. */
- X/* */
- X/* how invoked - parse_LP(argc, argv) */
- X/* int argc; */
- X/* char *argv[]; */
- X/* */
- X/* inputs - none */
- X/* */
- X/* outputs - none */
- X/* */
- X/* subroutines (in addition to standard C) - none */
- X/* */
- X/* */
- X/* */
- X/* */
- X/* */
- X/****************************************************************************/
- X
- Xparse_LP(argc, argv)
- Xint argc;
- Xchar *argv[];
- X
- X{
- X
- X
- X
- X /*
- X the number of arguments is: argc
- X the 0th argument is: exec path to this file
- X the 1st argument is: spool member name passed by ispintrfce program
- X the 2nd argument is: request id returned by lp
- X the 3rd argument is: logname of user who made request
- X the 4th argument is: title, if specified by user
- X the 5th argument is: number of copies requested by user
- X the 6th argument is: optional string specified by user on
- X the command line as the argument to
- X the "-o" flag
- X the 7th thru nth of arguments is: full path name of file to print
- X */
- X
- X /* dest is used as the search key for table lookup. */
- X /* It is the queue member's (printer's) name */
- X
- X
- X dest = &argv[1][0];
- X
- X from = &argv[3][0];
- X
- X title = &argv[4][0];
- X
- X
- X if(strlen(title) > 0)
- X {
- X /* if user bothers to specify title, assume he wants a banner */
- X banner = 1;
- X }
- X
- X
- X prtimes = atoi(argv[5]);
- X
- X
- X usr_strng = &argv[6][0];
- X
- X if(strlen(usr_strng) > 0)
- X {
- X /* if user bothers to specify arg to "-o" flag */
- X ++usr_addr;
- X }
- X
- X
- X fyles = &argv[7];
- X
- X
- X
- X /* how many args for file names to print ? */
- X num_ofile = numfiles = argc - 7;
- X
- X
- X
- X /* Since we're sending all of our messages to LOGFILE, */
- X /* close the standard error file we were given. */
- X fclose(stderr);
- X
- X
- X
- X /* LP gives us stdin assigned to /dev/null. We'll just */
- X /* close it in the interest of conservation. */
- X fclose(stdin);
- X
- X
- X
- X /* Since we're choosing our own output file from specs */
- X /* given in rtab, also close the stdout LP gave us. */
- X /* See installation notes and notes on control terminal. */
- X fclose(stdout);
- X
- X
- X
- X /* We'll assign our generic output output file pointer */
- X /* after the daemon tells us where we're going. */
- X
- X
- X
- X}
- X#endif
- X
- X
- X/****************************************************************************/
- X/* pid = read_tbl author = lbartz 22nov88 */
- X/****************************************************************************/
- X/* */
- X/* subroutine to read and parse the table of remote printer info */
- X/* */
- X/****************************************************************************/
- X/* */
- X/* description - */
- X/* This subroutine is invoked to collect info necessary to make */
- X/* contact with the remote printer. */
- X/* */
- X/* how invoked - read_tbl() */
- X/* */
- X/* inputs - none */
- X/* */
- X/* outputs - none */
- X/* */
- X/* subroutines (in addition to standard C) - none */
- X/* */
- X/* comments - The success of this subroutine depends on the existence */
- X/* of the external file which is #defined as RTAB: */
- X
- Xread_tbl()
- X{
- X ushort not_yet = 1; /* we haven't found the entry we're looking for yet */
- X
- X int buf_ctr = 0;
- X
- X int c;
- X
- X
- X
- X if((rtab = fopen(RTAB,"r")) == NULL)
- X {
- X /* format an error message */
- X time(&tloc);
- X nowtime = (struct tm *)localtime(&tloc);
- X time_str = asctime(nowtime);
- X
- X sprintf(errmsg,"ISPIN: printer %s: open %s: %s.\n",dest,RTAB,sys_errlist[errno]);
- X sprintf(errmsg2," USER: %s\n",from);
- X strcat(errmsg,errmsg2);
- X if(usr_addr)
- X {
- X sprintf(errmsg2," ADDR: %s\n",usr_strng);
- X strcat(errmsg,errmsg2);
- X }
- X#ifdef NQ
- X sprintf(errmsg2," FILE: %s\n",fyle);
- X#else
- X sprintf(errmsg2," FILE: %s\n",fyles[0]);
- X#endif
- X strcat(errmsg,errmsg2);
- X sprintf(errmsg2," TIME: %s\n",time_str);
- X strcat(errmsg,errmsg2);
- X
- X /* call the error routine, never come back */
- X my_error(SYSERR);
- X
- X }
- X
- X
- X
- X while(not_yet)
- X {
- X while(((c = getc(rtab)) == ' ') || (c == '\t')); /* ignore spaces */
- X
- X while((c != EOF) && (not_yet))
- X {
- X buf_ctr = 0;
- X switch(c)
- X {
- X case '#':
- X ignore_line(); /* if line begins with a # */
- X break;
- X default:
- X line_buf[buf_ctr] = c;
- X ++buf_ctr;
- X while(((c = getc(rtab)) != '\n') && (c != EOF))
- X {
- X line_buf[buf_ctr] = c;
- X ++buf_ctr;
- X }
- X line_buf[buf_ctr] = '\0';
- X /* check here to see if we got the correct line */
- X status = 0;
- X status = parse_tokens();
- X
- X
- X if(status == 0)
- X {
- X /* we found what we were looking for */
- X not_yet = 0;
- X return(0);
- X }
- X break;
- X }
- X if((c != EOF)&&(not_yet))
- X while(((c = getc(rtab)) == ' ') || (c == '\t'));
- X }
- X if((c == EOF)&&(not_yet))
- X {
- X /* we got all the way through the file but didn't find the printer */
- X return(1);
- X }
- X }
- X return(0);
- X}
- X
- X
- Xignore_line()
- X{
- X int c;
- X
- X /* ignore everything after # char as a comment */
- X while(((c = getc(rtab)) != '\n') && (c != EOF));
- X}
- X
- X
- X
- X
- X
- Xparse_tokens()
- X{
- X char *tokptr, *movptr, *lastptr ;
- X char *strptr = line_buf;
- X int ctr1 = 0; /* a counter, which token is this? */
- X int toggle = 0; /* a toggle switch for EXPECT/SEND */
- X int n = 0;
- X
- X
- X
- X if((tokptr = strtok(strptr, ";")) != NULLCHARPTR)
- X {
- X
- X
- X strptr = NULLCHARPTR; /* so we can proceed if we want to */
- X if(strcmp(tokptr,dest) == 0)
- X {
- X /* This is the line from RTAB we are looking for. */
- X
- X
- X
- X /* First, set up the heads of our lists. */
- X
- X busy_head = (struct busy_list *) calloc(1,sizeof(struct busy_list));
- X busy_head->next = NULL;
- X busy_list = busy_curr = busy_head;
- X
- X dead_head = (struct dead_list *) calloc(1,sizeof(struct dead_list));
- X dead_head->next = NULL;
- X dead_list = dead_curr = dead_head;
- X
- X quit_head = (struct quit_list *) calloc(1,sizeof(struct quit_list));
- X quit_head->next = NULL;
- X quit_list = quit_curr = quit_head;
- X
- X disc_head = (struct disc_list *) calloc(1,sizeof(struct disc_list));
- X disc_head->next = NULL;
- X disc_list = disc_curr = disc_head;
- X
- X expt_head = (struct expt_list *) calloc(1,sizeof(struct expt_list));
- X expt_head->prev = NULL;
- X expt_head->next = NULL;
- X expt_list = expt_curr = expt_head;
- X
- X send_head = (struct send_list *) calloc(1,sizeof(struct send_list));
- X send_head->prev = NULL;
- X send_head->next = NULL;
- X send_list = send_curr = send_head;
- X
- X /* Now we'll get the info we need to make the connection. */
- X
- X while((tokptr = strtok(strptr, ";")) != NULLCHARPTR)
- X {
- X strptr = NULLCHARPTR; /* so we can proceed if we want to */
- X ++ctr1;
- X
- X
- X switch(ctr1)
- X {
- X case 1:
- X /* strtok can only parse one string at a time,*/
- X /* so we have to process the DEVICES field */
- X /* ourselves. */
- X /* PROCESS DEVICES FIELD HERE */
- X /**********************************************/
- X if((movptr = strchr(tokptr,',')) != NULLCHARPTR)
- X {
- X /* we have more than one device */
- X
- X /* save current position */
- X ++movptr;
- X lastptr = movptr;
- X
- X /* get the first one */
- X /* how many characters before the first comma ? */
- X n = strcspn(tokptr,",");
- X strncpy(dev_ray[0].name,tokptr,n);
- X dev_ray[0].name[n] = '\0';
- X
- X ret_val = 0;
- X
- X while((movptr = strchr(lastptr,',')) != NULLCHARPTR)
- X {
- X ++ret_val;
- X if(ret_val <= 10)
- X {
- X /* get the next one */
- X /* how many characters before the next comma ? */
- X n = strcspn(lastptr,",");
- X strncpy(dev_ray[ret_val].name,lastptr,n);
- X dev_ray[ret_val].name[n] = '\0';
- X }
- X ++movptr;
- X lastptr = movptr;
- X }
- X
- X /* get the last one */
- X /* how many characters before the end ? */
- X n = strlen(lastptr);
- X ++ret_val;
- X if(ret_val <= 10)
- X {
- X strcpy(dev_ray[ret_val].name,lastptr);
- X }
- X
- X for(++ret_val; ret_val <= 10; ++ret_val)
- X {
- X strcpy(dev_ray[ret_val].name,"NONE");
- X }
- X }
- X else
- X {
- X /* only one device has been specified */
- X strcpy(dev_ray[0].name,tokptr);
- X
- X
- X for(ret_val = 1; ret_val <= 10; ++ret_val)
- X {
- X strcpy(dev_ray[ret_val].name,"NONE");
- X }
- X }
- X /**********************************************/
- X break;
- X case 2:
- X speed = atoi(tokptr);
- X break;
- X default:
- X switch(tokptr[0])
- X {
- X case '-':
- X switch(tokptr[1])
- X {
- X case 'B':
- X /* BUSY */
- X while(busy_curr->next != NULL) /* until end o'list */
- X {
- X /* walk down the list */
- X busy_curr = busy_curr->next;
- X }
- X
- X /* don't really use the head for data storage */
- X /* allocate a new one */
- X busy_list = (struct busy_list *) calloc(1,sizeof(struct busy_list));
- X
- X /* link it */
- X busy_curr->next = busy_list;
- X
- X /* make the new list member the current list member */
- X busy_curr = busy_list;
- X
- X /* Put our new-found data in the newly allocated storage */
- X /* after first aiming the pointer at more new storage. */
- X /* string begins at tokptr[2] */
- X busy_curr->busy_strg = (char *) calloc(1, ((strlen(&tokptr[2]))+1));
- X strcpy(busy_curr->busy_strg,&tokptr[2]);
- X
- X
- X
- X
- X
- X /* terminate the list */
- X busy_curr->next = NULL;
- X break;
- X case 'I':
- X /* DEAD */
- X while(dead_curr->next != NULL) /* until end o'list */
- X {
- X /* walk down the list */
- X dead_curr = dead_curr->next;
- X }
- X
- X /* don't really use the head for data storage */
- X /* allocate a new one */
- X dead_list = (struct dead_list *) calloc(1,sizeof(struct dead_list));
- X
- X /* link it */
- X dead_curr->next = dead_list;
- X
- X /* make the new list member the current list member */
- X dead_curr = dead_list;
- END_OF_FILE
- if test 38857 -ne `wc -c <'ISPIN/src/ISPIN.c.aa'`; then
- echo shar: \"'ISPIN/src/ISPIN.c.aa'\" unpacked with wrong size!
- fi
- # end of 'ISPIN/src/ISPIN.c.aa'
- fi
- if test -f 'ISPIN/doc/TECH.doc' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'ISPIN/doc/TECH.doc'\"
- else
- echo shar: Extracting \"'ISPIN/doc/TECH.doc'\" \(7256 characters\)
- sed "s/^X//" >'ISPIN/doc/TECH.doc' <<'END_OF_FILE'
- X
- X
- X Indianapolis Standard Printer Interface for Networked printers
- X
- X ISPIN
- X
- X ISPIN was developed by the Internal Revenue Service at Indianapolis. It
- X supports printing to networked printers through the native print spooler.
- X The author has secured permission through appropriate channels to release
- X ISPIN into the public domain.
- X
- X
- X /* WHY? */
- X
- X Why would you want to use ISPIN?
- X
- X - You've got more printers than you like hardwired to your cpu(s)
- X already and your users want more. You'd like to be able to
- X support more printers while using fewer ttys than you do now.
- X
- X - You've got users at far-flung remote sites. Their printers are
- X "slaved" to a few terminals. This limits the access of those
- X printers to those users who are using those particular terminals.
- X Everybody has their own "personal" printer - wasteful.
- X
- X - You have several cpus at your site, each with their own hardwired
- X printers. This limits your flexibility in balancing workload
- X across multiple systems. If you move an application to another
- X system, you've got to make sure the printers go with it.
- X
- X - You're bored. You need a new software toy.
- X
- X - If all users on all of your systems could access all of your
- X printers through all of your applications, life would be so
- X sweet. You'd do a lot less wiring/re-wiring and spend much
- X less time adding/deleting queue members and maintaining printer
- X selection menus.
- X
- X - You have already tried uux'ing print jobs from one system to
- X another to overcome the limitations imposed by hardwired printers.
- X But your users gripe about the delays, and you are sick of the
- X maintenance.
- X
- X - Your system(s) support(s) System V's lp/lpsched or
- X (the old, Old, OLD) Zilog ZEUS 3.21 nq/xq/dqueuer.
- X (ISPIN does not, at present, support the Berzerkeley lpr.)
- X
- X - You're bored. You need a new software toy. Not just something
- X to diddle around with and clear the screen when the boss walks
- X by. Something that will save money, increase productivity, and
- X make you a systems administration/datacomm hero in your shop
- X (or in your own mind, like me).
- X
- X
- X /* HOW? */
- X
- X How could you implement ISPIN?
- X
- X 1. Disconnect all/some printers from their hardwired-to-cpu
- X connections.
- X
- X 2. Connect all/some of your printers to a network, like:
- X
- X - statistical switching multiplexor, such as Tellabs, Equinox,
- X David, Gandolph, Mitron, whatever. (examples, NOT ENDORSEMENT!)
- X
- X or
- X
- X - X.25 with asynchronous pads
- X
- X 3. Connect one or more ttys per cpu to the network. How many depends
- X only upon how many simultaneous print jobs you want to support.
- X In any case, it'll be far fewer ports than you use to support
- X hardwired printers.
- X
- X 4. Install and configure ISPIN, the easiest and least time-consuming
- X step.
- X
- X 5. Use your native print spooling software to add/delete, enable/
- X disable queue members. Also use native commands to issue and
- X cancel print requests.
- X
- X
- X /* HUH? */
- X
- X How does ISPIN work?
- X
- X - Your native spooler/queuer subsystem is fine for hardwired
- X printers. It accepts enqueueing and cancellation requests,
- X reports on its status, and allows you to add and remove queue
- X members (printers). When the spooler/queuer daemon determines
- X that it is time for a user's request to be satisfied, it
- X passes pertinent information to an executable or a shell script
- X which sends the print job out the designated tty to the printer.
- X This last process is known as the backend, or interface.
- X
- X - We substitute a call to the ISPIN executable for the backend.
- X
- X - The ISPIN process reads an entry for itself from a table
- X called "rtab". The rtab is intentionally similar to the uucp
- X L.sys file (or Systems file under HoneyDanBer uucp). There
- X is one rtab entry per virtual printer (any given physical printer
- X may be known or treated as several virtual printers).
- X
- X - The rtab entry contains the chat data (EXPECT/SEND) necessary
- X for the ISPIN process to negotiate through the network to the
- X printer. This data may also include printer initialization and
- X configuration commands which can be passed both before and after
- X the print job.
- X
- X - The rtab entry also contains a field which defines which tty(s)
- X (from one to eleven possible) this printer may be called through.
- X
- X - The ISPIN process passes a formatted message to a daemon process
- X known as IQUEUER. IQUEUER determines which of the requested
- X ttys is available, and issues a message back to the ISPIN, telling
- X it to proceed, using a particular tty. IQUEUER also maintains
- X lock files, thereby avoiding conflicts with uucp, cu, uugetty,
- X etc.
- X
- X - The ISPIN process, after receipt of its marching orders, sets
- X up the tty, negotiates the network, and sends the job to the
- X printer.
- X
- X - The rtab entry also contains flags and arguments which indicate
- X network and printer busy and fault conditions. The ISPIN process
- X watches for these indications to determine whether it should
- X terminate and loop or quit.
- X
- X - All the while, the ISPIN process is under the complete control
- X of the native spooler/queuer. Its status (active or waiting) is
- X known to the native spooler/queuer daemon. It may be cancelled,
- X rescheduled, whatever by the native commands.
- X
- X - While the ISPIN is "active" with respect to the native queuer,
- X the IQUEUER daemon is notified by the ISPIN process of its
- X current phase of execution (startup, negotiating the network,
- X printing, disconnecting, looping). The current status of all
- X currently executing ISPIN processes may be queryied via another
- X executable, known as "iq".
- X
- X - This all sounds very busy. But is is quite efficient and is
- X gratifyingly robust. If the printer is offline or busy, or
- X the network is unable to make the connection, the ISPIN will
- X loop and resubmit itself to the IQUEUER. If other jobs are
- X waiting for network access through the tty(s), the looper is
- X made to wait while other potentially successful jobs go ahead.
- X If a Greyhound takes out a telephone pole between the cpu and
- X the printer (or other mid-job disconnection), ISPIN detects
- X the fault and loops as above. Upon successful re-connection,
- X the job will be printed in its entirety.
- X
- X - ISPIN is not experimental software. It has been in production
- X use since June 1989 and is currently (Nov 1991) operational at
- X more than forty multiple-cpu sites.
- END_OF_FILE
- if test 7256 -ne `wc -c <'ISPIN/doc/TECH.doc'`; then
- echo shar: \"'ISPIN/doc/TECH.doc'\" unpacked with wrong size!
- fi
- # end of 'ISPIN/doc/TECH.doc'
- fi
- if test -f 'ISPIN/doc/OLD-DOCS/README.beta.1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'ISPIN/doc/OLD-DOCS/README.beta.1'\"
- else
- echo shar: Extracting \"'ISPIN/doc/OLD-DOCS/README.beta.1'\" \(3950 characters\)
- sed "s/^X//" >'ISPIN/doc/OLD-DOCS/README.beta.1' <<'END_OF_FILE'
- X
- X
- X
- X date: February 1, 1989
- X
- X to: ISPIN Beta Test Site Volunteer
- X
- X from: Chief, Operations Branch, Information Systems Division, 35:IS
- X
- X subject: Indianapolis Standard Printer Interface (for Network printers)
- X
- X
- X
- X Thank you for accepting my invitation to help me test ISPIN.
- X I chose you and your site for extension of my invitation because I
- X trust your judgement, your technical expertise, and your potential
- X for helping me "market" this thing, should our testing prove
- X successful. I am also counting on your impartiality to help me
- X me discover and address whatever shortcomings may become
- X apparent during the course of testing.
- X
- X This test is a test of the application, not of installation procedures,
- X nor of documentation, so please accept what is included here under
- X that premise for now. I promise to "pretty it up" for the general
- X release.
- X
- X ISPIN is designed so that it may be installed anywhere on your system.
- X The decision about where files and directories will reside is made at
- X compile time. I have, however, defined default locations in the code
- X and in the install scripts. For purposes of our testing, please just
- X use the default locations.
- X
- X The tape upon which I have transmitted the application was created
- X in cpio format. cd to a directory in which you want this release to
- X be written, then cpio -iudmvB < your_nine_track_drive
- X
- X The result of this cpio will be the creation of a directory named
- X ISPIN.beta. ISPIN.beta will contain two subdirectories, namely
- X ISPI and ISPIN.
- X
- X ISPIN contains the source code, install documents, and install
- X scripts for the new ISPIN application. Of course, the ISPIN
- X application serves as a BACKEND for either of two native
- X queuer/spoolers, lp or dqueuer.
- X
- X The ISPI directory contains the freshest version of our ISPI
- X application. ISPI is an application which serves as a FRONTEND
- X for the two queuer/spoolers. The ISPI application is fully self-
- X contained, with its own source code, documentation, etc. Use it
- X if you like, or don't use it. I sent ISPI along because we have
- X found it to be an extremely useful tool to support the native
- X queuer/spoolers.
- X
- X ISPIN and ISPI are TWO SEPARATE AND DISTINCT APPLICATIONS.
- X Neither depends upon the other for functionality. You may use ISPIN
- X without ISPI. You may use ISPI without ISPIN.
- X
- X The documentation of the formal type is sparse, but the code is
- X overflowing with comments. Read comments in the files common.h
- X and rtab to get a general idea of what is going on in ISPIN and
- X its related entities.
- X
- X If you are installing this application under ZEUS 3.21 and its
- X nq/xq/dqueuer queuer family, read NQinstall.doc.
- X
- X If you are installing this application under System V UNIX and
- X the lp spooler, read LPinstall.doc.
- X
- X For now, install on Zilogs only, please. I haven't yet had an
- X opportunity to test in any other environment. I expect, however,
- X to have the code running on a Sequent Balance B8 soon.
- X
- X Here's a late news flash: ISPIN also compiles and runs just fine
- X on the AT&T UNIX PC (mine is a 3B1). I have included an install
- X script called 3B1install.csh, which is identical to LPinstall.csh
- X except for deletion of the "-f" flag from the compile lines.
- X
- X I'll also say that after my testing, my confidence level is high.
- X Indianapolis is currently proceeding with full scale implementation
- X of ISPIN.
- X
- X Feedback is what I need. Please communicate whatever observations
- X you may have soon and often.
- X
- X
- X
- X Larry Bartz
- X
- X
- END_OF_FILE
- if test 3950 -ne `wc -c <'ISPIN/doc/OLD-DOCS/README.beta.1'`; then
- echo shar: \"'ISPIN/doc/OLD-DOCS/README.beta.1'\" unpacked with wrong size!
- fi
- # end of 'ISPIN/doc/OLD-DOCS/README.beta.1'
- fi
- if test -f 'ISPIN/doc/OLD-DOCS/rel_1.2.fixes' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'ISPIN/doc/OLD-DOCS/rel_1.2.fixes'\"
- else
- echo shar: Extracting \"'ISPIN/doc/OLD-DOCS/rel_1.2.fixes'\" \(2255 characters\)
- sed "s/^X//" >'ISPIN/doc/OLD-DOCS/rel_1.2.fixes' <<'END_OF_FILE'
- X
- X
- X ISPIN RELEASE 1.2 CHANGES
- X
- X ISPIN release 1.2 includes updates to correct a problem which existed
- X in release 1.1. The method by which waiting jobs are queued has
- X been modified. Formerly, waiting print jobs were assigned to a device
- X (port) and remained in queue for that device, even if another device which
- X the job could use became available. Now under release 1.2, all waiting
- X jobs are put in one queue and are not assigned a device until they are
- X actually ready to be printed. This results in more efficient scheduling
- X of print jobs. The files which are affected by this change are iqueuer.h,
- X IQUEUER.c, iqueuer, IQ.c, and iq.
- X
- X Release 1.2 also corrects a problem with ISPIN flow control on Sequent Balance
- X systems which are connected directly to CDN. The DYNIX SVAE Summary (Section
- X A.2.16) states that the AT&T UNIX System V general terminal interface is
- X not fully supported under the Sequent System V Applications Environment.
- X Since the Sequent Balance is NOT a TRUE System V machine, a portion of the
- X ISPIN application was not properly working. The program ISPIN.c has been
- X modified to correct this problem. The rtab entries on Sequent Balance machines
- X connected directly to CDN should also be modified to fix this problem. At
- X least two disconnect arguments - "-Dpad>" and "-De" should be included in
- X each rtab entry. Otherwise, a disconnection because of a printer being
- X turned off may not be recognized. See rtab for an example of a Sequent
- X Balance rtab entry.
- X
- X Also, the example rtab entries for "CPU to CDN to PRINTER" connections
- X have been enhanced to add features which make printing more reliable.
- X In most cases, the old examples work fine. However, the new rtab entries
- X are more flexible in case of a failure to negotiate successfully to a
- X printer. The examples include entries to try again if no characters are
- X received from CDN. Also, the disconnect sequence has been changed to use
- X a CDN disconnect command other than the break character. The break
- X character causes parity errors to occur on some printers (i.e. Qume 11/55).
- X For more details, see the example files in the directory
- X "ISPIN.rel_1.2/ISPIN/install/lib_rtab/CPU_CDN_PTR".
- X
- END_OF_FILE
- if test 2255 -ne `wc -c <'ISPIN/doc/OLD-DOCS/rel_1.2.fixes'`; then
- echo shar: \"'ISPIN/doc/OLD-DOCS/rel_1.2.fixes'\" unpacked with wrong size!
- fi
- # end of 'ISPIN/doc/OLD-DOCS/rel_1.2.fixes'
- fi
- if test -f 'ISPIN/misc/ISPIT.dr/ispit.sh' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'ISPIN/misc/ISPIT.dr/ispit.sh'\"
- else
- echo shar: Extracting \"'ISPIN/misc/ISPIT.dr/ispit.sh'\" \(395 characters\)
- sed "s/^X//" >'ISPIN/misc/ISPIT.dr/ispit.sh' <<'END_OF_FILE'
- X#!/bin/sh
- X# ispit.sh 080791 LSB
- X# written to run as the user ispit's default shell (last field in passwd entry)
- X# stty call is of "att" type, so must be run under att on dual universe boxes
- Xecho "OUTPUT_FILE?"
- Xread OF
- Xecho "OK"
- Xstty raw ixoff -echo hupcl brkint
- Xecho "ISPIT START" >> ispit.log
- Xdate >> ispit.log
- Xecho $OF >> ispit.log
- X./eot_trap > $OF
- Xdate >> ispit.log
- Xstty sane
- Xexit
- END_OF_FILE
- if test 395 -ne `wc -c <'ISPIN/misc/ISPIT.dr/ispit.sh'`; then
- echo shar: \"'ISPIN/misc/ISPIT.dr/ispit.sh'\" unpacked with wrong size!
- fi
- # end of 'ISPIN/misc/ISPIT.dr/ispit.sh'
- fi
- echo shar: End of archive 7 \(of 15\).
- cp /dev/null ark7isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 15 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-
-