home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / ZIP19P1.ZIP / zipnote.c < prev    next >
C/C++ Source or Header  |  1993-01-23  |  10KB  |  359 lines

  1. /*
  2.  
  3.  Copyright (C) 1990-1992 Mark Adler, Richard B. Wales, Jean-loup Gailly,
  4.  Kai Uwe Rommel and Igor Mandrichenko.
  5.  Permission is granted to any individual or institution to use, copy, or
  6.  redistribute this software so long as all of the original files are included
  7.  unmodified, that it is not sold for profit, and that this copyright notice
  8.  is retained.
  9.  
  10. */
  11.  
  12. /*
  13.  *  zipnote.c by Mark Adler.
  14.  */
  15.  
  16. #define UTIL
  17. #include "revision.h"
  18. #include "zip.h"
  19. #include <signal.h>
  20.  
  21.  
  22. /* Character to mark zip entry names in the comment file */
  23. #define MARK '@'
  24.  
  25. /* Temporary zip file name and file pointer */
  26. local char *tempzip;
  27. local FILE *tempzf;
  28.  
  29.  
  30. /* Local functions */
  31. #ifdef PROTO
  32.    local void handler(int);
  33.    local void license(void);
  34.    local void help(void);
  35.    local void putclean(char *, int);
  36.    local int catalloc(char * far *, char *);
  37.    void main(int, char **);
  38. #endif /* PROTO */
  39.  
  40.  
  41.  
  42. void err(c, h)
  43. int c;                  /* error code from the ZE_ class */
  44. char *h;                /* message about how it happened */
  45. /* Issue a message for the error, clean up files and memory, and exit. */
  46. {
  47.   if (PERR(c))
  48.     perror("zipnote error");
  49.   fprintf(stderr, "zipnote error: %s (%s)\n", errors[c-1], h);
  50.   if (tempzf != NULL)
  51.     fclose(tempzf);
  52.   if (tempzip != NULL)
  53.   {
  54.     destroy(tempzip);
  55.     free((voidp *)tempzip);
  56.   }
  57.   if (zipfile != NULL)
  58.     free((voidp *)zipfile);
  59. #ifdef VMS
  60.   exit(0);
  61. #else /* !VMS */
  62.   exit(c);
  63. #endif /* ?VMS */
  64. }
  65.  
  66.  
  67. local void handler(s)
  68. int s;                  /* signal number (ignored) */
  69. /* Upon getting a user interrupt, abort cleanly using err(). */
  70. {
  71. #ifndef MSDOS
  72.   putc('\n', stderr);
  73. #endif /* !MSDOS */
  74.   err(ZE_ABORT, "aborting");
  75.   s++;                                  /* keep some compilers happy */
  76. }
  77.  
  78.  
  79. void warn(a, b)
  80. char *a, *b;            /* message strings juxtaposed in output */
  81. /* Print a warning message to stderr and return. */
  82. {
  83.   fprintf(stderr, "zipnote warning: %s%s\n", a, b);
  84. }
  85.  
  86.  
  87. local void license()
  88. /* Print license information to stdout. */
  89. {
  90.   extent i;             /* counter for copyright array */
  91.  
  92.   for (i = 0; i < sizeof(copyright)/sizeof(char *); i++) {
  93.     printf(copyright[i], "zipnote");
  94.     putchar('\n');
  95.   }
  96.   for (i = 0; i < sizeof(disclaimer)/sizeof(char *); i++)
  97.     puts(disclaimer[i]);
  98. }
  99.  
  100.  
  101. local void help()
  102. /* Print help (along with license info) to stdout. */
  103. {
  104.   extent i;             /* counter for help array */
  105.  
  106.   /* help array */
  107.   static char *text[] = {
  108. "",
  109. "ZipNote %d.%d (%s)",
  110. "Usage:  zipnote [-w] [-b path] zipfile",
  111. "  the default action is to write the comments in zipfile to stdout",
  112. "  -w   write the zipfile comments from stdin",
  113. "  -b   use \"path\" for the temporary zip file",
  114. "  -h   show this help               -L   show software license",
  115. "",
  116. "Example:",
  117. #ifdef VMS
  118. "     define/user sys$output foo.tmp",
  119. "     zipnote foo.zip",
  120. "     edit foo.tmp",
  121. "     ... then you edit the comments, save, and exit ...",
  122. "     define/user sys$input foo.tmp",
  123. "     zipnote -w foo.zip"
  124. #else /* !VMS */
  125. "     zipnote foo.zip > foo.tmp",
  126. "     ed foo.tmp",
  127. "     ... then you edit the comments, save, and exit ...",
  128. "     zipnote -w foo.zip < foo.tmp"
  129. #endif /* ?VMS */
  130.   };
  131.  
  132.   for (i = 0; i < sizeof(copyright)/sizeof(char *); i++) {
  133.     printf(copyright[i], "zipnote");
  134.     putchar('\n');
  135.   }
  136.   for (i = 0; i < sizeof(text)/sizeof(char *); i++)
  137.   {
  138.     printf(text[i], REVISION / 10, REVISION % 10, REVDATE);
  139.     putchar('\n');
  140.   }
  141. }
  142.  
  143.  
  144. local void putclean(s, n)
  145. char *s;                /* string to write to stdout */
  146. int n;                  /* length of string */
  147. /* Write the string s to stdout, filtering out control characters that are
  148.    not tab or newline (mainly to remove carriage returns), and prefix MARK's
  149.    and backslashes with a backslash.  Also, terminate with a newline if
  150.    needed. */
  151. {
  152.   int c;                /* next character in string */
  153.   int e;                /* last character written */
  154.  
  155.   e = '\n';                     /* if empty, write nothing */
  156.   while (n--)
  157.   {
  158.     c = *(uch *)s++;
  159.     if (c == MARK || c == '\\')
  160.       putchar('\\');
  161.     if (c >= ' ' || c == '\t' || c == '\n')
  162.       putchar(e = c);
  163.   }
  164.   if (e != '\n')
  165.     putchar('\n');
  166. }
  167.  
  168.  
  169. local int catalloc(a, s)
  170. char * far *a;          /* pointer to a pointer to a malloc'ed string */
  171. char *s;                /* string to concatenate on a */
  172. /* Concatentate the string s to the malloc'ed string pointed to by a.
  173.    Preprocess s by removing backslash escape characters. */
  174. {
  175.   char *p;              /* temporary pointer */
  176.   char *q;              /* temporary pointer */
  177.  
  178.   for (p = q = s; *q; *p++ = *q++)
  179.     if (*q == '\\' && *(q+1))
  180.       q++;
  181.   *p = 0;
  182.   if ((p = malloc(strlen(*a) + strlen(s) + 3)) == NULL)
  183.     return ZE_MEM;
  184.   strcat(strcat(strcpy(p, *a), **a ? "\r\n" : ""), s);
  185.   free((voidp *)*a);
  186.   *a = p;
  187.   return ZE_OK;
  188. }
  189.  
  190.  
  191. void main(argc, argv)
  192. int argc;               /* number of tokens in command line */
  193. char **argv;            /* command line tokens */
  194. /* Write the comments in the zipfile to stdout, or read them from stdin. */
  195. {
  196.   char a[FNMAX+1];      /* input line buffer */
  197.   ulg c;                /* start of central directory */
  198.   int k;                /* next argument type */
  199.   char *q;              /* steps through option arguments */
  200.   int r;                /* arg counter, temporary variable */
  201.   ulg s;                /* length of central directory */
  202.   int t;                /* attributes of zip file */
  203.   int w;                /* true if updating zip file from stdin */
  204.   FILE *x, *y;          /* input and output zip files */
  205.   struct zlist far *z;  /* steps through zfiles linked list */
  206.  
  207.  
  208.   /* If no args, show help */
  209.   if (argc == 1)
  210.   {
  211.     help();
  212.     exit(0);
  213.   }
  214.  
  215.   init_upper();           /* build case map table */
  216.  
  217.   /* Go through args */
  218.   zipfile = tempzip = NULL;
  219.   tempzf = NULL;
  220.   signal(SIGINT, handler);
  221.   signal(SIGTERM, handler);
  222.   k = w = 0;
  223.   for (r = 1; r < argc; r++)
  224.     if (*argv[r] == '-')
  225.       if (argv[r][1])
  226.         for (q = argv[r]+1; *q; q++)
  227.           switch(*q)
  228.           {
  229.             case 'b':   /* Specify path for temporary file */
  230.               if (k)
  231.                 err(ZE_PARMS, "use -b before zip file name");
  232.               else
  233.                 k = 1;          /* Next non-option is path */
  234.               break;
  235.             case 'h':   /* Show help */
  236.               help();  exit(0);
  237.             case 'l':  case 'L':  /* Show copyright and disclaimer */
  238.               license();  exit(0);
  239.             case 'w':
  240.               w = 1;  break;
  241.             default:
  242.               err(ZE_PARMS, "unknown option");
  243.           }
  244.       else
  245.         err(ZE_PARMS, "zip file cannot be stdin");
  246.     else
  247.       if (k == 0)
  248.         if (zipfile == NULL)
  249.         {
  250.           if ((zipfile = ziptyp(argv[r])) == NULL)
  251.             err(ZE_MEM, "was processing arguments");
  252.         }
  253.         else
  254.           err(ZE_PARMS, "can only specify one zip file");
  255.       else
  256.       {
  257.         tempath = argv[r];
  258.         k = 0;
  259.       }
  260.   if (zipfile == NULL)
  261.     err(ZE_PARMS, "need to specify zip file");
  262.  
  263.   /* Read zip file */
  264.   if ((r = readzipfile()) != ZE_OK)
  265.     err(r, zipfile);
  266.   if (zfiles == NULL)
  267.     err(ZE_NAME, zipfile);
  268.  
  269.   /* Put comments to stdout, if not -w */
  270.   if (!w)
  271.   {
  272.     for (z = zfiles; z != NULL; z = z->nxt)
  273.     {
  274.       printf("%c %s\n", MARK, z->zname);
  275.       putclean(z->comment, z->com);
  276.       putchar(MARK);  putchar('\n');
  277.     }
  278.     putchar(MARK);  putchar('\n');
  279.     putclean(zcomment, zcomlen);
  280.     exit(ZE_OK);
  281.   }
  282.  
  283.   /* If updating comments, make sure zip file is writeable */
  284.   if ((x = fopen(zipfile, "a")) == NULL)
  285.     err(ZE_CREAT, zipfile);
  286.   fclose(x);
  287.   t = getfileattr(zipfile);
  288.  
  289.   /* Process stdin, replacing comments */
  290.   for (z = zfiles; z != NULL; z = z->nxt)
  291.   {
  292.     if (gets(a) == NULL || a[0] != MARK || a[1] != ' ' ||
  293.         strcmp(a + 2, z->zname))
  294.       err(ZE_NOTE, "missing entry name");
  295.     if (z->com)
  296.       free((voidp *)z->comment);
  297.     z->comment = malloc(1);  *(z->comment) = 0;
  298.     while (gets(a) != NULL && *a != MARK)
  299.       if ((r = catalloc(&(z->comment), a)) != ZE_OK)
  300.         err(r, "was building new comments");
  301.     if (a[1])
  302.       err(ZE_NOTE, "missing comment end line");
  303.     z->com = strlen(z->comment);
  304.   }
  305.   if (gets(a) == NULL || a[0] != MARK || a[1])
  306.     err(ZE_NOTE, "missing zip file comment marker line");
  307.   zcomment = malloc(1);  *zcomment = 0;
  308.   while (gets(a) != NULL)
  309.     if ((r = catalloc(&zcomment, a)) != ZE_OK)
  310.       err(r, "was building new comments");
  311.   zcomlen = strlen(zcomment);
  312.  
  313.   /* Open output zip file for writing */
  314.   if ((tempzf = y = fopen(tempzip = tempname(zipfile), FOPW)) == NULL)
  315.     err(ZE_TEMP, tempzip);
  316.  
  317.   /* Open input zip file again, copy preamble if any */
  318.   if ((x = fopen(zipfile, FOPR)) == NULL)
  319.     err(ZE_NAME, zipfile);
  320.   if (zipbeg && (r = fcopy(x, y, zipbeg)) != ZE_OK)
  321.     err(r, r == ZE_TEMP ? tempzip : zipfile);
  322.  
  323.   /* Go through local entries, copying them over as is */
  324.   for (z = zfiles; z != NULL; z = z->nxt)
  325.     if ((r = zipcopy(z, x, y)) != ZE_OK)
  326.       err(r, "was copying an entry");
  327.   fclose(x);
  328.  
  329.   /* Write central directory and end of central directory with new comments */
  330.   if ((c = ftell(y)) == -1L)    /* get start of central */
  331.     err(ZE_TEMP, tempzip);
  332.   for (z = zfiles; z != NULL; z = z->nxt)
  333.     if ((r = putcentral(z, y)) != ZE_OK)
  334.       err(r, tempzip);
  335.   if ((s = ftell(y)) == -1L)    /* get end of central */
  336.     err(ZE_TEMP, tempzip);
  337.   s -= c;                       /* compute length of central */
  338.   if ((r = putend((int)zcount, s, c, zcomlen, zcomment, y)) != ZE_OK)
  339.     err(r, tempzip);
  340.   tempzf = NULL;
  341.   if (fclose(y))
  342.     err(ZE_TEMP, tempzip);
  343.   if ((r = replace(zipfile, tempzip)) != ZE_OK)
  344.   {
  345.     warn("new zip file left as: ", tempzip);
  346.     free((voidp *)tempzip);
  347.     tempzip = NULL;
  348.     err(r, "was replacing the original zip file");
  349.   }
  350.   free((voidp *)tempzip);
  351.   tempzip = NULL;
  352.   setfileattr(zipfile, t);
  353.   free((voidp *)zipfile);
  354.   zipfile = NULL;
  355.  
  356.   /* Done! */
  357.   exit(ZE_OK);
  358. }
  359.