home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume15 / mcat2 / mcat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-06-07  |  5.9 KB  |  250 lines

  1. /*
  2.  * This file is mcat.c and contains a sort of cat utility for use with
  3.  * pmap devices.  It was originally written on sequent Dynix 2.1.1.
  4.  *
  5.  * to do:
  6.  *    mmap disk files.
  7.  *    mcat multiple files in, out.
  8.  *    -x write at offset x.
  9.  *    trunc old disk files.
  10.  *
  11.  * Original Author: K. Richard Magill Fri Nov 20 16:00:53 EST 1987
  12.  * Last Mod Mon Mar 21 00:31:18 EST 1988, by rich@oxtrap
  13.  *
  14.  *$Header: /u1/rich/bin/src/RCS/mcat.c,v 1.2 88/03/21 00:42:41 rich Exp $
  15.  */
  16.  
  17. #include <stdio.h>
  18. #include <sys/types.h>
  19. #include <sys/file.h>
  20. #include <sys/ioctl.h>
  21. #include <sys/mman.h>
  22. #include <sys/stat.h>
  23. #include <machine/pmap.h>
  24.  
  25. #define Perror(s)    {if(Silent==0)perror(s);}
  26.  
  27. extern char *optarg;
  28. extern int optind;
  29.  
  30. char *malloc();
  31. char *valloc();
  32.  
  33. main(argc, argv)
  34. int argc;
  35. char *argv[];
  36. {
  37.     char *InBase = ((char *) 0);
  38.     char *OutBase = ((char *) 0);
  39.  
  40.     int BufferSize = BUFSIZ;
  41.     int InPut = fileno(stdin);
  42.     int OutPut = fileno(stdout);
  43.     int Silent = 0;
  44.     int Verbose = 0;
  45.     int WriteFlags = 0;
  46.     int c;
  47.  
  48.     struct pmap_ioc InSize, OutSize;
  49.  
  50. /*
  51.  * parse args.
  52.  */
  53.  
  54.     while ((c = getopt(argc, argv, "b:i:o:sv")) != EOF) {
  55.         switch (c) {
  56.  
  57.         case 'b':
  58.             BufferSize = atoi(optarg);
  59.  
  60.             if (Verbose != 0) {
  61.                 (void) fprintf(stderr, "%s: Using %d byte i/o.\n", argv[0], BufferSize);
  62.             } /* verbose */
  63.  
  64.             break;
  65.  
  66.         case 'i':
  67.  
  68.             if ((InPut = open(optarg, O_RDONLY, 0666)) < 0) {
  69.                 Perror("opening input:");
  70.                 exit(1);
  71.             } /* on error opening for read */
  72.  
  73.             break;
  74.  
  75.         case 'o':
  76.             if (access(optarg, F_OK) == 0) {
  77.                 if (Verbose != 0) {
  78.                     (void) fprintf(stderr, "%s: output exists.\n", argv[0]);
  79.                 } /* verbose */
  80.  
  81.                 if (access(optarg, R_OK) == 0) {
  82.                     if (Verbose != 0) {
  83.                         (void) fprintf(stderr, "%s: output is readable.\n", argv[0]);
  84.                     } /* verbose */
  85.  
  86.                     WriteFlags |= O_RDWR;
  87.                 }
  88.  
  89.             } else {
  90.                 if (Verbose != 0) {
  91.                     (void) fprintf(stderr, "%s: output does not exist.  creating.\n", argv[0]);
  92.                 } /* verbose */
  93.  
  94.                 WriteFlags = O_CREAT | O_RDWR;
  95.             }
  96.  
  97.             if ((OutPut = open(optarg, WriteFlags, 0666)) < 0) {
  98.                 Perror("mcat: opening output");
  99.                 exit(1);
  100.             } /* on error opening for write */
  101.  
  102.             break;
  103.  
  104.         case 's':
  105.             Silent = 1;
  106.             break;
  107.  
  108.         case 'v':
  109.             Verbose = 1;
  110.             break;
  111.  
  112.         case '?':
  113.         default:
  114.             if (Silent == 0) {
  115.                 (void) fprintf(stderr, "%s: usage: -b buffer_size -i input_file -o output_file -s -v\n", argv[0]);
  116.             } /* not silent */
  117.  
  118.             exit(1);
  119.  
  120.         } /* switch on switch character */
  121.     } /* while there are switch characters */
  122.  
  123. /*
  124.  * I presume that if the ioctl fails, this is not a pmap device and we
  125.  * aren't mapping.  If you know of a better way to check a a descriptor
  126.  * for mmap'ability, (short of chasing the major number through the kernel),
  127.  * let me know.
  128.  */
  129.  
  130.      if (ioctl(InPut, PMAPIOCGETP, (char *) &InSize) == 0) { /* not pmap */
  131.         if ((InBase = valloc((unsigned) InSize.pi_size)) == 0) {
  132.             Perror("valloc'ing output buffer:");
  133.             exit(1);
  134.         } /* on error valloc'ing */
  135.  
  136.         if (mmap(InBase, (int) InSize.pi_size, PROT_READ, MAP_SHARED, InPut, 0) != 0) {
  137.             Perror("on error mmap'ing input:");
  138.             exit(1);
  139.         } /* on error mmap'ing input */
  140.  
  141.         if (Verbose != 0) {
  142.             (void) fprintf(stderr, "%s: mmap'ing input.\n",
  143.                        argv[0]);
  144.         } /* verbose */
  145.  
  146.     } /* not mapped or not mappable */
  147.  
  148.     if ((ioctl(OutPut, PMAPIOCGETP, (char *) &OutSize) == 0)) { /* not mapping */
  149.         if  ((OutBase = valloc((unsigned) OutSize.pi_size)) == 0) {
  150.             Perror("valloc'ing for output buffer:");
  151.             exit(1);
  152.         } /* on valloc error */
  153.  
  154.         if (mmap(OutBase, (int) OutSize.pi_size, PROT_RDWR, MAP_SHARED, OutPut, 0) != 0) {
  155.             Perror("mmap'ing output:");
  156.  
  157.             if (Silent == 0) {
  158.                 (void) fprintf(stderr, "%s: remember you can't redirect output.\n", argv[0]);
  159.             } /* not silent */
  160.  
  161.             exit(1);
  162.         } /* on error mmap'ing output */
  163.  
  164.         if (Verbose != 0) {
  165.             (void) fprintf(stderr, "%s: mmap'ing output.\n",
  166.                        argv[0]);
  167.         } /* verbose */
  168.  
  169.     } /* not mapped or not mappable */
  170.  
  171.     if (InBase != ((char *) NULL)) { /* mapping input */
  172.         if (OutBase != ((char *) NULL)) { /* and output */
  173.             (void) bcopy(InBase, OutBase, (unsigned) ((InSize.pi_size < OutSize.pi_size) ? InSize.pi_size : OutSize.pi_size));
  174.         } else { /* map in, no map out */
  175.             int ReallyWrote;
  176.  
  177.             OutBase = malloc((unsigned) BufferSize);
  178.  
  179.             while (InSize.pi_size > 0) {
  180.                 if (BufferSize > InSize.pi_size) {
  181.                     BufferSize = InSize.pi_size;
  182.                 } /* if buffer now holds it all */
  183.  
  184.                 (void) bcopy(InBase, OutBase, (unsigned) BufferSize); /* silly new limitation */
  185.  
  186.                 if ((ReallyWrote = write(OutPut, OutBase, BufferSize)) != BufferSize) {
  187.                     Perror("writing output:");
  188.                     exit(1);
  189.                 } /* on error writing */
  190.  
  191.                 InSize.pi_size -= ReallyWrote;
  192.                 InBase += ReallyWrote;
  193.             }    /* while data to write */
  194.         } /* if mapping output */
  195.  
  196.     } else { /* not mapping input */
  197.  
  198.         if (OutBase != ((char *) NULL)) { /* but mapping output */
  199.             int ReallyRead = 1;
  200.  
  201.             InBase = malloc((unsigned) BufferSize);
  202.  
  203.             while (ReallyRead != 0 && OutSize.pi_size > 0) {
  204.                 if (BufferSize > OutSize.pi_size) {
  205.                     BufferSize = OutSize.pi_size;
  206.                 } /* if buffer now holds it all */
  207.  
  208.                 if ((ReallyRead = read(InPut, InBase, BufferSize)) == -1) {
  209.                     Perror("reading input:");
  210.                     exit(1);
  211.                 } /* on error reading */
  212.  
  213.                 (void) bcopy(InBase, OutBase, (unsigned) ReallyRead); 
  214.  
  215.                 OutSize.pi_size -= ReallyRead;
  216.                 OutBase += ReallyRead;
  217.             }    /* while data to write */
  218.  
  219.         } else { /* mapping nothing, should use cat instead */
  220.             if (Silent == 0) {
  221.                 (void) fprintf(stderr, "%s: not mapping anything.  use cat instead.\n", argv[0]);
  222.             } /* not silent */
  223.  
  224.             exit(1);
  225.         } /* if mapping output */
  226.     } /* if mapping input */
  227.  
  228.     exit(0);
  229. } /* main() */
  230.  
  231. /*
  232.  * $Log:    mcat.c,v $
  233.  * Revision 1.2  88/03/21  00:42:41  rich
  234.  * now double bufferred to cover dynix 3.0.4 limitation.
  235.  * 
  236.  * Revision 1.1  87/11/27  18:06:45  rich
  237.  * Initial revision
  238.  * 
  239.  *
  240.  * Local Variables:
  241.  * comment-column: 0
  242.  * fill-column: 130
  243.  * fill-prefix: " * "
  244.  * mode: c
  245.  * version-control: t
  246.  * End:
  247.  */
  248.  
  249. /* end of mcat.c */
  250.