/* * $Id: cpsdecode.c,v 1.2.4.2 2002/02/27 17:41:10 pwessel Exp $ * * Copyright (c) 1999-2002 by P. Wessel * See COPYING file for copying and redistribution conditions. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * Contact info: www.soest.hawaii.edu/wessel *--------------------------------------------------------------------*/ /* * cpsdecode - Decoding Complete PostScript (cps) files that * contain all the commands and the data required * to recreate a plot. * * Author: Paul Wessel, SOEST, U. of Hawaii * Version: 1.3 * Date: 01-MAR-2000 * * cpsdecode will extract a plot script and any required data * files (including other scripts) from the PostScript file comments. * * e.g., * cpsdecode Figure_3.ps * * WIN32: Note we open all files (except input script) in binary mode * since we dont know if files are binary or ascii. We must therefore * deal explicitly with CR/LF issues. */ #include "cps.h" #include "uu.h" main (int argc, char **argv) { int i, k, n_files, cps_indent; unsigned int mode; int verbose = FALSE, first, error = FALSE, expand = TRUE, decode = TRUE, listing = FALSE; char buffer[BUFSIZ], cmd[BUFSIZ], file[BUFSIZ], *s, *tag, cps_comment[32]; FILE *fp = stdin, *process; for (i = 1; i < argc; i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { case '\0': fp = stdin; /* For folks who are used to give - for stdin */ break; case 'n': case 'N': listing = TRUE; break; case 'e': case 'E': /* Backwards compatibility, option no longer needed */ fprintf (stderr, "cpsdecode: -e no longer required\n"); break; case 'u': case 'U': /* Backwards compatibility, option no longer needed */ fprintf (stderr, "cpsdecode: -u no longer required\n"); break; case 'v': case 'V': verbose = TRUE; break; default: error = TRUE; break; } } else { k = i; if ((fp = fopen (argv[k], "r")) == NULL) { fprintf (stderr, "cpsdecode: Could not open file %s\n", argv[k]); exit (EXIT_FAILURE); } } } if (argc < 2 || error) { fprintf (stderr, "cpsdecode - Extract embedded files from CPS Postscript file\n\n"); fprintf (stderr, "usage: cpsdecode [PostScriptfile] [-n] [-v]\n\n"); fprintf (stderr, " Give name of PostScript-file or read from stdin\n\n"); fprintf (stderr, " OPTIONS\n"); fprintf (stderr, " -n will NOT extract files, just report on what it would do\n"); fprintf (stderr, " -v will report on progress [Default is silent]\n"); exit (EXIT_FAILURE); } if (verbose && fp == stdin) fprintf (stderr, "cpsdecode: Reading standard input\n"); else if (verbose) fprintf (stderr, "cpsdecode: Reading %s\n", argv[k]); fgets (buffer, BUFSIZ, fp); if (strncmp (buffer, "%!PS", 4)) { fprintf (stderr, "cpsdecode: %s is not a PostScript file\n", argv[1]); exit (EXIT_FAILURE); } tag = cmd; /* Just two names for the same space */ n_files = 0; first = TRUE; /* Skip to first occurrence of %%CPS-I: */ while ((s = fgets (buffer, BUFSIZ, fp)) && strncmp (buffer, "%%CPS-I:", 8)); for (i = 0; s && i < 3; i++) s = fgets (buffer, BUFSIZ, fp); /* Go to the 4th such line */ if (!s || strncmp (buffer, "%%CPS-I:\tRun cpsdecode", 22)) { /* Trouble, could not find CPS-I flag? */ fprintf (stderr, "cpsdecode: %s was not processed by cpsencode\n", argv[1]); exit (EXIT_FAILURE); } else { /* OK, get command options */ expand = !(int)strstr (buffer, " -u"); decode = !(int)strstr (buffer, " -e"); } s = fgets (buffer, BUFSIZ, fp); if (!s || strncmp (buffer, "%%CPS-I:\tCPS_MARKER = ", 22)) { /* Probably older CPS file, use old default */ fprintf (stderr, "cpsdecode: WARNING: %s processed by cpsencode v 1.2 or older\n", argv[1]); strcpy (cps_comment, "%%CPS|"); } else { /* OK, get command options */ strcpy (cps_comment, "%"); } cps_indent = strlen (cps_comment); if (expand && !decode) { fprintf (stderr, "cpsdecode: ERROR. Cannot decompress without first decoding (check PS file)\n"); exit (EXIT_FAILURE); } if (listing) { /* Just list what is inside the file - no extraction occurs */ fprintf (stderr, "-------------------------------------------------------------------\n"); fprintf (stderr, "Embedded contents of CPS file: %s\n", (fp == stdin) ? "" : argv[k]); fprintf (stderr, "Compressed?: %s\n", (expand) ? "YES" : "NO"); fprintf (stderr, "Encoded?: %s\n", (decode) ? "YES" : "NO"); fprintf (stderr, "CPS Marker: %s\n", cps_comment); fprintf (stderr, "Filenames of embedded files follow:\n"); fprintf (stderr, "-------------------------------------------------------------------\n"); while ((s = fgets (buffer, BUFSIZ, fp))) { if (!strncmp (buffer, CPS_FLAG, CPS_FLAG_WIDTH)) { buffer[strlen (buffer)-1] = '\0'; /* Chop off newline */ strcpy (file, &buffer[CPS_FLAG_WIDTH]); /* Name of this file */ fprintf (stderr, "%s\n", file); n_files++; } } if (fp != stdin) fclose (fp); fprintf (stderr, "-------------------------------------------------------------------\n"); fprintf (stderr, "Total of %d embedded files\n", n_files); fprintf (stderr, "-------------------------------------------------------------------\n"); exit (EXIT_SUCCESS); } /* Skip to first occurrence of CPS_FLAG */ while ((s = fgets (buffer, BUFSIZ, fp)) && strncmp (buffer, CPS_FLAG, CPS_FLAG_WIDTH)); while (s) { /* There is more to decode */ buffer[strlen (buffer)-1] = '\0'; /* Chop off newline */ sscanf (&buffer[CPS_FLAG_WIDTH], "%s %o", file, &mode); /* Name of this file and its file mode */ if (verbose) { fprintf (stderr, "cpsdecode: Extract %s ", file); if (first) fprintf (stderr, "(master script) "); fprintf (stderr, "["); } if (expand && !first) { /* Data must be unscrambled so we must write to a bzip2 process */ if (verbose) fprintf (stderr, "EXPAND"); sprintf (cmd, "%s > %s", EXPAND, file); if ((process = popen (cmd, "wb")) == NULL) { fprintf (stderr, "cpsdecode: Trouble opening process %s\n", cmd); exit (EXIT_FAILURE); } } else { /* Here, files are not compressed, just [possibly] encoded, so we write to a file */ if ((process = fopen (file, "wb")) == NULL) { fprintf (stderr, "cpsdecode: Trouble creating file %s\n", file); exit (EXIT_FAILURE); } } if (decode && !first) { /* Must undo uuencoding first, which feeds to process or file */ if (verbose) { if (expand) fprintf (stderr, "+"); fprintf (stderr, "DECODE]\n", file); } uu_decoder (fp, process, NULL, tag, cps_comment); s = fgets (buffer, BUFSIZ, fp); } else { /* Read and feed to file */ if (verbose) fprintf (stderr, "COPY]\n", file); while ((s = fgets (buffer, BUFSIZ, fp)) && strncmp (buffer, CPS_FLAG, CPS_FLAG_WIDTH)) { #ifdef WIN32 buffer[strlen(buffer)-1] = 0; /* Strip off LF */ fprintf (process, "%s\r\n", &buffer[cps_indent]); #else fprintf (process, "%s", &buffer[cps_indent]); #endif } } (expand) ? pclose (process) : fclose (process); #ifdef WIN32 _chmod (file, mode); /* Set correct file permission - ignore failure */ #else chmod (file, (mode_t)mode); /* Set correct file permission - ignore failure */ #endif first = FALSE; n_files++; } if (fp != stdin) fclose (fp); if (n_files == 0) fprintf (stderr, "cpsdecode: No files extracted. %s is probably not a CPS file\n", argv[k]); else if (verbose) fprintf (stderr, "cpsdecode: Extracted %d files from %s\n", n_files, argv[k]); exit (EXIT_SUCCESS); }