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

  1. #ifndef lint
  2. static char sccs_id[] = "@(#)2.4  ftaperead.c 91/09/03 FAST TAPE";
  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 tape blocks to shared memory buffers.
  10.  *
  11.  * Handles tape changing if we're attached to terminal, otherwise exits.
  12.  */
  13.  
  14. #include <stdio.h>
  15. #include <fcntl.h>
  16. #include <errno.h>
  17. #include <signal.h>
  18. #include <sys/types.h>
  19. #include <sys/ipc.h>
  20. #include <sys/shm.h>
  21. #include <sys/stat.h>
  22. #include "ftape.h"
  23.  
  24. extern void perror(), exit();
  25. extern char *strrchr();
  26. extern int  errno;
  27.  
  28. extern struct SHBUF *shbuf;   /* shared memory */
  29. static struct SHBUF *buf;     /* current buffer */
  30. static int  nbuf = 0;         /* buffer counter */
  31. static void quit();           /* signal catching */
  32. static char *progname;        /* name of this program */
  33.  
  34. /*
  35.  * main
  36.  */
  37. main(argc, argv)
  38. int argc;
  39. char  *argv[];
  40. {
  41.   extern int  optind;         /* option index */
  42.   extern char *optarg;        /* option's argument */
  43.   int opt;                    /* current option */
  44.   char *tape_device = TAPE;   /* default tape device */
  45.   int shbufs = SHBUFS;        /* default # of buffers */
  46.   int debug = 0;              /* default: nodebug mode */
  47.   int fdtape;                 /* tape file desciptor */
  48.   int end = 0;                /* flag to stop reading */
  49.   FILE * ttyin, *ttyout;      /* terminal (if any) */
  50.   char *cp;                   /* local pointer */
  51.   int n;                      /* local counter */
  52.  
  53.   progname = ((cp = strrchr (argv[0], '/')) ? cp+1 : argv[0]);
  54.     
  55.   /*
  56.    * options
  57.    */
  58.   while ( (opt = getopt(argc, argv, "dn:f:")) != EOF ) {
  59.     switch (opt) {
  60.     case 'n':      /* # of buffers */
  61.       shbufs = atoi(optarg);
  62.       if (shbufs <= 0) {
  63.         (void) fprintf (stderr, "%s: too few buffers: %d\n", progname, shbufs);
  64.     exit(1);
  65.       }
  66.       break;
  67.     case 'f':
  68.       tape_device = optarg;
  69.       break;
  70.     case 'd':
  71.       debug++;
  72.       break;
  73.     default:      /* unknown option */
  74.       (void) fprintf (stderr, "%s: unknown option -- %c\n", progname, opt);
  75.       exit(1);
  76.       break;
  77.     }
  78.   }
  79.  
  80.   /* catch signals */
  81.   for (n = 0; n < NSIG; n++)
  82.     (void) signal (n, quit);
  83.  
  84.   /* 
  85.    * Try to attach to terminal if possible.
  86.    * It may not be possible if we're running in background
  87.    * or started by 'cron'. In that case tty{in,out} == NULL
  88.    */
  89.   ttyin = fopen ("/dev/tty", "r");
  90.   ttyout = fopen ("/dev/tty", "w");
  91.  
  92.   /* shared memory should already be created - attach to it */
  93.   if (attach_shared(tape_device) == -1)
  94.     exit (1);
  95.  
  96.   if ((fdtape = open(tape_device, O_RDONLY)) == -1) {
  97.     (void) fprintf (stderr, "%s: cannot open tape, errno %d\n"
  98.             , progname, errno);
  99.     exit (1);
  100.   }
  101.  
  102.   /* READING LOOP */
  103.   nbuf = 0;
  104.   buf = shbuf;
  105.   end = 0;
  106.   while (!end) {
  107.     semdown (BUFFERS_FREE, 1);
  108.  
  109.     errno = 0; /* clear errno, read doesn't do it */
  110.     buf->nread = read (fdtape, buf->buf, SHBUFSIZE*512);
  111.     
  112.     switch (buf->nread) {
  113.     case 0:  /* end of archive */
  114.       DEBUG fprintf (ttyout, "\n%s: READ %d bytes, errno %d\n",
  115.              progname, buf->nread, errno);
  116.  
  117.       semup (BUFFERS_AVAIL, 1);
  118.       end = 1;
  119.       break;
  120.  
  121.     case -1: /* End Of Media with no data */
  122.       DEBUG fprintf (ttyout, "\n%s: READ %d bytes, errno %d\n",
  123.              progname, buf->nread, errno);
  124.       (void) close(fdtape);
  125.       /*
  126.        * If we're attached to a terminal ask user to change the tape.
  127.        * otherwise exit.
  128.        */
  129.       if (ttyin && ttyout)
  130.         fdtape = change_tape(ttyin, ttyout, tape_device);
  131.       else {
  132.         (void) fprintf (stderr, "Reached end of medium.\n");
  133.         (void) fprintf (stderr, "No controlling terminal. Exit.\n");
  134.         quit(-1);
  135.       }
  136.       break; /* continue reading to the same buffer */
  137.  
  138.     case SHBUFSIZE*512: /* OK, buffer read */
  139.     default:     /* 
  140.          * EOM or smaller buffer at end of archive (EOA).
  141.          * We simply pass the data on and check it during the 
  142.          * next read cycle.
  143.          * If we're at EOA, next read should give "0" bytes.
  144.          * If we're at EOM, next read should give "-1" bytes
  145.          */
  146.       DEBUG fprintf (ttyout, "%s: READ %d bytes, errno %d     \r",
  147.              progname, buf->nread, errno), fflush(ttyout);
  148.  
  149.       semup (BUFFERS_AVAIL, 1);
  150.  
  151.       /* next buffer */
  152.       nbuf++; buf++;
  153.       if (nbuf >= shbufs) {
  154.     nbuf = 0;
  155.     buf = shbuf;
  156.       }
  157.  
  158.       break;
  159.     }
  160.   }
  161.   return (0);
  162. }
  163.  
  164. /*
  165.  * quit is called either by a signal interrupt (sig > 0) or
  166.  * explicitly (sig < 0).
  167.  *
  168.  * Signal interrupt is written to stderr
  169.  */
  170. static void quit (sig)
  171. int sig;
  172. {
  173.   if (sig > 0)
  174.     fprintf (stderr, "%s: exit signal %d\n", progname, sig);
  175.   buf->nread = 0;
  176.   semup (BUFFERS_AVAIL, 1);
  177.   exit (1);
  178. }
  179.  
  180. /*
  181.  * change_tape
  182.  */
  183. change_tape(ttyin, ttyout, device)
  184. FILE *ttyin, *ttyout;
  185. char *device;
  186. {
  187.   static char inbuf[BUFSIZ];
  188.   int (fdtape);
  189.  
  190.   (void) fprintf (ttyout, "\nReached end of medium.\n");
  191.   (void) fprintf (ttyout, "Change tape after the light is off.\n");
  192.   while (1) {
  193.     (void) fprintf (ttyout, "Press 'y' <RETURN> to continue: ");
  194.  
  195.     fgets (inbuf, sizeof(inbuf), ttyin);  /* read tty */
  196.  
  197.     if (tolower(inbuf[0]) != 'y') {
  198.       (void) fprintf (ttyout, "\007"); /* BEEP - illegal reply */
  199.       continue;
  200.     }
  201.     
  202.     if ((fdtape = open(device, O_RDONLY)) != -1)
  203.       break; /* succeeded opening tape */
  204.  
  205.     (void) fprintf (ttyout, "\007Could not open tape for reading.\n");
  206.     (void) fprintf (ttyout, "Check if it's properly installed.\n");
  207.     continue;
  208.   }
  209.   return fdtape;
  210. }
  211.