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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* Copyright (c) 1988 AT&T */ 22 /* All Rights Reserved */ 23 24 /* 25 * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. 26 */ 27 28 #include "inc.h" 29 #include "conv.h" 30 31 /* 32 * Forward declarations 33 */ 34 static void setup(int, char **, Cmd_info *); 35 static void setcom(Cmd_info *, Cmd_func); 36 static void usage(void); 37 static void sigexit(int sig); 38 static int notfound(Cmd_info *); 39 static void check_swap(); 40 41 const char * 42 _ar_msg(Msg mid) 43 { 44 return (gettext(MSG_ORIG(mid))); 45 } 46 47 48 void 49 establish_sighandler(void (*handler)()) 50 { 51 static const int signum[] = {SIGHUP, SIGINT, SIGQUIT, 0}; 52 int i; 53 54 if (handler == SIG_IGN) { 55 /* Ignore all the specified signals */ 56 for (i = 0; signum[i]; i++) 57 (void) signal(signum[i], SIG_IGN); 58 59 } else { 60 /* 61 * Set any signal that doesn't default to being ignored 62 * to our signal handler. 63 */ 64 for (i = 0; signum[i]; i++) 65 if (signal(signum[i], SIG_IGN) != SIG_IGN) 66 (void) signal(signum[i], handler); 67 } 68 } 69 70 int 71 main(int argc, char **argv, char *envp[]) 72 { 73 int fd; 74 Cmd_info *cmd_info; 75 int ret; 76 char *new = NULL; 77 78 #ifndef XPG4 79 /* 80 * Check for a binary that better fits this architecture. 81 */ 82 (void) conv_check_native(argv, envp); 83 #endif 84 85 /* 86 * Establish locale. 87 */ 88 (void) setlocale(LC_ALL, MSG_ORIG(MSG_STR_EMPTY)); 89 (void) textdomain(MSG_ORIG(MSG_SUNW_OST_SGS)); 90 91 /* Allow a graceful exit up until we start to write an archive */ 92 establish_sighandler(sigexit); 93 94 /* 95 * Initialize cmd_info 96 */ 97 cmd_info = (Cmd_info *)calloc(1, sizeof (Cmd_info)); 98 if (cmd_info == NULL) { 99 int err = errno; 100 (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(err)); 101 exit(1); 102 } 103 104 if (argc < 2) 105 usage(); 106 107 /* 108 * Option handling. 109 */ 110 if (argv[1][0] != '-') { 111 new = (char *)malloc(strlen(argv[1]) + 2); 112 if (new == NULL) { 113 int err = errno; 114 (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), 115 strerror(err)); 116 exit(1); 117 } 118 (void) strcpy(new, MSG_ORIG(MSG_STR_HYPHEN)); 119 (void) strcat(new, argv[1]); 120 argv[1] = new; 121 } 122 setup(argc, argv, cmd_info); 123 124 /* 125 * Check SWAP 126 */ 127 if (cmd_info->opt_flgs & z_FLAG) 128 check_swap(); 129 130 if (cmd_info->comfun == NULL) { 131 if ((cmd_info->opt_flgs & (d_FLAG | r_FLAG | q_FLAG | 132 t_FLAG | p_FLAG | m_FLAG | x_FLAG)) == 0) { 133 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_01)); 134 exit(1); 135 } 136 } 137 138 cmd_info->modified = (cmd_info->opt_flgs & s_FLAG); 139 fd = getaf(cmd_info); 140 141 if ((fd == -1) && 142 (cmd_info->opt_flgs & 143 (d_FLAG | m_FLAG | p_FLAG | t_FLAG | x_FLAG)) || 144 ((cmd_info->opt_flgs & r_FLAG) && 145 (cmd_info->opt_flgs & (a_FLAG | b_FLAG)))) { 146 (void) fprintf(stderr, MSG_INTL(MSG_NOT_FOUND_AR), 147 cmd_info->arnam); 148 exit(1); 149 } 150 151 (*cmd_info->comfun)(cmd_info); 152 if (cmd_info->modified) { 153 writefile(cmd_info); 154 } else 155 (void) close(fd); 156 157 ret = notfound(cmd_info); 158 159 /* 160 * Check SWAP 161 */ 162 if (cmd_info->opt_flgs & z_FLAG) 163 check_swap(); 164 165 free(new); 166 free(cmd_info); 167 return (ret); 168 169 } 170 171 /* 172 * Option handing function. 173 * Using getopt(), following xcu4 convention. 174 */ 175 static void 176 setup(int argc, char *argv[], Cmd_info *cmd_info) 177 { 178 int Vflag = 0; 179 int c; 180 int usage_err = 0; 181 182 while ((c = getopt(argc, argv, MSG_ORIG(MSG_STR_OPTIONS))) != -1) { 183 switch (c) { 184 case 'a': /* position after named archive member file */ 185 cmd_info->opt_flgs |= a_FLAG; 186 cmd_info->ponam = trim(optarg); 187 break; 188 case 'b': /* position before named archive member file */ 189 case 'i': /* position before named archive member: same as b */ 190 cmd_info->opt_flgs |= b_FLAG; 191 cmd_info->ponam = trim(optarg); 192 break; 193 case 'c': /* supress messages */ 194 cmd_info->opt_flgs |= c_FLAG; 195 break; 196 case 'd': 197 /* 198 * key operation: 199 * delete files from the archive 200 */ 201 setcom(cmd_info, dcmd); 202 cmd_info->opt_flgs |= d_FLAG; 203 break; 204 case 'l': /* ignored */ 205 break; 206 case 'm': 207 /* 208 * key operation: 209 * move files to end of the archive 210 * or as indicated by position flag 211 */ 212 setcom(cmd_info, mcmd); 213 cmd_info->opt_flgs |= m_FLAG; 214 break; 215 case 'p': 216 /* 217 * key operation: 218 * print files in the archive 219 */ 220 setcom(cmd_info, pcmd); 221 cmd_info->opt_flgs |= p_FLAG; 222 break; 223 case 'q': 224 /* 225 * key operation: 226 * quickly append files to end of the archive 227 */ 228 setcom(cmd_info, qcmd); 229 cmd_info->opt_flgs |= q_FLAG; 230 break; 231 case 'r': 232 /* 233 * key operation: 234 * replace or add files to the archive 235 */ 236 setcom(cmd_info, rcmd); 237 cmd_info->opt_flgs |= r_FLAG; 238 break; 239 case 's': /* force symbol table regeneration */ 240 cmd_info->opt_flgs |= s_FLAG; 241 break; 242 case 'S': /* Build SYM64 symbol table */ 243 cmd_info->opt_flgs |= S_FLAG; 244 break; 245 case 't': 246 /* 247 * key operation: 248 * print table of contents 249 */ 250 setcom(cmd_info, tcmd); 251 cmd_info->opt_flgs |= t_FLAG; 252 break; 253 case 'u': /* update: change archive dependent on file dates */ 254 cmd_info->opt_flgs |= u_FLAG; 255 break; 256 case 'v': /* verbose */ 257 cmd_info->opt_flgs |= v_FLAG; 258 break; 259 case 'x': 260 /* 261 * key operation: 262 * extract files from the archive 263 */ 264 setcom(cmd_info, xcmd); 265 cmd_info->opt_flgs |= x_FLAG; 266 break; 267 case 'z': 268 cmd_info->opt_flgs |= z_FLAG; 269 break; 270 case 'V': 271 /* 272 * print version information. 273 * adjust command line access accounting 274 */ 275 if (Vflag == 0) { 276 (void) fprintf(stderr, 277 MSG_ORIG(MSG_FMT_VERSION), 278 (const char *)SGU_PKG, 279 (const char *)SGU_REL); 280 Vflag++; 281 } 282 break; 283 case 'C': 284 cmd_info->opt_flgs |= C_FLAG; 285 break; 286 case 'M': 287 /* 288 * -M was an original undocumented AT&T feature that 289 * would force the use of mmap() instead of read() 290 * for pulling file data into the process before 291 * writing it to the archive. Ignored. 292 */ 293 break; 294 case 'T': 295 cmd_info->opt_flgs |= T_FLAG; 296 break; 297 case ':': 298 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_02), optopt); 299 usage_err++; 300 break; 301 case '?': 302 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_03), optopt); 303 usage_err++; 304 break; 305 } 306 } 307 308 if (usage_err || argc - optind < 1) 309 usage(); 310 311 cmd_info->arnam = argv[optind]; 312 cmd_info->namv = &argv[optind+1]; 313 cmd_info->namc = argc - optind - 1; 314 } 315 316 317 /* 318 * Set the function to be called to do the key operation. 319 * Check that only one key is indicated. 320 */ 321 static void 322 setcom(Cmd_info *cmd_info, Cmd_func *fun) 323 { 324 if (cmd_info->comfun != 0) { 325 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_04)); 326 exit(1); 327 } 328 cmd_info->comfun = fun; 329 } 330 331 static void 332 usage(void) 333 { 334 (void) fprintf(stderr, MSG_INTL(MSG_USAGE)); 335 exit(1); 336 } 337 338 /*ARGSUSED0*/ 339 static void 340 sigexit(int sig) 341 { 342 exit(100); 343 } 344 345 /* tells the user which of the listed files were not found in the archive */ 346 347 static int 348 notfound(Cmd_info *cmd_info) 349 { 350 int i, n; 351 352 n = 0; 353 for (i = 0; i < cmd_info->namc; i++) 354 if (cmd_info->namv[i]) { 355 (void) fprintf(stderr, MSG_INTL(MSG_NOT_FOUND_FILE), 356 cmd_info->namv[i]); 357 n++; 358 } 359 return (n); 360 } 361 362 /* 363 * Debugging info 364 */ 365 static void 366 check_swap(void) 367 { 368 (void) system(MSG_ORIG(MSG_CMD_SWAP)); 369 } 370