xref: /freebsd/bin/pax/options.c (revision a8445737e740901f5f2c8d24c12ef7fc8b00134e)
1 /*-
2  * Copyright (c) 1992 Keith Muller.
3  * Copyright (c) 1992, 1993
4  *	The Regents of the University of California.  All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * Keith Muller of the University of California, San Diego.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *	This product includes software developed by the University of
20  *	California, Berkeley and its contributors.
21  * 4. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  */
37 
38 #ifndef lint
39 #if 0
40 static char sccsid[] = "@(#)options.c	8.2 (Berkeley) 4/18/94";
41 #endif
42 static const char rcsid[] =
43 	"$Id$";
44 #endif /* not lint */
45 
46 #include <sys/types.h>
47 #include <sys/stat.h>
48 #include <sys/mtio.h>
49 #include <stdio.h>
50 #include <string.h>
51 #include <unistd.h>
52 #include <stdlib.h>
53 #include <limits.h>
54 #include "pax.h"
55 #include "options.h"
56 #include "cpio.h"
57 #include "tar.h"
58 #include "extern.h"
59 
60 /*
61  * Routines which handle command line options
62  */
63 
64 static char flgch[] = FLGCH;	/* list of all possible flags */
65 static OPLIST *ophead = NULL;	/* head for format specific options -x */
66 static OPLIST *optail = NULL;	/* option tail */
67 
68 static int no_op __P((void));
69 static void printflg __P((unsigned int));
70 static int c_frmt __P((const void *, const void *));
71 static off_t str_offt __P((char *));
72 static void pax_options __P((register int, register char **));
73 static void pax_usage __P((void));
74 static void tar_options __P((register int, register char **));
75 static void tar_usage __P((void));
76 #ifdef notdef
77 static void cpio_options __P((register int, register char **));
78 static void cpio_usage __P((void));
79 #endif
80 
81 /*
82  *	Format specific routine table - MUST BE IN SORTED ORDER BY NAME
83  *	(see pax.h for description of each function)
84  *
85  * 	name, blksz, hdsz, udev, hlk, blkagn, inhead, id, st_read,
86  *	read, end_read, st_write, write, end_write, trail,
87  *	rd_data, wr_data, options
88  */
89 
90 FSUB fsub[] = {
91 /* 0: OLD BINARY CPIO */
92 	{"bcpio", 5120, sizeof(HD_BCPIO), 1, 0, 0, 1, bcpio_id, cpio_strd,
93 	bcpio_rd, bcpio_endrd, cpio_stwr, bcpio_wr, cpio_endwr, cpio_trail,
94 	rd_wrfile, wr_rdfile, bad_opt},
95 
96 /* 1: OLD OCTAL CHARACTER CPIO */
97 	{"cpio", 5120, sizeof(HD_CPIO), 1, 0, 0, 1, cpio_id, cpio_strd,
98 	cpio_rd, cpio_endrd, cpio_stwr, cpio_wr, cpio_endwr, cpio_trail,
99 	rd_wrfile, wr_rdfile, bad_opt},
100 
101 /* 2: SVR4 HEX CPIO */
102 	{"sv4cpio", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, vcpio_id, cpio_strd,
103 	vcpio_rd, vcpio_endrd, cpio_stwr, vcpio_wr, cpio_endwr, cpio_trail,
104 	rd_wrfile, wr_rdfile, bad_opt},
105 
106 /* 3: SVR4 HEX CPIO WITH CRC */
107 	{"sv4crc", 5120, sizeof(HD_VCPIO), 1, 0, 0, 1, crc_id, crc_strd,
108 	vcpio_rd, vcpio_endrd, crc_stwr, vcpio_wr, cpio_endwr, cpio_trail,
109 	rd_wrfile, wr_rdfile, bad_opt},
110 
111 /* 4: OLD TAR */
112 	{"tar", 10240, BLKMULT, 0, 1, BLKMULT, 0, tar_id, no_op,
113 	tar_rd, tar_endrd, no_op, tar_wr, tar_endwr, tar_trail,
114 	rd_wrfile, wr_rdfile, tar_opt},
115 
116 /* 5: POSIX USTAR */
117 	{"ustar", 10240, BLKMULT, 0, 1, BLKMULT, 0, ustar_id, ustar_strd,
118 	ustar_rd, tar_endrd, ustar_stwr, ustar_wr, tar_endwr, tar_trail,
119 	rd_wrfile, wr_rdfile, bad_opt},
120 };
121 #define F_TAR	4	/* format when called as tar */
122 #define DEFLT	5	/* default write format from list above */
123 
124 /*
125  * ford is the archive search order used by get_arc() to determine what kind
126  * of archive we are dealing with. This helps to properly id  archive formats
127  * some formats may be subsets of others....
128  */
129 int ford[] = {5, 4, 3, 2, 1, 0, -1 };
130 
131 /*
132  * options()
133  *	figure out if we are pax, tar or cpio. Call the appropriate options
134  *	parser
135  */
136 
137 #if __STDC__
138 void
139 options(register int argc, register char **argv)
140 #else
141 void
142 options(argc, argv)
143 	register int argc;
144 	register char **argv;
145 #endif
146 {
147 
148 	/*
149 	 * Are we acting like pax, tar or cpio (based on argv[0])
150 	 */
151 	if ((argv0 = strrchr(argv[0], '/')) != NULL)
152 		argv0++;
153 	else
154 		argv0 = argv[0];
155 
156 	if (strcmp(NM_TAR, argv0) == 0)
157 		return(tar_options(argc, argv));
158 #	ifdef notdef
159 	else if (strcmp(NM_CPIO, argv0) == 0)
160 		return(cpio_options(argc, argv));
161 #	endif
162 	/*
163 	 * assume pax as the default
164 	 */
165 	argv0 = NM_PAX;
166 	return(pax_options(argc, argv));
167 }
168 
169 /*
170  * pax_options()
171  *	look at the user specified flags. set globals as required and check if
172  *	the user specified a legal set of flags. If not, complain and exit
173  */
174 
175 #if __STDC__
176 static void
177 pax_options(register int argc, register char **argv)
178 #else
179 static void
180 pax_options(argc, argv)
181 	register int argc;
182 	register char **argv;
183 #endif
184 {
185 	register int c;
186 	register int i;
187 	unsigned int flg = 0;
188 	unsigned int bflg = 0;
189 	register char *pt;
190         FSUB tmp;
191 	extern char *optarg;
192 	extern int optind;
193 
194 	/*
195 	 * process option flags
196 	 */
197 	while ((c=getopt(argc,argv,"ab:cdf:iklno:p:rs:tuvwx:B:DE:G:HLPT:U:XYZ"))
198 	    != -1) {
199 		switch (c) {
200 		case 'a':
201 			/*
202 			 * append
203 			 */
204 			flg |= AF;
205 			break;
206 		case 'b':
207 			/*
208 			 * specify blocksize
209 			 */
210 			flg |= BF;
211 			if ((wrblksz = (int)str_offt(optarg)) <= 0) {
212 				pax_warn(1, "Invalid block size %s", optarg);
213 				pax_usage();
214 			}
215 			break;
216 		case 'c':
217 			/*
218 			 * inverse match on patterns
219 			 */
220 			cflag = 1;
221 			flg |= CF;
222 			break;
223 		case 'd':
224 			/*
225 			 * match only dir on extract, not the subtree at dir
226 			 */
227 			dflag = 1;
228 			flg |= DF;
229 			break;
230 		case 'f':
231 			/*
232 			 * filename where the archive is stored
233 			 */
234 			arcname = optarg;
235 			flg |= FF;
236 			break;
237 		case 'i':
238 			/*
239 			 * interactive file rename
240 			 */
241 			iflag = 1;
242 			flg |= IF;
243 			break;
244 		case 'k':
245 			/*
246 			 * do not clobber files that exist
247 			 */
248 			kflag = 1;
249 			flg |= KF;
250 			break;
251 		case 'l':
252 			/*
253 			 * try to link src to dest with copy (-rw)
254 			 */
255 			lflag = 1;
256 			flg |= LF;
257 			break;
258 		case 'n':
259 			/*
260 			 * select first match for a pattern only
261 			 */
262 			nflag = 1;
263 			flg |= NF;
264 			break;
265 		case 'o':
266 			/*
267 			 * pass format specific options
268 			 */
269 			flg |= OF;
270 			if (opt_add(optarg) < 0)
271 				pax_usage();
272 			break;
273 		case 'p':
274 			/*
275 			 * specify file characteristic options
276 			 */
277 			for (pt = optarg; *pt != '\0'; ++pt) {
278 				switch(*pt) {
279 				case 'a':
280 					/*
281 					 * do not preserve access time
282 					 */
283 					patime = 0;
284 					break;
285 				case 'e':
286 					/*
287 					 * preserve user id, group id, file
288 					 * mode, access/modification times
289 					 */
290 					pids = 1;
291 					pmode = 1;
292 					patime = 1;
293 					pmtime = 1;
294 					break;
295 				case 'm':
296 					/*
297 					 * do not preserve modification time
298 					 */
299 					pmtime = 0;
300 					break;
301 				case 'o':
302 					/*
303 					 * preserve uid/gid
304 					 */
305 					pids = 1;
306 					break;
307 				case 'p':
308 					/*
309 					 * preserver file mode bits
310 					 */
311 					pmode = 1;
312 					break;
313 				default:
314 					pax_warn(1, "Invalid -p string: %c", *pt);
315 					pax_usage();
316 					break;
317 				}
318 			}
319 			flg |= PF;
320 			break;
321 		case 'r':
322 			/*
323 			 * read the archive
324 			 */
325 			flg |= RF;
326 			break;
327 		case 's':
328 			/*
329 			 * file name substitution name pattern
330 			 */
331 			if (rep_add(optarg) < 0) {
332 				pax_usage();
333 				break;
334 			}
335 			flg |= SF;
336 			break;
337 		case 't':
338 			/*
339 			 * preserve access time on filesystem nodes we read
340 			 */
341 			tflag = 1;
342 			flg |= TF;
343 			break;
344 		case 'u':
345 			/*
346 			 * ignore those older files
347 			 */
348 			uflag = 1;
349 			flg |= UF;
350 			break;
351 		case 'v':
352 			/*
353 			 * verbose operation mode
354 			 */
355 			vflag = 1;
356 			flg |= VF;
357 			break;
358 		case 'w':
359 			/*
360 			 * write an archive
361 			 */
362 			flg |= WF;
363 			break;
364 		case 'x':
365 			/*
366 			 * specify an archive format on write
367 			 */
368 			tmp.name = optarg;
369 			if ((frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub,
370 			   sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt))) {
371 				flg |= XF;
372 				break;
373 			}
374 			pax_warn(1, "Unknown -x format: %s", optarg);
375 			(void)fputs("pax: Known -x formats are:", stderr);
376 			for (i = 0; i < (sizeof(fsub)/sizeof(FSUB)); ++i)
377 				(void)fprintf(stderr, " %s", fsub[i].name);
378 			(void)fputs("\n\n", stderr);
379 			pax_usage();
380 			break;
381 		case 'B':
382 			/*
383 			 * non-standard option on number of bytes written on a
384 			 * single archive volume.
385 			 */
386 			if ((wrlimit = str_offt(optarg)) <= 0) {
387 				pax_warn(1, "Invalid write limit %s", optarg);
388 				pax_usage();
389 			}
390 			if (wrlimit % BLKMULT) {
391 				pax_warn(1, "Write limit is not a %d byte multiple",
392 				    BLKMULT);
393 				pax_usage();
394 			}
395 			flg |= CBF;
396 			break;
397 		case 'D':
398 			/*
399 			 * On extraction check file inode change time before the
400 			 * modification of the file name. Non standard option.
401 			 */
402 			Dflag = 1;
403 			flg |= CDF;
404 			break;
405 		case 'E':
406 			/*
407 			 * non-standard limit on read faults
408 			 * 0 indicates stop after first error, values
409 			 * indicate a limit, "NONE" try forever
410 			 */
411 			flg |= CEF;
412 			if (strcmp(NONE, optarg) == 0)
413 				maxflt = -1;
414 			else if ((maxflt = atoi(optarg)) < 0) {
415 				pax_warn(1, "Error count value must be positive");
416 				pax_usage();
417 			}
418 			break;
419 		case 'G':
420 			/*
421 			 * non-standard option for selecting files within an
422 			 * archive by group (gid or name)
423 			 */
424 			if (grp_add(optarg) < 0) {
425 				pax_usage();
426 				break;
427 			}
428 			flg |= CGF;
429 			break;
430 		case 'H':
431 			/*
432 			 * follow command line symlinks only
433 			 */
434 			Hflag = 1;
435 			flg |= CHF;
436 			break;
437 		case 'L':
438 			/*
439 			 * follow symlinks
440 			 */
441 			Lflag = 1;
442 			flg |= CLF;
443 			break;
444 		case 'P':
445 			/*
446 			 * do NOT follow symlinks (default)
447 			 */
448 			Lflag = 0;
449 			flg |= CPF;
450 			break;
451 		case 'T':
452 			/*
453 			 * non-standard option for selecting files within an
454 			 * archive by modification time range (lower,upper)
455 			 */
456 			if (trng_add(optarg) < 0) {
457 				pax_usage();
458 				break;
459 			}
460 			flg |= CTF;
461 			break;
462 		case 'U':
463 			/*
464 			 * non-standard option for selecting files within an
465 			 * archive by user (uid or name)
466 			 */
467 			if (usr_add(optarg) < 0) {
468 				pax_usage();
469 				break;
470 			}
471 			flg |= CUF;
472 			break;
473 		case 'X':
474 			/*
475 			 * do not pass over mount points in the file system
476 			 */
477 			Xflag = 1;
478 			flg |= CXF;
479 			break;
480 		case 'Y':
481 			/*
482 			 * On extraction check file inode change time after the
483 			 * modification of the file name. Non standard option.
484 			 */
485 			Yflag = 1;
486 			flg |= CYF;
487 			break;
488 		case 'Z':
489 			/*
490 			 * On extraction check modification time after the
491 			 * modification of the file name. Non standard option.
492 			 */
493 			Zflag = 1;
494 			flg |= CZF;
495 			break;
496 		case '?':
497 		default:
498 			pax_usage();
499 			break;
500 		}
501 	}
502 
503 	/*
504 	 * figure out the operation mode of pax read,write,extract,copy,append
505 	 * or list. check that we have not been given a bogus set of flags
506 	 * for the operation mode.
507 	 */
508 	if (ISLIST(flg)) {
509 		act = LIST;
510 		bflg = flg & BDLIST;
511 	} else if (ISEXTRACT(flg)) {
512 		act = EXTRACT;
513 		bflg = flg & BDEXTR;
514 	} else if (ISARCHIVE(flg)) {
515 		act = ARCHIVE;
516 		bflg = flg & BDARCH;
517 	} else if (ISAPPND(flg)) {
518 		act = APPND;
519 		bflg = flg & BDARCH;
520 	} else if (ISCOPY(flg)) {
521 		act = COPY;
522 		bflg = flg & BDCOPY;
523 	} else
524 		pax_usage();
525 	if (bflg) {
526 		printflg(flg);
527 		pax_usage();
528 	}
529 
530 	/*
531 	 * if we are writing (ARCHIVE) we use the default format if the user
532 	 * did not specify a format. when we write during an APPEND, we will
533 	 * adopt the format of the existing archive if none was supplied.
534 	 */
535 	if (!(flg & XF) && (act == ARCHIVE))
536 		frmt = &(fsub[DEFLT]);
537 
538 	/*
539 	 * process the args as they are interpreted by the operation mode
540 	 */
541 	switch (act) {
542 	case LIST:
543 	case EXTRACT:
544 		for (; optind < argc; optind++)
545 			if (pat_add(argv[optind]) < 0)
546 				pax_usage();
547 		break;
548 	case COPY:
549 		if (optind >= argc) {
550 			pax_warn(0, "Destination directory was not supplied");
551 			pax_usage();
552 		}
553 		--argc;
554 		dirptr = argv[argc];
555 		/* FALL THROUGH */
556 	case ARCHIVE:
557 	case APPND:
558 		for (; optind < argc; optind++)
559 			if (ftree_add(argv[optind]) < 0)
560 				pax_usage();
561 		/*
562 		 * no read errors allowed on updates/append operation!
563 		 */
564 		maxflt = 0;
565 		break;
566 	}
567 }
568 
569 
570 /*
571  * tar_options()
572  *	look at the user specified flags. set globals as required and check if
573  *	the user specified a legal set of flags. If not, complain and exit
574  */
575 
576 #if __STDC__
577 static void
578 tar_options(register int argc, register char **argv)
579 #else
580 static void
581 tar_options(argc, argv)
582 	register int argc;
583 	register char **argv;
584 #endif
585 {
586 	register char *cp;
587 	int fstdin = 0;
588 
589 	if (argc < 2)
590 		tar_usage();
591 	/*
592 	 * process option flags
593 	 */
594 	++argv;
595 	for (cp = *argv++; *cp != '\0'; ++cp) {
596 		switch (*cp) {
597 		case '-':
598 			/*
599 			 * skip over -
600 			 */
601 			break;
602 		case 'b':
603 			/*
604 			 * specify blocksize
605 			 */
606 			if (*argv == (char *)NULL) {
607 				pax_warn(1,"blocksize must be specified with 'b'");
608 				tar_usage();
609 			}
610 			if ((wrblksz = (int)str_offt(*argv)) <= 0) {
611 				pax_warn(1, "Invalid block size %s", *argv);
612 				tar_usage();
613 			}
614 			++argv;
615 			break;
616 		case 'c':
617 			/*
618 			 * create an archive
619 			 */
620 			act = ARCHIVE;
621 			break;
622 		case 'e':
623 			/*
624 			 * stop after first error
625 			 */
626 			maxflt = 0;
627 			break;
628 		case 'f':
629 			/*
630 			 * filename where the archive is stored
631 			 */
632 			if (*argv == (char *)NULL) {
633 				pax_warn(1, "filename must be specified with 'f'");
634 				tar_usage();
635 			}
636 			if ((argv[0][0] == '-') && (argv[0][1]== '\0')) {
637 				/*
638 				 * treat a - as stdin
639 				 */
640 				++argv;
641 				++fstdin;
642 				arcname = (char *)0;
643 				break;
644 			}
645 			fstdin = 0;
646 			arcname = *argv++;
647 			break;
648 		case 'm':
649 			/*
650 			 * do not preserve modification time
651 			 */
652 			pmtime = 0;
653 			break;
654 		case 'o':
655 			if (opt_add("write_opt=nodir") < 0)
656 				tar_usage();
657 			break;
658 		case 'p':
659 			/*
660 			 * preserve user id, group id, file
661 			 * mode, access/modification times
662 			 */
663 			pids = 1;
664 			pmode = 1;
665 			patime = 1;
666 			pmtime = 1;
667 			break;
668 		case 'r':
669 		case 'u':
670 			/*
671 			 * append to the archive
672 			 */
673 			act = APPND;
674 			break;
675 		case 't':
676 			/*
677 			 * list contents of the tape
678 			 */
679 			act = LIST;
680 			break;
681 		case 'v':
682 			/*
683 			 * verbose operation mode
684 			 */
685 			vflag = 1;
686 			break;
687 		case 'w':
688 			/*
689 			 * interactive file rename
690 			 */
691 			iflag = 1;
692 			break;
693 		case 'x':
694 			/*
695 			 * write an archive
696 			 */
697 			act = EXTRACT;
698 			break;
699 		case 'B':
700 			/*
701 			 * Nothing to do here, this is pax default
702 			 */
703 			break;
704 		case 'H':
705 			/*
706 			 * follow command line symlinks only
707 			 */
708 			Hflag = 1;
709 			break;
710 		case 'L':
711 			/*
712 			 * follow symlinks
713 			 */
714 			Lflag = 1;
715 			break;
716 		case 'P':
717 			/*
718 			 * do not follow symlinks
719 			 */
720 			Lflag = 0;
721 			break;
722 		case 'X':
723 			/*
724 			 * do not pass over mount points in the file system
725 			 */
726 			Xflag = 1;
727 			break;
728 		case '0':
729 			arcname = DEV_0;
730 			break;
731 		case '1':
732 			arcname = DEV_1;
733 			break;
734 		case '4':
735 			arcname = DEV_4;
736 			break;
737 		case '5':
738 			arcname = DEV_5;
739 			break;
740 		case '7':
741 			arcname = DEV_7;
742 			break;
743 		case '8':
744 			arcname = DEV_8;
745 			break;
746 		default:
747 			tar_usage();
748 			break;
749 		}
750 	}
751 
752 	/*
753 	 * if we are writing (ARCHIVE) specify tar, otherwise run like pax
754 	 */
755 	if (act == ARCHIVE)
756 		frmt = &(fsub[F_TAR]);
757 
758 	/*
759 	 * process the args as they are interpreted by the operation mode
760 	 */
761 	switch (act) {
762 	case LIST:
763 	case EXTRACT:
764 	default:
765 		while (*argv != (char *)NULL)
766 			if (pat_add(*argv++) < 0)
767 				tar_usage();
768 		break;
769 	case ARCHIVE:
770 	case APPND:
771 		while (*argv != (char *)NULL)
772 			if (ftree_add(*argv++) < 0)
773 				tar_usage();
774 		/*
775 		 * no read errors allowed on updates/append operation!
776 		 */
777 		maxflt = 0;
778 		break;
779 	}
780 	if (!fstdin && ((arcname == (char *)NULL) || (*arcname == '\0'))) {
781 		arcname = getenv("TAPE");
782 		if ((arcname == (char *)NULL) || (*arcname == '\0'))
783 			arcname = DEV_8;
784 	}
785 }
786 
787 #ifdef notdef
788 /*
789  * cpio_options()
790  *	look at the user specified flags. set globals as required and check if
791  *	the user specified a legal set of flags. If not, complain and exit
792  */
793 
794 #if __STDC__
795 static void
796 cpio_options(register int argc, register char **argv)
797 #else
798 static void
799 cpio_options(argc, argv)
800 	register int argc;
801 	register char **argv;
802 #endif
803 {
804 }
805 #endif
806 
807 /*
808  * printflg()
809  *	print out those invalid flag sets found to the user
810  */
811 
812 #if __STDC__
813 static void
814 printflg(unsigned int flg)
815 #else
816 static void
817 printflg(flg)
818 	unsigned int flg;
819 #endif
820 {
821 	int nxt;
822 	int pos = 0;
823 
824 	(void)fprintf(stderr,"%s: Invalid combination of options:", argv0);
825 	while ((nxt = ffs(flg))) {
826 		flg = flg >> nxt;
827 		pos += nxt;
828 		(void)fprintf(stderr, " -%c", flgch[pos-1]);
829 	}
830 	(void)putc('\n', stderr);
831 }
832 
833 /*
834  * c_frmt()
835  *	comparison routine used by bsearch to find the format specified
836  *	by the user
837  */
838 
839 #if __STDC__
840 static int
841 c_frmt(const void *a, const void *b)
842 #else
843 static int
844 c_frmt(a, b)
845         void *a;
846         void *b;
847 #endif
848 {
849         return(strcmp(((FSUB *)a)->name, ((FSUB *)b)->name));
850 }
851 
852 /*
853  * opt_next()
854  *	called by format specific options routines to get each format specific
855  *	flag and value specified with -o
856  * Return:
857  *	pointer to next OPLIST entry or NULL (end of list).
858  */
859 
860 #if __STDC__
861 OPLIST *
862 opt_next(void)
863 #else
864 OPLIST *
865 opt_next()
866 #endif
867 {
868 	OPLIST *opt;
869 
870 	if ((opt = ophead) != NULL)
871 		ophead = ophead->fow;
872 	return(opt);
873 }
874 
875 /*
876  * bad_opt()
877  *	generic routine used to complain about a format specific options
878  *	when the format does not support options.
879  */
880 
881 #if __STDC__
882 int
883 bad_opt(void)
884 #else
885 int
886 bad_opt()
887 #endif
888 {
889 	register OPLIST *opt;
890 
891 	if (ophead == NULL)
892 		return(0);
893 	/*
894 	 * print all we were given
895 	 */
896 	pax_warn(1,"These format options are not supported");
897 	while ((opt = opt_next()) != NULL)
898 		(void)fprintf(stderr, "\t%s = %s\n", opt->name, opt->value);
899 	pax_usage();
900 	return(0);
901 }
902 
903 /*
904  * opt_add()
905  *	breaks the value supplied to -o into a option name and value. options
906  *	are given to -o in the form -o name-value,name=value
907  *	mulltiple -o may be specified.
908  * Return:
909  *	0 if format in name=value format, -1 if -o is passed junk
910  */
911 
912 #if __STDC__
913 int
914 opt_add(register char *str)
915 #else
916 int
917 opt_add(str)
918 	register char *str;
919 #endif
920 {
921 	register OPLIST *opt;
922 	register char *frpt;
923 	register char *pt;
924 	register char *endpt;
925 
926 	if ((str == NULL) || (*str == '\0')) {
927 		pax_warn(0, "Invalid option name");
928 		return(-1);
929 	}
930 	frpt = endpt = str;
931 
932 	/*
933 	 * break into name and values pieces and stuff each one into a
934 	 * OPLIST structure. When we know the format, the format specific
935 	 * option function will go through this list
936 	 */
937 	while ((frpt != NULL) && (*frpt != '\0')) {
938 		if ((endpt = strchr(frpt, ',')) != NULL)
939 			*endpt = '\0';
940 		if ((pt = strchr(frpt, '=')) == NULL) {
941 			pax_warn(0, "Invalid options format");
942 			return(-1);
943 		}
944 		if ((opt = (OPLIST *)malloc(sizeof(OPLIST))) == NULL) {
945 			pax_warn(0, "Unable to allocate space for option list");
946 			return(-1);
947 		}
948 		*pt++ = '\0';
949 		opt->name = frpt;
950 		opt->value = pt;
951 		opt->fow = NULL;
952 		if (endpt != NULL)
953 			frpt = endpt + 1;
954 		else
955 			frpt = NULL;
956 		if (ophead == NULL) {
957 			optail = ophead = opt;
958 			continue;
959 		}
960 		optail->fow = opt;
961 		optail = opt;
962 	}
963 	return(0);
964 }
965 
966 /*
967  * str_offt()
968  *	Convert an expression of the following forms to an off_t > 0.
969  * 	1) A positive decimal number.
970  *	2) A positive decimal number followed by a b (mult by 512).
971  *	3) A positive decimal number followed by a k (mult by 1024).
972  *	4) A positive decimal number followed by a m (mult by 512).
973  *	5) A positive decimal number followed by a w (mult by sizeof int)
974  *	6) Two or more positive decimal numbers (with/without k,b or w).
975  *	   seperated by x (also * for backwards compatibility), specifying
976  *	   the product of the indicated values.
977  * Return:
978  *	0 for an error, a positive value o.w.
979  */
980 
981 #if __STDC__
982 static off_t
983 str_offt(char *val)
984 #else
985 static off_t
986 str_offt(val)
987 	char *val;
988 #endif
989 {
990 	char *expr;
991 	off_t num, t;
992 
993 #	ifdef NET2_STAT
994 	num = strtol(val, &expr, 0);
995 	if ((num == LONG_MAX) || (num <= 0) || (expr == val))
996 #	else
997 	num = strtoq(val, &expr, 0);
998 	if ((num == QUAD_MAX) || (num <= 0) || (expr == val))
999 #	endif
1000 		return(0);
1001 
1002 	switch(*expr) {
1003 	case 'b':
1004 		t = num;
1005 		num *= 512;
1006 		if (t > num)
1007 			return(0);
1008 		++expr;
1009 		break;
1010 	case 'k':
1011 		t = num;
1012 		num *= 1024;
1013 		if (t > num)
1014 			return(0);
1015 		++expr;
1016 		break;
1017 	case 'm':
1018 		t = num;
1019 		num *= 1048576;
1020 		if (t > num)
1021 			return(0);
1022 		++expr;
1023 		break;
1024 	case 'w':
1025 		t = num;
1026 		num *= sizeof(int);
1027 		if (t > num)
1028 			return(0);
1029 		++expr;
1030 		break;
1031 	}
1032 
1033 	switch(*expr) {
1034 		case '\0':
1035 			break;
1036 		case '*':
1037 		case 'x':
1038 			t = num;
1039 			num *= str_offt(expr + 1);
1040 			if (t > num)
1041 				return(0);
1042 			break;
1043 		default:
1044 			return(0);
1045 	}
1046 	return(num);
1047 }
1048 
1049 /*
1050  * no_op()
1051  *	for those option functions where the archive format has nothing to do.
1052  * Return:
1053  *	0
1054  */
1055 
1056 #if __STDC__
1057 static int
1058 no_op(void)
1059 #else
1060 static int
1061 no_op()
1062 #endif
1063 {
1064 	return(0);
1065 }
1066 
1067 /*
1068  * pax_usage()
1069  *	print the usage summary to the user
1070  */
1071 
1072 #if __STDC__
1073 void
1074 pax_usage(void)
1075 #else
1076 void
1077 pax_usage()
1078 #endif
1079 {
1080 	(void)fputs("usage: pax [-cdnv] [-E limit] [-f archive] ", stderr);
1081 	(void)fputs("[-s replstr] ... [-U user] ...", stderr);
1082 	(void)fputs("\n           [-G group] ... ", stderr);
1083 	(void)fputs("[-T [from_date][,to_date]] ... ", stderr);
1084 	(void)fputs("[pattern ...]\n", stderr);
1085 	(void)fputs("       pax -r [-cdiknuvDYZ] [-E limit] ", stderr);
1086 	(void)fputs("[-f archive] [-o options] ... \n", stderr);
1087 	(void)fputs("           [-p string] ... [-s replstr] ... ", stderr);
1088 	(void)fputs("[-U user] ... [-G group] ...\n           ", stderr);
1089 	(void)fputs("[-T [from_date][,to_date]] ... ", stderr);
1090 	(void)fputs(" [pattern ...]\n", stderr);
1091 	(void)fputs("       pax -w [-dituvHLPX] [-b blocksize] ", stderr);
1092 	(void)fputs("[ [-a] [-f archive] ] [-x format] \n", stderr);
1093 	(void)fputs("           [-B bytes] [-s replstr] ... ", stderr);
1094 	(void)fputs("[-o options] ... [-U user] ...", stderr);
1095 	(void)fputs("\n           [-G group] ... ", stderr);
1096 	(void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr);
1097 	(void)fputs("[file ...]\n", stderr);
1098 	(void)fputs("       pax -r -w [-diklntuvDHLPXYZ] ", stderr);
1099 	(void)fputs("[-p string] ... [-s replstr] ...", stderr);
1100 	(void)fputs("\n           [-U user] ... [-G group] ... ", stderr);
1101 	(void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr);
1102 	(void)fputs("\n           [file ...] directory\n", stderr);
1103 	exit(1);
1104 }
1105 
1106 /*
1107  * tar_usage()
1108  *	print the usage summary to the user
1109  */
1110 
1111 #if __STDC__
1112 void
1113 tar_usage(void)
1114 #else
1115 void
1116 tar_usage()
1117 #endif
1118 {
1119 	(void)fputs("usage: tar -{txru}[cevfbmopwBHLPX014578] [tapefile] ",
1120 		 stderr);
1121 	(void)fputs("[blocksize] file1 file2...\n", stderr);
1122 	exit(1);
1123 }
1124 
1125 #ifdef notdef
1126 /*
1127  * cpio_usage()
1128  *	print the usage summary to the user
1129  */
1130 
1131 #if __STDC__
1132 void
1133 cpio_usage(void)
1134 #else
1135 void
1136 cpio_usage()
1137 #endif
1138 {
1139 	exit(1);
1140 }
1141 #endif
1142