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