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