xref: /freebsd/contrib/elftoolchain/ar/ar.c (revision ae500c1ff8974130f7f2692772cf288b90349e0d)
13fe401a5SEd Maste /*-
23fe401a5SEd Maste  * Copyright (c) 2007 Kai Wang
33fe401a5SEd Maste  * Copyright (c) 2007 Tim Kientzle
43fe401a5SEd Maste  * Copyright (c) 2007 Joseph Koshy
53fe401a5SEd Maste  * All rights reserved.
63fe401a5SEd Maste  *
73fe401a5SEd Maste  * Redistribution and use in source and binary forms, with or without
83fe401a5SEd Maste  * modification, are permitted provided that the following conditions
93fe401a5SEd Maste  * are met:
103fe401a5SEd Maste  * 1. Redistributions of source code must retain the above copyright
113fe401a5SEd Maste  *    notice, this list of conditions and the following disclaimer
123fe401a5SEd Maste  *    in this position and unchanged.
133fe401a5SEd Maste  * 2. Redistributions in binary form must reproduce the above copyright
143fe401a5SEd Maste  *    notice, this list of conditions and the following disclaimer in the
153fe401a5SEd Maste  *    documentation and/or other materials provided with the distribution.
163fe401a5SEd Maste  *
173fe401a5SEd Maste  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
183fe401a5SEd Maste  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
193fe401a5SEd Maste  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
203fe401a5SEd Maste  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
213fe401a5SEd Maste  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
223fe401a5SEd Maste  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
233fe401a5SEd Maste  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
243fe401a5SEd Maste  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
253fe401a5SEd Maste  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
263fe401a5SEd Maste  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
273fe401a5SEd Maste  */
283fe401a5SEd Maste 
293fe401a5SEd Maste /*-
303fe401a5SEd Maste  * Copyright (c) 1990, 1993, 1994
313fe401a5SEd Maste  *	The Regents of the University of California.  All rights reserved.
323fe401a5SEd Maste  *
333fe401a5SEd Maste  * This code is derived from software contributed to Berkeley by
343fe401a5SEd Maste  * Hugh Smith at The University of Guelph.
353fe401a5SEd Maste  *
363fe401a5SEd Maste  * Redistribution and use in source and binary forms, with or without
373fe401a5SEd Maste  * modification, are permitted provided that the following conditions
383fe401a5SEd Maste  * are met:
393fe401a5SEd Maste  * 1. Redistributions of source code must retain the above copyright
403fe401a5SEd Maste  *    notice, this list of conditions and the following disclaimer.
413fe401a5SEd Maste  * 2. Redistributions in binary form must reproduce the above copyright
423fe401a5SEd Maste  *    notice, this list of conditions and the following disclaimer in the
433fe401a5SEd Maste  *    documentation and/or other materials provided with the distribution.
443fe401a5SEd Maste  * 3. Neither the name of the University nor the names of its contributors
453fe401a5SEd Maste  *    may be used to endorse or promote products derived from this software
463fe401a5SEd Maste  *    without specific prior written permission.
473fe401a5SEd Maste  *
483fe401a5SEd Maste  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
493fe401a5SEd Maste  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
503fe401a5SEd Maste  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
513fe401a5SEd Maste  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
523fe401a5SEd Maste  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
533fe401a5SEd Maste  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
543fe401a5SEd Maste  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
553fe401a5SEd Maste  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
563fe401a5SEd Maste  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
573fe401a5SEd Maste  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
583fe401a5SEd Maste  * SUCH DAMAGE.
593fe401a5SEd Maste  */
603fe401a5SEd Maste 
613fe401a5SEd Maste #include <sys/queue.h>
623fe401a5SEd Maste #include <sys/types.h>
633fe401a5SEd Maste #include <archive.h>
643fe401a5SEd Maste #include <errno.h>
653fe401a5SEd Maste #include <getopt.h>
663fe401a5SEd Maste #include <libelftc.h>
673fe401a5SEd Maste #include <libgen.h>
683fe401a5SEd Maste #include <stdio.h>
693fe401a5SEd Maste #include <stdlib.h>
703fe401a5SEd Maste #include <stdint.h>
713fe401a5SEd Maste #include <string.h>
723fe401a5SEd Maste 
733fe401a5SEd Maste #include "ar.h"
743fe401a5SEd Maste 
75*ae500c1fSEd Maste ELFTC_VCSID("$Id: ar.c 3629 2018-09-30 19:26:28Z jkoshy $");
763fe401a5SEd Maste 
773fe401a5SEd Maste enum options
783fe401a5SEd Maste {
793fe401a5SEd Maste 	OPTION_HELP
803fe401a5SEd Maste };
813fe401a5SEd Maste 
823fe401a5SEd Maste static struct option longopts[] =
833fe401a5SEd Maste {
843fe401a5SEd Maste 	{"flavor", required_argument, NULL, 'F'},
853fe401a5SEd Maste 	{"help", no_argument, NULL, OPTION_HELP},
863fe401a5SEd Maste 	{"version", no_argument, NULL, 'V'},
873fe401a5SEd Maste 	{NULL, 0, NULL, 0}
883fe401a5SEd Maste };
893fe401a5SEd Maste 
903fe401a5SEd Maste static void	bsdar_usage(void);
913fe401a5SEd Maste static void	ranlib_usage(void);
923fe401a5SEd Maste static void	set_mode(struct bsdar *bsdar, char opt);
933fe401a5SEd Maste static void	only_mode(struct bsdar *bsdar, const char *opt,
943fe401a5SEd Maste 		    const char *valid_modes);
953fe401a5SEd Maste static void	bsdar_version(void);
963fe401a5SEd Maste 
973fe401a5SEd Maste int
main(int argc,char ** argv)983fe401a5SEd Maste main(int argc, char **argv)
993fe401a5SEd Maste {
1003fe401a5SEd Maste 	struct bsdar	*bsdar, bsdar_storage;
1013fe401a5SEd Maste 	char		*arcmd, *argv1_saved;
1023fe401a5SEd Maste 	size_t		 len;
103*ae500c1fSEd Maste 	int		 exitcode, i, opt;
1043fe401a5SEd Maste 
1053fe401a5SEd Maste 	bsdar = &bsdar_storage;
1063fe401a5SEd Maste 	memset(bsdar, 0, sizeof(*bsdar));
1073fe401a5SEd Maste 
108*ae500c1fSEd Maste 	exitcode = EXIT_SUCCESS;
1093fe401a5SEd Maste 	arcmd = argv1_saved = NULL;
1103fe401a5SEd Maste 	bsdar->output = stdout;
1113fe401a5SEd Maste 
1123fe401a5SEd Maste 	if ((bsdar->progname = ELFTC_GETPROGNAME()) == NULL)
1133fe401a5SEd Maste 		bsdar->progname = "ar";
1143fe401a5SEd Maste 
1153fe401a5SEd Maste 	if (elf_version(EV_CURRENT) == EV_NONE)
1163fe401a5SEd Maste 		bsdar_errc(bsdar, 0, "ELF library initialization failed: %s",
1173fe401a5SEd Maste 		    elf_errmsg(-1));
1183fe401a5SEd Maste 
1193fe401a5SEd Maste 	/*
1203fe401a5SEd Maste 	 * Act like ranlib if our name ends in "ranlib"; this
1213fe401a5SEd Maste 	 * accommodates names like "arm-freebsd7.1-ranlib",
1223fe401a5SEd Maste 	 * "bsdranlib", etc.
1233fe401a5SEd Maste 	 */
1243fe401a5SEd Maste 	len = strlen(bsdar->progname);
1253fe401a5SEd Maste 	if (len >= strlen("ranlib") &&
1263fe401a5SEd Maste 	    strcmp(bsdar->progname + len - strlen("ranlib"), "ranlib") == 0) {
127656f49f8SEd Maste 		while ((opt = getopt_long(argc, argv, "tDUV", longopts,
1283fe401a5SEd Maste 		    NULL)) != -1) {
1293fe401a5SEd Maste 			switch(opt) {
1303fe401a5SEd Maste 			case 't':
1313fe401a5SEd Maste 				/* Ignored. */
1323fe401a5SEd Maste 				break;
1333fe401a5SEd Maste 			case 'D':
1343fe401a5SEd Maste 				bsdar->options |= AR_D;
1353fe401a5SEd Maste 				break;
136656f49f8SEd Maste 			case 'U':
137656f49f8SEd Maste 				bsdar->options &= ~AR_D;
138656f49f8SEd Maste 				break;
1393fe401a5SEd Maste 			case 'V':
1403fe401a5SEd Maste 				bsdar_version();
1413fe401a5SEd Maste 				break;
1423fe401a5SEd Maste 			case OPTION_HELP:
1433fe401a5SEd Maste 				ranlib_usage();
1443fe401a5SEd Maste 			default:
1453fe401a5SEd Maste 				ranlib_usage();
1463fe401a5SEd Maste 			}
1473fe401a5SEd Maste 		}
1483fe401a5SEd Maste 		argv += optind;
1493fe401a5SEd Maste 		argc -= optind;
1503fe401a5SEd Maste 
1513fe401a5SEd Maste 		if (*argv == NULL)
1523fe401a5SEd Maste 			ranlib_usage();
1533fe401a5SEd Maste 
1543fe401a5SEd Maste 		bsdar->options |= AR_S;
155656f49f8SEd Maste 		while ((bsdar->filename = *argv++) != NULL)
156*ae500c1fSEd Maste 			exitcode |= ar_write_archive(bsdar, 's');
1573fe401a5SEd Maste 
158*ae500c1fSEd Maste 		exit(exitcode);
1593fe401a5SEd Maste 	} else {
1603fe401a5SEd Maste 		if (argc < 2)
1613fe401a5SEd Maste 			bsdar_usage();
1623fe401a5SEd Maste 
1633fe401a5SEd Maste 		/*
1643fe401a5SEd Maste 		 * Tack on a leading '-', for old-style usage.
1653fe401a5SEd Maste 		 */
1663fe401a5SEd Maste 		if (*argv[1] != '-') {
1673fe401a5SEd Maste 			argv1_saved = argv[1];
1683fe401a5SEd Maste 			len = strlen(argv[1]) + 2;
1693fe401a5SEd Maste 			if ((arcmd = malloc(len)) == NULL)
1703fe401a5SEd Maste 				bsdar_errc(bsdar, errno, "malloc failed");
1713fe401a5SEd Maste 			(void) snprintf(arcmd, len, "-%s", argv[1]);
1723fe401a5SEd Maste 			argv[1] = arcmd;
1733fe401a5SEd Maste 		}
1743fe401a5SEd Maste 	}
1753fe401a5SEd Maste 
176656f49f8SEd Maste 	while ((opt = getopt_long(argc, argv, "abCcdDfF:ijlMmopqrSsTtUuVvxz",
1773fe401a5SEd Maste 	    longopts, NULL)) != -1) {
1783fe401a5SEd Maste 		switch(opt) {
1793fe401a5SEd Maste 		case 'a':
1803fe401a5SEd Maste 			bsdar->options |= AR_A;
1813fe401a5SEd Maste 			break;
1823fe401a5SEd Maste 		case 'b':
1833fe401a5SEd Maste 		case 'i':
1843fe401a5SEd Maste 			bsdar->options |= AR_B;
1853fe401a5SEd Maste 			break;
1863fe401a5SEd Maste 		case 'C':
1873fe401a5SEd Maste 			bsdar->options |= AR_CC;
1883fe401a5SEd Maste 			break;
1893fe401a5SEd Maste 		case 'c':
1903fe401a5SEd Maste 			bsdar->options |= AR_C;
1913fe401a5SEd Maste 			break;
1923fe401a5SEd Maste 		case 'd':
1933fe401a5SEd Maste 			set_mode(bsdar, opt);
1943fe401a5SEd Maste 			break;
1953fe401a5SEd Maste 		case 'D':
1963fe401a5SEd Maste 			bsdar->options |= AR_D;
1973fe401a5SEd Maste 			break;
1983fe401a5SEd Maste 		case 'F':
1993fe401a5SEd Maste 			if (!strcasecmp(optarg, "svr4") ||
2003fe401a5SEd Maste 			    !strcasecmp(optarg, "gnu"))
2013fe401a5SEd Maste 				bsdar->options &= ~AR_BSD;
2023fe401a5SEd Maste 			else if (!strcasecmp(optarg, "bsd"))
2033fe401a5SEd Maste 				bsdar->options |= AR_BSD;
2043fe401a5SEd Maste 			else
2053fe401a5SEd Maste 				bsdar_usage();
2063fe401a5SEd Maste 			break;
2073fe401a5SEd Maste 		case 'f':
2083fe401a5SEd Maste 		case 'T':
2093fe401a5SEd Maste 			bsdar->options |= AR_TR;
2103fe401a5SEd Maste 			break;
2113fe401a5SEd Maste 		case 'j':
2123fe401a5SEd Maste 			/* ignored */
2133fe401a5SEd Maste 			break;
2143fe401a5SEd Maste 		case 'l':
2153fe401a5SEd Maste 			/* ignored, for GNU ar comptibility */
2163fe401a5SEd Maste 			break;
2173fe401a5SEd Maste 		case 'M':
2183fe401a5SEd Maste 			set_mode(bsdar, opt);
2193fe401a5SEd Maste 			break;
2203fe401a5SEd Maste 		case 'm':
2213fe401a5SEd Maste 			set_mode(bsdar, opt);
2223fe401a5SEd Maste 			break;
2233fe401a5SEd Maste 		case 'o':
2243fe401a5SEd Maste 			bsdar->options |= AR_O;
2253fe401a5SEd Maste 			break;
2263fe401a5SEd Maste 		case 'p':
2273fe401a5SEd Maste 			set_mode(bsdar, opt);
2283fe401a5SEd Maste 			break;
2293fe401a5SEd Maste 		case 'q':
2303fe401a5SEd Maste 			set_mode(bsdar, opt);
2313fe401a5SEd Maste 			break;
2323fe401a5SEd Maste 		case 'r':
2333fe401a5SEd Maste 			set_mode(bsdar, opt);
2343fe401a5SEd Maste 			break;
2353fe401a5SEd Maste 		case 'S':
2363fe401a5SEd Maste 			bsdar->options |= AR_SS;
2373fe401a5SEd Maste 			break;
2383fe401a5SEd Maste 		case 's':
2393fe401a5SEd Maste 			bsdar->options |= AR_S;
2403fe401a5SEd Maste 			break;
2413fe401a5SEd Maste 		case 't':
2423fe401a5SEd Maste 			set_mode(bsdar, opt);
2433fe401a5SEd Maste 			break;
244656f49f8SEd Maste 		case 'U':
245656f49f8SEd Maste 			bsdar->options &= ~AR_D;
246656f49f8SEd Maste 			break;
2473fe401a5SEd Maste 		case 'u':
2483fe401a5SEd Maste 			bsdar->options |= AR_U;
2493fe401a5SEd Maste 			break;
2503fe401a5SEd Maste 		case 'V':
2513fe401a5SEd Maste 			bsdar_version();
2523fe401a5SEd Maste 			break;
2533fe401a5SEd Maste 		case 'v':
2543fe401a5SEd Maste 			bsdar->options |= AR_V;
2553fe401a5SEd Maste 			break;
2563fe401a5SEd Maste 		case 'x':
2573fe401a5SEd Maste 			set_mode(bsdar, opt);
2583fe401a5SEd Maste 			break;
2593fe401a5SEd Maste 		case 'z':
2603fe401a5SEd Maste 			/* ignored */
2613fe401a5SEd Maste 			break;
2623fe401a5SEd Maste 		case OPTION_HELP:
2633fe401a5SEd Maste 			bsdar_usage();
2643fe401a5SEd Maste 		default:
2653fe401a5SEd Maste 			bsdar_usage();
2663fe401a5SEd Maste 		}
2673fe401a5SEd Maste 	}
2683fe401a5SEd Maste 
2693fe401a5SEd Maste 	/* Restore argv[1] if we had modified it. */
2703fe401a5SEd Maste 	if (arcmd != NULL) {
2713fe401a5SEd Maste 		argv[1] = argv1_saved;
2723fe401a5SEd Maste 		free(arcmd);
2733fe401a5SEd Maste 		arcmd = argv1_saved = NULL;
2743fe401a5SEd Maste 	}
2753fe401a5SEd Maste 
2763fe401a5SEd Maste 	argv += optind;
2773fe401a5SEd Maste 	argc -= optind;
2783fe401a5SEd Maste 
2793fe401a5SEd Maste 	if (*argv == NULL && bsdar->mode != 'M')
2803fe401a5SEd Maste 		bsdar_usage();
2813fe401a5SEd Maste 
2823fe401a5SEd Maste 	if (bsdar->options & AR_A && bsdar->options & AR_B)
2833fe401a5SEd Maste 		bsdar_errc(bsdar, 0,
2843fe401a5SEd Maste 		    "only one of -a and -[bi] options allowed");
2853fe401a5SEd Maste 
2863fe401a5SEd Maste 	if (bsdar->options & AR_J && bsdar->options & AR_Z)
2873fe401a5SEd Maste 		bsdar_errc(bsdar, 0,
2883fe401a5SEd Maste 		    "only one of -j and -z options allowed");
2893fe401a5SEd Maste 
2903fe401a5SEd Maste 	if (bsdar->options & AR_S && bsdar->options & AR_SS)
2913fe401a5SEd Maste 		bsdar_errc(bsdar, 0,
2923fe401a5SEd Maste 		    "only one of -s and -S options allowed");
2933fe401a5SEd Maste 
2943fe401a5SEd Maste 	if (bsdar->options & (AR_A | AR_B)) {
2953fe401a5SEd Maste 		if (*argv == NULL)
2963fe401a5SEd Maste 			bsdar_errc(bsdar, 0,
2973fe401a5SEd Maste 			    "no position operand specified");
2983fe401a5SEd Maste 		if ((bsdar->posarg = basename(*argv)) == NULL)
2993fe401a5SEd Maste 			bsdar_errc(bsdar, errno,
3003fe401a5SEd Maste 			    "basename failed");
3013fe401a5SEd Maste 		argc--;
3023fe401a5SEd Maste 		argv++;
3033fe401a5SEd Maste 	}
3043fe401a5SEd Maste 
3053fe401a5SEd Maste 	if (bsdar->options & AR_A)
3063fe401a5SEd Maste 		only_mode(bsdar, "-a", "mqr");
3073fe401a5SEd Maste 	if (bsdar->options & AR_B)
3083fe401a5SEd Maste 		only_mode(bsdar, "-b", "mqr");
3093fe401a5SEd Maste 	if (bsdar->options & AR_C)
3103fe401a5SEd Maste 		only_mode(bsdar, "-c", "qr");
3113fe401a5SEd Maste 	if (bsdar->options & AR_CC)
3123fe401a5SEd Maste 		only_mode(bsdar, "-C", "x");
3133fe401a5SEd Maste 	if (bsdar->options & AR_D)
3143fe401a5SEd Maste 		only_mode(bsdar, "-D", "qr");
3153fe401a5SEd Maste 	if (bsdar->options & AR_O)
3163fe401a5SEd Maste 		only_mode(bsdar, "-o", "x");
3173fe401a5SEd Maste 	if (bsdar->options & AR_SS)
3183fe401a5SEd Maste 		only_mode(bsdar, "-S", "mqr");
3193fe401a5SEd Maste 	if (bsdar->options & AR_U)
3203fe401a5SEd Maste 		only_mode(bsdar, "-u", "qrx");
3213fe401a5SEd Maste 
3223fe401a5SEd Maste 	if (bsdar->mode == 'M') {
3233fe401a5SEd Maste 		ar_mode_script(bsdar);
3243fe401a5SEd Maste 		exit(EXIT_SUCCESS);
3253fe401a5SEd Maste 	}
3263fe401a5SEd Maste 
3273fe401a5SEd Maste 	if ((bsdar->filename = *argv) == NULL)
3283fe401a5SEd Maste 		bsdar_usage();
3293fe401a5SEd Maste 
3303fe401a5SEd Maste 	bsdar->argc = --argc;
3313fe401a5SEd Maste 	bsdar->argv = ++argv;
3323fe401a5SEd Maste 
3333fe401a5SEd Maste 	if ((!bsdar->mode || strchr("ptx", bsdar->mode)) &&
3343fe401a5SEd Maste 	    bsdar->options & AR_S) {
335*ae500c1fSEd Maste 		exitcode = ar_write_archive(bsdar, 's');
3363fe401a5SEd Maste 		if (!bsdar->mode)
337*ae500c1fSEd Maste 			exit(exitcode);
3383fe401a5SEd Maste 	}
3393fe401a5SEd Maste 
3403fe401a5SEd Maste 	switch(bsdar->mode) {
3413fe401a5SEd Maste 	case 'd': case 'm': case 'q': case 'r':
342*ae500c1fSEd Maste 		exitcode = ar_write_archive(bsdar, bsdar->mode);
3433fe401a5SEd Maste 		break;
3443fe401a5SEd Maste 
3453fe401a5SEd Maste 	case 'p': case 't': case 'x':
346*ae500c1fSEd Maste 		exitcode = ar_read_archive(bsdar, bsdar->mode);
3473fe401a5SEd Maste 		break;
3483fe401a5SEd Maste 	default:
3493fe401a5SEd Maste 		bsdar_usage();
3503fe401a5SEd Maste 		/* NOTREACHED */
3513fe401a5SEd Maste 	}
3523fe401a5SEd Maste 
353*ae500c1fSEd Maste 	for (i = 0; i < bsdar->argc; i++) {
354*ae500c1fSEd Maste 		if (bsdar->argv[i] != NULL) {
3553fe401a5SEd Maste 			bsdar_warnc(bsdar, 0, "%s: not found in archive",
3563fe401a5SEd Maste 			    bsdar->argv[i]);
357*ae500c1fSEd Maste 			exitcode = EXIT_FAILURE;
358*ae500c1fSEd Maste 		}
359*ae500c1fSEd Maste 	}
3603fe401a5SEd Maste 
361*ae500c1fSEd Maste 	exit(exitcode);
3623fe401a5SEd Maste }
3633fe401a5SEd Maste 
3643fe401a5SEd Maste static void
set_mode(struct bsdar * bsdar,char opt)3653fe401a5SEd Maste set_mode(struct bsdar *bsdar, char opt)
3663fe401a5SEd Maste {
3673fe401a5SEd Maste 
3683fe401a5SEd Maste 	if (bsdar->mode != '\0' && bsdar->mode != opt)
3693fe401a5SEd Maste 		bsdar_errc(bsdar, 0, "Can't specify both -%c and -%c",
3703fe401a5SEd Maste 		    opt, bsdar->mode);
3713fe401a5SEd Maste 	bsdar->mode = opt;
3723fe401a5SEd Maste }
3733fe401a5SEd Maste 
3743fe401a5SEd Maste static void
only_mode(struct bsdar * bsdar,const char * opt,const char * valid_modes)3753fe401a5SEd Maste only_mode(struct bsdar *bsdar, const char *opt, const char *valid_modes)
3763fe401a5SEd Maste {
3773fe401a5SEd Maste 
3783fe401a5SEd Maste 	if (strchr(valid_modes, bsdar->mode) == NULL)
3793fe401a5SEd Maste 		bsdar_errc(bsdar, 0, "Option %s is not permitted in mode -%c",
3803fe401a5SEd Maste 		    opt, bsdar->mode);
3813fe401a5SEd Maste }
3823fe401a5SEd Maste 
3833fe401a5SEd Maste #define	AR_USAGE_MESSAGE	"\
3843fe401a5SEd Maste Usage: %s <command> [options] archive file...\n\
3853fe401a5SEd Maste   Manage archives.\n\n\
3863fe401a5SEd Maste   Where <command> is one of:\n\
3873fe401a5SEd Maste   -d            Delete members from the archive.\n\
3883fe401a5SEd Maste   -m            Move archive members within the archive.\n\
3893fe401a5SEd Maste   -p            Write the contents of members to standard output.\n\
3903fe401a5SEd Maste   -q            Append files to an archive.\n\
3913fe401a5SEd Maste   -r            Replace (add) files to an archive.\n\
3923fe401a5SEd Maste   -s            Add an archive symbol to an archive.\n\
3933fe401a5SEd Maste   -t            List files in an archive.\n\
3943fe401a5SEd Maste   -x            Extract members from an archive.\n\
3953fe401a5SEd Maste   -M            Execute MRI librarian commands.\n\
3963fe401a5SEd Maste   -V            Print a version identifier and exit.\n\n\
3973fe401a5SEd Maste   Options:\n\
3983fe401a5SEd Maste   -a MEMBER     Add members after the specified member.\n\
3993fe401a5SEd Maste   -b MEMBER | -i MEMBER\n\
4003fe401a5SEd Maste                 Add members before the specified member.\n\
4013fe401a5SEd Maste   -c            Do not print a message when creating a new archive.\n\
4023fe401a5SEd Maste   -f | -T       Only use the first fifteen characters of the member name.\n\
4033fe401a5SEd Maste   -j            (This option is accepted, but is ignored).\n\
4043fe401a5SEd Maste   -l            (This option is accepted, but is ignored).\n\
4053fe401a5SEd Maste   -o            Preserve modification times when extracting members.\n\
4063fe401a5SEd Maste   -u            Conditionally update or extract members.\n\
4073fe401a5SEd Maste   -v            Be verbose.\n\
4083fe401a5SEd Maste   -z            (This option is accepted, but is ignored).\n\
4093fe401a5SEd Maste   -C            Do not overwrite existing files in the file system.\n\
4103fe401a5SEd Maste   -D            Use fixed metadata, for consistent archive checksums.\n\
4113fe401a5SEd Maste   -F FORMAT | --flavor=FORMAT\n\
4123fe401a5SEd Maste                 Create archives with the specified format.\n\
413656f49f8SEd Maste   -S            Do not generate an archive symbol table.\n\
414839529caSEd Maste   -U            Use original metadata for archive members.\n"
4153fe401a5SEd Maste 
4163fe401a5SEd Maste static void
bsdar_usage(void)4173fe401a5SEd Maste bsdar_usage(void)
4183fe401a5SEd Maste {
4193fe401a5SEd Maste 	(void) fprintf(stderr, AR_USAGE_MESSAGE, ELFTC_GETPROGNAME());
4203fe401a5SEd Maste 	exit(EXIT_FAILURE);
4213fe401a5SEd Maste }
4223fe401a5SEd Maste 
4233fe401a5SEd Maste #define	RANLIB_USAGE_MESSAGE	"\
4243fe401a5SEd Maste Usage: %s [options] archive...\n\
4253fe401a5SEd Maste   Update or create archive symbol tables.\n\n\
4263fe401a5SEd Maste   Options:\n\
4273fe401a5SEd Maste   -t              (This option is accepted, but ignored).\n\
4283fe401a5SEd Maste   -D              Use fixed metadata, for consistent archive checksums.\n\
429656f49f8SEd Maste   -U              Use original metadata, for unique archive checksums.\n\
4303fe401a5SEd Maste   -V              Print a version identifier and exit.\n"
4313fe401a5SEd Maste 
4323fe401a5SEd Maste static void
ranlib_usage(void)4333fe401a5SEd Maste ranlib_usage(void)
4343fe401a5SEd Maste {
4353fe401a5SEd Maste 	(void)fprintf(stderr, RANLIB_USAGE_MESSAGE, ELFTC_GETPROGNAME());
4363fe401a5SEd Maste 	exit(EXIT_FAILURE);
4373fe401a5SEd Maste }
4383fe401a5SEd Maste 
4393fe401a5SEd Maste static void
bsdar_version(void)4403fe401a5SEd Maste bsdar_version(void)
4413fe401a5SEd Maste {
4423fe401a5SEd Maste 	(void)printf("%s (%s, %s)\n", ELFTC_GETPROGNAME(), archive_version_string(),
4433fe401a5SEd Maste 	    elftc_version());
4443fe401a5SEd Maste 	exit(EXIT_SUCCESS);
4453fe401a5SEd Maste }
446