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