home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V7 / usr / src / cmd / standalone / vtcat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-02-03  |  4.3 KB  |  171 lines

  1. #include <stdio.h>
  2. #include <sgtty.h>
  3.  
  4. /* Command sent to tape server */
  5. struct vtcmd {
  6.     char hdr1;            /* Header, 31 followed by 42 (decimal) */
  7.     char hdr2;
  8.     char cmd;            /* Command, one of VTC_XXX below */
  9.                 /* Error comes back in top 4 bits */
  10.     char record;        /* Record we're accessing */
  11.     char blklo;            /* Block number, in lo/hi format */
  12.     char blkhi;
  13.     char sum0;            /* 16-bit checksum */
  14.     char sum1;
  15. };
  16.  
  17. /* Header bytes */
  18. #define VT_HDR1        31
  19. #define VT_HDR2        42
  20.  
  21. /* Commands available */
  22. #define VTC_QUICK    0    /* Quick read, no cksum sent */
  23. #define VTC_OPEN    1
  24. #define VTC_CLOSE    2
  25. #define VTC_READ    3    /* This file only uses READ and OPEN */
  26. #define VTC_WRITE    4
  27.  
  28. /* Errors returned */
  29. #define VTE_NOREC    1    /* No such record available */
  30. #define VTE_OPEN    2    /* Can't open requested block */
  31. #define VTE_CLOSE    3    /* Can't close requested block */
  32. #define VTE_READ    4    /* Can't read requested block */
  33. #define VTE_WRITE    5    /* Can't write requested block */
  34. #define VTE_NOCMD       6       /* No such command */
  35. #define VTE_EOF         7       /* End of file: no blocks left to read */
  36.  
  37. #define BLKSIZE        512
  38.  
  39. int fd;
  40. struct vtcmd vtcmd;        /* Command buffer */
  41. struct vtcmd vtreply;        /* Reply from server */
  42. char vtbuf[BLKSIZE];        /* Pointer to input buffer */
  43. char *vterr[8]= {
  44.     "", "No such record available", "Can't open requested record",
  45.     "Can't close requested record", "Can't read requested block",
  46.     "Can't write requested block", "No such command",
  47.     "End of file: no blocks left to read"
  48. };
  49.  
  50. char vtgetc();
  51.  
  52. usage()
  53.  {
  54.   fprintf(stderr, "Usage: vtcat serial_device record_number\n"); exit(1);
  55.  }
  56.  
  57. main(argc, argv)
  58.  int argc;
  59.  char *argv[];
  60.  {
  61.   extern int errno;
  62.   extern char *sys_errlist[];
  63.   struct sgttyb tty;
  64.   int i;
  65.   int record;
  66.   char error, cmd, sum0, sum1;
  67.  
  68.   if (argc!=3) usage();
  69.   
  70.   record= atoi(argv[2]);    /* Get the record we want */
  71.  
  72.   fd=open(argv[1], 2);        /* Open the terminal */
  73.   if (fd==-1) {
  74.     fprintf(stderr, "Error opening %s: %s\n", argv[1], sys_errlist[errno]);
  75.     exit(1);
  76.   }
  77.  
  78.                 /* Set the terminal state to raw */
  79.   i=gtty(fd, &tty);
  80.   if (i==-1) {
  81.     fprintf(stderr, "Error getting %s state: %s\n",
  82.                         argv[1], sys_errlist[errno]);
  83.     exit(1);
  84.   }
  85.   tty.sg_flags |= RAW;
  86.   i=stty(fd, &tty);
  87.   if (i==-1) {
  88.     fprintf(stderr, "Error setting %s state: %s\n",
  89.                         argv[1], sys_errlist[errno]);
  90.     exit(1);
  91.   }
  92.  
  93.                 /* Set up the basic command */
  94.                 /* and the block number of 0 */
  95.  
  96.   vtcmd.record= record; vtcmd.cmd= VTC_READ;
  97.   vtcmd.blklo=0; vtcmd.blkhi=0;
  98.  
  99.                 /* Loop getting blocks until an error */
  100.   while (1) {
  101.  
  102.                 /* Build the checksum */
  103.     vtcmd.hdr1= VT_HDR1; vtcmd.hdr2= VT_HDR2;
  104.     vtcmd.sum0= VT_HDR1 ^ vtcmd.cmd ^ vtcmd.blklo;
  105.     vtcmd.sum1= VT_HDR2 ^ vtcmd.record ^ vtcmd.blkhi;
  106.  
  107.             /* Send the command to the server */
  108.   sendcmd:
  109.     vtputc(vtcmd.hdr1);  vtputc(vtcmd.hdr2);
  110.     vtputc(vtcmd.cmd);   vtputc(vtcmd.record);
  111.     vtputc(vtcmd.blklo); vtputc(vtcmd.blkhi);
  112.     vtputc(vtcmd.sum0);  vtputc(vtcmd.sum1);
  113.  
  114.               /* Now get a valid reply from the server */
  115.   getreply:
  116.     vtreply.hdr1= vtgetc(); if (vtreply.hdr1!=VT_HDR1) goto getreply;
  117.     vtreply.hdr2= vtgetc(); if (vtreply.hdr2!=VT_HDR2) goto getreply;
  118.     vtreply.cmd= vtgetc();  vtreply.record= vtgetc();
  119.     vtreply.blklo= vtgetc(); vtreply.blkhi= vtgetc();
  120.  
  121.  
  122.             /* Calc. the cksum to date */
  123.     sum0= VT_HDR1 ^ vtreply.cmd ^ vtreply.blklo;
  124.     sum1= VT_HDR2 ^ vtreply.record ^ vtreply.blkhi;
  125.  
  126.             /* Retrieve the block if no errs and a READ cmd */
  127.     if (vtreply.cmd==VTC_READ) {
  128.       for (i=0; i< BLKSIZE; i++) {
  129.     vtbuf[i]= vtgetc(); sum0 ^= vtbuf[i]; i++;
  130.     vtbuf[i]= vtgetc(); sum1 ^= vtbuf[i];
  131.       }
  132.     }
  133.             /* Get the checksum */
  134.     vtreply.sum0= vtgetc(); vtreply.sum1= vtgetc();
  135.  
  136.             /* Try again on a bad checksum */
  137.     if ((sum0!=vtreply.sum0) || (sum1!=vtreply.sum1)) goto sendcmd;
  138.     
  139.  
  140.             /* Extract any error. Exit if one */
  141.     error= vtreply.cmd >> 4;
  142.  
  143.     if (error) {
  144.     if (error==VTE_EOF) exit(0);
  145.     fprintf(stderr, "Error from vtserver: %s\n", vterr[error]); exit(1);
  146.     }
  147.  
  148.             /* Else, send the block to stdout */
  149.     write(1, vtbuf, BLKSIZE);
  150.  
  151.             /* Move to the next block and loop */
  152.     vtcmd.blklo++; if (vtcmd.blklo==0) vtcmd.blkhi++;
  153.   }
  154.  }
  155.  
  156. /* I could have inlined these, but I couldn't be bothered */
  157.  
  158. char vtgetc()
  159.  {   
  160.   char c;
  161.  
  162.   read(fd, &c, 1); return(c);
  163.  }
  164.  
  165.  
  166. vtputc(c)
  167.  char c;
  168.  {
  169.   write(fd, &c, 1);
  170.  }
  171.