1/* 2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. 3 * 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. 12 * 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. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 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 $ */ 25 26/*- 27 * Copyright (c) 1990, 1993, 1994 28 * The Regents of the University of California. All rights reserved. 29 * 30 * This code is derived from software contributed to Berkeley by 31 * Hugh Smith at The University of Guelph. 32 * 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. 48 * 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. 60 */ 61 62#ifndef lint 63#if 0 64static char copyright[] = 65"@(#) Copyright (c) 1990, 1993, 1994\n\ 66 The Regents of the University of California. All rights reserved.\n"; 67static char sccsid[] = "@(#)ar.c 8.3 (Berkeley) 4/2/94"; 68static char rcsid[] = "$OpenBSD: ar.c,v 1.3 1997/01/15 23:42:11 millert Exp $"; 69#endif 70#endif /* not lint */ 71 72#include <sys/param.h> 73 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> 82 83#include "archive.h" 84#include "extern.h" 85#include "stuff/execute.h" 86#include "stuff/unix_standard_mode.h" 87 88CHDR chdr; 89u_int options; 90char *archive, *envtmp, *posarg, *posname; 91static void badoptions __P((char *)); 92static void usage __P((void)); 93char *progname; 94 95/* 96 * main -- 97 * main basically uses getopt to parse options and calls the appropriate 98 * functions. Some hacks that let us be backward compatible with 4.3 ar 99 * option parsing and sanity checking. 100 */ 101int 102main(argc, argv) 103 int argc; 104 char **argv; 105{ 106 int c, retval, verbose, run_ranlib; 107 char *p; 108 int (*fcall) __P((char **)); 109 110 fcall = 0; 111 verbose = 0; 112 progname = argv[0]; 113 run_ranlib = 1; 114 115 if (argc < 3) 116 usage(); 117 118 /* 119 * Historic versions didn't require a '-' in front of the options. 120 * Fix it, if necessary. 121 */ 122 if (*argv[1] != '-') { 123 if (!(p = malloc((u_int)(strlen(argv[1]) + 2)))) 124 err(1, NULL); 125 *p = '-'; 126 (void)strcpy(p + 1, argv[1]); 127 argv[1] = p; 128 } 129 130 /* 131 * For Rhapsody Premier the option to use long member names, -L, is the 132 * default. The compiler tools for Rhapsody Premier do understand 133 * extended format #1. The new option -L allows ar to use the extended 134 * format and the old -T option causes the truncation of names. 135 */ 136 while ((c = getopt(argc, argv, "abcdilLmopqrSsTtuVvx")) != -1) { 137 switch(c) { 138 case 'a': 139 options |= AR_A; 140 break; 141 case 'b': 142 case 'i': 143 options |= AR_B; 144 break; 145 case 'c': 146 options |= AR_C; 147 break; 148 case 'd': 149 options |= AR_D; 150 fcall = delete; 151 break; 152 case 'l': /* not documented, compatibility only */ 153 envtmp = "."; 154 break; 155 case 'L': 156 options &= ~AR_TR; 157 break; 158 case 'm': 159 options |= AR_M; 160 fcall = move; 161 break; 162 case 'o': 163 options |= AR_O; 164 break; 165 case 'p': 166 options |= AR_P; 167 fcall = print; 168 break; 169 case 'q': 170 options |= AR_Q; 171 fcall = append; 172 break; 173 case 'r': 174 options |= AR_R; 175 fcall = replace; 176 break; 177 case 's': 178 options |= AR_S; 179 break; 180 case 'S': 181 options &= ~AR_S; 182 run_ranlib = 0; 183 break; 184 case 'T': 185 options |= AR_TR; 186 break; 187 case 't': 188 options |= AR_T; 189 fcall = contents; 190 break; 191 case 'u': 192 options |= AR_U; 193 break; 194 case 'V': 195 verbose = 1; 196 break; 197 case 'v': 198 options |= AR_V; 199 break; 200 case 'x': 201 options |= AR_X; 202 fcall = extract; 203 break; 204 default: 205 usage(); 206 } 207 } 208 209 argv += optind; 210 argc -= optind; 211 212 /* One of -dmpqrtsx required. */ 213 if (!(options & (AR_D|AR_M|AR_P|AR_Q|AR_R|AR_S|AR_T|AR_X))) { 214 warnx("one of options -dmpqrtsx is required"); 215 usage(); 216 } 217 /* Only one of -a and -bi allowed. */ 218 if (options & AR_A && options & AR_B) { 219 warnx("only one of -a and -[bi] options allowed"); 220 usage(); 221 } 222 /* -ab require a position argument. */ 223 if (options & (AR_A|AR_B)) { 224 if (!(posarg = *argv++)) { 225 warnx("no position operand specified"); 226 usage(); 227 } 228 posname = rname(posarg); 229 } 230 /* -d only valid with -Tsv. */ 231 if (options & AR_D && options & ~(AR_D|AR_TR|AR_S|AR_V)) 232 badoptions("-d"); 233 /* -m only valid with -abiTsv. */ 234 if (options & AR_M && options & ~(AR_A|AR_B|AR_M|AR_TR|AR_S|AR_V)) 235 badoptions("-m"); 236 /* -p only valid with -Tsv. */ 237 if (options & AR_P && options & ~(AR_P|AR_TR|AR_S|AR_V)) 238 badoptions("-p"); 239 /* -q only valid with -cTsv. */ 240 if (options & AR_Q && options & ~(AR_C|AR_Q|AR_TR|AR_S|AR_V)) 241 badoptions("-q"); 242 /* -r only valid with -abcuTsv. */ 243 if (options & AR_R && options & ~(AR_A|AR_B|AR_C|AR_R|AR_U|AR_TR|AR_S|AR_V)) 244 badoptions("-r"); 245 /* -t only valid with -Tsv. */ 246 if (options & AR_T && options & ~(AR_T|AR_TR|AR_S|AR_V)) 247 badoptions("-t"); 248 /* -x only valid with -ouTsv. */ 249 if (options & AR_X && options & ~(AR_O|AR_U|AR_TR|AR_S|AR_V|AR_X)) 250 badoptions("-x"); 251 252 if (!(archive = *argv++)) { 253 warnx("no archive specified"); 254 usage(); 255 } 256 257 /* -dmqr require a list of archive elements. */ 258 if (options & (AR_D|AR_M|AR_Q|AR_R) && !*argv) { 259 warnx("no archive members specified"); 260 usage(); 261 } 262 263 if(fcall != 0){ 264 retval = (*fcall)(argv); 265 if(retval != EXIT_SUCCESS || 266 ((options & AR_S) != AR_S && 267 (get_unix_standard_mode() == FALSE || 268 archive_opened_for_writing == 0))) 269 exit(retval); 270 } 271 272 /* 273 * The default is to run ranlib(1) for UNIX conformance. But if the -S 274 * option is specified by the user we don't run it. 275 */ 276 if(run_ranlib){ 277 /* run ranlib -f or -q on the archive */ 278 reset_execute_list(); 279 add_execute_list_with_prefix("ranlib"); 280 if(options & AR_S) 281 add_execute_list("-f"); 282 else 283 add_execute_list("-q"); 284 add_execute_list(archive); 285 if(execute_list(verbose) == 0){ 286 (void)fprintf(stderr, "%s: internal ranlib command failed\n", 287 progname); 288 exit(EXIT_FAILURE); 289 } 290 } 291 exit(EXIT_SUCCESS); 292} 293 294static void 295badoptions(arg) 296 char *arg; 297{ 298 299 warnx("illegal option combination for %s", arg); 300 usage(); 301} 302 303static void 304usage() 305{ 306 307 (void)fprintf(stderr, "usage: ar -d [-TLsv] archive file ...\n"); 308 (void)fprintf(stderr, "\tar -m [-TLsv] archive file ...\n"); 309 (void)fprintf(stderr, "\tar -m [-abiTLsv] position archive file ...\n"); 310 (void)fprintf(stderr, "\tar -p [-TLsv] archive [file ...]\n"); 311 (void)fprintf(stderr, "\tar -q [-cTLsv] archive file ...\n"); 312 (void)fprintf(stderr, "\tar -r [-cuTLsv] archive file ...\n"); 313 (void)fprintf(stderr, "\tar -r [-abciuTLsv] position archive file ...\n"); 314 (void)fprintf(stderr, "\tar -t [-TLsv] archive [file ...]\n"); 315 (void)fprintf(stderr, "\tar -x [-ouTLsv] archive [file ...]\n"); 316 exit(1); 317} 318