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