1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* Copyright (c) 1988 AT&T */ 23 /* All Rights Reserved */ 24 25 /* 26 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 27 * Use is subject to license terms. 28 */ 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 #include "inc.h" 33 #include "extern.h" 34 35 static char *arnam; 36 37 /* 38 * Function prototypes 39 */ 40 static void setup(int, char **, Cmd_info *); 41 static void setcom(Cmd_info *, int (*)()); 42 static void usage(void); 43 static void sigexit(int sig); 44 static int notfound(Cmd_info *); 45 static void check_swap(); 46 47 #define OPTSTR ":a:b:i:vucsrdxtplmqVCTzM" 48 49 int 50 main(int argc, char **argv) 51 { 52 int i; 53 int fd; 54 Cmd_info *cmd_info; 55 int ret; 56 char *new = NULL; 57 char *data = NULL; 58 59 (void) setlocale(LC_ALL, ""); 60 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 61 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 62 #endif 63 (void) textdomain(TEXT_DOMAIN); 64 65 for (i = 0; signum[i]; i++) 66 if (signal(signum[i], SIG_IGN) != SIG_IGN) 67 (void) signal(signum[i], sigexit); 68 /* 69 * Initialize cmd_info 70 */ 71 cmd_info = (Cmd_info *)calloc(1, sizeof (Cmd_info)); 72 if (cmd_info == NULL) { 73 error_message(MALLOC_ERROR, PLAIN_ERROR, (char *)0); 74 exit(1); 75 } 76 77 if (argc < 2) 78 usage(); 79 80 /* 81 * Option handling. 82 */ 83 if (argv[1][0] != '-') { 84 new = (char *)malloc(strlen(argv[1]) + 2); 85 if (new == NULL) { 86 error_message(MALLOC_ERROR, PLAIN_ERROR, (char *)0); 87 exit(1); 88 } 89 (void) strcpy(new, "-"); 90 (void) strcat(new, argv[1]); 91 argv[1] = new; 92 } 93 setup(argc, argv, cmd_info); 94 95 /* 96 * Check SWAP 97 */ 98 if (opt_FLAG((cmd_info), z_FLAG)) 99 check_swap(); 100 101 if (cmd_info->comfun == 0) { 102 if (!(opt_FLAG((cmd_info), d_FLAG) || 103 opt_FLAG(cmd_info, r_FLAG) || 104 opt_FLAG(cmd_info, q_FLAG) || opt_FLAG(cmd_info, t_FLAG) || 105 opt_FLAG(cmd_info, p_FLAG) || opt_FLAG(cmd_info, m_FLAG) || 106 opt_FLAG(cmd_info, x_FLAG))) { 107 error_message(USAGE_01_ERROR, PLAIN_ERROR, (char *)0); 108 exit(1); 109 } 110 } 111 112 cmd_info->modified = opt_FLAG(cmd_info, s_FLAG); 113 fd = getaf(cmd_info); 114 115 if ((fd == -1) && 116 (opt_FLAG(cmd_info, d_FLAG) || opt_FLAG(cmd_info, t_FLAG) || 117 opt_FLAG(cmd_info, p_FLAG) || opt_FLAG(cmd_info, m_FLAG) || 118 opt_FLAG(cmd_info, x_FLAG) || 119 (opt_FLAG(cmd_info, r_FLAG) && (opt_FLAG(cmd_info, a_FLAG) || 120 opt_FLAG(cmd_info, b_FLAG))))) { 121 error_message(NOT_FOUND_01_ERROR, 122 PLAIN_ERROR, (char *)0, arnam); 123 exit(1); 124 } 125 126 (*cmd_info->comfun)(cmd_info); 127 #ifdef BROWSER 128 sb_data.fd = NULL; 129 sb_data.failed = 0; 130 #endif 131 if (cmd_info->modified) { 132 data = writefile(cmd_info); 133 } else 134 (void) close(fd); 135 #ifdef BROWSER 136 sbfocus_close(&sb_data); 137 #endif 138 139 ret = notfound(cmd_info); 140 141 /* 142 * Check SWAP 143 */ 144 if (opt_FLAG((cmd_info), z_FLAG)) 145 check_swap(); 146 147 free(data); 148 free(new); 149 free(cmd_info); 150 return (ret); 151 152 } 153 154 /* 155 * Option hadning function. 156 * Using getopt(), following xcu4 convention. 157 */ 158 static void 159 setup(int argc, char *argv[], Cmd_info *cmd_info) 160 { 161 int Vflag = 0; 162 int c; 163 int usage_err = 0; 164 165 while ((c = getopt(argc, argv, OPTSTR)) != -1) { 166 switch (c) { 167 case 'a': /* position after named archive member file */ 168 cmd_info->opt_flgs |= a_FLAG; 169 cmd_info->ponam = trim(optarg); 170 break; 171 case 'b': /* position before named archive member file */ 172 case 'i': /* position before named archive member: same as b */ 173 cmd_info->opt_flgs |= b_FLAG; 174 cmd_info->ponam = trim(optarg); 175 break; 176 case 'c': /* supress messages */ 177 cmd_info->opt_flgs |= c_FLAG; 178 break; 179 case 'd': 180 /* 181 * key operation: 182 * delete files from the archive 183 */ 184 setcom(cmd_info, dcmd); 185 cmd_info->opt_flgs |= d_FLAG; 186 break; 187 case 'l': /* temporary directory */ 188 cmd_info->opt_flgs |= l_FLAG; 189 break; 190 case 'm': 191 /* 192 * key operation: 193 * move files to end of the archive 194 * or as indicated by position flag 195 */ 196 setcom(cmd_info, mcmd); 197 cmd_info->opt_flgs |= m_FLAG; 198 break; 199 case 'p': 200 /* 201 * key operation: 202 * print files in the archive 203 */ 204 setcom(cmd_info, pcmd); 205 cmd_info->opt_flgs |= p_FLAG; 206 break; 207 case 'q': 208 /* 209 * key operation: 210 * quickly append files to end of the archive 211 */ 212 setcom(cmd_info, qcmd); 213 cmd_info->opt_flgs |= q_FLAG; 214 break; 215 case 'r': 216 /* 217 * key operation: 218 * replace or add files to the archive 219 */ 220 setcom(cmd_info, rcmd); 221 cmd_info->opt_flgs |= r_FLAG; 222 break; 223 case 's': /* force symbol table regeneration */ 224 cmd_info->opt_flgs |= s_FLAG; 225 break; 226 case 't': 227 /* 228 * key operation: 229 * print table of contents 230 */ 231 setcom(cmd_info, tcmd); 232 cmd_info->opt_flgs |= t_FLAG; 233 break; 234 case 'u': /* update: change archive dependent on file dates */ 235 cmd_info->opt_flgs |= u_FLAG; 236 break; 237 case 'v': /* verbose */ 238 cmd_info->opt_flgs |= v_FLAG; 239 break; 240 case 'x': 241 /* 242 * key operation: 243 * extract files from the archive 244 */ 245 setcom(cmd_info, xcmd); 246 cmd_info->opt_flgs |= x_FLAG; 247 break; 248 case 'z': 249 cmd_info->opt_flgs |= z_FLAG; 250 break; 251 case 'V': 252 /* 253 * print version information. 254 * adjust command line access accounting 255 */ 256 if (Vflag == 0) { 257 (void) fprintf(stderr, "ar: %s %s\n", 258 (const char *)SGU_PKG, 259 (const char *)SGU_REL); 260 Vflag++; 261 } 262 break; 263 case 'C': 264 cmd_info->OPT_flgs |= C_FLAG; 265 break; 266 case 'M': 267 cmd_info->OPT_flgs |= M_FLAG; 268 break; 269 case 'T': 270 cmd_info->OPT_flgs |= T_FLAG; 271 break; 272 case ':': 273 error_message(USAGE_02_ERROR, 274 PLAIN_ERROR, (char *)0, optopt); 275 usage_err++; 276 break; 277 case '?': 278 error_message(USAGE_03_ERROR, 279 PLAIN_ERROR, (char *)0, optopt); 280 usage_err++; 281 break; 282 } 283 } 284 285 if (usage_err || argc - optind < 1) 286 usage(); 287 288 cmd_info->arnam = arnam = argv[optind]; 289 cmd_info->namv = &argv[optind+1]; 290 cmd_info->namc = argc - optind - 1; 291 } 292 293 294 /* 295 * Set the function to be called to do the key operation. 296 * Check that only one key is indicated. 297 */ 298 static void 299 setcom(Cmd_info *cmd_info, int (*fun)()) 300 { 301 if (cmd_info->comfun != 0) { 302 error_message(USAGE_04_ERROR, PLAIN_ERROR, (char *)0); 303 exit(1); 304 } 305 cmd_info->comfun = fun; 306 } 307 308 static void 309 usage(void) 310 { 311 (void) fprintf(stderr, gettext( 312 "usage: ar -d[-vV] archive file ...\n" 313 " ar -m[-abivV] [posname] archive file ...\n" 314 " ar -p[-vV][-s] archive [file ...]\n" 315 " ar -q[-cuvV] [-abi] [posname] [file ...]\n" 316 " ar -r[-cuvV] [-abi] [posname] [file ...]\n" 317 " ar -t[-vV][-s] archive [file ...]\n" 318 " ar -x[-vV][-sCT] archive [file ...]\n")); 319 exit(1); 320 } 321 322 /*ARGSUSED0*/ 323 static void 324 sigexit(int sig) 325 { 326 exit(100); 327 } 328 329 /* tells the user which of the listed files were not found in the archive */ 330 331 static int 332 notfound(Cmd_info *cmd_info) 333 { 334 int i, n; 335 336 n = 0; 337 for (i = 0; i < cmd_info->namc; i++) 338 if (cmd_info->namv[i]) { 339 error_message(NOT_FOUND_03_ERROR, 340 PLAIN_ERROR, (char *)0, cmd_info->namv[i]); 341 n++; 342 } 343 return (n); 344 } 345 346 /* 347 * Debugging info 348 */ 349 static void 350 check_swap(void) 351 { 352 (void) system("/usr/sbin/swap -s"); 353 } 354