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