1
2 /*
3 * xvvd.c - extract archived file automatically and regard it as a
4 * (virtual) directory.
5 */
6
7 #define NEEDSDIR
8
9 #include "xv.h"
10
11 #ifdef AUTO_EXPAND
12
13 static void vd_Dirtovd PARM((char *));
14 static void vd_Vdtodir PARM((char *));
15 static int vd_Mkvdir PARM((char *));
16 static int vd_Rmvdir PARM((char *));
17 static int vd_Movevdir PARM((char *, char *));
18 static void vd_addvdtable PARM((char *));
19 static void vd_packvdtable PARM((void));
20 static int vd_recursive_mkdir PARM((char *));
21 static int vd_recursive_rmdir PARM((char *));
22 static void vd_optimize_path PARM((char *));
23 static int vd_ftype PARM((char *));
24 static int vd_compp PARM((char *, char *));
25 static int vd_UncompressFile PARM((char *, char *));
26 static int vd_tarc PARM((char *));
27 static u_int vd_tar_sumchk PARM((char *));
28
29 #define VD_VDTABLESIZE 100
30
31 #define VD_ERR -2
32 #define VD_UKN -1
33
34 static char *ext_command[] = {
35 /* KEEP 0 */
36 NULL,
37 #define VD_ARC 1
38 "arc xo %s",
39 #define VD_ARJ 2
40 "unarj x %s",
41 #define VD_LZH 3
42 "lha -xf %s",
43 #define VD_TAR 4
44 "tar xvf %s",
45 #define VD_ZIP 5
46 "unzip -xo %s",
47 #define VD_ZOO 6
48 "zoo xOS %s",
49 };
50
51 int vdcount = 0;
52
53 static char vdroot[MAXPATHLEN+1];
54 static char *vdtable[VD_VDTABLESIZE];
55
56 /*
57 * These functions initialize and settle virtual directory system.
58 * Vdinit:
59 * creates root of virtual directory.
60 * Vdsettle:
61 * sweeps virtual directories.
62 */
Vdinit()63 void Vdinit()
64 {
65 #ifndef VMS
66 char tmp[MAXPATHLEN+1];
67
68 xv_getwd(tmp, MAXPATHLEN+1);
69 if (chdir(tmpdir)) {
70 fprintf(stderr, "Warning: cannot chdir to tmpdir = '%s'.\n", tmpdir);
71 fprintf(stderr,
72 " I will use current directory '%s' instead of tmpdir.\n",
73 tmp);
74 }
75 xv_getwd(vdroot, MAXPATHLEN+1);
76 strcat(vdroot, "/.xvvdXXXXXX");
77 chdir(tmp);
78 #else
79 sprintf(vdroot, "Sys$Scratch:xvvdXXXXXX");
80 #endif /* VMS */
81 #ifdef USE_MKSTEMP
82 close(mkstemp(vdroot));
83 #else
84 mktemp(vdroot);
85 #endif
86
87 if (!vd_recursive_mkdir(vdroot))
88 tmpdir = vdroot;
89 }
90
Vdsettle()91 void Vdsettle()
92 {
93 int i;
94
95 for (i = 0; i < vdcount; i++)
96 free(vdtable[i]);
97
98 vdcount = 0;
99
100 vd_recursive_rmdir(vdroot);
101 }
102
103 /*
104 * This function chdir to virtual directory, if specified path is in
105 * virtual directlry.
106 */
Chvdir(dir)107 int Chvdir(dir)
108 char *dir;
109 {
110 char buf[MAXPATHLEN+1];
111
112 if (Mkvdir(dir) == VD_ERR)
113 return -1;
114
115 strcpy(buf, dir);
116 Dirtovd(buf);
117
118 return (chdir(buf));
119 }
120
121 /*
122 * These functions convert directory <-> virtual directory.
123 * Dirtovd:
124 * front interface of vd_Dirtovd.
125 * vd_Dirtovd:
126 * converts directory to virtual directory.
127 * Vdtodir:
128 * front interface of vd_Vdtodir.
129 * vd_Vdtodir:
130 * converts virtual directory to normal directory.
131 * Dirtosubst:
132 * converts directory to substance of archive.
133 */
Dirtovd(dir)134 void Dirtovd(dir)
135 char *dir;
136 {
137 vd_optimize_path(dir);
138
139 vd_Dirtovd(dir);
140 }
141
vd_Dirtovd(dir)142 static void vd_Dirtovd(dir)
143 char *dir;
144 {
145 int i;
146
147 for (i = 0; i < vdcount; i++)
148 if (!strncmp(dir, vdtable[i], strlen(vdtable[i]))) {
149 char tmp[MAXPATHLEN+1];
150
151 sprintf(tmp, "%s%s", vdroot, dir);
152 strcpy(dir, tmp);
153 Dirtovd(dir);
154 }
155 }
156
Vdtodir(dir)157 void Vdtodir(dir)
158 char *dir;
159 {
160 vd_optimize_path(dir);
161
162 vd_Vdtodir(dir);
163 }
164
vd_Vdtodir(vd)165 static void vd_Vdtodir(vd)
166 char *vd;
167 {
168 int i;
169 char tmp[MAXPATHLEN+1];
170
171 for (i = vdcount-1; i >= 0; i--) {
172 sprintf(tmp, "%s%s", vdroot, vdtable[i]);
173 if(!strncmp(vd, tmp, strlen(tmp))) {
174 strcpy(tmp, vd+strlen(vdroot));
175 strcpy(vd, tmp);
176 Vdtodir(vd);
177 }
178 }
179 }
180
Dirtosubst(dir)181 void Dirtosubst(dir)
182 char *dir;
183 {
184 char tmp[MAXPATHLEN+1];
185
186 Dirtovd(dir);
187
188 strcpy(tmp, dir+strlen(vdroot));
189
190 if (Isarchive(tmp))
191 strcpy(dir, tmp);
192 }
193
194 /*
195 * These functions make virtual directory and extracts archive, if
196 * specified path is archive.
197 * Mkvdir:
198 * front interface of vd_Mkvdir.
199 * vd_Mkvdir:
200 * does real work.
201 * Mkvdir_force: (used by makeThumbDir(in xvbrowse.c) only)
202 * make virtual directory by force.
203 */
Mkvdir(dir)204 int Mkvdir(dir)
205 char *dir;
206 {
207 char dir1[MAXPATHLEN+1], dir2[MAXPATHLEN+1];
208 char *d1, *d2;
209 int rv;
210
211 #if defined(SYSV) || defined(SVR4) || defined(__USE_XOPEN_EXTENDED)
212 sighold(SIGHUP);
213 sighold(SIGCHLD);
214 #else
215 int mask;
216 mask = sigblock(sigmask(SIGHUP)|sigmask(SIGCHLD));
217 #endif
218
219 strcpy(dir1, dir);
220 vd_optimize_path(dir1);
221
222 if ((rv = vd_Mkvdir(dir1)) != VD_ERR)
223 goto MKVDIR_END;
224
225 strcpy(dir2, dir1);
226 d2 = dir2 + strlen(dir2);
227 while (rv == VD_ERR) {
228 d2--;
229 while (*d2 != '/')
230 d2--;
231 *d2 = '\0';
232 rv = vd_Mkvdir(dir2);
233 }
234 d1 = dir1 + strlen(dir2);
235 while ((rv != VD_ERR) && (*d1 != '\0')) {
236 *d2++ = *d1++;
237 while ((*d1 != '/') && (*d1 != '\0'))
238 *d2++ = *d1++;
239 *d2 = '\0';
240 rv = vd_Mkvdir(dir2);
241 }
242
243 MKVDIR_END:
244 #if defined(SYSV) || defined(SVR4) || defined(__USE_XOPEN_EXTENDED)
245 sigrelse(SIGHUP);
246 sigrelse(SIGCHLD);
247 #else
248 sigsetmask(mask);
249 #endif
250
251 return rv;
252 }
253
vd_Mkvdir(dir)254 static int vd_Mkvdir(dir)
255 char *dir;
256 {
257 char dir1[MAXPATHLEN+1], dir2[MAXPATHLEN+1], tmp[MAXPATHLEN+1];
258 int ftype, i;
259 struct stat st;
260 FILE *pfp;
261
262 strcpy(dir1, dir);
263 Dirtovd(dir1);
264 strcpy(dir2, dir1);
265
266 WaitCursor();
267
268 if ((ftype = vd_ftype(dir1)) < 0) {
269 SetCursors(-1);
270 return ftype;
271 }
272 if (ftype == RFT_COMPRESS) {
273 if (!(ftype = vd_compp(dir1, tmp))) {
274 SetCursors(-1);
275 return ftype;
276 }
277 strcpy(dir1, tmp);
278 }
279
280 if (!stat(dir1, &st)) {
281 for(i = 0; i < vdcount; i++)
282 if (!strcmp(vdtable[i], dir2)) {
283 SetCursors(-1);
284 return 0;
285 }
286
287 if (!S_ISDIR(st.st_mode)) {
288 char origdir[MAXPATHLEN+1], buf[MAXPATHLEN+10], buf1[100];
289
290 if (vdcount >= VD_VDTABLESIZE) {
291 ErrPopUp("Sorry, you can't make virtual directory any more.",
292 "\nBummer!");
293 goto VD_MKVDIR_ERR;
294 }
295
296 WaitCursor();
297
298 xv_getwd(origdir, MAXPATHLEN+1);
299
300 sprintf(tmp, "%s%s", vdroot, dir2);
301 if (vd_recursive_mkdir(tmp) || chdir(tmp)) {
302 SetISTR(ISTR_INFO, "fail to make virtual directory.");
303 Warning();
304 goto VD_MKVDIR_ERR;
305 }
306 sprintf(buf, ext_command[ftype], dir1);
307
308 WaitCursor();
309
310 if((pfp = popen(buf, "r")) == NULL) {
311 SetISTR(ISTR_INFO, "fail to extract archive '%s'.",
312 BaseName(dir2));
313 Warning();
314 goto VD_MKVDIR_ERR;
315 }
316 while (1) {
317 if (fread(buf1, 1, sizeof(buf1), pfp) < sizeof(buf1))
318 break;
319 WaitCursor();
320 }
321 if (!feof(pfp)) {
322 SetISTR(ISTR_INFO, "Pipe was broken.");
323 Warning();
324 pclose(pfp);
325 goto VD_MKVDIR_ERR;
326 }
327 pclose(pfp);
328
329 if (strcmp(dir1, dir2))
330 unlink(dir1);
331
332 vd_addvdtable(dir2);
333 Dirtovd(origdir);
334 chdir(origdir);
335 SetCursors(-1);
336 return 0;
337
338 VD_MKVDIR_ERR:
339 if (strcmp(dir1, dir2))
340 unlink(dir1);
341 SetCursors(-1);
342 return VD_ERR;
343 }
344 }
345 SetCursors(-1);
346 return VD_ERR;
347 }
348
349 #ifdef VIRTUAL_TD
Mkvdir_force(dir)350 void Mkvdir_force(dir)
351 char *dir;
352 {
353 char tmp[MAXPATHLEN+1];
354
355 if (vdcount >= VD_VDTABLESIZE) {
356 ErrPopUp("Sorry, you can't make virtual directory any more.",
357 "\nBummer!");
358 return;
359 }
360
361 sprintf(tmp, "%s%s", vdroot, dir);
362 if (vd_recursive_mkdir(tmp)) {
363 SetISTR(ISTR_INFO, "Failed to make virtual directory.");
364 Warning();
365 return;
366 }
367
368 vd_addvdtable(dir);
369 }
370 #endif /* VIRTUAL_TD */
371
372 /*
373 * These functions remove virtual directory, if exists.
374 * Rmvdir:
375 * front interface of vd_Rmvdir.
376 * vd_Rmvdir:
377 * remove virtual directory function.
378 */
Rmvdir(dir)379 int Rmvdir(dir)
380 char *dir;
381 {
382 int rv;
383 char buf[MAXPATHLEN+1];
384
385 strcpy(buf, dir);
386 vd_optimize_path(buf);
387
388 rv = vd_Rmvdir(buf);
389 vd_packvdtable();
390 return rv;
391 }
392
vd_Rmvdir(dir)393 static int vd_Rmvdir(dir)
394 char *dir;
395 {
396 int i;
397 char tmp[MAXPATHLEN+1];
398
399 for(i = 0; i < vdcount; i++)
400 if (!strncmp(dir, vdtable[i], strlen(dir))) {
401 sprintf(tmp, "%s%s", vdroot, vdtable[i]);
402 if (vd_Rmvdir(tmp))
403 return 1;
404 if (vd_recursive_rmdir(tmp))
405 return 1;
406 vdtable[i][0] = '\0';
407 }
408 return 0;
409 }
410
411 /*
412 * These functions move virtual directory, if exists.
413 * Movevdir:
414 * front interface of move virtual directory function.
415 * vd_Movevdir:
416 * does real work.
417 */
Movevdir(src,dst)418 int Movevdir(src, dst)
419 char *src, *dst;
420 {
421 /*
422 char sbuf[MAXPATHLEN+1], dbuf[MAXPATHLEN+1];
423
424 strcpy(sbuf, src);
425 vd_optimize_path(sbuf);
426
427 strcpy(dbuf, dst);
428 vd_optimize_path(dbuf);
429
430 return (vd_Movevdir(sbuf, dbuf));
431 */
432 return (vd_Movevdir(src, dst));
433 }
434
vd_Movevdir(src,dst)435 static int vd_Movevdir(src, dst)
436 char *src, *dst;
437 {
438 int i;
439 char *p, *pp;
440 char tmp[MAXPATHLEN+1], tmps[MAXPATHLEN+1], tmpd[MAXPATHLEN+1];
441
442 for (i = 0; i < vdcount; i++)
443 if (!strncmp(src, vdtable[i], strlen(src))) {
444 sprintf(tmps, "%s%s", vdroot, vdtable[i]);
445 sprintf(tmp, "%s%s", dst, vdtable[i]+strlen(src));
446 sprintf(tmpd, "%s%s", vdroot, tmp);
447
448 if (vd_Movevdir(tmps, tmpd))
449 return 1;
450
451 pp = vdtable[i];
452 p = (char *) malloc(strlen(tmp)+1);
453 strcpy(p, tmp);
454 vdtable[i] = p;
455
456 strcpy(tmp, tmpd);
457 for (p = tmp+strlen(tmp); *p != '/'; p--)
458 ;
459 *p = '\0';
460
461 if (vd_recursive_mkdir(tmp))
462 goto VD_MOVEVDIR_ERR;
463
464 if (rename(tmps, tmpd) < 0)
465 goto VD_MOVEVDIR_ERR;
466
467 free(pp);
468 }
469 return 0;
470
471 VD_MOVEVDIR_ERR:
472 free(vdtable[i]);
473 vdtable[i] = pp;
474 return 1;
475 }
476
477 /*
478 * These functions handle table of virtual directories.
479 * vd_addvdtable:
480 * adds virtual directory to table.
481 * vd_packvdtable:
482 * removes disused virtual directories from table.
483 */
vd_addvdtable(vd)484 static void vd_addvdtable(vd)
485 char *vd;
486 {
487 char *p;
488 p = (char *) malloc(strlen(vd)+1);
489 strcpy(p, vd);
490 vdtable[vdcount] = p;
491 vdcount++;
492 }
493
vd_packvdtable()494 static void vd_packvdtable()
495 {
496 int i, j;
497
498 for (i = j = 0; i < vdcount; i++)
499 if (vdtable[i][0] != '\0')
500 vdtable[j++] = vdtable[i];
501 else
502 free(vdtable[i]);
503
504 vdcount = j;
505 }
506
507 /*
508 * These are utility functions.
509 * vd_recursive_mkdir:
510 * makes directories recursively.
511 * vd_recursive_rmdir
512 * removes directories recursively.
513 */
vd_recursive_mkdir(dir)514 static int vd_recursive_mkdir(dir)
515 char *dir;
516 {
517 char buf[MAXPATHLEN+1], *p;
518 struct stat st;
519
520 strcpy(buf, dir);
521
522 if (buf[strlen(buf) - 1] == '/')
523 buf[strlen(buf) - 1] = '\0';
524
525 p = rindex(buf, '/');
526 *p = '\0';
527
528 if (stat(buf, &st) < 0)
529 if (vd_recursive_mkdir(buf) < 0)
530 return (-1);
531
532 *p = '/';
533 if (mkdir(buf, 0700) < 0)
534 return (-1);
535
536 return (0);
537 }
538
vd_recursive_rmdir(dir)539 static int vd_recursive_rmdir(dir)
540 char *dir;
541 {
542 char buf[MAXPATHLEN+1], buf2[MAXPATHLEN+1];
543 DIR *dp;
544 struct dirent *di;
545
546 strcpy(buf, dir);
547
548 if (buf[strlen(buf) - 1] == '/')
549 buf[strlen(buf) - 1] = '\0';
550
551 if ((dp = opendir(buf)) == NULL)
552 return (-1);
553
554 while ((di = readdir(dp)) != NULL) {
555 struct stat st;
556
557 if (!strcmp(di->d_name, ".") || !strcmp(di->d_name, ".."))
558 continue;
559
560 sprintf(buf2, "%s/%s", dir, di->d_name);
561
562 stat(buf2, &st);
563 if (S_ISDIR(st.st_mode)) {
564 if (vd_recursive_rmdir(buf2) < 0)
565 goto VD_RECURSIVE_RMDIR_ERR;
566 } else
567 unlink(buf2);
568 }
569 if (rmdir(buf) < 0)
570 goto VD_RECURSIVE_RMDIR_ERR;
571
572 closedir(dp);
573 return (0);
574
575 VD_RECURSIVE_RMDIR_ERR:
576 closedir(dp);
577 return (-1);
578 }
579
580 /*
581 * These functions test specified path.
582 * Isarchive:
583 * tests whether it's an archive?
584 * Isvdir:
585 * tests whether it's in the virtual directory?
586 */
Isarchive(path)587 int Isarchive(path)
588 char *path;
589 {
590 int ftype;
591
592 if ((ftype = vd_ftype(path)) < 0)
593 return 0;
594
595 if (ftype == RFT_COMPRESS)
596 if (!(ftype = vd_compp(path, NULL)))
597 return 0;
598
599 return ftype;
600 }
601
Isvdir(path)602 int Isvdir(path)
603 char *path;
604 {
605 int rv = 0;
606 char tmp1[MAXPATHLEN+1], tmp2[MAXPATHLEN+1];
607 int archive1, archive2;
608
609 strcpy(tmp1, path);
610 strcpy(tmp2, path);
611
612 vd_optimize_path(tmp1);
613 Dirtovd(tmp2);
614
615 archive1 = Isarchive(tmp1);
616 archive2 = Isarchive(tmp2);
617
618 if (strcmp(tmp1, tmp2)) {
619 char tmp3[MAXPATHLEN+1], tmp4[MAXPATHLEN+1];
620 int archive3, archive4;
621
622 sprintf(tmp3, "%s%s", vdroot, tmp1);
623 strcpy(tmp4, tmp2+strlen(vdroot));
624
625 archive3 = Isarchive(tmp3);
626 archive4 = Isarchive(tmp4);
627
628 if (archive4 && !strcmp(tmp1, tmp4)) {
629 rv |= 06;
630 return rv;
631 }
632 rv |= 01;
633 if (archive2)
634 rv |= 02;
635 else if (archive4)
636 rv |= 06;
637 return rv;
638 }
639 if (archive1)
640 rv |= 02;
641
642 return rv;
643 }
644
645 /*
646 * This function optimizes given path.
647 * Expand '~' to home directory and removes '.', and treat '..'.
648 */
vd_optimize_path(path)649 static void vd_optimize_path(path)
650 char *path;
651 {
652 char *tmp, *reserve;
653
654 if (!strcmp(path, STDINSTR))
655 return;
656
657 if (*path == '\0') {
658 xv_getwd(path, MAXPATHLEN+1);
659 return;
660 }
661 if (*path == '~')
662 Globify(path);
663 if (*path != '/') {
664 char tmp[MAXPATHLEN+1];
665
666 strcpy(tmp, path);
667 xv_getwd(path, MAXPATHLEN+1);
668 strcat(path, "/");
669 strcat(path, tmp);
670 }
671
672 reserve = tmp = path;
673 while(*path != '\0') {
674 if (*path == '/') {
675 *tmp++ = *path;
676 while (*++path == '/')
677 ;
678 continue;
679 }
680 if ((*path == '.') && (*(path-1) == '/')) {
681 if (*(path+1) == '/') {
682 tmp--;
683 path++;
684 continue;
685 } else if (*(path+1) == '\0') {
686 tmp--;
687 break;
688 } else if (*(path+1) == '.') {
689 if (*(path+2) == '/') {
690 if ((tmp - reserve) > 1)
691 for (tmp-=2; (*tmp != '/'); tmp--)
692 ;
693 else
694 tmp = reserve;
695 path+=2;
696 continue;
697 } else if (*(path+2) == '\0') {
698 if ((tmp - reserve) > 1)
699 for (tmp-=2; (*tmp != '/'); tmp--)
700 ;
701 else
702 tmp = reserve+1;
703 break;
704 }
705 }
706 }
707 *tmp++ = *path++;
708 }
709 if (((tmp - reserve) > 1) && *(tmp-1) == '/')
710 tmp--;
711 if (tmp == reserve)
712 *tmp++ = '/';
713
714 *tmp = '\0';
715 }
716
717 /*
718 * These functions detect file type.
719 */
vd_ftype(fname)720 static int vd_ftype(fname)
721 char *fname;
722 {
723 /* check archive type */
724
725 FILE *fp;
726 byte magicno[30]; /* first 30 bytes of file */
727 int rv, n;
728 struct stat st;
729
730 if (!fname) return VD_ERR; /* shouldn't happen */
731
732 if ((!stat(fname, &st)) && (st.st_mode & S_IFMT) == S_IFDIR)
733 return VD_UKN;
734 fp = xv_fopen(fname, "r");
735 if (!fp) return VD_ERR;
736
737 n = fread(magicno, (size_t) 1, (size_t) 30, fp);
738 fclose(fp);
739
740 if (n<30) return VD_UKN; /* files less than 30 bytes long... */
741
742 rv = VD_UKN;
743
744 if (magicno[0] == 0x60 && magicno[1]==0xea) rv = VD_ARJ;
745
746 else if (magicno[2] == '-' && magicno[3] == 'l' &&
747 magicno[4] == 'h') rv = VD_LZH;
748
749 else if (strncmp((char *) magicno,"PK", (size_t) 2)==0) rv = VD_ZIP;
750
751 else if (magicno[20]==0xdc && magicno[21]==0xa7 &&
752 magicno[22]==0xc4 && magicno[23]==0xfd) rv = VD_ZOO;
753
754 else if (vd_tarc(fname)) rv = VD_TAR;
755
756 else if (magicno[0]==0x1f && magicno[1]==0x9d) rv = RFT_COMPRESS;
757
758 else if (!strncmp((char *) &magicno[11], "MAJYO", (size_t) 5))
759 rv = VD_UKN; /* XXX */
760
761 else if (magicno[0] == 26) rv = VD_ARC;
762
763 #ifdef GUNZIP
764 else if (magicno[0]==0x1f && magicno[1]==0x8b) rv = RFT_COMPRESS;/* gzip */
765 else if (magicno[0]==0x1f && magicno[1]==0x9e) rv = RFT_COMPRESS;/* old */
766 else if (magicno[0]==0x1f && magicno[1]==0x1e) rv = RFT_COMPRESS;/* pack */
767 #endif
768
769 return rv;
770 }
771
vd_compp(path,newpath)772 static int vd_compp(path, newpath)
773 char *path, *newpath;
774 {
775 /*
776 * uncompress and check archive type.
777 *
778 * If newpath is NULL, uncompress only 512 byte of 'path' and
779 * check archive type, so it is for SPEED-UP strategy.
780 * In this case, caller this function does not have to unlink
781 * tempoary file.
782 * Unfortunately it does not work in VMS system.
783 */
784
785 int file_type, r;
786 char uncompname[128], basename[128];
787 int comptype;
788
789 if (newpath) *newpath = '\0';
790 strncpy(basename, path, 127);
791 comptype = ReadFileType(path);
792 #if (defined(VMS) && !defined(GUNZIP))
793 /* VMS decompress doesn't like the file to have a trailing .Z in fname
794 however, GUnZip is OK with it, which we are calling UnCompress */
795 *rindex (basename, '.') = '\0';
796 #endif
797 #ifdef VMS
798 if (UncompressFile(basename, uncompname)) {
799 #else
800 if (newpath == NULL)
801 r = vd_UncompressFile(basename, uncompname);
802 else
803 r = UncompressFile(basename, uncompname, comptype);
804 if (r) {
805 #endif
806 if ((file_type = vd_ftype(uncompname)) < 0) {
807 unlink(uncompname);
808 return 0;
809 }
810 if (newpath) strcpy(newpath, uncompname);
811 else unlink(uncompname);
812 } else {
813 return 0;
814 }
815 return file_type;
816 }
817
818 #define HEADERSIZE 512
819
820 static void vd_Dirtovd PARM((char *));
821 static int stderr_on PARM((void));
822 static int stderr_off PARM((void));
823 static FILE *popen_nul PARM((char *, char *));
824
vd_UncompressFile(name,uncompname)825 static int vd_UncompressFile(name, uncompname)
826 char *name, *uncompname;
827 {
828 /* Yap, I`m nearly same as original `UncompnameFile' function, but,
829 1) I extract `name' file ONLY first 512 byte.
830 2) I'm called only from UNIX and UNIX like OS, *NOT* VMS */
831 /* returns '1' on success, with name of uncompressed file in uncompname
832 returns '0' on failure */
833
834 char namez[128], *fname, buf[512], tmp[HEADERSIZE];
835 int n, tmpfd;
836 FILE *pfp, *tfp;
837
838 fname = name;
839 namez[0] = '\0';
840
841
842 #ifndef GUNZIP
843 /* see if compressed file name ends with '.Z'. If it *doesn't*, we need
844 to temporarily rename it so it *does*, uncompress it, and rename it
845 *back* to what it was. necessary because uncompress doesn't handle
846 files that don't end with '.Z' */
847
848 if (strlen(name) >= (size_t) 2 &&
849 strcmp(name + strlen(name)-2,".Z")!=0 &&
850 strcmp(name + strlen(name)-2,".z")!=0) {
851 strcpy(namez, name);
852 strcat(namez,".Z");
853
854 if (rename(name, namez) < 0) {
855 sprintf(buf, "Error renaming '%s' to '%s': %s",
856 name, namez, ERRSTR(errno));
857 ErrPopUp(buf, "\nBummer!");
858 return 0;
859 }
860
861 fname = namez;
862 }
863 #endif /* not GUNZIP */
864
865 sprintf(uncompname, "%s/xvuXXXXXX", tmpdir);
866 #ifdef USE_MKSTEMP
867 tmpfd = mkstemp(uncompname);
868 #else
869 mktemp(uncompname);
870 #endif
871
872 sprintf(buf,"%s -c %s", UNCOMPRESS, fname);
873 SetISTR(ISTR_INFO, "Uncompressing Header '%s'...", BaseName(fname));
874 if ((pfp = popen_nul(buf, "r")) == NULL) {
875 SetISTR(ISTR_INFO, "Cannot extract for archive '%s'.",
876 BaseName(fname));
877 Warning();
878 #ifdef USE_MKSTEMP
879 if (tmpfd >= 0)
880 close(tmpfd);
881 #endif
882 return 0;
883 }
884 #ifdef USE_MKSTEMP
885 if (tmpfd < 0)
886 #else
887 if ((tmpfd = open(uncompname,O_WRONLY|O_CREAT|O_EXCL,S_IRWUSR)) < 0)
888 #endif
889 {
890 SetISTR(ISTR_INFO, "Unable to create temporary file.",
891 BaseName(uncompname));
892 Warning();
893 pclose(pfp);
894 }
895 if ((tfp = fdopen(tmpfd, "w")) == NULL) {
896 SetISTR(ISTR_INFO, "Unable to create temporary file.",
897 BaseName(uncompname));
898 Warning();
899 close(tmpfd);
900 pclose(pfp);
901 return 0;
902 }
903 if ((n = fread(tmp, 1, sizeof(tmp), pfp)) != HEADERSIZE) {
904 SetISTR(ISTR_INFO, "Unable to read '%s'.",
905 BaseName(fname));
906 Warning();
907 pclose(pfp);
908 fflush(tfp);
909 fclose(tfp);
910 close(tmpfd);
911 return 0;
912 }
913 fwrite(tmp, 1, n, tfp);
914 fflush(tfp);
915 fclose(tfp);
916 close(tmpfd);
917 pclose(pfp);
918
919 /* if we renamed the file to end with a .Z for the sake of 'uncompress',
920 rename it back to what it once was... */
921
922 if (strlen(namez)) {
923 if (rename(namez, name) < 0) {
924 sprintf(buf, "Error renaming '%s' to '%s': %s",
925 namez, name, ERRSTR(errno));
926 ErrPopUp(buf, "\nBummer!");
927 }
928 }
929
930 return 1;
931 }
932
933 #define TARBLOCK 512
934 #define CKSTART 148 /* XXX */
935 #define CKSIZE 8
936
937 /*
938 * Tar file: 1, other: 0
939 */
vd_tarc(fname)940 static int vd_tarc(fname)
941 char *fname;
942 {
943 FILE *fp;
944 unsigned int sum;
945 char *ckp, buf[TARBLOCK];
946
947 if ((fp = fopen(fname, "r")) == NULL)
948 return 0;
949
950 fread(buf, TARBLOCK, 1, fp);
951 fclose(fp);
952
953 for (sum = 0, ckp = buf + CKSTART;
954 (ckp < buf + CKSTART + CKSIZE) && *ckp != '\0';
955 ckp++) {
956 sum *= 8;
957 if (*ckp == ' ')
958 continue;
959 if (*ckp < '0' || '7' < *ckp)
960 return 0;
961 sum += *ckp - '0';
962 }
963 if (sum != vd_tar_sumchk(buf))
964 return 0;
965
966 return 1;
967 }
968
vd_tar_sumchk(buf)969 static unsigned int vd_tar_sumchk(buf)
970 char *buf;
971 {
972 int i;
973 unsigned int sum = 0;
974
975 for (i = 0; i < CKSTART; i++) {
976 sum += *(buf + i);
977 }
978 sum += ' ' * 8;
979 for (i += 8; i < TARBLOCK; i++) {
980 sum += *(buf + i);
981 }
982 return sum;
983 }
984
985
986 static int stde = -1; /* fd of stderr */
987 static int nul = -1; /* fd of /dev/null */
988
989 /*
990 * switch off the output to stderr(bypass to /dev/null).
991 */
stderr_off()992 static int stderr_off()
993 {
994 if (nul < 0)
995 nul = open("/dev/null", O_RDONLY);
996 if (nul < 0) {
997 fprintf(stderr, "/dev/null open failure\n");
998 return -1;
999 }
1000 if (stde < 0)
1001 stde = dup(2);
1002 if (stde < 0) {
1003 fprintf(stderr, "duplicate stderr failure\n");
1004 return -1;
1005 }
1006 close(2);
1007 dup(nul);
1008 return 0;
1009 }
1010
1011 /*
1012 * turn on stderr output.
1013 */
stderr_on()1014 static int stderr_on()
1015 {
1016 if ((stde < 0) || (nul < 0)) {
1017 fprintf(stderr, "stderr_on should call after stderr_off\n");
1018 return -1;
1019 }
1020 close(2);
1021 dup(stde);
1022 return 0;
1023 }
1024
1025 /*
1026 * popen with no output to stderr.
1027 */
popen_nul(prog,mode)1028 static FILE *popen_nul(prog, mode)
1029 char *prog, *mode;
1030 {
1031 FILE *fp;
1032
1033 stderr_off();
1034 fp = popen(prog, mode);
1035 stderr_on();
1036 return fp;
1037 }
1038
1039 /*
1040 * These functions are for SIGNAL.
1041 * If XV end by C-c, there are dust of directory which name is .xvvd???,
1042 * made by xvvd. Then, I handle SIGINT, and add good finish.
1043 */
vd_HUPhandler()1044 void vd_HUPhandler()
1045 {
1046 #if defined(SYSV) || defined(SVR4) || defined(__USE_XOPEN_EXTENDED)
1047 sighold(SIGHUP);
1048 #else
1049 int mask;
1050 mask = sigblock(sigmask(SIGHUP));
1051 #endif
1052
1053 Vdsettle();
1054
1055 #if defined(SYSV) || defined(SVR4) || defined(__USE_XOPEN_EXTENDED)
1056 sigrelse(SIGHUP);
1057 signal(SIGHUP, (void (*)PARM((int))) vd_HUPhandler);
1058 #else
1059 sigsetmask(mask);
1060 #endif
1061 }
1062
1063 int InSignal = 0;
1064
vd_handler(sig)1065 void vd_handler(sig)
1066 int sig;
1067 {
1068 #if defined(SYSV) || defined(SVR4) || defined(__USE_XOPEN_EXTENDED)
1069 sighold(sig);
1070 #else
1071 sigblock(sigmask(sig));
1072 #endif
1073 InSignal = 1;
1074 Quit(1); /*exit(1);*/
1075 }
1076
vd_Xhandler(disp,event)1077 int vd_Xhandler(disp,event)
1078 Display *disp;
1079 XErrorEvent *event;
1080 {
1081 Quit(1); /*exit(1);*/
1082 return (1); /* Not reached */
1083 }
1084
vd_XIOhandler(disp)1085 int vd_XIOhandler(disp)
1086 Display *disp;
1087 {
1088 fprintf(stderr, "XIO fatal IO error ? (?) on X server\n");
1089 fprintf(stderr, "You must exit normally in xv usage.\n");
1090 Quit(1); /*exit(1);*/
1091 return (1); /* Not reached */
1092 }
1093
vd_handler_setup()1094 void vd_handler_setup()
1095 {
1096 signal(SIGHUP, (void (*)PARM((int))) vd_HUPhandler);
1097 signal(SIGINT, (void (*)PARM((int))) vd_handler);
1098 signal(SIGTERM,(void (*)PARM((int))) vd_handler);
1099
1100 (void)XSetErrorHandler(vd_Xhandler);
1101 (void)XSetIOErrorHandler(vd_XIOhandler);
1102 }
1103 #endif /* AUTO_EXPAND */
1104