home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume36 / chiaro / part02 < prev    next >
Encoding:
Text File  |  1993-03-24  |  55.1 KB  |  1,849 lines

  1. Newsgroups: comp.sources.misc
  2. From: jwbirdsa@picarefy.picarefy.com (James W. Birdsall)
  3. Subject: v36i072:  chiaro - Image Utilities, Part02/18
  4. Message-ID: <1993Mar25.180932.19878@sparky.imd.sterling.com>
  5. X-Md4-Signature: e3dad866687630cb75736edd0e8a4bd1
  6. Date: Thu, 25 Mar 1993 18:09:32 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: jwbirdsa@picarefy.picarefy.com (James W. Birdsall)
  10. Posting-number: Volume 36, Issue 72
  11. Archive-name: chiaro/part02
  12. Environment: UNIX, Sun, DECstation, 3B1
  13.  
  14. #! /bin/sh
  15. # This is a shell archive.  Remove anything before this line, then feed it
  16. # into a shell via "sh file" or similar.  To overwrite existing files,
  17. # type "sh file -c".
  18. # Contents:  src/Makefile src/gifstrip.c
  19. # Wrapped by kent@sparky on Thu Mar 25 11:20:00 1993
  20. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  21. echo If this archive is complete, you will see the following message:
  22. echo '          "shar: End of archive 2 (of 18)."'
  23. if test -f 'src/Makefile' -a "${1}" != "-c" ; then 
  24.   echo shar: Will not clobber existing file \"'src/Makefile'\"
  25. else
  26.   echo shar: Extracting \"'src/Makefile'\" \(4530 characters\)
  27.   sed "s/^X//" >'src/Makefile' <<'END_OF_FILE'
  28. X#
  29. X# Makefile for the Chiaro suite.
  30. X#
  31. X# Copyright (c) 1993 by James W. Birdsall, all rights reserved.
  32. X#
  33. X
  34. Xinclude template.mk
  35. X
  36. XCCC    = $(CC) $(CFLAGS) $(CINC)
  37. XLLL    = $(LINK) $(LFLAGS)
  38. X
  39. X
  40. Xall:    chils$(EXE) gifstrip$(EXE) gifcheck$(EXE)
  41. X
  42. X
  43. Xclean:
  44. X    $(RM) core *.$O chils$(EXE) gifstrip$(EXE) gifcheck$(EXE)
  45. X    $(RM) fbro.c gifnofb.c gldc.c gldm.c pgm.c ppm.c
  46. X
  47. X
  48. Xchils$(EXE):    chils.$O depend.$O comsrch.$O fbro.$O chidisp.$O \
  49. X        formats.$O re.$O token.$O \
  50. X        gifnofb.$O img.$O jfif.$O sr.$O tga.$O pbm.$O pgm.$O \
  51. X        ppm.$O xbm.$O bmp.$O pcx.$O
  52. X    $(LLL) -o $@ $(LOBJS) chils.$O depend.$O comsrch.$O fbro.$O chidisp.$O \
  53. X        formats.$O re.$O token.$O gifnofb.$O img.$O jfif.$O sr.$O \
  54. X        tga.$O pbm.$O pgm.$O ppm.$O xbm.$O bmp.$O pcx.$O $(LLIBS)
  55. X    $(POST_CHILS)
  56. X
  57. Xgifstrip$(EXE):    gifstrip.$O depend.$O stdinarg.$O gif.$O fb.$O mf.$O
  58. X    $(LLL) -o $@ $(LOBJS) gifstrip.$O depend.$O stdinarg.$O gif.$O fb.$O \
  59. X         mf.$O $(LLIBS)
  60. X    $(POST_GIFSTRIP)
  61. X
  62. Xgifcheck$(EXE):    gifcheck.$O depend.$O stdinarg.$O fb.$O colors.$O blocproc.$O \
  63. X        gif.$O gldm.$O 
  64. X    $(LLL) -o $@ $(LOBJS) gifcheck.$O depend.$O stdinarg.$O fb.$O \
  65. X        colors.$O blocproc.$O gif.$O gldm.$O $(LLIBS)
  66. X    $(POST_GIFCHECK)
  67. X
  68. X
  69. Xblocproc.$O:    blocproc.c config.h depend.h fb.h formats.h gif.h gld.h \
  70. X        colors.h gifcheck.h blocproc.h
  71. X    $(CCC) blocproc.c
  72. X
  73. Xbmp.$O:        bmp.c config.h depend.h formats.h bmp.h
  74. X    $(CCC) bmp.c
  75. X
  76. Xchidisp.$O:    chidisp.c config.h depend.h fb.h formats.h gif.h img.h \
  77. X        jfif.h sr.h tga.h pnm.h xbm.h bmp.h pcx.h chils.h chidisp.h
  78. X    $(CCC) chidisp.c
  79. X
  80. Xchils.$O:    chils.c config.h depend.h chils.h fb.h formats.h gif.h \
  81. X        img.h jfif.h sr.h tga.h pnm.h xbm.h bmp.h pcx.h comsrch.h \
  82. X        patchlevel.h
  83. X    $(CCC) chils.c
  84. X
  85. Xcolors.$O:    colors.c config.h depend.h formats.h colors.h
  86. X    $(CCC) colors.c
  87. X
  88. Xcomsrch.$O:    comsrch.c config.h depend.h formats.h comsrch.h
  89. X    $(CCC) comsrch.c
  90. X
  91. Xdepend.$O:    depend.c config.h depend.h
  92. X    $(CCC) depend.c
  93. X
  94. Xfb.$O:        fb.c config.h fb.h depend.h
  95. X    $(CCC) fb.c
  96. X
  97. Xfbro.$O:    fb.c config.h fb.h depend.h
  98. X    $(RM) fbro.c
  99. X    $(LN) fb.c fbro.c
  100. X    $(CCC) -DREADONLY fbro.c
  101. X    $(RM) fbro.c
  102. X
  103. Xformats.$O:    formats.c config.h depend.h fb.h formats.h gif.h img.h \
  104. X        jfif.h sr.h tga.h pnm.h xbm.h bmp.h pcx.h
  105. X    $(CCC) formats.c
  106. X
  107. Xgif.$O:        gif.c config.h depend.h fb.h formats.h gif.h
  108. X    $(CCC) gif.c
  109. X
  110. Xgifnofb.$O:    gif.c config.h depend.h fb.h formats.h gif.h
  111. X    $(RM) gifnofb.c
  112. X    $(LN) gif.c gifnofb.c
  113. X    $(CCC) -DNO_FB gifnofb.c
  114. X    $(RM) gifnofb.c
  115. X
  116. Xgifcheck.$O:    gifcheck.c config.h depend.h fb.h formats.h gif.h gld.h \
  117. X        colors.h gifcheck.h blocproc.h stdinarg.h patchlevel.h
  118. X    $(CCC) gifcheck.c
  119. X
  120. Xgifstrip.$O:    gifstrip.c config.h depend.h fb.h mf.h formats.h gif.h \
  121. X        stdinarg.h patchlevel.h
  122. X    $(CCC) gifstrip.c
  123. X
  124. Xgldc.$O:    gld.c config.h depend.h gld.h
  125. X    $(RM) gldc.c
  126. X    $(LN) gld.c gldc.c
  127. X    $(CCC) -DCODE_CHECK gldc.c
  128. X    $(RM) gldc.c
  129. X
  130. Xgldm.$O:    gld.c config.h depend.h gld.h
  131. X    $(RM) gldm.c
  132. X    $(LN) gld.c gldm.c
  133. X    $(CCC) -DMINIMAL gldm.c
  134. X    $(RM) gldm.c
  135. X
  136. Ximg.$O:        img.c config.h depend.h formats.h img.h
  137. X    $(CCC) img.c
  138. X
  139. Xjfif.$O:    jfif.c config.h depend.h fb.h formats.h jfif.h
  140. X    $(CCC) jfif.c
  141. X
  142. Xmf.$O:        mf.c config.h depend.h mf.h fb.h
  143. X    $(CCC) mf.c
  144. X
  145. Xpbm.$O:        pbm.c config.h depend.h formats.h token.h pnm.h
  146. X    $(CCC) pbm.c
  147. X
  148. Xpcx.$O:        pcx.c config.h depend.h formats.h pcx.h
  149. X    $(CCC) pcx.c
  150. X
  151. Xpgm.$O:        pgmppm.c depend.h formats.h token.h pnm.h
  152. X    $(RM) pgm.c
  153. X    $(LN) pgmppm.c pgm.c
  154. X    $(CCC) -DPGM pgm.c
  155. X    $(RM) pgm.c
  156. X
  157. Xppm.$O:        pgmppm.c depend.h formats.h token.h pnm.h
  158. X    $(RM) ppm.c
  159. X    $(LN) pgmppm.c ppm.c
  160. X    $(CCC) ppm.c
  161. X    $(RM) ppm.c
  162. X
  163. Xre.$O:        re.c config.h depend.h formats.h re.h fb.h gif.h img.h \
  164. X        jfif.h sr.h tga.h pnm.h xbm.h bmp.h pcx.h
  165. X    $(CCC) re.c
  166. X
  167. Xsr.$O:        sr.c config.h depend.h formats.h sr.h
  168. X    $(CCC) sr.c
  169. X
  170. Xstdinarg.$O:    stdinarg.c config.h depend.h stdinarg.h
  171. X    $(CCC) stdinarg.c
  172. X
  173. Xtga.$O:        tga.c config.h depend.h formats.h tga.h
  174. X    $(CCC) tga.c
  175. X
  176. Xtoken.$O:    token.c config.h depend.h formats.h token.h
  177. X    $(CCC) token.c
  178. X
  179. Xxbm.$O:        xbm.c config.h depend.h formats.h xbm.h token.h
  180. X    $(CCC) xbm.c
  181. X
  182. X
  183. Xbmp.h:    status.h
  184. X
  185. Xfb.h:    status.h
  186. X
  187. Xformats.h:    re.h
  188. X
  189. Xgif.h:    status.h
  190. X
  191. Xgld.h:    status.h
  192. X
  193. Ximg.h:    status.h
  194. X
  195. Xjfif.h:    status.h
  196. X
  197. Xmf.h:    status.h
  198. X
  199. Xpbm.h:    status.h
  200. X
  201. Xpcx.h:    status.h
  202. X
  203. Xpgm.h:    status.h
  204. X
  205. Xpnm.h:    status.h pbm.h pgm.h ppm.h
  206. X
  207. Xppm.h:    status.h
  208. X
  209. Xre.h:    status.h
  210. X
  211. Xsr.h:    status.h
  212. X
  213. Xtga.h:    status.h
  214. X
  215. Xxbm.h:    status.h
  216. X
  217. X
  218. X#
  219. X# WARNING: THESE TARGETS ARE FOR TEST USE ONLY.
  220. X#
  221. Xgldtest3$(EXE):    gldtest3.$O gif.$O gldc.$O fb.$O depend.$O
  222. X    $(LLL) -o $@ $(LOBJS) gldtest3.$O gif.$O gldc.$O fb.$O depend.$O \
  223. X        $(LLIBS)
  224. X
  225. Xgldtest3.$O:    gldtest3.c config.h depend.h fb.h formats.h gif.h gld.h
  226. X    $(CCC) gldtest3.c
  227. X
  228. Xgldtest3.c:    ../masters/gldtest3.c
  229. X    $(CP) ../masters/gldtest3.c .
  230. END_OF_FILE
  231.   if test 4530 -ne `wc -c <'src/Makefile'`; then
  232.     echo shar: \"'src/Makefile'\" unpacked with wrong size!
  233.   fi
  234.   # end of 'src/Makefile'
  235. fi
  236. if test -f 'src/gifstrip.c' -a "${1}" != "-c" ; then 
  237.   echo shar: Will not clobber existing file \"'src/gifstrip.c'\"
  238. else
  239.   echo shar: Extracting \"'src/gifstrip.c'\" \(47919 characters\)
  240.   sed "s/^X//" >'src/gifstrip.c' <<'END_OF_FILE'
  241. X/***************************************************************************
  242. X*   GIFSTRIP.C                                                             *
  243. X*   MODULE:  -                                                             *
  244. X*   OS:      UNIX                                                          *
  245. X*                                                                          *
  246. X*   Copyright (c) 1993 James W. Birdsall. All Rights Reserved.             *
  247. X*                                                                          *
  248. X*   The Graphics Interchange Format(c) is the Copyright property of        *
  249. X*   CompuServe Incorporated. GIF(sm) is a Service Mark property of         *
  250. X*   CompuServe Incorporated.                                               *
  251. X*                                                                          *
  252. X*   $Id: gifstrip.c,v 1.10 1993/03/02 00:49:36 jwbirdsa Exp $
  253. X*                                                                          *
  254. X*   Chiaro suite GIF rebuild program.                                      *
  255. X*                                                                          *
  256. X***************************************************************************/
  257. X
  258. X#include "config.h"
  259. X
  260. X/*
  261. X** system includes <>
  262. X*/
  263. X
  264. X#include <stdio.h>
  265. X#include <ctype.h>
  266. X#include <sys/types.h>
  267. X#include <sys/stat.h>
  268. X#ifndef NO_STDLIB
  269. X#include <stdlib.h>
  270. X#endif
  271. X#ifndef NO_MALLOCHDR
  272. X#include <malloc.h>
  273. X#endif
  274. X#ifndef NO_STR_INC
  275. X#ifdef STRING_PLURAL
  276. X#include <strings.h>
  277. X#else
  278. X#include <string.h>
  279. X#endif
  280. X#endif
  281. X#ifdef UTIME_HDR
  282. X#include <utime.h>
  283. X#endif
  284. X
  285. X
  286. X/*
  287. X** custom includes ""
  288. X*/
  289. X
  290. X#include "depend.h"
  291. X
  292. X#include "fb.h"
  293. X#include "mf.h"
  294. X
  295. X#include "formats.h"
  296. X#include "gif.h"
  297. X
  298. X#include "stdinarg.h"
  299. X
  300. X#include "patchlevel.h"
  301. X
  302. X
  303. X/*
  304. X** local #defines
  305. X*/
  306. X
  307. X#define FB_TABLESIZE         5
  308. X#ifdef SMALL_MEM
  309. X#define FB_BUFSIZE           4096
  310. X#else
  311. X#define FB_BUFSIZE           30000
  312. X#endif
  313. X
  314. X#define TBUFSIZ              15
  315. X
  316. X#define EARLY                0
  317. X#define LATE                 1
  318. X
  319. X/* Returns from strip(). */
  320. X
  321. X#define EXIT_OK              0
  322. X#define EXIT_NOTGIF          1
  323. X#define EXIT_UNEOF           2
  324. X#define EXIT_ERROR           3
  325. X
  326. X
  327. X/*
  328. X** misc: copyright strings, version macros, etc.
  329. X*/
  330. X
  331. Xstatic char CONST copyright[] = "Copyright (c) 1992 James W. Birdsall. All Rights Reserved";
  332. Xstatic char CONST rcsid[] = "$Id: gifstrip.c,v 1.10 1993/03/02 00:49:36 jwbirdsa Exp $";
  333. X
  334. X#define VERS                 "2.0"
  335. X
  336. X
  337. X/*
  338. X** typedefs
  339. X*/
  340. X
  341. X#ifndef UTIME_HDR
  342. Xstruct utimbuf
  343. X{
  344. X    time_t actime;
  345. X    time_t modtime;
  346. X};
  347. X#endif
  348. X
  349. X/*
  350. X** global variables
  351. X*/
  352. X
  353. X/*
  354. X** static globals
  355. X*/
  356. X
  357. X/* Default: use memory and disk. */
  358. X
  359. Xstatic int mf_flags = (USE_CONMEM | USE_DISKMEM);
  360. X
  361. X/* Default: no recopy if no extra bytes or no format violations. */
  362. X
  363. Xstatic int forced_copy = 0;
  364. X
  365. X/* Default: strict format -- report and recopy on format violations. */
  366. X
  367. Xstatic int strict = 1;
  368. X
  369. X/* Default: assume no leading junk. */
  370. X
  371. Xstatic int nolead = 1;
  372. X
  373. X/* Default: late unlink. */
  374. X
  375. Xstatic int unlinktime = LATE;
  376. X
  377. X/* File handles for standard and error output. */
  378. X
  379. Xstatic FILE *outstr = stdout;
  380. Xstatic FILE *outerr = stdout;
  381. X
  382. X/* Temporary file path. */
  383. X
  384. Xstatic char *tpath = (char *) NULL;
  385. X
  386. X/* Global scratch space. */
  387. X
  388. Xstatic char scratch[80];
  389. X
  390. X
  391. X/*
  392. X** function prototypes
  393. X*/
  394. X
  395. X#ifdef  __STDC__
  396. X# define P_(s) s
  397. X#else
  398. X# define P_(s) ()
  399. X#endif
  400. X
  401. Xstatic int strip P_((char *filename));
  402. X
  403. Xstatic VOID usage();
  404. Xstatic char *errxlate P_((ULONG errcode));
  405. X
  406. X#undef P_
  407. X
  408. X#ifdef NO_STR_INC
  409. X#ifndef NO_STRDUP
  410. Xextern char *strdup();
  411. X#endif
  412. X#endif
  413. X
  414. X
  415. X/*
  416. X** functions
  417. X*/
  418. X
  419. X
  420. X/***************************************************************************
  421. X *   FUNCTION MAIN                                                         *
  422. X ***************************************************************************/
  423. X#ifdef __STDC__
  424. Xmain(int argc, char *argv[])
  425. X#else
  426. Xmain(argc, argv)
  427. Xint argc;
  428. Xchar *argv[];
  429. X#endif
  430. X{
  431. X    int loop, loop2;
  432. X    int onlyflags = 1;
  433. X    int argcc;
  434. X    char **argvv;
  435. X    char **namelist;
  436. X    char separator;
  437. X    char *temp;
  438. X    int stdinkey = 1;    /* Nonzero = stdin is keyboard, zero = redirected. */
  439. X    int errorlevel;
  440. X
  441. X    /* Search for option and parse if found. */
  442. X
  443. X    for(loop = 1; loop < argc; loop++)
  444. X    {
  445. X        if ('-' == argv[loop][0])
  446. X        {
  447. X            switch (argv[loop][1])
  448. X            {
  449. X                /* Don't use memory. */
  450. X                case 'c':
  451. X                    mf_flags &= (~(USE_CONMEM));
  452. X                    if ((mf_flags & USE_MASK) == 0)
  453. X                    {
  454. X                        fprintf(outerr, "ERROR: Cannot process files unless some form of temporary storage is\n");
  455. X                        fprintf(outerr, "available and allowed. Type GIFSTRIP -h for usage.\n");
  456. X                        exit(EXIT_ERROR);
  457. X                    }
  458. X                    break;
  459. X
  460. X                /* Don't use disk. */
  461. X                case 'd':
  462. X                    mf_flags &= (~(USE_DISKMEM));
  463. X                    if ((mf_flags & USE_MASK) == 0)
  464. X                    {
  465. X                        fprintf(outerr, "ERROR: Cannot process files unless some form of temporary storage is\n");
  466. X                        fprintf(outerr, "available and allowed. Type GIFSTRIP -h for usage.\n");
  467. X                        exit(EXIT_ERROR);
  468. X                    }
  469. X                    break;
  470. X
  471. X                /* Safety mode, use only disk. */
  472. X                case 's':
  473. X                    mf_flags &= (~(USE_CONMEM));
  474. X                    if ((mf_flags & USE_MASK) == 0)
  475. X                    {
  476. X                        fprintf(outerr, "ERROR: Cannot process files unless some form of temporary storage is\n");
  477. X                        fprintf(outerr, "available and allowed. Type GIFSTRIP -h for usage.\n");
  478. X                        exit(EXIT_ERROR);
  479. X                    }
  480. X                    break;
  481. X
  482. X                /* Batch mode option. */
  483. X                case 'b': 
  484. X                    if ((outstr = fopen(NULL_DEVICE, "w")) == (FILE *) NULL)
  485. X                    {
  486. X                        fprintf(stderr, "ERROR: Cannot open %s\n", NULL_DEVICE);
  487. X                        exit(EXIT_ERROR);
  488. X                    }
  489. X                    outerr = outstr;
  490. X                    break;
  491. X
  492. X                /* Force rebuild of file. */
  493. X                case 'f':
  494. X                    forced_copy = 1;
  495. X                    break;
  496. X
  497. X                /* Disable strict format enforcement. */
  498. X                case 'n':
  499. X                    strict = 0;
  500. X                    break;
  501. X
  502. X                /* Allow handling of leading junk. */
  503. X                case 'm':
  504. X                    nolead = 0;
  505. X                    break;
  506. X                /* Redirect errors to stderr. */
  507. X                case 'r':
  508. X                    outerr = stderr;
  509. X                    break;
  510. X
  511. X                /* Overwrite original file early. */
  512. X                case 'o':
  513. X                    unlinktime = EARLY;
  514. X                    break;
  515. X
  516. X                /* Specify temporary path. */
  517. X                case 't':
  518. X                    if ((tpath = strdup(&(argv[loop][2]))) == (char *) NULL)
  519. X                    {
  520. X                        fprintf(stderr, "ERROR: Out of memory.\n");
  521. X                        exit(EXIT_ERROR);
  522. X                    }
  523. X                    break;
  524. X
  525. X                /* Take filenames from stdin. */
  526. X                case '-':
  527. X                    stdinkey = 0;
  528. X                    break;
  529. X
  530. X                /* Help option. */
  531. X                case 'h':
  532. X                /* Unknown option. */
  533. X                default:
  534. X                    usage();
  535. X                    break;
  536. X            }
  537. X        }
  538. X        else
  539. X        {
  540. X            /*
  541. X            ** onlyflags == 1 when the command line contains only options.
  542. X            ** If this clause is executed, means there is at least one arg
  543. X            ** which is not an option and therefore is a target.
  544. X            */
  545. X
  546. X            onlyflags = 0;
  547. X        }
  548. X    }
  549. X
  550. X    /* If no target(s) specified and stdin not redirected, error. */
  551. X
  552. X    if ((onlyflags != 0) && (stdinkey != 0))
  553. X    {
  554. X        usage();
  555. X    }
  556. X
  557. X    /* Initialize file buffering package. */
  558. X
  559. X    if (fb_init(FB_TABLESIZE, FB_BUFSIZE) != 0)
  560. X    {
  561. X        fprintf(outerr, "%s\n", fb_errstring(fb_error));
  562. X        exit(EXIT_ERROR);
  563. X    }
  564. X
  565. X    /* Check for stdin redirection -- load targets from stdin if redirected. */
  566. X
  567. X    if (stdinkey != 0)
  568. X    {
  569. X        argcc = argc;
  570. X        argvv = argv;
  571. X    }
  572. X    else
  573. X    {
  574. X        argvv = stdinload(&argcc);
  575. X        argvv[0] = argv[0];
  576. X    }
  577. X
  578. X    /* Loop through targets, processing. */
  579. X
  580. X    for(loop = 1; loop < argcc; loop++)
  581. X    {
  582. X        if (argvv[loop][0] != '-')
  583. X        {
  584. X            /* Extract an argument from the command line and expand it. */
  585. X
  586. X            if ((namelist = scand(argvv[loop])) == NULL)
  587. X            {
  588. X                fprintf(outerr, "ERROR: bad target %s\n", argvv[loop]);
  589. X                continue;
  590. X            }
  591. X            else if (NULL == namelist[0])
  592. X            {
  593. X                fprintf(outerr, "WARNING: No files matching %s found.\n",
  594. X                        argvv[loop]);
  595. X                continue;
  596. X            }
  597. X
  598. X            /* Strip each file. */
  599. X
  600. X            for(loop2 = 0; namelist[loop2]; loop2++)
  601. X            {
  602. X                fprintf(outstr, "\nProcessing %s...\n", namelist[loop2]);
  603. X                errorlevel = strip(namelist[loop2]);
  604. X            }
  605. X
  606. X            /* Cleanup. */
  607. X
  608. X            for(loop2 = 0; namelist[loop2]; loop2++)
  609. X            {
  610. X                free(namelist[loop2]);
  611. X            }
  612. X            free(namelist);
  613. X            if (0 == stdinkey)
  614. X            {
  615. X                free(argvv[loop]);
  616. X            }
  617. X        }
  618. X    }
  619. X
  620. X    /* Cleanup. */
  621. X
  622. X    if (0 == stdinkey)
  623. X    {
  624. X        free(argvv);
  625. X    }
  626. X
  627. X    exit(errorlevel);
  628. X} /* end of main */
  629. X
  630. X
  631. X/***************************************************************************
  632. X*   FUNCTION:    strip  STATIC                                             *
  633. X*                                                                          *
  634. X*   DESCRIPTION:                                                           *
  635. X*                                                                          *
  636. X*       This function rebuilds the named file, if necessary.               *
  637. X*                                                                          *
  638. X*   ENTRY:                                                                 *
  639. X*                                                                          *
  640. X*       filename - name of file to be rebuilt. May include drive and/or    *
  641. X*                  path.                                                   *
  642. X*                                                                          *
  643. X*   EXIT:                                                                  *
  644. X*                                                                          *
  645. X*       Returns EXIT_OK, EXIT_NOTGIF, or EXIT_ERROR, depending.            *
  646. X*                                                                          *
  647. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  648. X*                                                                          *
  649. X***************************************************************************/
  650. Xstatic int
  651. X#ifdef __STDC__
  652. Xstrip(char *filename)
  653. X#else
  654. Xstrip(filename)
  655. Xchar *filename;
  656. X#endif
  657. X{
  658. X    FILE *origfile, *stampset;
  659. X    FB *infile, *outfile;
  660. X    ULONG status;
  661. X    long size;
  662. X    int colors;
  663. X    int viol_copy = 0;
  664. X    ULONG skip;
  665. X    ULONG newbytes = 0L;
  666. X    ULONG blockbytes;
  667. X    unsigned int blocks;
  668. X    UCHAR *rebuf;
  669. X    struct stat statbuf;
  670. X    struct utimbuf times;
  671. X    char *tname;
  672. X    int myuid;
  673. X    int fileuid;
  674. X
  675. X    UCHAR tempbuf[TBUFSIZ];
  676. X    int loop;
  677. X
  678. X    GIF_LSD lsd;
  679. X    RGB_TRIPLET *ctable;
  680. X    int blocktype;
  681. X    int extype;
  682. X    GIF_IMD imd;
  683. X    UCHAR codesize;
  684. X    UCHAR *data;
  685. X    int datalen;
  686. X
  687. X    /* Open original GIF and perform other startup functions. */
  688. X
  689. X    if ((origfile = fopen(filename, FOPEN_READ_BINARY)) == (FILE *) NULL)
  690. X    {
  691. X        fprintf(outerr, "ERROR: Cannot open file %s\n", filename);
  692. X        return EXIT_ERROR;
  693. X    }
  694. X    mf_locked = 0;
  695. X
  696. X    /* Get the size and other data (owner, group, timestamps, mode). */
  697. X
  698. X    if (fstat(fileno(origfile), &statbuf) == -1)
  699. X    {
  700. X        fprintf(outerr, "ERROR: Error in fstat() on %s\n", filename);
  701. X        fclose(origfile);
  702. X        return EXIT_ERROR;
  703. X    }
  704. X    size = statbuf.st_size;
  705. X
  706. X    /* Open memory file and make sure there is enough space. */
  707. X
  708. X    if ((status = mf_open(mf_flags, (ULONG) size, tpath)) != 0)
  709. X    {
  710. X        fprintf(outerr, "%s\n", errxlate(status));
  711. X        fclose(origfile);
  712. X        return EXIT_ERROR;
  713. X    }
  714. X
  715. X    /* Get GIF logical screen descriptor. */
  716. X
  717. X    if (nolead != 0)
  718. X    {
  719. X        if ((status = gif_lsdget(origfile, &lsd)) != ST_SUCCESS)
  720. X        {
  721. X            fprintf(outerr, "%s\n", errxlate(status));
  722. X            fclose(origfile);
  723. X            mf_close();
  724. X            switch (ERRSEV(status))
  725. X            {
  726. X                case ERRSEV(GIF_NOTGIF_E):
  727. X                    return EXIT_NOTGIF;
  728. X
  729. X                case ERRSEV(GIF_UNEOF_E):
  730. X                    return EXIT_UNEOF;
  731. X
  732. X                default:
  733. X                    return EXIT_ERROR;
  734. X            }
  735. X        }
  736. X
  737. X        /* Attach buffering to original GIF file. */
  738. X
  739. X        infile = fb_retrofit(origfile, 'r');
  740. X        if (fb_error != 0)
  741. X        {
  742. X            fprintf(outerr, "%s\n", errxlate(fb_error));
  743. X            fclose(origfile);
  744. X            mf_close();
  745. X            return EXIT_ERROR;
  746. X        }
  747. X
  748. X    }
  749. X    else
  750. X    {
  751. X        /* Attach buffering to original GIF file. */
  752. X        infile = fb_retrofit(origfile, 'r');
  753. X        if (fb_error != 0)
  754. X        {
  755. X            fprintf(outerr, "%s\n", errxlate(fb_error));
  756. X            fclose(origfile);
  757. X            mf_close();
  758. X            return EXIT_ERROR;
  759. X        }
  760. X
  761. X        /* Search for potentially buried LSD. */
  762. X
  763. X        if ((status = gif_searchlsd(infile, &lsd, &skip)) != ST_SUCCESS)
  764. X        {
  765. X            fprintf(outerr, "%s\n", errxlate(status));
  766. X            fb_close(infile);
  767. X            mf_close();
  768. X            switch (ERRSEV(status))
  769. X            {
  770. X                case ERRSEV(GIF_NOTGIF_E):
  771. X                case ERRSEV(GIF_UNEOF_E):
  772. X                    return EXIT_NOTGIF;
  773. X
  774. X                default:
  775. X                    return EXIT_ERROR;
  776. X            }
  777. X        }
  778. X        if (skip != 0)
  779. X        {
  780. X            fprintf(outstr, "FYI: Skipped %lu leading junk bytes.\n", skip);
  781. X        }
  782. X    }
  783. X
  784. X    /* Print some info. */
  785. X
  786. X    fprintf(outstr, ((GIF_89A == lsd.version) ? "GIF89A  " : "GIF87A  "));
  787. X    fprintf(outstr, ((lsd.gct_flag) ? "G" : "-"));
  788. X    if (GIF_89A == lsd.version)
  789. X    {
  790. X        fprintf(outstr, ((lsd.sort_flag) ? "S" : "-"));
  791. X        fprintf(outstr, ((lsd.aspect) ? "A" : "-"));
  792. X    }
  793. X    else
  794. X    {
  795. X        fprintf(outstr, "--");
  796. X    }
  797. X    fprintf(outstr, "%8ld  %5u x %5u @ ", size, lsd.scr_wid, lsd.scr_hi);
  798. X    if (lsd.gct_flag)
  799. X    {
  800. X        colors = (0x1 << lsd.gct_size);
  801. X        fprintf(outstr, "%3d", colors);
  802. X    }
  803. X    else
  804. X    {
  805. X        fprintf(outstr, "---");
  806. X    }
  807. X    fprintf(outstr, "   %s\n", filename);
  808. X
  809. X    /* Reconstruct GIF header and logical screen descriptor. */
  810. X
  811. X    /* Output signatures. */
  812. X
  813. X    if ((status = mf_write(GIF_SIGNATURE, GIF_SIGNATURE_LEN)) != 0)
  814. X    {
  815. X        fprintf(outerr, "%s\n", errxlate(status));
  816. X        fb_close(infile);
  817. X        mf_close();
  818. X        return EXIT_ERROR;
  819. X    }
  820. X    newbytes += GIF_SIGNATURE_LEN;
  821. X
  822. X    /* Output version signature. */
  823. X
  824. X    if ((status = mf_write(((GIF_89A == lsd.version) ? GIF_VERS89A_SIG :
  825. X                                                       GIF_VERS87A_SIG),
  826. X                           GIF_VERS_SIG_LEN)) != 0)
  827. X    {
  828. X        fprintf(outerr, "%s\n", errxlate(status));
  829. X        fb_close(infile);
  830. X        mf_close();
  831. X        return EXIT_ERROR;
  832. X    }
  833. X    newbytes += GIF_VERS_SIG_LEN;
  834. X
  835. X    /* Create new logical screen descriptor. */
  836. X
  837. X    tempbuf[GIF_LSD_SCRWID_OFF] = (UCHAR) (lsd.scr_wid & 0x00FF);
  838. X    tempbuf[GIF_LSD_SCRWID_OFF + 1] = (UCHAR) (lsd.scr_wid >> 8);
  839. X    tempbuf[GIF_LSD_SCRHI_OFF] = (UCHAR) (lsd.scr_hi & 0x00FF);
  840. X    tempbuf[GIF_LSD_SCRHI_OFF + 1] = (UCHAR) (lsd.scr_hi >> 8);
  841. X    if (0 == strict)
  842. X    {
  843. X        tempbuf[GIF_LSD_PACKED_OFF] = lsd.raw_packed;
  844. X    }
  845. X    else
  846. X    {
  847. X        tempbuf[GIF_LSD_PACKED_OFF] = 0;
  848. X        if (lsd.gct_flag)
  849. X        {
  850. X            tempbuf[GIF_LSD_PACKED_OFF] |= GIF_LSD_GCTFLAG_MASK;
  851. X        }
  852. X        tempbuf[GIF_LSD_PACKED_OFF] |= (UCHAR)
  853. X           (((lsd.clr_res - 1) << GIF_LSD_CLRRES_SHIFT) & GIF_LSD_CLRRES_MASK);
  854. X        if (lsd.sort_flag != 0)
  855. X        {
  856. X            if (GIF_89A == lsd.version)
  857. X            {
  858. X                tempbuf[GIF_LSD_PACKED_OFF] |= GIF_LSD_SORTFLAG_MASK;
  859. X            }
  860. X            else
  861. X            {
  862. X                /*
  863. X                ** Can only get here if version is 87A, strict is on,
  864. X                ** and sort flag is set. This is illegal combination.
  865. X                */
  866. X
  867. X                fprintf(outstr,
  868. X                 "FYI: Ignoring illegal global color table sorted flag.\n   ");
  869. X
  870. X                /*
  871. X                ** Turn on viol_copy so that file is rebuilt
  872. X                ** even if size is same.
  873. X                */
  874. X
  875. X                viol_copy = 1;
  876. X            }
  877. X        }
  878. X        tempbuf[GIF_LSD_PACKED_OFF] |=
  879. X                           (UCHAR) ((lsd.gct_size - 1) & GIF_LSD_GCTSIZE_MASK);
  880. X    }
  881. X    tempbuf[GIF_LSD_BACKGROUND_OFF] = (UCHAR) (lsd.background);
  882. X    if ((GIF_89A == lsd.version) || (0 == strict))
  883. X    {
  884. X        tempbuf[GIF_LSD_ASPECT_OFF] = (UCHAR) (lsd.aspect);
  885. X    }
  886. X    else
  887. X    {
  888. X        tempbuf[GIF_LSD_ASPECT_OFF] = 0;
  889. X        if (lsd.aspect != 0)
  890. X        {
  891. X            fprintf(outstr, "FYI: Ignoring illegal aspect ratio value.   \n");
  892. X
  893. X            /* Turn on viol_copy so that file is rebuilt even if size same. */
  894. X            viol_copy = 1;
  895. X        }
  896. X    }
  897. X
  898. X    /* Write new logical screen descriptor. */
  899. X
  900. X    if ((status = mf_write(tempbuf, GIF_LSD_LEN)) != 0)
  901. X    {
  902. X        fprintf(outerr, "%s\n", errxlate(status));
  903. X        fb_close(infile);
  904. X        mf_close();
  905. X        return EXIT_ERROR;
  906. X    }
  907. X    newbytes += GIF_LSD_LEN;
  908. X
  909. X    /* Get and write global color table, if any. */
  910. X
  911. X    if (lsd.gct_flag)
  912. X    {
  913. X        if ((status = gif_gctget(infile, &ctable, colors)) != 0)
  914. X        {
  915. X            fprintf(outerr, "%s\n", errxlate(status));
  916. X            fb_close(infile);
  917. X            mf_close();
  918. X            return ((GIF_UNEOF_E == status) ? EXIT_UNEOF : EXIT_ERROR);
  919. X        }
  920. X
  921. X        for (loop = 0; loop < colors; loop++)
  922. X        {
  923. X            tempbuf[0] = ctable[loop].red;
  924. X            tempbuf[1] = ctable[loop].green;
  925. X            tempbuf[2] = ctable[loop].blue;
  926. X            if ((status = mf_write(tempbuf, 3)) != 0)
  927. X            {
  928. X                fprintf(outerr, "%s\n", errxlate(status));
  929. X                fb_close(infile);
  930. X                mf_close();
  931. X                return EXIT_ERROR;
  932. X            }
  933. X            newbytes += 3;
  934. X        }
  935. X
  936. X        free(ctable);
  937. X    }
  938. X
  939. X    /* Loop through data blocks. */
  940. X
  941. X    blocktype = 0;
  942. X    while (blocktype != GIF_TERMINATOR)
  943. X    {
  944. X        fprintf(outstr, "   ");
  945. X
  946. X        /* Find next block. */
  947. X
  948. X        if ((status = gif_findnext(infile, &blocktype, &skip, &extype)) != 0)
  949. X        {
  950. X            fprintf(outerr, "%s\n", errxlate(status));
  951. X            fb_close(infile);
  952. X            mf_close();
  953. X            return ((GIF_UNEOF_E == status) ? EXIT_UNEOF : EXIT_ERROR);
  954. X        }
  955. X
  956. X        /* If skipped characters, FYI. */
  957. X
  958. X        if (skip != 0)
  959. X        {
  960. X            fprintf(outstr, "FYI: %lu garbage characters skipped\n   ", skip);
  961. X        }
  962. X
  963. X        /* Process by type of block. */
  964. X
  965. X        switch (blocktype)
  966. X        {
  967. X            case GIF_IMAGE:
  968. X                /* Write image header. */
  969. X
  970. X                tempbuf[0] = GIF_IMAGE;
  971. X                if ((status = mf_write(tempbuf, 1)) != 0)
  972. X                {
  973. X                    fprintf(outerr, "%s\n", errxlate(status));
  974. X                    fb_close(infile);
  975. X                    mf_close();
  976. X                    return EXIT_ERROR;
  977. X                }
  978. X                newbytes++;
  979. X
  980. X                /* Get image descriptor. */
  981. X
  982. X                if ((status = gif_imdget(infile, &imd)) != 0)
  983. X                {
  984. X                    fprintf(outerr, "%s\n", errxlate(status));
  985. X                    fb_close(infile);
  986. X                    mf_close();
  987. X                    return ((GIF_UNEOF_E == status) ? EXIT_UNEOF : EXIT_ERROR);
  988. X                }
  989. X
  990. X                /* Create new image descriptor. */
  991. X
  992. X                tempbuf[GIF_IMD_IMLEFT_OFF] = (UCHAR) (imd.im_left & 0x00FF);
  993. X                tempbuf[GIF_IMD_IMLEFT_OFF + 1] = (UCHAR) (imd.im_left >> 8);
  994. X                tempbuf[GIF_IMD_IMTOP_OFF] = (UCHAR) (imd.im_top & 0x00FF);
  995. X                tempbuf[GIF_IMD_IMTOP_OFF + 1] = (UCHAR) (imd.im_top >> 8);
  996. X                tempbuf[GIF_IMD_IMWID_OFF] = (UCHAR) (imd.im_wid & 0x00FF);
  997. X                tempbuf[GIF_IMD_IMWID_OFF + 1] = (UCHAR) (imd.im_wid >> 8);
  998. X                tempbuf[GIF_IMD_IMHI_OFF] = (UCHAR) (imd.im_hi & 0x00FF);
  999. X                tempbuf[GIF_IMD_IMHI_OFF + 1] = (UCHAR) (imd.im_hi >> 8);
  1000. X                if (0 == strict)
  1001. X                {
  1002. X                    tempbuf[GIF_IMD_PACKED_OFF] = imd.raw_packed;
  1003. X                }
  1004. X                else
  1005. X                {
  1006. X                    tempbuf[GIF_IMD_PACKED_OFF] = 0;
  1007. X                    if (imd.lct_flag)
  1008. X                    {
  1009. X                        tempbuf[GIF_IMD_PACKED_OFF] |= GIF_IMD_LCTFLAG_MASK;
  1010. X                        tempbuf[GIF_IMD_PACKED_OFF] |= (UCHAR)
  1011. X                                   ((imd.lct_size - 1) & GIF_IMD_LCTSIZE_MASK);
  1012. X                    }
  1013. X                    else if ((imd.lct_size - 1) != 0)
  1014. X                    {
  1015. X                        fprintf(outstr, "FYI: Ignoring illegal local color table size (no local color table).\n   ");
  1016. X
  1017. X                        /*
  1018. X                        ** Turn on viol_copy so that file is rebuilt
  1019. X                        ** even if size is same.
  1020. X                        */
  1021. X
  1022. X                        viol_copy = 1;
  1023. X                    }
  1024. X                    if (imd.interlace_flag)
  1025. X                    {
  1026. X                        tempbuf[GIF_IMD_PACKED_OFF] |=
  1027. X                                                     GIF_IMD_INTRLACEFLAG_MASK;
  1028. X                    }
  1029. X                    if (imd.sort_flag)
  1030. X                    {
  1031. X                        if ((GIF_89A == lsd.version) && (imd.lct_flag))
  1032. X                        {
  1033. X                            tempbuf[GIF_IMD_PACKED_OFF] |=
  1034. X                                                         GIF_IMD_SORTFLAG_MASK;
  1035. X                        }
  1036. X                        else
  1037. X                        {
  1038. X                            fprintf(outstr,
  1039. X                                "FYI: Ignoring illegal local color table sorted flag");
  1040. X                            if (0 == imd.lct_flag)
  1041. X                            {
  1042. X                                fprintf(outstr, " (no local color table)");
  1043. X                            }
  1044. X                            fprintf(outstr, ".\n   ");
  1045. X
  1046. X                            /*
  1047. X                            ** Turn on viol_copy so that file is rebuilt
  1048. X                            ** even if size is same.
  1049. X                            */
  1050. X
  1051. X                            viol_copy = 1;
  1052. X                        }
  1053. X                    }
  1054. X                }
  1055. X
  1056. X                /* Write new image descriptor. */
  1057. X
  1058. X                if ((status = mf_write(tempbuf, GIF_IMD_LEN)) != 0)
  1059. X                {
  1060. X                    fprintf(outerr, "%s\n", errxlate(status));
  1061. X                    fb_close(infile);
  1062. X                    mf_close();
  1063. X                    return EXIT_ERROR;
  1064. X                }
  1065. X                newbytes += GIF_IMD_LEN;
  1066. X
  1067. X                /* Print some info. */
  1068. X
  1069. X                fprintf(outstr, ((imd.lct_flag) ? "L" : "G"));
  1070. X                if (GIF_89A == lsd.version)
  1071. X                {
  1072. X                    fprintf(outstr, ((imd.sort_flag) ? "S" : "-"));
  1073. X                }
  1074. X                else
  1075. X                {
  1076. X                    fprintf(outstr, "-");
  1077. X                }
  1078. X                fprintf(outstr, ((imd.interlace_flag) ? "I" : "S"));
  1079. X                fprintf(outstr, "  (%3u,%3u)", imd.im_left, imd.im_top);
  1080. X                fprintf(outstr, "  %5u x %5u", imd.im_wid, imd.im_hi);
  1081. X                fprintf(outstr, " @ %3d  ", (0x1 << ((imd.lct_flag) ?
  1082. X                                            imd.lct_size : lsd.gct_size)));
  1083. X
  1084. X                /* Read and write local color table, if any. */
  1085. X
  1086. X                if (imd.lct_flag)
  1087. X                {
  1088. X                    if ((status = gif_lctget(infile, &ctable,
  1089. X                                             (0x1 << imd.lct_size))) != 0)
  1090. X                    {
  1091. X                        fprintf(outerr, "%s\n", errxlate(status));
  1092. X                        fb_close(infile);
  1093. X                        mf_close();
  1094. X                        return ((GIF_UNEOF_E == status) ? EXIT_UNEOF :
  1095. X                                                          EXIT_ERROR);
  1096. X                    }
  1097. X
  1098. X                    for (loop = 0; loop < (0x1 << imd.lct_size); loop++)
  1099. X                    {
  1100. X                        tempbuf[0] = ctable[loop].red;
  1101. X                        tempbuf[1] = ctable[loop].green;
  1102. X                        tempbuf[2] = ctable[loop].blue;
  1103. X                        if ((status = mf_write(tempbuf, 3)) != 0)
  1104. X                        {
  1105. X                            fprintf(outerr, "%s\n", errxlate(status));
  1106. X                            fb_close(infile);
  1107. X                            mf_close();
  1108. X                            return EXIT_ERROR;
  1109. X                        }
  1110. X                        newbytes += 3;
  1111. X                    }
  1112. X
  1113. X                    free(ctable);
  1114. X                }
  1115. X
  1116. X                /* Read and write codesize. */
  1117. X
  1118. X                codesize = (UCHAR) fb_getc(infile);
  1119. X                if (fb_error != 0)
  1120. X                {
  1121. X                    fprintf(outerr, "%s\n", errxlate(fb_error));
  1122. X                    fb_close(infile);
  1123. X                    mf_close();
  1124. X                    return ((FB_EOF_W == status) ? EXIT_UNEOF : EXIT_ERROR);
  1125. X                }
  1126. X                if ((status = mf_write(&codesize, 1)) != 0)
  1127. X                {
  1128. X                    fprintf(outerr, "%s\n", errxlate(status));
  1129. X                    fb_close(infile);
  1130. X                    mf_close();
  1131. X                    return EXIT_ERROR;
  1132. X                }
  1133. X                newbytes++;
  1134. X
  1135. X                /* Read and write data blocks until done. */
  1136. X
  1137. X                blockbytes = 0;
  1138. X                blocks = 0;
  1139. X                while (1)
  1140. X                {
  1141. X                    /* Read block. */
  1142. X
  1143. X                    if ((status = gif_readblock(infile, &data, &datalen)) != 0)
  1144. X                    {
  1145. X                        fprintf(outerr, "%s\n", errxlate(status));
  1146. X                        fb_close(infile);
  1147. X                        mf_close();
  1148. X                        return ((GIF_UNEOF_E == status) ? EXIT_UNEOF :
  1149. X                                                          EXIT_ERROR);
  1150. X                    }
  1151. X
  1152. X                    /* Check length. */
  1153. X
  1154. X                    if (0 == datalen)
  1155. X                    {
  1156. X                        /* If zero length, at end. */
  1157. X
  1158. X                        break;
  1159. X                    }
  1160. X                    blockbytes += (ULONG) datalen;
  1161. X                    blocks++;
  1162. X
  1163. X                    /* Write block length. */
  1164. X
  1165. X                    tempbuf[0] = (UCHAR) datalen;
  1166. X                    if ((status = mf_write(tempbuf, 1)) != 0)
  1167. X                    {
  1168. X                        fprintf(outerr, "%s\n", errxlate(status));
  1169. X                        fb_close(infile);
  1170. X                        mf_close();
  1171. X                        return EXIT_ERROR;
  1172. X                    }
  1173. X                    newbytes++;
  1174. X
  1175. X                    /* Write block. */
  1176. X
  1177. X                    if ((status = mf_write(data, (unsigned int) datalen)) != 0)
  1178. X                    {
  1179. X                        fprintf(outerr, "%s\n", errxlate(status));
  1180. X                        fb_close(infile);
  1181. X                        mf_close();
  1182. X                        return EXIT_ERROR;
  1183. X                    }
  1184. X                    newbytes += (ULONG) datalen;
  1185. X
  1186. X                    /* Free block. */
  1187. X
  1188. X                    free(data);
  1189. X                }
  1190. X
  1191. X                /* Write terminating block. */
  1192. X
  1193. X                tempbuf[0] = '\0';
  1194. X                if ((status = mf_write(tempbuf, 1)) != 0)
  1195. X                {
  1196. X                    fprintf(outerr, "%s\n", errxlate(status));
  1197. X                    fb_close(infile);
  1198. X                    mf_close();
  1199. X                    return EXIT_ERROR;
  1200. X                }
  1201. X                newbytes++;
  1202. X
  1203. X                /* Print more info. */
  1204. X
  1205. X                fprintf(outstr, "%6luBY  %4uBL\n", blockbytes, blocks);
  1206. X
  1207. X                break;
  1208. X
  1209. X            case GIF_EXTBLOCK:
  1210. X                /* Write out extension block header and type. */
  1211. X
  1212. X                tempbuf[0] = GIF_EXTBLOCK;
  1213. X                tempbuf[1] = (UCHAR) extype;
  1214. X                if ((status = mf_write(tempbuf, 2)) != 0)
  1215. X                {
  1216. X                    fprintf(outerr, "%s\n", errxlate(status));
  1217. X                    fb_close(infile);
  1218. X                    mf_close();
  1219. X                    return EXIT_ERROR;
  1220. X                }
  1221. X                newbytes += 2;
  1222. X
  1223. X                /* Print some info. */
  1224. X
  1225. X                if (GIF_89A == lsd.version)
  1226. X                {
  1227. X                    switch (extype)
  1228. X                    {
  1229. X                        case GIF_EXT_PLAIN_TEXT:
  1230. X                            fprintf(outstr, "Plain Text Extension Block");
  1231. X                            break;
  1232. X
  1233. X                        case GIF_EXT_GRAPHIC_CONTROL:
  1234. X                            fprintf(outstr, "Graphic Control Extension Block");
  1235. X                            break;
  1236. X
  1237. X                        case GIF_EXT_COMMENT:
  1238. X                            fprintf(outstr, "Comment Extension Block");
  1239. X                            break;
  1240. X
  1241. X                        case GIF_EXT_APPLICATION:
  1242. X                            fprintf(outstr, "Application Extension Block");
  1243. X                            break;
  1244. X
  1245. X                        default:
  1246. X                            fprintf(outstr, "Type %3d Extension Block", extype);
  1247. X                            break;
  1248. X                    }
  1249. X                }
  1250. X                else
  1251. X                {
  1252. X                    fprintf(outstr, "Type %3d Extension Block", extype);
  1253. X                }
  1254. X
  1255. X                /* Read and write data blocks until done. */
  1256. X
  1257. X                blockbytes = 0;
  1258. X                blocks = 0;
  1259. X                while (1)
  1260. X                {
  1261. X                    /* Read block. */
  1262. X
  1263. X                    if ((status = gif_readblock(infile, &data, &datalen)) != 0)
  1264. X                    {
  1265. X                        fprintf(outerr, "%s\n", errxlate(status));
  1266. X                        fb_close(infile);
  1267. X                        mf_close();
  1268. X                        return ((GIF_UNEOF_E == status) ? EXIT_UNEOF :
  1269. X                                                          EXIT_ERROR);
  1270. X                    }
  1271. X
  1272. X                    /* Check length. */
  1273. X
  1274. X                    if (0 == datalen)
  1275. X                    {
  1276. X                        /* If zero length, at end. */
  1277. X
  1278. X                        break;
  1279. X                    }
  1280. X                    blockbytes += (ULONG) datalen;
  1281. X                    blocks++;
  1282. X
  1283. X                    /* Write block length. */
  1284. X
  1285. X                    tempbuf[0] = (UCHAR) datalen;
  1286. X                    if ((status = mf_write(tempbuf, 1)) != 0)
  1287. X                    {
  1288. X                        fprintf(outerr, "%s\n", errxlate(status));
  1289. X                        fb_close(infile);
  1290. X                        mf_close();
  1291. X                        return EXIT_ERROR;
  1292. X                    }
  1293. X                    newbytes++;
  1294. X                    /* Write block. */
  1295. X
  1296. X                    if ((status = mf_write(data, (unsigned int) datalen)) != 0)
  1297. X                    {
  1298. X                        fprintf(outerr, "%s\n", errxlate(status));
  1299. X                        fb_close(infile);
  1300. X                        mf_close();
  1301. X                        return EXIT_ERROR;
  1302. X                    }
  1303. X                    newbytes += (ULONG) datalen;
  1304. X
  1305. X                    /* Free block. */
  1306. X
  1307. X                    free(data);
  1308. X                }
  1309. X
  1310. X                /* Write terminating block. */
  1311. X
  1312. X                tempbuf[0] = '\0';
  1313. X                if ((status = mf_write(tempbuf, 1)) != 0L)
  1314. X                {
  1315. X                    fprintf(outerr, "%s\n", errxlate(status));
  1316. X                    fb_close(infile);
  1317. X                    mf_close();
  1318. X                    return EXIT_ERROR;
  1319. X                }
  1320. X                newbytes++;
  1321. X
  1322. X                /* Print more info. */
  1323. X
  1324. X                fprintf(outstr, "%6luBY  %4uBL\n", blockbytes, blocks);
  1325. X
  1326. X                break;
  1327. X
  1328. X            case GIF_TERMINATOR:
  1329. X                /* Print info. */
  1330. X
  1331. X                fprintf(outstr, "GIF Terminator\n");
  1332. X
  1333. X                /* Write terminator. */
  1334. X
  1335. X                tempbuf[0] = GIF_TERMINATOR;
  1336. X                if ((status = mf_write(tempbuf, 1)) != 0)
  1337. X                {
  1338. X                    fprintf(outerr, "%s\n", errxlate(status));
  1339. X                    fb_close(infile);
  1340. X                    mf_close();
  1341. X                    return EXIT_ERROR;
  1342. X                }
  1343. X                newbytes++;
  1344. X
  1345. X                break;
  1346. X
  1347. X            default:
  1348. X                fprintf(outerr, "FATAL ERROR: Internal error.\n");
  1349. X                break;
  1350. X
  1351. X        } /* end of switch (blocktype) */
  1352. X    } /* end of while (blocktype != GIF_TERMINATOR) */
  1353. X
  1354. X    /* Read all good data from file, clean up. */
  1355. X
  1356. X    if ((status = fb_close(infile)) != 0)
  1357. X    {
  1358. X        fprintf(outerr, "%s\n", errxlate(status));
  1359. X        mf_close();
  1360. X        return EXIT_ERROR;
  1361. X    }
  1362. X    if ((status = mf_reset()) != 0)
  1363. X    {
  1364. X        fprintf(outerr, "%s\n", errxlate(status));
  1365. X        mf_close();
  1366. X        return EXIT_ERROR;
  1367. X    }
  1368. X
  1369. X    /* Check for change in file size. */
  1370. X
  1371. X    if ((newbytes == size) && (0 == forced_copy) && (0 == viol_copy))
  1372. X    {
  1373. X        fprintf(outstr, "   No work to be done. File unchanged.\n");
  1374. X        if ((status = mf_close()) != 0)
  1375. X        {
  1376. X            fprintf(outerr, "%s\n", errxlate(status));
  1377. X            return EXIT_ERROR;
  1378. X        }
  1379. X        return EXIT_OK;
  1380. X    }
  1381. X
  1382. X    /* Prepare to recopy. */
  1383. X
  1384. X    fprintf(outstr, "   New size: %6lu   Bytes removed: %6lu\n", newbytes,
  1385. X             (size - newbytes));
  1386. X
  1387. X    /* Lock temporary file, if there is one. */
  1388. X
  1389. X    mf_locked = 1;
  1390. X
  1391. X    if (EARLY == unlinktime)
  1392. X    {
  1393. X        /* Delete original file. */
  1394. X
  1395. X        if (unlink(filename) != 0)
  1396. X        {
  1397. X            fprintf(outerr, "   FATAL ERROR: Cannot remove original file.\n");
  1398. X            mf_locked = 0;
  1399. X            mf_close();
  1400. X            return EXIT_ERROR;
  1401. X        }
  1402. X
  1403. X        /* Open output file. */
  1404. X
  1405. X        outfile = fb_open(filename, 'w', &size);
  1406. X        if (fb_error != 0)
  1407. X        {
  1408. X            fprintf(outerr, "%s\n", errxlate(fb_error));
  1409. X            mf_close();
  1410. X            return EXIT_ERROR;
  1411. X        }
  1412. X    }
  1413. X    else
  1414. X    {
  1415. X        /* Check free space. */
  1416. X
  1417. X        if (dfree(filename) < newbytes)
  1418. X        {
  1419. X            fprintf(outerr, "   ERROR: Insufficient space on disk for recopy. Try using -o\n");
  1420. X            mf_locked = 0;
  1421. X            mf_close();
  1422. X            return EXIT_ERROR;
  1423. X        }
  1424. X
  1425. X        /* Get a name for a temporary file in the current directory. */
  1426. X
  1427. X        tname = tempname(".", "GIF.");
  1428. X        if (NULL == tname)
  1429. X        {
  1430. X            fprintf(outerr, "Cannot get name for temporary file.\n");
  1431. X            mf_close();
  1432. X            return EXIT_ERROR;
  1433. X        }
  1434. X
  1435. X        /* Open temporary file. */
  1436. X
  1437. X        outfile = fb_open(tname, 'w', &size);
  1438. X        if (fb_error != 0L)
  1439. X        {
  1440. X            fprintf(outerr, "%s\n", errxlate(fb_error));
  1441. X            mf_close();
  1442. X            free(tname);
  1443. X            return EXIT_ERROR;
  1444. X        }
  1445. X    }
  1446. X
  1447. X    /* Allocate recopy buffer. */
  1448. X
  1449. X    blockbytes = FB_BUFSIZE;
  1450. X    while ((rebuf = (UCHAR *) malloc((unsigned int) blockbytes)) ==
  1451. X           (UCHAR *) NULL)
  1452. X    {
  1453. X        blockbytes /= 2;
  1454. X        if (blockbytes < TBUFSIZ)
  1455. X        {
  1456. X            rebuf = tempbuf;
  1457. X            blockbytes = TBUFSIZ;
  1458. X            break;
  1459. X        }
  1460. X    }
  1461. X
  1462. X    /* Recopy.  */
  1463. X
  1464. X    fprintf(outstr, "Recopying... ");
  1465. X    for (; newbytes != 0; newbytes -= blockbytes)
  1466. X    {
  1467. X        if (newbytes < blockbytes)
  1468. X        {
  1469. X            blockbytes = newbytes;
  1470. X        }
  1471. X        if ((status = mf_read(rebuf, (unsigned int) blockbytes, &blocks)) != 0)
  1472. X        {
  1473. X            fprintf(outerr, "%s\n", errxlate(status));
  1474. X            fb_close(outfile);
  1475. X            mf_close();
  1476. X            if (rebuf != tempbuf)
  1477. X            {
  1478. X                free(rebuf);
  1479. X            }
  1480. X            unlink(tname);
  1481. X            if (LATE == unlinktime)
  1482. X            {
  1483. X                free(tname);
  1484. X            }
  1485. X            return EXIT_ERROR;
  1486. X        }
  1487. X        if ((status = fb_write(outfile, rebuf, (int) blockbytes)) != 0)
  1488. X        {
  1489. X            fprintf(outerr, "%s\n", errxlate(status));
  1490. X            fb_close(outfile);
  1491. X            mf_close();
  1492. X            if (rebuf != tempbuf)
  1493. X            {
  1494. X                free(rebuf);
  1495. X            }
  1496. X            unlink(tname);
  1497. X            if (LATE == unlinktime)
  1498. X            {
  1499. X                free(tname);
  1500. X            }
  1501. X            return EXIT_ERROR;
  1502. X        }
  1503. X    }
  1504. X    fprintf(outstr, "done.\n");
  1505. X
  1506. X    /* Close all, clean up. */
  1507. X
  1508. X    /* Close rebuilt file. */
  1509. X
  1510. X    if ((status = fb_close(outfile)) != 0)
  1511. X    {
  1512. X        fprintf(outerr, "%s\n", errxlate(status));
  1513. X        mf_close();
  1514. X        if (rebuf != tempbuf)
  1515. X        {
  1516. X            free(rebuf);
  1517. X        }
  1518. X        unlink(tname);
  1519. X        if (LATE == unlinktime)
  1520. X        {
  1521. X            free(tname);
  1522. X        }
  1523. X        return EXIT_ERROR;
  1524. X    }
  1525. X
  1526. X    /* Close memory file. */
  1527. X
  1528. X    mf_locked = 0;
  1529. X    if ((status = mf_close()) != 0)
  1530. X    {
  1531. X        fprintf(outerr, "%s\n", errxlate(status));
  1532. X        if (rebuf != tempbuf)
  1533. X        {
  1534. X            free(rebuf);
  1535. X        }
  1536. X        unlink(tname);
  1537. X        if (LATE == unlinktime)
  1538. X        {
  1539. X            free(tname);
  1540. X        }
  1541. X        return EXIT_ERROR;
  1542. X    }
  1543. X
  1544. X    /* Release recopy buffer. */
  1545. X
  1546. X    if (rebuf != tempbuf)
  1547. X    {
  1548. X        free(rebuf);
  1549. X    }
  1550. X
  1551. X    if (LATE == unlinktime)
  1552. X    {
  1553. X        /* Now remove original file. */
  1554. X
  1555. X        if (unlink(filename) != 0)
  1556. X        {
  1557. X            fprintf(outerr, "   FATAL ERROR: Cannot remove original file.\n");
  1558. X            unlink(tname);
  1559. X            free(tname);
  1560. X            return EXIT_ERROR;
  1561. X        }
  1562. X
  1563. X        /* And rename temporary file. */
  1564. X
  1565. X        if (rename(tname, filename) != 0)
  1566. X        {
  1567. X            fprintf(outerr, "   FATAL ERROR: Cannot move %s to %s.\n", tname, filename);
  1568. X            unlink(tname);
  1569. X            free(tname);
  1570. X            return EXIT_ERROR;
  1571. X        }
  1572. X        free(tname);
  1573. X    }
  1574. X
  1575. X    /* Reset the time stamp, owner, mode, etc. of the recopied file. */
  1576. X
  1577. X    /* First, update mode. */
  1578. X
  1579. X    if (chmod(filename, (statbuf.st_mode & 07777)) == -1)
  1580. X    {
  1581. X        fprintf(outerr, "ERROR: Error setting mode of recopied file!\n");
  1582. X        return EXIT_ERROR;
  1583. X    }
  1584. X
  1585. X    /* Next, try to change owner, but only if necessary. */
  1586. X
  1587. X    fileuid = myuid = getuid();
  1588. X    if (myuid != statbuf.st_uid)
  1589. X    {
  1590. X#ifdef ROOT_CHOWN
  1591. X        if (myuid != 0)
  1592. X        {
  1593. X            /* If ROOT_CHOWN, only root can give away files with chown(). */
  1594. X
  1595. X            fprintf(outerr, "WARNING: Cannot reset owner of recopied file!\n");
  1596. X        }
  1597. X        else
  1598. X        {
  1599. X#endif
  1600. X            if (chown(filename, statbuf.st_uid, statbuf.st_gid) == -1)
  1601. X            {
  1602. X                fprintf(outerr,
  1603. X                        "ERROR: Error setting owner of recopied file!\n");
  1604. X                return EXIT_ERROR;
  1605. X            }
  1606. X            else
  1607. X            {
  1608. X                fileuid = statbuf.st_uid;
  1609. X            }
  1610. X#ifdef ROOT_CHOWN
  1611. X        }
  1612. X#endif
  1613. X    }
  1614. X    else if (getgid() != statbuf.st_gid)
  1615. X    {
  1616. X        /*
  1617. X        ** Owner is same, group is not. since owner is same, can
  1618. X        ** change group no problem.
  1619. X        */
  1620. X
  1621. X        if (chown(filename, statbuf.st_uid, statbuf.st_gid) == -1)
  1622. X        {
  1623. X            fprintf(outerr, "ERROR: Error setting group of recopied file!\n");
  1624. X            return EXIT_ERROR;
  1625. X        }
  1626. X    }
  1627. X
  1628. X    /* Finally, reset timestamps. */
  1629. X
  1630. X    if (myuid != fileuid)
  1631. X    {
  1632. X        /* We're not owner of file anymore, but are we root? */
  1633. X
  1634. X        if (0 == myuid)
  1635. X        {
  1636. X            /* We're root, so we can still update file timestamp. */
  1637. X
  1638. X            times.actime = statbuf.st_atime;
  1639. X            times.modtime = statbuf.st_mtime;
  1640. X            if (utime(filename, ×) == -1)
  1641. X            {
  1642. X                fprintf(outerr,
  1643. X                        "ERROR: Error setting timestamp on recopied file!\n");
  1644. X                return EXIT_ERROR;
  1645. X            }
  1646. X        }
  1647. X        else
  1648. X        {
  1649. X            fprintf(outerr, 
  1650. X                    "WARNING: Cannot set timestamp on recopied file!\n");
  1651. X        }
  1652. X    } 
  1653. X    else
  1654. X    {
  1655. X        /* We are owner, so can update timestamps no problem. */
  1656. X
  1657. X        times.actime = statbuf.st_atime;
  1658. X        times.modtime = statbuf.st_mtime;
  1659. X        if (utime(filename, ×) == -1)
  1660. X        {
  1661. X            fprintf(outerr, 
  1662. X                    "ERROR: Error setting timestamp on recopied file!\n");
  1663. X            return EXIT_ERROR;
  1664. X        }
  1665. X    }
  1666. X
  1667. X    /* All done, return OK. */
  1668. X
  1669. X    return EXIT_OK;
  1670. X} /* end of static strip() */
  1671. X
  1672. X
  1673. X/***************************************************************************
  1674. X*   FUNCTION:    usage  STATIC                                             *
  1675. X*                                                                          *
  1676. X*   DESCRIPTION:                                                           *
  1677. X*                                                                          *
  1678. X*      Prints out usage message.                                           *
  1679. X*                                                                          *
  1680. X*   ENTRY:                                                                 *
  1681. X*                                                                          *
  1682. X*      None.                                                               *
  1683. X*                                                                          *
  1684. X*   EXIT:                                                                  *
  1685. X*                                                                          *
  1686. X*      Never returns.                                                      *
  1687. X*                                                                          *
  1688. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  1689. X*                                                                          *
  1690. X*      Exit()s with errorlevel EXIT_ERROR.                                 *
  1691. X*                                                                          *
  1692. X***************************************************************************/
  1693. Xstatic VOID 
  1694. Xusage()
  1695. X{
  1696. X    fprintf(outstr, "\n");
  1697. X    fprintf(outstr, 
  1698. X            "GIFSTRIP version %s, patchlevel %d by James W. Birdsall.\n", 
  1699. X            VERS, PATCHLEVEL);
  1700. X    fprintf(outstr, "   Strips extraneous characters from GIF files.\n");
  1701. X    fprintf(outstr, "   usage: gifstrip [options] target [target ...]\n");
  1702. X    fprintf(outstr, "     target       filename or directory. If a directory, all files in that\n");
  1703. X    fprintf(outstr, "                   directory will be processed. If no targets are given,\n");
  1704. X    fprintf(outstr, "                   this usage message is displayed.\n");
  1705. X
  1706. X    fprintf(outstr, "     -b           BATCH: suppresses all console output. Should be first on the\n");
  1707. X    fprintf(outstr, "                   line. Returns 0 if OK or stripped OK, 1 if a non-GIF file\n");
  1708. X    fprintf(outstr, "                   was found, 2 if unexpected EOF in a GIF file, or 3 on error.\n");
  1709. X    fprintf(outstr, "     -r           Sends error messages to stderr instead of stdout.\n");
  1710. X    fprintf(outstr, "     --           Take targets from stdin. For use with -f option of CHILS.\n");
  1711. X    fprintf(outstr, "                   Targets must be separated by newlines. Directories are\n");
  1712. X    fprintf(outstr, "                   expanded but wildcards are not. Command-line targets are\n");
  1713. X    fprintf(outstr, "                   ignored if this option is given.\n");
  1714. X
  1715. X    fprintf(outstr, "     -f           Forces rebuild. Normally file is not rebuilt if no extra\n");
  1716. X    fprintf(outstr, "                   characters are found and file meets format requirements.\n");
  1717. X    fprintf(outstr, "     -n           Disables strict format requirements.\n");
  1718. X    fprintf(outstr, "     -m           Enables checking for leading junk characters (from a Mac,\n");
  1719. X    fprintf(outstr, "                   for example).\n");
  1720. X    fprintf(outstr, "     -o           OVERWRITE: erases original before recopying.\n");
  1721. X
  1722. X    fprintf(outstr, "     -c           Do not use memory for temporary storage.\n");
  1723. X    fprintf(outstr, "     -d           Do not use DISK for temporary storage.\n");
  1724. X    fprintf(outstr, "     -s           Use ONLY DISK for temporary storage. Equivalent to -c\n");
  1725. X    fprintf(outstr, "     -tpath       Specify path for DISK temporary storage.\n");
  1726. X    fprintf(outstr, "     -h           HELP: Prints this message.\n");
  1727. X
  1728. X    fprintf(outstr, "   Note that at least one of memory or disk must be allowed.\n");
  1729. X    fprintf(outstr, "\n");
  1730. X    fprintf(outstr, "   Options may not be combined.\n");
  1731. X    fprintf(outstr, "\n");
  1732. X
  1733. X    exit(EXIT_ERROR);
  1734. X} /* end of static usage() */
  1735. X
  1736. X
  1737. X/***************************************************************************
  1738. X*   FUNCTION: errxlate STATIC                                              *
  1739. X*                                                                          *
  1740. X*   DESCRIPTION:                                                           *
  1741. X*                                                                          *
  1742. X*       Translates an error code into a string.                            *
  1743. X*                                                                          *
  1744. X*   ENTRY:                                                                 *
  1745. X*                                                                          *
  1746. X*       errcode - code to be translated                                    *
  1747. X*                                                                          *
  1748. X*   EXIT:                                                                  *
  1749. X*                                                                          *
  1750. X*       Returns a pointer to the appropriate string.                       *
  1751. X*                                                                          *
  1752. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  1753. X*                                                                          *
  1754. X***************************************************************************/
  1755. Xstatic char *
  1756. X#ifdef __STDC__
  1757. Xerrxlate(ULONG errcode)
  1758. X#else
  1759. Xerrxlate(errcode)
  1760. XULONG errcode;
  1761. X#endif
  1762. X{
  1763. X    char *errstring;
  1764. X    char *sever;
  1765. X
  1766. X    /* Determine severity of error. */
  1767. X
  1768. X    switch (SEVERITY(errcode))
  1769. X    {
  1770. X        case SEVERITY(ST_SUCCESS):
  1771. X            sever = "SUCCESS";
  1772. X            break;
  1773. X
  1774. X        case SEVERITY(ST_WARNING):
  1775. X            sever = "WARNING";
  1776. X            break;
  1777. X
  1778. X        case SEVERITY(ST_ERROR):
  1779. X            sever = "ERROR";
  1780. X            break;
  1781. X
  1782. X        case SEVERITY(ST_FATAL):
  1783. X        default:
  1784. X            sever = "FATAL";
  1785. X            break;
  1786. X    }
  1787. X
  1788. X    /* Get error string from module. */
  1789. X
  1790. X    switch (MODULE(errcode))
  1791. X    {
  1792. X        case MODULE(GIF_MODULE):
  1793. X            errstring = gif_errstring(errcode);
  1794. X            break;
  1795. X
  1796. X        case MODULE(FB_MODULE):
  1797. X            errstring = fb_errstring(errcode);
  1798. X            break;
  1799. X
  1800. X        case MODULE(MF_MODULE):
  1801. X            errstring = mf_errstring(errcode);
  1802. X            break;
  1803. X
  1804. X        default:
  1805. X            errstring = NULL;
  1806. X            break;
  1807. X    }
  1808. X
  1809. X    /* Composite strings. */
  1810. X
  1811. X    if (errstring != NULL)
  1812. X    {
  1813. X        sprintf(scratch, "%s: %s", sever, errstring);
  1814. X    }
  1815. X    else
  1816. X    {
  1817. X        /* Error not recognized by any module. */
  1818. X
  1819. X        sprintf(scratch, "%s: %08lX.", sever, errcode);
  1820. X    }
  1821. X
  1822. X    return scratch;
  1823. X} /* end of static errxlate() */
  1824. X
  1825. END_OF_FILE
  1826.   if test 47919 -ne `wc -c <'src/gifstrip.c'`; then
  1827.     echo shar: \"'src/gifstrip.c'\" unpacked with wrong size!
  1828.   fi
  1829.   # end of 'src/gifstrip.c'
  1830. fi
  1831. echo shar: End of archive 2 \(of 18\).
  1832. cp /dev/null ark2isdone
  1833. MISSING=""
  1834. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ; do
  1835.     if test ! -f ark${I}isdone ; then
  1836.     MISSING="${MISSING} ${I}"
  1837.     fi
  1838. done
  1839. if test "${MISSING}" = "" ; then
  1840.     echo You have unpacked all 18 archives.
  1841.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1842. else
  1843.     echo You still must unpack the following archives:
  1844.     echo "        " ${MISSING}
  1845. fi
  1846. exit 0
  1847. exit 0 # Just in case...
  1848.