xref: /original-bsd/usr.bin/ar/ar.c (revision 767d859e)
1 /*-
2  * Copyright (c) 1990 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Hugh Smith at The University of Guelph.
7  *
8  * %sccs.include.redist.c%
9  */
10 
11 #ifndef lint
12 char copyright[] =
13 "@(#) Copyright (c) 1990 The Regents of the University of California.\n\
14  All rights reserved.\n";
15 #endif /* not lint */
16 
17 #ifndef lint
18 static char sccsid[] = "@(#)ar.c	5.6 (Berkeley) 01/17/91";
19 #endif /* not lint */
20 
21 #include <sys/param.h>
22 #include <sys/errno.h>
23 #include <dirent.h>
24 #include <stdio.h>
25 #include <ar.h>
26 #include <paths.h>
27 #include "archive.h"
28 
29 CHDR chdr;
30 u_int options;
31 char *archive, *envtmp, *posname;
32 
33 /*
34  * main --
35  *	main basically uses getopt to parse options and calls the appropriate
36  *	functions.  Some hacks that let us be backward compatible with 4.3 ar
37  *	option parsing and sanity checking.
38  */
39 main(argc, argv)
40 	int argc;
41 	char **argv;
42 {
43 	extern int optind;
44 	int c, rval;
45 	char *p;
46 	int (*fcall)(), append(), contents(), delete(), extract(),
47 	    move(), print(), replace();
48 	char *rname();
49 
50 	if (argc < 3)
51 		usage();
52 
53 	/*
54 	 * Historic versions didn't require a '-' in front of the options.
55 	 * Fix it, if necessary.
56 	*/
57 	if (*argv[1] != '-') {
58 		if (!(p = malloc((u_int)(strlen(argv[1]) + 2)))) {
59 			(void)fprintf(stderr, "ar: %s.\n", strerror(errno));
60 			exit(1);
61 		}
62 		*p = '-';
63 		(void)strcpy(p + 1, argv[1]);
64 		argv[1] = p;
65 	}
66 
67 	while ((c = getopt(argc, argv, "abcdilmopqrtuvx")) != EOF) {
68 		switch(c) {
69 		case 'a':
70 			options |= AR_A;
71 			break;
72 		case 'b':
73 		case 'i':
74 			options |= AR_B;
75 			break;
76 		case 'c':
77 			options |= AR_C;
78 			break;
79 		case 'd':
80 			options |= AR_D;
81 			fcall = delete;
82 			break;
83 		case 'l':		/* not documented, compatibility only */
84 			envtmp = ".";
85 			break;
86 		case 'm':
87 			options |= AR_M;
88 			fcall = move;
89 			break;
90 		case 'o':
91 			options |= AR_O;
92 			break;
93 		case 'p':
94 			options |= AR_P;
95 			fcall = print;
96 			break;
97 		case 'q':
98 			options |= AR_Q;
99 			fcall = append;
100 			break;
101 		case 'r':
102 			options |= AR_R;
103 			fcall = replace;
104 			break;
105 		case 't':
106 			options |= AR_T;
107 			fcall = contents;
108 			break;
109 		case 'u':
110 			options |= AR_U;
111 			break;
112 		case 'v':
113 			options |= AR_V;
114 			break;
115 		case 'x':
116 			options |= AR_X;
117 			fcall = extract;
118 			break;
119 		default:
120 			usage();
121 		}
122 	}
123 
124 	argv += optind;
125 	argc -= optind;
126 
127 	/* One of -dmpqrtx required. */
128 	if (!(options & (AR_D|AR_M|AR_P|AR_Q|AR_R|AR_T|AR_X))) {
129 		(void)fprintf(stderr,
130 		    "ar: one of options -dmpqrtx is required.\n");
131 		usage();
132 	}
133 	/* Only one of -a and -bi. */
134 	if (options & AR_A && options & AR_B) {
135 		(void)fprintf(stderr,
136 		    "ar: only one of -a and -[bi] options allowed.\n");
137 		usage();
138 	}
139 	/* -ab require a position argument. */
140 	if (options & (AR_A|AR_B)) {
141 		if (!(posname = *argv++)) {
142 			(void)fprintf(stderr,
143 			    "ar: no position operand specified.\n");
144 			usage();
145 		}
146 		posname = rname(posname);
147 	}
148 	/* -d only valid with -v. */
149 	if (options & AR_D && options & ~(AR_D|AR_V))
150 		badoptions("-d");
151 	/* -m only valid with -abiv. */
152 	if (options & AR_M && options & ~(AR_A|AR_B|AR_M|AR_V))
153 		badoptions("-m");
154 	/* -p only valid with -v. */
155 	if (options & AR_P && options & ~(AR_P|AR_V))
156 		badoptions("-p");
157 	/* -q only valid with -cv. */
158 	if (options & AR_Q && options & ~(AR_C|AR_Q|AR_V))
159 		badoptions("-q");
160 	/* -r only valid with -abcuv. */
161 	if (options & AR_R && options & ~(AR_A|AR_B|AR_C|AR_R|AR_U|AR_V))
162 		badoptions("-r");
163 	/* -t only valid with -v. */
164 	if (options & AR_T && options & ~(AR_T|AR_V))
165 		badoptions("-t");
166 	/* -x only valid with -ouv. */
167 	if (options & AR_X && options & ~(AR_O|AR_U|AR_V|AR_X))
168 		badoptions("-x");
169 
170 	if (!(archive = *argv++)) {
171 		(void)fprintf(stderr, "ar: no archive specified.\n");
172 		usage();
173 	}
174 
175 	/* -dmqr require a list of archive elements. */
176 	if (options & (AR_D|AR_M|AR_Q|AR_R) && !*argv) {
177 		(void)fprintf(stderr, "ar: no archive members specified.\n");
178 		usage();
179 	}
180 
181 	rval = (*fcall)(argv);
182 	exit(rval);
183 }
184 
185 badoptions(arg)
186 	char *arg;
187 {
188 	(void)fprintf(stderr,
189 	    "ar: illegal option combination for %s.\n", arg);
190 	usage();
191 }
192 
193 usage()
194 {
195 	(void)fprintf(stderr, "usage:  ar -d [-v] archive file ...\n");
196 	(void)fprintf(stderr, "\tar -m [-v] archive file ...\n");
197 	(void)fprintf(stderr, "\tar -m [-abiv] position archive file ...\n");
198 	(void)fprintf(stderr, "\tar -p [-v] archive [file ...]\n");
199 	(void)fprintf(stderr, "\tar -q [-cv] archive file ...\n");
200 	(void)fprintf(stderr, "\tar -r [-cuv] archive file ...\n");
201 	(void)fprintf(stderr, "\tar -r [-abciuv] position archive file ...\n");
202 	(void)fprintf(stderr, "\tar -t [-v] archive [file ...]\n");
203 	(void)fprintf(stderr, "\tar -x [-ouv] archive [file ...]\n");
204 	exit(1);
205 }
206