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: * Redistribution and use in source and binary forms, with or without 9: * modification, are permitted provided that the following conditions 10: * are met: 11: * 1. Redistributions of source code must retain the above copyright 12: * notice, this list of conditions and the following disclaimer. 13: * 2. Redistributions in binary form must reproduce the above copyright 14: * notice, this list of conditions and the following disclaimer in the 15: * documentation and/or other materials provided with the distribution. 16: * 3. All advertising materials mentioning features or use of this software 17: * must display the following acknowledgement: 18: * This product includes software developed by the University of 19: * California, Berkeley and its contributors. 20: * 4. Neither the name of the University nor the names of its contributors 21: * may be used to endorse or promote products derived from this software 22: * without specific prior written permission. 23: * 24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34: * SUCH DAMAGE. 35: */ 36: 37: #if defined(DOSCCS) && !defined(lint) 38: char copyright[] = 39: "@(#) Copyright (c) 1990 The Regents of the University of California.\n\ 40: All rights reserved.\n"; 41: 42: static char sccsid[] = "@(#)ar.c 5.11 (Berkeley) 3/21/91"; 43: #endif 44: 45: #include <sys/param.h> 46: #include <sys/errno.h> 47: #include <sys/dir.h> 48: #include <stdio.h> 49: #include <ar.h> 50: #include <string.h> 51: #include <paths.h> 52: #include "archive.h" 53: #include "extern.h" 54: 55: extern char *malloc(); 56: extern int errno; 57: 58: CHDR chdr; 59: u_int options; 60: char *archive, *envtmp, *posarg, *posname; 61: static void badoptions(), usage(); 62: 63: /* 64: * main -- 65: * main basically uses getopt to parse options and calls the appropriate 66: * functions. Some hacks that let us be backward compatible with 4.3 ar 67: * option parsing and sanity checking. 68: */ 69: main(argc, argv) 70: int argc; 71: char **argv; 72: { 73: extern int optind; 74: int c; 75: char *p; 76: int (*fcall)(), append(), contents(), delete(), extract(), 77: move(), print(), replace(); 78: 79: if (argc < 3) 80: usage(); 81: 82: /* 83: * Historic versions didn't require a '-' in front of the options. 84: * Fix it, if necessary. 85: */ 86: if (*argv[1] != '-') { 87: if (!(p = malloc((u_int)(strlen(argv[1]) + 2)))) { 88: (void)fprintf(stderr, "ar: %s.\n", strerror(errno)); 89: exit(1); 90: } 91: *p = '-'; 92: (void)strcpy(p + 1, argv[1]); 93: argv[1] = p; 94: } 95: 96: while ((c = getopt(argc, argv, "abcdilmopqrTtuvx")) != EOF) { 97: switch(c) { 98: case 'a': 99: options |= AR_A; 100: break; 101: case 'b': 102: case 'i': 103: options |= AR_B; 104: break; 105: case 'c': 106: options |= AR_C; 107: break; 108: case 'd': 109: options |= AR_D; 110: fcall = delete; 111: break; 112: case 'l': /* not documented, compatibility only */ 113: envtmp = "."; 114: break; 115: case 'm': 116: options |= AR_M; 117: fcall = move; 118: break; 119: case 'o': 120: options |= AR_O; 121: break; 122: case 'p': 123: options |= AR_P; 124: fcall = print; 125: break; 126: case 'q': 127: options |= AR_Q; 128: fcall = append; 129: break; 130: case 'r': 131: options |= AR_R; 132: fcall = replace; 133: break; 134: case 'T': 135: options |= AR_TR; 136: break; 137: case 't': 138: options |= AR_T; 139: fcall = contents; 140: break; 141: case 'u': 142: options |= AR_U; 143: break; 144: case 'v': 145: options |= AR_V; 146: break; 147: case 'x': 148: options |= AR_X; 149: fcall = extract; 150: break; 151: default: 152: usage(); 153: } 154: } 155: 156: argv += optind; 157: argc -= optind; 158: 159: /* One of -dmpqrtx required. */ 160: if (!(options & (AR_D|AR_M|AR_P|AR_Q|AR_R|AR_T|AR_X))) { 161: (void)fprintf(stderr, 162: "ar: one of options -dmpqrtx is required.\n"); 163: usage(); 164: } 165: /* Only one of -a and -bi allowed. */ 166: if (options & AR_A && options & AR_B) { 167: (void)fprintf(stderr, 168: "ar: only one of -a and -[bi] options allowed.\n"); 169: usage(); 170: } 171: /* -ab require a position argument. */ 172: if (options & (AR_A|AR_B)) { 173: if (!(posarg = *argv++)) { 174: (void)fprintf(stderr, 175: "ar: no position operand specified.\n"); 176: usage(); 177: } 178: posname = rname(posarg); 179: } 180: /* -d only valid with -Tv. */ 181: if (options & AR_D && options & ~(AR_D|AR_TR|AR_V)) 182: badoptions("-d"); 183: /* -m only valid with -abiTv. */ 184: if (options & AR_M && options & ~(AR_A|AR_B|AR_M|AR_TR|AR_V)) 185: badoptions("-m"); 186: /* -p only valid with -Tv. */ 187: if (options & AR_P && options & ~(AR_P|AR_TR|AR_V)) 188: badoptions("-p"); 189: /* -q only valid with -cTv. */ 190: if (options & AR_Q && options & ~(AR_C|AR_Q|AR_TR|AR_V)) 191: badoptions("-q"); 192: /* -r only valid with -abcuTv. */ 193: if (options & AR_R && options & ~(AR_A|AR_B|AR_C|AR_R|AR_U|AR_TR|AR_V)) 194: badoptions("-r"); 195: /* -t only valid with -Tv. */ 196: if (options & AR_T && options & ~(AR_T|AR_TR|AR_V)) 197: badoptions("-t"); 198: /* -x only valid with -ouTv. */ 199: if (options & AR_X && options & ~(AR_O|AR_U|AR_TR|AR_V|AR_X)) 200: badoptions("-x"); 201: 202: if (!(archive = *argv++)) { 203: (void)fprintf(stderr, "ar: no archive specified.\n"); 204: usage(); 205: } 206: 207: /* -dmqr require a list of archive elements. */ 208: if (options & (AR_D|AR_M|AR_Q|AR_R) && !*argv) { 209: (void)fprintf(stderr, "ar: no archive members specified.\n"); 210: usage(); 211: } 212: 213: exit((*fcall)(argv)); 214: } 215: 216: static void 217: badoptions(arg) 218: char *arg; 219: { 220: (void)fprintf(stderr, 221: "ar: illegal option combination for %s.\n", arg); 222: usage(); 223: } 224: 225: static void 226: usage() 227: { 228: (void)fprintf(stderr, "usage: ar -d [-Tv] archive file ...\n"); 229: (void)fprintf(stderr, "\tar -m [-Tv] archive file ...\n"); 230: (void)fprintf(stderr, "\tar -m [-abiTv] position archive file ...\n"); 231: (void)fprintf(stderr, "\tar -p [-Tv] archive [file ...]\n"); 232: (void)fprintf(stderr, "\tar -q [-cTv] archive file ...\n"); 233: (void)fprintf(stderr, "\tar -r [-cuTv] archive file ...\n"); 234: (void)fprintf(stderr, "\tar -r [-abciuTv] position archive file ...\n"); 235: (void)fprintf(stderr, "\tar -t [-Tv] archive [file ...]\n"); 236: (void)fprintf(stderr, "\tar -x [-ouTv] archive [file ...]\n"); 237: exit(1); 238: }