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