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