home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume22 / ftape / part01 / ftapewrite.c < prev    next >
C/C++ Source or Header  |  1991-09-04  |  6KB  |  216 lines

  1. #ifndef lint
  2. static char sccs_id[] = "@(#)2.4 ftapewrite.c 91/09/03 FAST TAPE WRITE";
  3. #endif
  4. /*
  5.  * Original author: Kari Yli-Kuha, SQ Consulting Ltd.
  6.  * Address: Kanslerinkatu 8, 33720 Tampere, Finland
  7.  * Phone: (358) 31 165200 
  8.  *
  9.  * Reads from shared memory buffers and writes to tape.
  10.  *
  11.  * Handles tape changing if we're attached to terminal, otherwise exits
  12.  *
  13.  * There seems to be no reliable way to determine tape ending with
  14.  * ISC 386/ix Wangtek tape driver other then counting the bytes written
  15.  * to the tape - and even that ain't reliable. We're doing the counting here.
  16.  * DON'T use cheap tapes - I've had all sorts of trouble with them.
  17.  *
  18.  * The last buffer which didn't fit in the tape is rewritten to the new tape.
  19.  */
  20.  
  21. #include <stdio.h>
  22. #include <fcntl.h>
  23. #include <errno.h>
  24. #include <signal.h>
  25. #include <sys/types.h>
  26. #include <sys/ipc.h>
  27. #include <sys/shm.h>
  28. #include <sys/stat.h>
  29. #include <ctype.h>
  30. #include "ftape.h"
  31.  
  32. extern void perror(), exit();
  33. extern char *strrchr();
  34. extern int  errno;
  35.  
  36. extern struct SHBUF *shbuf;   /* shared memory */
  37. void quit();                  /* signal catching */
  38. static char *progname;        /* name of this program */
  39.  
  40. /*
  41.  * main
  42.  */
  43. main(argc, argv)
  44. int argc;
  45. char  *argv[];
  46. {
  47.   extern int  optind;         /* option index */
  48.   extern char *optarg;        /* option's argument */
  49.   int opt;                    /* current option */
  50.   char *tape_device = TAPE;   /* default tape device */
  51.   int shbufs = SHBUFS;        /* default # of buffers */
  52.   int fdtape;                 /* tape device file descriptor */
  53.   unsigned  written = 0;      /* # of bytes written to tape */
  54.   int nread = 0;              /* # of bytes in shared memory buffer */
  55.   int nbuf = 0;               /* # of buffer we currently use */
  56.   struct SHBUF *buf;          /* ptr to current buffer */
  57.   FILE * ttyin, *ttyout;      /* terminal (if any) */
  58.   int debug = 0;              /* default: nodebug */
  59.   int n;                      /* local */
  60.   char *cp;                   /* local */
  61.  
  62.   progname = ((cp = strrchr (argv[0], '/')) ? cp+1 : argv[0]);
  63.  
  64.   /* options */
  65.   while ( (opt = getopt(argc, argv, "dn:f:")) != EOF ) {
  66.     switch (opt) {
  67.     case 'n':      /* # of buffers */
  68.       shbufs = atoi(optarg);
  69.       if (shbufs <= 0) {
  70.         (void) fprintf (stderr, "%s: too few buffers: %d\n", progname, shbufs);
  71.     exit(1);
  72.       }
  73.       break;
  74.     case 'f':
  75.       tape_device = optarg;
  76.       break;
  77.     case 'd':
  78.       debug++;
  79.       break;
  80.     default:      /* unknown option */
  81.       (void) fprintf (stderr, "%s: unknown option -- %c\n", progname, opt);
  82.       exit(1);
  83.       break;
  84.     }
  85.   }
  86.  
  87.   /* catch signals */
  88.   for (n = 0; n < NSIG; n++)
  89.     (void) signal (n, quit);
  90.  
  91.   /* 
  92.    * Try to attach to terminal if possible.
  93.    * It may not be possible if we're running in background
  94.    * or started by 'cron'.
  95.    */
  96.   ttyin = fopen ("/dev/tty", "r");
  97.   ttyout = fopen ("/dev/tty", "w");
  98.   
  99.   /* attach to shared memory */
  100.   if (attach_shared(tape_device) == -1)
  101.     exit (1);
  102.  
  103.   /* open tape */
  104.   if ((fdtape = open(tape_device, O_WRONLY, 0777)) == -1) {
  105.     (void) fprintf (stderr, "\n Could not open tape\n");
  106.     exit (1);
  107.   }
  108.  
  109.   /*
  110.    * loop until all data is written to the tape
  111.    */
  112.   nbuf = 0;
  113.   buf = shbuf;
  114.   while (1) {
  115.     semdown (BUFFERS_AVAIL, 1);
  116.  
  117.     if (buf->nread == 0)  /* end of data */
  118.       break;
  119.  
  120.     nread = buf->nread;
  121.     if (!nread) /* empty buffer */
  122.       break;
  123.  
  124.     DEBUG fprintf (ttyout, "%s: READ %-6d", progname, nread), fflush(ttyout);
  125.  
  126.     errno = 0; /* clear errno, write doesn't do it */
  127.     written = write (fdtape, (char *)buf->buf, nread);
  128.     if (errno == EINTR) {
  129.       (void) fprintf (stderr, "Write to tape failed\n");
  130.       perror ("write");
  131.       exit (1);
  132.     }
  133.  
  134.     DEBUG fprintf (ttyout, "%s: WRITTEN %d bytes, errno %d     \r",
  135.            progname, written, errno), fflush(ttyout);
  136.  
  137.     if ( written != nread) {
  138.       /* 
  139.        * We obviously ran to EOM - close the tape, reopen after changing 
  140.        * the tape and rewrite rest of the buffer.
  141.        */
  142.       (void) close(fdtape);
  143.  
  144.       if (ttyin && ttyout)
  145.         fdtape = change_tape(ttyin, ttyout, tape_device);
  146.       else {
  147.         (void) fprintf (stderr, "Reached end of medium.\n");
  148.         (void) fprintf (stderr, "No controlling terminal. Exit.\n");
  149.         exit(1);
  150.       }
  151.       /* 
  152.        * write the rest of the buffer and continue.
  153.        */
  154.       (void) write (fdtape, (char *)buf->buf+written, nread-written);
  155.  
  156.       DEBUG fprintf (ttyout, "\n%s: WRITTEN %d bytes, errno %d\n",
  157.              progname, written, errno);
  158.     }
  159.     semup (BUFFERS_FREE, 1);
  160.  
  161.     nbuf++; buf++;
  162.     if (nbuf >= shbufs) {
  163.       nbuf = 0;
  164.       buf = shbuf;
  165.     }
  166.   }
  167.   (void) close (fdtape);
  168.   exit (0);
  169.  
  170.   /*NOTREACHED*/
  171.   return (0);
  172. }
  173.  
  174. /*
  175.  * Signal interrupt is written to stderr
  176.  * exit() called with sig as parameter
  177.  */
  178.  
  179. void quit(sig)
  180. int sig;
  181. {
  182.   if (sig > 0)
  183.     fprintf (stderr, "%s: exit signal %d\n", progname, sig);
  184.   exit (sig);
  185. }
  186.  
  187. /*
  188.  * change_tape
  189.  */
  190. change_tape(ttyin, ttyout, device)
  191. FILE *ttyin, *ttyout;
  192. char *device;
  193. {
  194.   static char inbuf[BUFSIZ];
  195.   int (fdtape);
  196.  
  197.   (void) fprintf (ttyout, "\nReached end of medium.\n");
  198.   (void) fprintf (ttyout, "Change tape after the light is off.\n");
  199.   while (1) {
  200.     (void) fprintf (ttyout, "Press 'y' <RETURN> to continue: ");
  201.     fgets (inbuf, sizeof(inbuf), ttyin);
  202.     
  203.     if (tolower(inbuf[0]) != 'y') {
  204.       (void) fprintf (ttyout, "\007"); /* BEEP - illegal reply */
  205.       continue;
  206.     }
  207.     
  208.     if ((fdtape = open(device, O_WRONLY, 0777)) != -1)
  209.       break;
  210.     
  211.     (void) fprintf (ttyout, "\007Could not open tape for writing.\n");
  212.     (void) fprintf (ttyout, "Check if it's write protected.\n");
  213.   }
  214.   return fdtape;
  215. }
  216.