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