Newsgroups: comp.sources.unix
From: sir-alan!ispin!lbartz@iuvax.cs.indiana.edu (Larry Bartz)
Subject: v25i121: Indianapolis Standard Printer Interface for Networked printers, Part10/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 121
Archive-Name: ispin/part10

#! /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 10 (of 15)."
# Contents:  ISPIN/src/ISPIN.c.ad ISPIN/doc/rtab
# Wrapped by socrates@indy6 on Tue Jan 28 15:27:01 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'ISPIN/src/ISPIN.c.ad' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'ISPIN/src/ISPIN.c.ad'\"
else
echo shar: Extracting \"'ISPIN/src/ISPIN.c.ad'\" \(34683 characters\)
sed "s/^X//" >'ISPIN/src/ISPIN.c.ad' <<'END_OF_FILE'
X            nowtime = (struct tm *)localtime(&tloc);
X            time_str = asctime(nowtime);
X
X            sprintf(errmsg,"ISPIN: printer %s: received SIGSTOP.\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          if(port_open == 1)
X          {
X            sprintf(errmsg2,"     DEV: %s\n",GO_dev);
X            strcat(errmsg,errmsg2);
X          }
X          sprintf(errmsg2,"    FILE: %s\n",fyle);
X          strcat(errmsg,errmsg2);
X          sprintf(errmsg2,"    TIME: %s\n",time_str);
X          strcat(errmsg,errmsg2);
X
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	    if(port_open == 1)
X	    {
X              savd_errno = SIGSTOP;
X              stayt = QUITTING;
X              if(quit_once > 0)
X              {
X                LONGJMP(kwit, quit_once);
X              }
X              else
X              {
X	        ret_val = quit_net();
X              }
X	    }
X            my_exit(reason);
X      break;
X#endif
X    default:
X  /************************************************************************/
X  /* Reset traps on all signals!                                          */
X  /* We don't want to be interrupted when we already know we're           */
X  /* on our way out!                                                      */
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        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);   /* ignore "stop" signal */
X#endif
X         if((logfile = fopen(LOGFILE,"a+")) != NULL)
X         {
X            fprintf(logfile,errmsg);
X            fclose(logfile);
X         }
X	    if(port_open == 1)
X	    {
X              savd_errno = reason;
X              stayt = QUITTING;
X              if(quit_once > 0)
X              {
X                LONGJMP(kwit, quit_once);
X              }
X              else
X              {
X	        ret_val = quit_net();
X              }
X	    }
X            my_exit(reason);
X      break;
X  }
X  return;
X}
X
X
Xmy_exit(reason)
Xint reason;
X{
X  switch(reason)
X  {
X    case 0:
X      notify(DONE);
X      if(savd_errno > 255)
X      {
X        /* see other references to savd_errno */
X        savd_errno -= 255;
X      }
X      exit(savd_errno);
X      break;
X
X    case SIGTERM:
X    case SIGHUP:
X      notify(TROUBLE);
X      exit(reason);
X      break;
X
X    case NONOTIFY:
X      exit(reason);
X      break;
X
X#ifdef NQ
X    case SIGSTOP:
X      notify(TROUBLE);
X      exit(reason);
X      break;
X#endif
X
X    default:
X      notify(TROUBLE);
X      if(reason > 255)
X      {
X        /* see other references to savd_errno */
X        reason -= 255;
X      }
X      exit(reason);
X      break;
X  }
X}
X
X
Xbusyordead()
X{
X  /* called whenever the EXPECT string is not matched.    */
X  /* compare to BUSY and DEAD (in separate functions)     */
X  /* If it is BUSY, we'll come back here, close the port, */
X  /* sleep a while, then call setuptty(), negotiate(),    */
X  /* and do_it(). We need to keep and increment a static  */
X  /* to compare to the BUSYLOOP constant.                 */
X  /* If it is DEAD, we'll come back here, close the port, */
X  /* compose an error message, and error out.             */
X
X  /* If it is neither BUSY nor DEAD, just return.             */
X
X
X
X  if(busy_head->next != NULL)
X  /* user has specified busy flag(s) */
X  {
X
X
X    if(netloop <= MAXNET_TRY)
X    {
X
X
X      if(busy()== 1)
X      {
X        /* try again */
X        again();
X      }
X
X
X     }
X     else
X     {
X       /* need to send out an error msg */
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: %d BUSY LOOPS, so quitting.\n",dest,netloop);
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          if(port_open == 1)
X          {
X            sprintf(errmsg2,"     DEV: %s\n",GO_dev);
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  if(dead_head->next != NULL)
X  /* user has specified inactive flag(s) */
X  {
X
X
X    if(dead() == 1)
X    {
X     /* need to send out an error msg */
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: DEAD connection.\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          if(port_open == 1)
X          {
X            sprintf(errmsg2,"     DEV: %s\n",GO_dev);
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
X
X              /* Doesn't match, is neither BUSY nor DEAD */
X
X  return(0);
X}
X
X
Xbusy()
X{
X  ushort answer;
X
X  /* set our list pointers to point at head of the list */
X  busy_list = busy_curr = busy_head;
X
X  while(busy_curr->next != NULL)
X  {
X    busy_curr = busy_curr->next;
X
X
X
X
X    answer = matcher(in_buf,busy_curr->busy_strg);
X
X    if(answer == 0)
X    {
X      return(1);
X    }
X  }
X  return(0);
X}
X
X
Xdead()
X{
X  ushort answer;
X
X  /* set our list pointers to point at head of the list */
X  dead_list = dead_curr = dead_head;
X
X  while(dead_curr->next != NULL)
X  {
X    dead_curr = dead_curr->next;
X    answer = matcher(in_buf,dead_curr->dead_strg);
X
X    if(answer == 0)
X    {
X      return(1);
X    }
X  }
X  return(0);
X}
X
X
X/****************************************************************************/
X/****************************************************************************/
X/*                                                                          */
X/*                                                                          */
X/****************************************************************************/
X/*                                                                          */
X/*   description - the global pointer i_stream will be set to the file      */
X/*                 before this module is called.                            */
X/*                                                                          */
X/****************************************************************************/
X
X
Xdo_it()
X{
X        int z;                  /* general purpose counter */
X        int w;                  /* general purpose counter */
X        int n;                  /* general purpose counter */
X        int do_times;           /* how many times do we print it? */
X        char  ff = '\f';        /* 'C' formfeed character */
X        char  line[BURSTSIZ + 1];     /* a burst of text */
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: inside do_it. time:\n",dest);
X          strcat(errmsg,"                            ");
X          strcat(errmsg,time_str);
X          strcat(errmsg,"\n");
X          if(port_open == 1)
X          {
X            sprintf(errmsg2,"     DEV: %s\n",GO_dev);
X            strcat(errmsg,errmsg2);
X          }
X         if((logfile = fopen(LOGFILE,"a+")) != NULL)
X         {
X            fprintf(logfile,errmsg);
X            fclose(logfile);
X         }
X#endif
X
X          if(logging)
X          {
X            /* format an event message */
X            time(&tloc);
X            nowtime = (struct tm *)localtime(&tloc);
X            time_str = asctime(nowtime);
X
X            sprintf(errmsg,"ISPIN: printer %s: now printing.\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          if(port_open == 1)
X          {
X            sprintf(errmsg2,"     DEV: %s\n",GO_dev);
X            strcat(errmsg,errmsg2);
X          }
X#ifdef NQ
X            sprintf(errmsg2,"    FILE: %s\n",fyle);
X#else
X            sprintf(errmsg2,"    FILE: %s\n",fyles[numfiles]);
X#endif
X            strcat(errmsg,errmsg2);
X            sprintf(errmsg2,"    TIME: %s\n",time_str);
X            strcat(errmsg,errmsg2);
X
X            if((logfile = fopen(LOGFILE,"a+")) != NULL)
X            {
X               fprintf(logfile,errmsg);
X               fclose(logfile);
X            }
X          }
X
X                                /* set up timeout for write */
X        signal(SIGALRM, my_error);
X
X                                /* assume no timeout */
X                                time_out = 0; 
X
X                                /* Wait a long time for the write to */
X                                /* happen. This allows user time to  */
X                                /* change the ribbon, clear paper    */
X                                /* jam, or replenish paper supply.   */
X                                /* On the other hand, we won't wait  */
X                                /* forever.                          */
X                                alarm(WRITEWAIT);
X
X        /* wait here for the output to drain */
X        ioctl(out_file, TCSBRK, 1);
X
X                                /* turn off the alarm clock */
X                                alarm(0);
X
X                                /* ignore alarm */
X        signal(SIGALRM, SIG_IGN);
X
X                                if(time_out == 1)
X                                {
X                                  /* We timed out on the write.*/
X                                  /* Behave as though we were  */
X                                  /* disconnected.             */
X
X                                  my_error(TIMEOUT);
X                                }
X
X
X        /* start out with clean buffers */
X        ioctl(out_file, TCFLSH, 2);
X
X        /* advise IQUEUER of our current state */
X        notify(PRINTING);
X
X        /* do a banner, if apropos */
X        if(banner)
X        {
X          ret_val = prtbanner();
X        }
X
X
X
X        for(do_times = prtimes;do_times > 0;do_times--)
X        {
X                rewind(i_stream);
X                z = 0;
X                w = 0;
X
X                while ((z = fread(line, 1, BURSTSIZ, i_stream)) > 0) 
X                {
X                                w = z;
X                                line[z] = '\0';
X
X                                /* set up timeout for write */
X        signal(SIGALRM, my_error);
X
X                                /* assume no timeout */
X                                time_out = 0; 
X
X                                /* Wait a long time for the write to */
X                                /* happen. This allows user time to  */
X                                /* change the ribbon, clear paper    */
X                                /* jam, or replenish paper supply.   */
X                                /* On the other hand, we won't wait  */
X                                /* forever.                          */
X                                alarm(WRITEWAIT);
X
X                                n = write (out_file, line, z);
X
X                                count1 = alarm(0);
X
X                                if((n < z)||(time_out == 1))
X                                {
X                                  if(time_out == 1)
X                                  {
X                                    my_error(TIMEOUT);
X                                  }
X                                  else
X                                  {
X                                    my_error(DISCONNECTING);
X                                  }
X                                }
X
X                                alarm((unsigned)count1);
X
X                                /* wait here for the output to drain */
X                                ioctl(out_file, TCSBRK, 1);
X
X                                /* turn off the alarm clock */
X                                alarm(0);
X
X                                /* ignore alarm */
X        signal(SIGALRM, SIG_IGN);
X
X                                if(time_out == 1)
X                                {
X                                  /* We timed out on the write.*/
X                                  /* Behave as though we were  */
X                                  /* disconnected.             */
X
X                                  my_error(TIMEOUT);
X                                }
X
X
X  /*************************************************************/
X  /* If our list of possible "disconnect" strings is non-NULL, */
X  /* check for disconnections.                                 */
X  if(disc_head->next != NULL)
X  {
X
X    /* Don't worry about this read taking any time. With       */
X    /* VMIN == 0 and VTIME == 15, we'll only be here for       */
X    /* VTIME tenths of a second if there is nothing to read.   */
X    /* Of course, if things are going well, there will be      */
X    /* no chars here. HOWEVER, if the network config is goofed,*/
X    /* and all of the chars we send out are being echoed back  */
X    /* to us, we'll waste several cpu cycles reading and eval- */
X    /* uating them.                                            */
X
X    /* If I could wrap my hands around the neck of the Sequent */
X    /* BOZO responsible for this goofy ioctl implementation... */
X
X#ifndef DYNIX
X    ioctl(out_file, TCSETA, &T_RAW);
X#endif
X
X    /* set the no delay bit so we can do a quickie read */
X    fcntl(out_file,F_SETFL,flgs_ndelay);
X
X    chars_got = read(out_file,in_buf,(BUFSIZ -1));
X    
X    /* turn the delay bit back on, so we can accomodate flow control */
X    fcntl(out_file,F_SETFL,flgs_delay);
X
X#ifndef DYNIX
X    ioctl(out_file, TCSETA, &T_COOK);
X#endif
X
X    if(chars_got > 0)
X    {
X      isit_gone();
X    }
X
X  }
X
X                                /* Flush the input buffer */
X                                /* in case some fool has the line */
X                                /* configured to echo back to us. */
X                                /* This should help the older Zilogs cope */
X                                /* by keeping their incoming c_lists from */
X                                /* overflowing. */
X                                ioctl(out_file, TCFLSH, 0);
X
X                                /* no need to hurry a printer! */
X                                /* 03/28/89: All alpha and beta*/
X                                /* testing has shown that a    */
X                                /* BURSTWAIT of 0 is just fine.*/
X                                /* I'll leave it in here just  */
X                                /* in case...                  */
X                                /* sleep(BURSTWAIT); */
X                }
X                if(raw < 1)
X                {
X                  /* if user has not requested REALLY RAW output */
X                  if (line[w - 1] != ff)
X                  {
X
X                                /* set up timeout for write */
X        signal(SIGALRM, my_error);
X
X                                /* assume no timeout */
X                                time_out = 0; 
X
X                                /* Wait a long time for the write to */
X                                /* happen. This allows user time to  */
X                                /* change the ribbon, clear paper    */
X                                /* jam, or replenish paper supply.   */
X                                /* On the other hand, we won't wait  */
X                                /* forever.                          */
X                                alarm(WRITEWAIT);
X
X                                write (out_file, &ff, 1);
X
X                                /* turn off the alarm clock */
X                                alarm(0);
X
X                                /* ignore alarm */
X        signal(SIGALRM, SIG_IGN);
X
X                                if(time_out == 1)
X                                {
X                                  /* We timed out on the write.*/
X                                  /* Behave as though we were  */
X                                  /* disconnected.             */
X
X                                  my_error(TIMEOUT);
X                                }
X
X                  }
X                }
X        }
X
X
X
X                                /* set up timeout for write */
X        signal(SIGALRM, my_error);
X
X                                /* assume no timeout */
X                                time_out = 0; 
X
X                                /* Wait a long time for the write to */
X                                /* happen. This allows user time to  */
X                                /* change the ribbon, clear paper    */
X                                /* jam, or replenish paper supply.   */
X                                /* On the other hand, we won't wait  */
X                                /* forever.                          */
X                                alarm(WRITEWAIT);
X
X        /* wait here for the output to drain */
X        ioctl(out_file, TCSBRK, 1);
X
X                                /* turn off the alarm clock */
X                                alarm(0);
X
X                                /* ignore alarm */
X        signal(SIGALRM, SIG_IGN);
X
X                                if(time_out == 1)
X                                {
X                                  /* We timed out on the write.*/
X                                  /* Behave as though we were  */
X                                  /* disconnected.             */
X
X                                  my_error(TIMEOUT);
X                                }
X
X}
X
X
X
X/****************************************************************************/
X/* pid = prtbanner            author = loftin                      14apr87  */
X/****************************************************************************/
X/*                                                                          */
X/*   subroutine to print the banner page                                    */
X/*                                                                          */
X/****************************************************************************/
X/*                                                                          */
X/*   description -                                                          */
X/*       This subroutine prints the banner page.                            */
X/*                                                                          */
X/*   how invoked - prtbanner()                                              */
X/*                                                                          */
X/*   inputs - none                                                          */
X/*                                                                          */
X/*   outputs - none                                                         */
X/*                                                                          */
X/*   subroutines (in addition to standard C) - none                         */
X/*                                                                          */
X/*   comments -                                                             */
X/*                                                                          */
X/*                                                                          */
X/****************************************************************************/
X
Xprtbanner()
X{
X        char banline[160];     /* one print line */
X
X
X        uname(&sysnam);
X
X        time(&tloc);
X        nowtime = (struct tm *)localtime(&tloc);
X        time_str = asctime(nowtime);
X/*****************************************************************************/
X/* get rid of the non-printable chars we received */
X
X  check_char = keep_char = 0;
X
X  while(time_str[check_char] != '\0')
X  {
X    if(isprint(time_str[check_char]))
X    {
X      time_str[keep_char++] = time_str[check_char];
X    }
X    ++check_char;
X  }
X  time_str[keep_char] = '\0';
X/*****************************************************************************/
X
X
X        sprintf(banline, "\n\n\n\n\n\n");
X
X                                /* set up timeout for write */
X        signal(SIGALRM, my_error);
X
X                                /* assume no timeout */
X                                time_out = 0; 
X
X                                /* Wait a long time for the write to */
X                                /* happen. This allows user time to  */
X                                /* change the ribbon, clear paper    */
X                                /* jam, or replenish paper supply.   */
X                                /* On the other hand, we won't wait  */
X                                /* forever.                          */
X                                alarm(WRITEWAIT);
X
X        write(out_file, banline, strlen(banline));
X
X                                /* turn off the alarm clock */
X                                alarm(0);
X
X                                /* ignore alarm */
X        signal(SIGALRM, SIG_IGN);
X
X                                if(time_out == 1)
X                                {
X                                  /* We timed out on the write.*/
X                                  /* Behave as though we were  */
X                                  /* disconnected.             */
X
X                                  my_error(TIMEOUT);
X                                }
X
X        sprintf(banline,
X                "**********************************************************\n");
X
X                                /* set up timeout for write */
X        signal(SIGALRM, my_error);
X
X                                /* assume no timeout */
X                                time_out = 0; 
X
X                                /* Wait a long time for the write to */
X                                /* happen. This allows user time to  */
X                                /* change the ribbon, clear paper    */
X                                /* jam, or replenish paper supply.   */
X                                /* On the other hand, we won't wait  */
X                                /* forever.                          */
X                                alarm(WRITEWAIT);
X
X        write(out_file, banline, strlen(banline));
X
X                                /* turn off the alarm clock */
X                                alarm(0);
X
X                                /* ignore alarm */
X        signal(SIGALRM, SIG_IGN);
X
X                                if(time_out == 1)
X                                {
X                                  /* We timed out on the write.*/
X                                  /* Behave as though we were  */
X                                  /* disconnected.             */
X
X                                  my_error(TIMEOUT);
X                                }
X
X        sprintf(banline,
X                "*                                                        *\n");
X
X                                /* set up timeout for write */
X        signal(SIGALRM, my_error);
X
X                                /* assume no timeout */
X                                time_out = 0; 
X
X                                /* Wait a long time for the write to */
X                                /* happen. This allows user time to  */
X                                /* change the ribbon, clear paper    */
X                                /* jam, or replenish paper supply.   */
X                                /* On the other hand, we won't wait  */
X                                /* forever.                          */
X                                alarm(WRITEWAIT);
X
X        write(out_file, banline, strlen(banline));
X
X                                /* turn off the alarm clock */
X                                alarm(0);
X
X                                /* ignore alarm */
X        signal(SIGALRM, SIG_IGN);
X
X                                if(time_out == 1)
X                                {
X                                  /* We timed out on the write.*/
X                                  /* Behave as though we were  */
X                                  /* disconnected.             */
X
X                                  my_error(TIMEOUT);
X                                }
X
X/*
X        sprintf(banline,
X                "* *****          INTERNAL REVENUE SERVICE          ***** *\n");
X*/
X
X                                /* set up timeout for write */
X        signal(SIGALRM, my_error);
X
X                                /* assume no timeout */
X                                time_out = 0; 
X
X                                /* Wait a long time for the write to */
X                                /* happen. This allows user time to  */
X                                /* change the ribbon, clear paper    */
X                                /* jam, or replenish paper supply.   */
X                                /* On the other hand, we won't wait  */
X                                /* forever.                          */
X                                alarm(WRITEWAIT);
X
X        write(out_file, banline, strlen(banline));
X
X
X                                count1 = alarm(0);
X
X                                if(time_out == 1)
X                                {
X                                  my_error(TIMEOUT);
X                                }
X
X                                alarm((unsigned)count1);
X
X        /* wait here for the output to drain */
X        ioctl(out_file, TCSBRK, 1);
X
X
X                                /* turn off the alarm clock */
X                                alarm(0);
X
X                                /* ignore alarm */
X        signal(SIGALRM, SIG_IGN);
X
X                                if(time_out == 1)
X                                {
X                                  /* We timed out on the write.*/
X                                  /* Behave as though we were  */
X                                  /* disconnected.             */
X
X                                  my_error(TIMEOUT);
X                                }
X
X        sprintf(banline,
X                "*                                                        *\n");
X
X                                /* set up timeout for write */
X        signal(SIGALRM, my_error);
X
X                                /* assume no timeout */
X                                time_out = 0; 
X
X                                /* Wait a long time for the write to */
X                                /* happen. This allows user time to  */
X                                /* change the ribbon, clear paper    */
X                                /* jam, or replenish paper supply.   */
X                                /* On the other hand, we won't wait  */
X                                /* forever.                          */
X                                alarm(WRITEWAIT);
X
X        write(out_file, banline, strlen(banline));
X
X                                /* turn off the alarm clock */
X                                alarm(0);
X
X                                /* ignore alarm */
X        signal(SIGALRM, SIG_IGN);
X
X                                if(time_out == 1)
X                                {
X                                  /* We timed out on the write.*/
X                                  /* Behave as though we were  */
X                                  /* disconnected.             */
X
X                                  my_error(TIMEOUT);
X                                }
X
X
X        /* SITELINE is #defined in localcnfg.h */
X
X        sprintf(banline, SITELINE);
X
X                                /* set up timeout for write */
X        signal(SIGALRM, my_error);
X
X                                /* assume no timeout */
X                                time_out = 0; 
X
X                                /* Wait a long time for the write to */
X                                /* happen. This allows user time to  */
X                                /* change the ribbon, clear paper    */
X                                /* jam, or replenish paper supply.   */
X                                /* On the other hand, we won't wait  */
X                                /* forever.                          */
X                                alarm(WRITEWAIT);
X
X        write(out_file, banline, strlen(banline));
X
X
X                                count1 = alarm(0);
X
X                                if(time_out == 1)
X                                {
X                                  my_error(TIMEOUT);
X                                }
X
X                                alarm((unsigned)count1);
X
X        /* wait here for the output to drain */
X        ioctl(out_file, TCSBRK, 1);
X
X
X                                /* turn off the alarm clock */
X                                alarm(0);
X
X                                /* ignore alarm */
X        signal(SIGALRM, SIG_IGN);
X
X                                if(time_out == 1)
X                                {
X                                  /* We timed out on the write.*/
X                                  /* Behave as though we were  */
X                                  /* disconnected.             */
X
X                                  my_error(TIMEOUT);
X                                }
X
X        sprintf(banline,
X                "*                                                        *\n");
X
X                                /* set up timeout for write */
X        signal(SIGALRM, my_error);
X
X                                /* assume no timeout */
X                                time_out = 0; 
X
X                                /* Wait a long time for the write to */
X                                /* happen. This allows user time to  */
X                                /* change the ribbon, clear paper    */
X                                /* jam, or replenish paper supply.   */
X                                /* On the other hand, we won't wait  */
X                                /* forever.                          */
X                                alarm(WRITEWAIT);
X
X        write(out_file, banline, strlen(banline));
X
X                                /* turn off the alarm clock */
X                                alarm(0);
X
X                                /* ignore alarm */
X        signal(SIGALRM, SIG_IGN);
X
X                                if(time_out == 1)
X                                {
X                                  /* We timed out on the write.*/
X                                  /* Behave as though we were  */
X                                  /* disconnected.             */
X
X                                  my_error(TIMEOUT);
X                                }
X
X        sprintf(banline,
X                "**********************************************************\n");
X
X                                /* set up timeout for write */
X        signal(SIGALRM, my_error);
X
X                                /* assume no timeout */
X                                time_out = 0; 
X
X                                /* Wait a long time for the write to */
X                                /* happen. This allows user time to  */
X                                /* change the ribbon, clear paper    */
X                                /* jam, or replenish paper supply.   */
X                                /* On the other hand, we won't wait  */
X                                /* forever.                          */
X                                alarm(WRITEWAIT);
X
X        write(out_file, banline, strlen(banline));
X
X                                /* turn off the alarm clock */
X                                alarm(0);
X
X                                /* ignore alarm */
X        signal(SIGALRM, SIG_IGN);
X
X                                if(time_out == 1)
X                                {
X                                  /* We timed out on the write.*/
X                                  /* Behave as though we were  */
X                                  /* disconnected.             */
X
X                                  my_error(TIMEOUT);
X                                }
X
X        sprintf(banline,
X                "*                                                        *\n");
X
X                                /* set up timeout for write */
X        signal(SIGALRM, my_error);
X
X                                /* assume no timeout */
X                                time_out = 0; 
X
X                                /* Wait a long time for the write to */
X                                /* happen. This allows user time to  */
X                                /* change the ribbon, clear paper    */
X                                /* jam, or replenish paper supply.   */
X                                /* On the other hand, we won't wait  */
X                                /* forever.                          */
X                                alarm(WRITEWAIT);
X
X        write(out_file, banline, strlen(banline));
X
X                                /* turn off the alarm clock */
X                                alarm(0);
X
X                                /* ignore alarm */
X        signal(SIGALRM, SIG_IGN);
X
X                                if(time_out == 1)
X                                {
X                                  /* We timed out on the write.*/
X                                  /* Behave as though we were  */
X                                  /* disconnected.             */
END_OF_FILE
if test 34683 -ne `wc -c <'ISPIN/src/ISPIN.c.ad'`; then
    echo shar: \"'ISPIN/src/ISPIN.c.ad'\" unpacked with wrong size!
fi
# end of 'ISPIN/src/ISPIN.c.ad'
fi
if test -f 'ISPIN/doc/rtab' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'ISPIN/doc/rtab'\"
else
echo shar: Extracting \"'ISPIN/doc/rtab'\" \(18255 characters\)
sed "s/^X//" >'ISPIN/doc/rtab' <<'END_OF_FILE'
X#
X#
X#NAME;DEVICE(s);SPEED;FLAGS;EXPECT;SEND;...;EXPECT;SEND;
X#
X# GENERAL INFORMATION:  A leading "#" makes the current line a comment. 
X#                       Blank lines are not valid - use a line with only a 
X#                       "#" instead.
X#                       Maximum line length is BUFSIZ for your cpu; plenty.
X#                       Line feed or carriage return terminates the line.
X#                       Allow long lines to wrap around.
X#
X# DELIMETER: The field delimiter is the semi-colon. The use of a field
X#            delimiter drags the syntax of the table away from the uucp-like
X#            format we were looking for. The positive side of the trade-off
X#            is that the delimiter makes it much easier for the user to specify
X#            tabs and spaces in the EXPECT/SEND pairs when or if necessary.
X#
X# CARRIAGE RETURNS: Uucp will generally tag its own carriage return on the end
X#                   of any sent string. The user is responsible (under Honey-
X#                   DanBer uucp, at least) for specifying when a carriage 
X#                   return should NOT be sent at the end of a string. 
X#                   In our case, however, WYSIWYG (what you see is what you
X#                   get). So if you want a carriage return to be issued at
X#                   any point, make a carriage return (a REAL <ctrl>M or a \r)
X#                   part of the string to be sent.
X#
X#
X# NAME is a required entry. NAME must match the name by which the
X# queuer knows the printer (LP), or the argument to the "-P" flag which
X# must be specified on the appropriate line in /usr/spool/queuer/config
X# (NQ).
X#
X#
X# DEVICE is a required entry. At least the primary device must be shown
X# in this field. A total of eleven devices may be specified. They can be used
X# as alternative routes to the printer. If ISPIN is unable to contact
X# the printer via the first device because IQUEUER has determined it is
X# busy, ISPIN will attempt to contact the printer via the subsequent
X# devices. If contact via the other devices is also blocked,
X# the print request will be queued in the shortest of IQUEUER's virtual
X# queues for the devices.
X# Within the DEVICES field, the primary and subsequent device are separated
X# by commas. No white space allowed. From one to eleven devices may be
X# defined.
X#
X#
X# SPEED is a required entry. Valid entries include
X#
X#                                                  50
X#                                                  75
X#                                                  110
X#                                                  134
X#                                                  150
X#                                                  200
X#                                                  300
X#                                                  600
X#                                                  1200
X#                                                  1800
X#                                                  2400
X#                                                  4800
X#                                                  9600
X#                                                  19200
X#
X# Any other value in this field will be considered nonsense.
X# The SPEED parameter must match the speed of the port to the
X# network connection through which the remote printer will
X# be addressed. The primary and subsequent devices must all
X# be the same speed. No white space allowed.
X#
X# Other tty communication parameters are presently hard-coded as:
X# 
X# 8  data bits
X# 1  stop bit
X# NO parity
X#
X# This seems to have suited everyone so far. If it causes you a pain,
X# let me know.
X#
X# FLAGS
X#
X# The seven flags and their associated arguments are optional but their
X# inclusion will help assure a successful network negotiation, assist in
X# the diagnosis of problems, and permit tuning of the behavior of the ispin
X# process.
X#
X# -Bstring
X# The "-B" flag allows specification as many "busy" strings as necessary.
X# What do we do in case of network busy? A "busy" condition could be 
X# encountered at any link in the net. The administrator should specify
X# a key string from each busy msg which may be encountered. The key word(s)
X# will vary from Tellabs, to X.25 async pad, Mitron, whatever. If more than one 
X# type of networking system will be encountered, multiple "busy" flags
X# and strings should be specified. If a designated busy situation is 
X# encountered, the ISPIN process will sleep a while (number of seconds
X# specified at compile time), quit the network, close the port, notify the
X# IQUEUER it has encountered "busy", then await another go ahead message 
X# from the IQUEUER.
X#
X# -Istring
X# The "-I" flag allows specification of as many "inactive" strings as necessary.
X# Inactive condition is just a FAILURE, so no looping is permitted. 
X# If a network negotiation fails due to an identified inactive condition,
X# the failure error message will so specify. The sysadm, datacom, and user
X# should rectify the inactive condition before the user re-requests.
X# Beta testing has shown that this flag is usually not necessary.
X#
X# -Qstring
X# the "-Q" flag and argument allows specification of as many "quit" strings
X# as necessary. These will be issued at the conlusion of the print job in the
X# sequence they are shown in the table. The purpose of these "quit" strings
X# is to allow the job to sever the network virtual connections in a clean and
X# logical manner. This is also the place to issue any post-printing commands
X# to the printer, such as to return it to a "standard" configuration if
X# necessary.
X#
X# -Dstring
X# The "-D" flag and argument allows the specification of a string the network
X# will send us when/if the printer is powered-down or otherwise disconnected.
X# After each burst of characters, the program will check to see if there are
X# any characters to be read. Under normal conditions, there will be none.
X# If the printer has been powered-down or disconnected, we expect the network
X# to somehow signify the event with a particular message or other readable
X# response. These possible responses are specified as argument(s) to the "-D" 
X# flag. ISPIN's reaction to this condition is to loop and try to re-establish
X# the connection. 
X#
X# -L
X# This flag takes no argument. If the -L flag is present, event logging is
X# enabled. ISPIN will write an entry to its log file for each file which is
X# printed. If the -L flag is absent, only error messages will be written to
X# the log file.
X#
X# -R
X# This flag takes no argument. If the -R flag is present, the tty through
X# which ISPIN communicates will be set so that it DOES NOT transmit the
X# "newline" (ascii "LF", or octal \012) as the newline/carriage return pair.
X# Note that the LF/LF-CR conversion is the default condition if -R is not
X# present. For most printers, DO NOT USE THIS FLAG. This flag is included
X# specifically for supporting the transmission of binary information (such
X# as would be the case with raster graphics).
X#
X# -T
X# This flag takes no argument. If the -T flag is present, tabs will be
X# expanded to spaces on output. If -R flag is present, -T has no effect.
X#
X# EXPECT SEND
X#
X# ISPIN supports uucp's EXPECT-SEND-EXPECT construct and logic. That is,
X# if there is an EXPECT string which contains two dashes, the string will
X# be parsed such that everything up to the first dash is expected. If it is
X# not received, the chars which lie between the dashes will be sent. Then, what
X# remains beyond the second dash is expected. Alternatively, if the first
X# expected string IS received, the remainder of the construct is ignored.
X#
X# ISPIN does support the HoneyDanBer-style faked ascii representation
X# of special characters (two-character pairs such as "\N" for the null
X# character, "\n" for the newline character, and "\t" for tab), as well as
X# the "\###" octal representation of ascii characters.
X# The set of such characters and the associated actions follows:
X#
X#           \N
X#             send a NULL
X#
X#           \b
X#             send a backspace
X#
X#           \L
X#             loaf 30 seconds
X#
X#           \w
X#             wait 10 seconds
X#
X#           \d
X#             delay 3 seconds
X#
X#           \p
X#             pause a second
X#
X#           \n
X#             send a newline
X#
X#           \e
X#             send "escape"
X#
X#           \r
X#             send a carriage return
X#
X#           \s
X#             send a space
X#
X#           \t
X#             send a tab
X#
X#           \f
X#             send a formfeed
X#
X#           \K
X#             send BREAK
X#
X#           \E
X#             send two EOT and newline pairs
X#
X#           \D
X#             send a DELETE
X#
X#           \U
X#             send the user-supplied string. The string is passed to 
X#             ISPIN via the "dest" argument to nq's "-d" flag, or
X#             via the "option" argument to lp's "-o" flag
X#
X#           \###
X#             not literally "###" but three digits which will be 
X#             interpreted as an octal representation of the character
X#             which is to be sent, such as \007 for ascii BEL, and
X#             \033 for ESCAPE.
X#             MUST BE THREE, and ONLY THREE DIGITS.
X#
X#
X# It is NOT possible to specify a null EXPECT or SEND string by placing the
X# field delimeter ";" (semicolon) which terminates the string IMMEDIATELY
X# adjacent to the delimeter which marks the beginning of the string.
X# This is because of a quirk of the C strtok function we are using to parse
X# the rtab entry.
X#
X# It is possible to "fake" null SEND and EXPECT sequences thusly:
X#
X#       NULL SEND string:         ;\p;
X#                                        A timing pause of any duration,
X#                                        with no other characters results
X#                                        proper parsing but no characters
X#                                        sent.
X#
X#       NULL EXPECT string:       ; -;
X#                                        This is quirky, but it works. 
X#                                        This gets parsed as "Expect a
X#                                        space. If not received, send 
X#                                        nothing".
X#
X#
X#
X# Keep in mind that we are treating all WHITE SPACE as SIGNIFICANT.
X# If you put space(s), or tabs(s), or anything else within a field, that
X# that is what will be expected or sent.
X# WYSIWYG. What you see is what you get!
X#
X# Each received string will be compared to the "expect", each 
X# of the "busy" strings and each of the "inactive" strings.
X# The flags are optional. If none are configured, then any 
X# deviation from the "EXPECT/SEND" sequence will be treated as a FAILURE.
X#
X# The EXPECT/SEND pairs must be set up as PAIRS in the sequence ;EXPECT;SEND;
X# Since most printers do not issue any sort of acknowledgement message, the 
X# last EXPECT will be issued by the network. Terminate the sequence with a
X# null SEND, even though we know that upon receiving the final EXPECT, we
X# are connected. The terminating SEND must be "closed" with a terminating ";".
X#
X# RESTRICTIONS
X#
X# Any field, the first character of which is a "-" (dash), will be inter-
X# preted as a FLAG field. The second character of such a field MUST be 
X# "B", "Q", "I", "D", "L", or "R". Any other field, the first character
X# of which is a "-" (dash), is ignored.
X#
X# EXAMPLES - The examples are "quoted-out" with a leading "#" for your
X#            convenience.
X#
X#NAME  DEVICE               SPEED       FLAGS                     EXPECT SEND
X# This the rtab entry for my printer. The printer is hung from the pad, and the
X# cpu is connected to the Tellabs switch. The printer's name is LSB1. We may
X# access it from two possible ports. The speed is 9600. I have configured three
X# possible "busy" messages, and one "inactive" message. The "quit" sequence
X# makes a clean break from the pad (with <BREAK>clr), then from my switch
X# (with <BREAK>bye). The EXPECT/SEND sequence goes like this: expect "System?"
X# (part of my switch's login herald). If you don't get it, send <BREAK>bye,
X# then expect "System?" again. send "pacout", which is a dial sequence to
X# access X.25 async pad through our switch. expect "connect" (info message from
X# our switch). If you don't get it, send a carriage return, then expect "pad>",
X# which is the prompt from the pad. Send a carriage return. expect "pad>". If we
X# don't get it, send <BREAK>clr, then expect "pad>". send the "connect" command
X# and network address of the printer. expect the pad's message which indicates
X# a successful connection. If we don't get it, send the connect command and 
X# address again, and expect a successful connection message. The next "send"
X# is simply a 3 second delay. The sequence MUST be terminated by a NULL "send",
X# and since we don't expect the printer to give any indication that we are
X# connected, the last "send" is preceded by an NULL "expect".
X#
X# PLEASE NOTE the liberal sprinkling of 1 second pauses and 3 second delays.
X# Believe it or not, even the lowly Zilog is capable of executing the ISPIN
X# code faster than the network is able to resond. The pauses and delays keep
X# us from getting ahead of the network so we don't get lost.
X#
X# PLEASE NOTE: I have chopped this entry into separate lines so you may print
X# it. A REAL rtab entry must be all one line.
X#
X#LSB1;/dev/ttyhd,/dev/ttyi8;9600;-Busy;-Bcongestion;-Bremote dte;-BFound;-Inacti
X#ve;-Q\d\d\d\d\d\d\d\p\K\p;-Q\pclr\r\d;-Q\p\K\p;-Q\pbye\p;-DConnection cleared;-
X#Dpad>;-DSystem?;System?-\K\pbye\r\p-System?;\ppacout\r\d;connect;\p\r\d;pad>-\p
X#\K\pclr\r\d-pad>;\pconnect\s00000099999999\r\d;pened-\p\K\pclr\r\pconnect\s0000
X#0099999999\r\d-pened;\d;;;
X#
X#
X#
X#
X# This is an rtab entry to go out from the cpu, through the Tellabs, to a
X# printer which hangs from the Tellabs switch. The printer's name is netind2.
X# In this case, we may only access it via one port. The speed is 9600. The one
X# "busy" message and one "inactive" messages are messages we may expect from
X# Tellabs. The "quit" sequence for this switch is <BREAK>bye. The first EXPECT 
X# is a compound construction in which we look for "System?". If we don't get it,
X# we send <BREAK>bye and carriage return, then expect "System?" again. Next,
X# we send the link/channel combo which is the printer's address. We expect 
X# a "connect" message (switch's info messages are turned on). If we don't get
X# it, we send the link/channel combo again, then expect the "connect" message.
X#
X# The final non-NULL send is SOMETHING SPECIAL because the printer in this
X# example is a Centronics C-351, a printer IRS bought by the metric ton a few
X# years ago. The C-351, when attached to the network (both the Tellabs and the
X# X.25 async pad, in our experience) apparently detects a parity error at the
X# instant the virtual connection (VC) is established. The C-351's response to
X# this condition is to print a "@". You can't stop it by setting the dip
X# switches to ignore parity. So, if you don't want this junk character in 
X# your hard copy, simply formfeed past the page which the C-351 has just spat
X# upon.
X#
X# PLEASE NOTE the liberal sprinkling of 1 second pauses and 3 second delays.
X# Believe it or not, even the lowly Zilog is capable of executing the ISPIN
X# code faster than the network is able to resond. The pauses and delays keep
X# us from getting ahead of the network so we don't get lost.
X#
X# PLEASE NOTE: I have chopped this entry into separate lines so you may print
X# it. A REAL rtab entry must be all one line.
X#
X#netind2;/dev/tty8;9600;-Busy;-Iinactive;-Q\p\K\p;-Q\pbye\p;-DSystem?;System?-\K
X#\pbye\r\p-System?;\p135/2.2\r\d;connect-\p135/2.2\r\d-connect;\d\f;;;
X#
X#
X#
X#
X# This is an example of an rtab entry in the case where both the cpu and the
X# printer are directly connected to X.25 async pad.  It is different than the
X# rtab entry that was sent out with earlier versions of this application.
X# The X.25 pad disconnect sequence is changed from normal <BREAK>clr command to 
X# <CTRL>Z via the "set recall = 26" command. This change was made because
X# the <BREAK> causes Qume printers to print a garbage character.
X
X#
X# PLEASE NOTE: I have chopped this entry into separate lines so you may print
X# it. A REAL rtab entry must be all one line and doesn't have # symbols in it.
X#
X#netind3;/dev/ttyhd,/dev/ttyi8;9600;-L;-Bcongest;-Bmote dte;-Q\w\032\dcl
X#r\r\d;-DConnection cleared;-Dpad>;pad>-\p\K\pclr\r-pad>;\r\p;pad>-\p\K\pclr\r\
X#d-pad>;set recall=26\r\p;pad>-\r\d-pad>;\pconnect\s00000099999999\r\d;pened-\p\
X#K\pclr\r\dset recall=26\r\p\pconnect\s00000099999999\r\d-pened;\d;;;
X#
X#
X#
X#
X# This is an example of an rtab entry for the case where both a 
X# cpu and the printer are directly connected to the X.25 pad. It is different
X# than the rtab entry that was sent out with earlier versions of this 
X# application. It is the same as the preceding example except that the 
X# disconnect argument "-De" is also included. Since the letter "e" is the
X# most frequently used letter in the alphabet, the "-De" will assure that
X# a disconnected print job (chars we sent out are being echoed back to us
X# because the network has reverted to command mode) will be detected sooner.
X#
X#netind3;/dev/ttyhd,/dev/ttyi8;9600;-L;-Bcongest;-Bmote dte;-Q\w\032\dclr\r\d
X#;-DConnection cleared;-Dpad>;-De;pad>-\p\K\pclr\r\d-pad>;\r\p;pad>-\p\K\pcl
X#r\r\d-pad>;set recall=26\r\p;pad>-\r\d-pad>;\pconnect\s00000099999999\r\d;pened
X#-\p\K\pclr\r\dset recall=26\r\p\pconnect\s00000099999999\r\d-pened;\d;;;
X#
X#
X#
X# This is an example rtab entry for a printer which is hard wired to the cpu
X# at tty15. Although sending print jobs to hard wired printers through ISPIN
X# costs a little more in terms of overhead, there are a couple of valid
X# reasons for doing so. Under the NQ/DQUEUER native spooler, you might choose
X# the ISPIN backend to support hardwired printers just to avoid the costly
X# and clunky status reporting which is performed by the native "/usr/lib/text"
X# backend. Under the LP spooler, you might choose the ISPIN interface to
X# support hardwired printers because ISPIN offers an opportunuty to issue both
X# pre- and post-printing commands to the printer.
X#
X#netind4;/dev/tty15;9600;;;
X#
X#
X# NOTE:
X#       SEE ISPIN/install/lib_rtab/README for further info and more examples
X#
X#
END_OF_FILE
if test 18255 -ne `wc -c <'ISPIN/doc/rtab'`; then
    echo shar: \"'ISPIN/doc/rtab'\" unpacked with wrong size!
fi
# end of 'ISPIN/doc/rtab'
fi
echo shar: End of archive 10 \(of 15\).
cp /dev/null ark10isdone
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

