cctools —version, package reporting and --help additions.
[darwin-xtools.git] / cctools / ar / ar.c
blob90ed5706da039dec2d0a28b02202ddefa0d504e6
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
23 /* $OpenBSD: ar.c,v 1.3 1997/01/15 23:42:11 millert Exp $ */
24 /* $NetBSD: ar.c,v 1.5 1995/03/26 03:27:44 glass Exp $ */
26 /*-
27 * Copyright (c) 1990, 1993, 1994
28 * The Regents of the University of California. All rights reserved.
30 * This code is derived from software contributed to Berkeley by
31 * Hugh Smith at The University of Guelph.
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
35 * are met:
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * 3. All advertising materials mentioning features or use of this software
42 * must display the following acknowledgement:
43 * This product includes software developed by the University of
44 * California, Berkeley and its contributors.
45 * 4. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE.
62 #ifndef lint
63 #if 0
64 static char copyright[] =
65 "@(#) Copyright (c) 1990, 1993, 1994\n\
66 The Regents of the University of California. All rights reserved.\n";
67 static char sccsid[] = "@(#)ar.c 8.3 (Berkeley) 4/2/94";
68 static char rcsid[] = "$OpenBSD: ar.c,v 1.3 1997/01/15 23:42:11 millert Exp $";
69 #endif
70 #endif /* not lint */
72 #include <sys/param.h>
74 #include <ar.h>
75 #include <dirent.h>
76 #include <err.h>
77 #include <paths.h>
78 #include <stdio.h>
79 #include <stdlib.h>
80 #include <string.h>
81 #include <unistd.h>
83 #include "archive.h"
84 #include "extern.h"
85 #include "stuff/execute.h"
86 #include "stuff/unix_standard_mode.h"
88 CHDR chdr;
89 u_int options;
90 char *archive, *envtmp, *posarg, *posname;
91 static void badoptions __P((char *));
92 static void usage __P((int));
93 char *progname;
95 /* apple_version is in cctools_version.c which is in libstuff and created by
96 the build process. */
97 extern char apple_version[];
99 /* likewise xtools_version and support_url. */
100 extern char xtools_version[];
101 extern char package_version[];
102 extern char support_url[];
105 * main --
106 * main basically uses getopt to parse options and calls the appropriate
107 * functions. Some hacks that let us be backward compatible with 4.3 ar
108 * option parsing and sanity checking.
111 main(argc, argv)
112 int argc;
113 char **argv;
115 int c, retval, verbose, run_ranlib, toc64;
116 char *p;
117 int (*fcall) __P((char **));
119 fcall = 0;
120 verbose = 0;
121 toc64 = 0;
122 progname = argv[0];
123 run_ranlib = 1;
125 if (argc < 3) {
126 if(strcmp(argv[1], "--version") == 0){
127 /* Implement a gnu-style --version to be friendly to GCC. */
128 fprintf(stdout, "xtools-%s ar %s\nBased on Apple Inc. %s\n",
129 xtools_version, package_version, apple_version);
130 exit(0);
131 } else if(strcmp(argv[1], "--help") == 0){
132 usage(0);
133 fprintf(stdout, "Please report bugs to %s\n", support_url);
134 exit(0);
135 } else
136 usage(1);
140 * Historic versions didn't require a '-' in front of the options.
141 * Fix it, if necessary.
143 if (*argv[1] != '-') {
144 if (!(p = malloc((u_int)(strlen(argv[1]) + 2))))
145 err(1, NULL);
146 *p = '-';
147 (void)strcpy(p + 1, argv[1]);
148 argv[1] = p;
152 * For Rhapsody Premier the option to use long member names, -L, is the
153 * default. The compiler tools for Rhapsody Premier do understand
154 * extended format #1. The new option -L allows ar to use the extended
155 * format and the old -T option causes the truncation of names.
157 while ((c = getopt(argc, argv, "abcdilLmopqrSsTtuVvx6")) != -1) {
158 switch(c) {
159 case 'a':
160 options |= AR_A;
161 break;
162 case 'b':
163 case 'i':
164 options |= AR_B;
165 break;
166 case 'c':
167 options |= AR_C;
168 break;
169 case 'd':
170 options |= AR_D;
171 fcall = delete;
172 break;
173 case 'l': /* not documented, compatibility only */
174 envtmp = ".";
175 break;
176 case 'L':
177 options &= ~AR_TR;
178 break;
179 case 'm':
180 options |= AR_M;
181 fcall = move;
182 break;
183 case 'o':
184 options |= AR_O;
185 break;
186 case 'p':
187 options |= AR_P;
188 fcall = print;
189 break;
190 case 'q':
191 options |= AR_Q;
192 fcall = append;
193 break;
194 case 'r':
195 options |= AR_R;
196 fcall = replace;
197 break;
198 case 's':
199 options |= AR_S;
200 break;
201 case 'S':
202 options &= ~AR_S;
203 run_ranlib = 0;
204 break;
205 case 'T':
206 options |= AR_TR;
207 break;
208 case 't':
209 options |= AR_T;
210 fcall = contents;
211 break;
212 case 'u':
213 options |= AR_U;
214 break;
215 case 'V':
216 verbose = 1;
217 break;
218 case '6':
219 toc64 = 1;
220 break;
221 case 'v':
222 options |= AR_V;
223 break;
224 case 'x':
225 options |= AR_X;
226 fcall = extract;
227 break;
228 default:
229 usage(1);
233 argv += optind;
234 argc -= optind;
236 /* One of -dmpqrtsx required. */
237 if (!(options & (AR_D|AR_M|AR_P|AR_Q|AR_R|AR_S|AR_T|AR_X))) {
238 warnx("one of options -dmpqrtsx is required");
239 usage(1);
241 /* Only one of -a and -bi allowed. */
242 if (options & AR_A && options & AR_B) {
243 warnx("only one of -a and -[bi] options allowed");
244 usage(1);
246 /* -ab require a position argument. */
247 if (options & (AR_A|AR_B)) {
248 if (!(posarg = *argv++)) {
249 warnx("no position operand specified");
250 usage(1);
252 posname = rname(posarg);
254 /* -d only valid with -Tsv. */
255 if (options & AR_D && options & ~(AR_D|AR_TR|AR_S|AR_V))
256 badoptions("-d");
257 /* -m only valid with -abiTsv. */
258 if (options & AR_M && options & ~(AR_A|AR_B|AR_M|AR_TR|AR_S|AR_V))
259 badoptions("-m");
260 /* -p only valid with -Tsv. */
261 if (options & AR_P && options & ~(AR_P|AR_TR|AR_S|AR_V))
262 badoptions("-p");
263 /* -q only valid with -cTsv. */
264 if (options & AR_Q && options & ~(AR_C|AR_Q|AR_TR|AR_S|AR_V))
265 badoptions("-q");
266 /* -r only valid with -abcuTsv. */
267 if (options & AR_R && options & ~(AR_A|AR_B|AR_C|AR_R|AR_U|AR_TR|AR_S|AR_V))
268 badoptions("-r");
269 /* -t only valid with -Tsv. */
270 if (options & AR_T && options & ~(AR_T|AR_TR|AR_S|AR_V))
271 badoptions("-t");
272 /* -x only valid with -ouTsv. */
273 if (options & AR_X && options & ~(AR_O|AR_U|AR_TR|AR_S|AR_V|AR_X))
274 badoptions("-x");
276 if (!(archive = *argv++)) {
277 warnx("no archive specified");
278 usage(1);
281 /* -dmqr require a list of archive elements. */
282 if (options & (AR_D|AR_M|AR_Q|AR_R) && !*argv) {
283 warnx("no archive members specified");
284 usage(1);
287 if(fcall != 0){
288 retval = (*fcall)(argv);
289 if(retval != EXIT_SUCCESS ||
290 ((options & AR_S) != AR_S &&
291 (get_unix_standard_mode() == FALSE ||
292 archive_opened_for_writing == 0)))
293 exit(retval);
297 * The default is to run ranlib(1) for UNIX conformance. But if the -S
298 * option is specified by the user we don't run it.
300 if(run_ranlib){
301 /* run ranlib -f or -q on the archive */
302 reset_execute_list();
303 add_execute_list_with_prefix("ranlib");
304 if(options & AR_S)
305 add_execute_list("-f");
306 else
307 add_execute_list("-q");
308 if(toc64)
309 add_execute_list("-toc64");
310 add_execute_list(archive);
311 if(execute_list(verbose) == 0){
312 (void)fprintf(stderr, "%s: internal ranlib command failed\n",
313 progname);
314 exit(EXIT_FAILURE);
317 exit(EXIT_SUCCESS);
320 static void
321 badoptions(arg)
322 char *arg;
325 warnx("illegal option combination for %s", arg);
326 usage(1);
329 /* print useage info; exit if with_exit_code is non-0. */
330 static void
331 usage(int with_exit_code)
333 FILE *out = with_exit_code ? stderr : stdout;
334 (void)fprintf(out, "usage: ar -d [-TLsv] archive file ...\n");
335 (void)fprintf(out, "\tar -m [-TLsv] archive file ...\n");
336 (void)fprintf(out, "\tar -m [-abiTLsv] position archive file ...\n");
337 (void)fprintf(out, "\tar -p [-TLsv] archive [file ...]\n");
338 (void)fprintf(out, "\tar -q [-cTLsv] archive file ...\n");
339 (void)fprintf(out, "\tar -r [-cuTLsv] archive file ...\n");
340 (void)fprintf(out, "\tar -r [-abciuTLsv] position archive file ...\n");
341 (void)fprintf(out, "\tar -t [-TLsv] archive [file ...]\n");
342 (void)fprintf(out, "\tar -x [-ouTLsv] archive [file ...]\n");
343 if (with_exit_code)
344 exit(with_exit_code);