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