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 /* 23 * Copyright (c) 1988 AT&T 24 * All Rights Reserved 25 * 26 * 27 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 28 * Use is subject to license terms. 29 */ 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 33 #include "stdlib.h" 34 #include "conv.h" 35 #include "mcs.h" 36 #include "extern.h" 37 #define OPTUNIT 100 38 39 static size_t optcnt = 0; 40 static size_t optbufsz = OPTUNIT; 41 42 /* 43 * Function prototypes. 44 */ 45 static void usage(int); 46 static void sigexit(int); 47 static int setup_sectname(char *, int); 48 static void check_swap(); 49 static void queue(int, char *); 50 51 int 52 main(int argc, char ** argv, char ** envp) 53 { 54 const char *opt; 55 char *str; 56 int error_count = 0, num_sect = 0, errflag = 0, Dflag = 0; 57 int c, i, my_prog; 58 Cmd_Info *cmd_info; 59 60 /* 61 * Check for a binary that better fits this architecture. 62 */ 63 conv_check_native(argv, envp); 64 65 /* 66 * mcs(1) and strip() are hard linked together, determine which command 67 * was invoked. 68 */ 69 prog = argv[0]; 70 if ((str = strrchr(prog, '/')) != NULL) 71 str++; 72 else 73 str = prog; 74 75 if (strcmp(str, "mcs") == 0) { 76 my_prog = MCS; 77 opt = "Da:cdn:pVz?"; 78 } else if (strcmp(str, "strip") == 0) { 79 my_prog = STRIP; 80 opt = "DlxV?"; 81 } else 82 exit(1); 83 84 (void) setlocale(LC_ALL, ""); 85 #if !defined(TEXT_DOMAIN) 86 #define TEXT_DOMAIN "SYS_TEST" 87 #endif 88 (void) textdomain(TEXT_DOMAIN); 89 90 for (i = 0; signum[i]; i++) 91 if (signal(signum[i], SIG_IGN) != SIG_IGN) 92 (void) signal(signum[i], sigexit); 93 94 if ((Action = 95 malloc(optbufsz * sizeof (struct action))) == NULL) { 96 error_message(MALLOC_ERROR, PLAIN_ERROR, (char *)0, prog); 97 exit(FAILURE); 98 } 99 100 /* 101 * Allocate command info structure 102 */ 103 cmd_info = (Cmd_Info *) calloc(1, sizeof (Cmd_Info)); 104 if (cmd_info == NULL) { 105 error_message(MALLOC_ERROR, PLAIN_ERROR, (char *)0, prog); 106 exit(FAILURE); 107 } 108 if (my_prog == STRIP) 109 cmd_info->flags |= I_AM_STRIP; 110 111 while ((c = getopt(argc, argv, (char *)opt)) != EOF) { 112 switch (c) { 113 case 'D': 114 optcnt++; 115 Dflag++; 116 break; 117 case 'a': 118 optcnt++; 119 queue(ACT_APPEND, optarg); 120 cmd_info->flags |= (MIGHT_CHG | aFLAG); 121 cmd_info->str_size += strlen(optarg) + 1; 122 break; 123 case 'c': 124 optcnt++; 125 queue(ACT_COMPRESS, NULL); 126 cmd_info->flags |= (MIGHT_CHG | cFLAG); 127 break; 128 case 'd': 129 optcnt++; 130 if (CHK_OPT(cmd_info, dFLAG) == 0) 131 queue(ACT_DELETE, NULL); 132 cmd_info->flags |= (MIGHT_CHG | dFLAG); 133 break; 134 case 'z': 135 optcnt++; 136 queue(ACT_ZAP, NULL); 137 cmd_info->flags |= (MIGHT_CHG | zFLAG); 138 break; 139 case 'n': 140 (void) setup_sectname(optarg, my_prog); 141 num_sect++; 142 break; 143 case 'l': 144 optcnt++; 145 cmd_info->flags |= lFLAG; 146 break; 147 case 'p': 148 optcnt++; 149 queue(ACT_PRINT, NULL); 150 cmd_info->flags |= pFLAG; 151 break; 152 case 'x': 153 optcnt++; 154 cmd_info->flags |= xFLAG; 155 break; 156 case 'V': 157 cmd_info->flags |= VFLAG; 158 (void) fprintf(stderr, "%s: %s %s\n", prog, 159 (const char *)SGU_PKG, (const char *)SGU_REL); 160 break; 161 case '?': 162 errflag++; 163 break; 164 default: 165 break; 166 } 167 } 168 169 if (errflag) { 170 usage(my_prog); 171 exit(FAILURE); 172 } 173 174 if (Dflag) 175 check_swap(); 176 177 /* 178 * strip command may not take any options. 179 */ 180 if (my_prog != STRIP) { 181 if (argc == optind && 182 (CHK_OPT(cmd_info, MIGHT_CHG) || CHK_OPT(cmd_info, pFLAG) || 183 argc == 1)) 184 usage(my_prog); 185 else if (!CHK_OPT(cmd_info, MIGHT_CHG) && 186 !CHK_OPT(cmd_info, pFLAG) && !CHK_OPT(cmd_info, VFLAG)) 187 usage(my_prog); 188 } 189 190 /* 191 * This version only allows multiple section names 192 * only for -d option. 193 */ 194 if ((num_sect >= 2) && (CHK_OPT(cmd_info, pFLAG) || 195 CHK_OPT(cmd_info, aFLAG) || 196 CHK_OPT(cmd_info, cFLAG))) { 197 error_message(USAGE_ERROR, PLAIN_ERROR, (char *)0, prog); 198 exit(1); 199 } 200 201 /* 202 * If no -n was specified, 203 * set the default, ".comment". 204 * This is for mcs only. 205 */ 206 if (num_sect == 0 && my_prog == MCS) { 207 (void) setup_sectname(".comment", MCS); 208 } 209 210 /* 211 * If I am strip command, then add needed 212 * section names. 213 */ 214 if (my_prog == STRIP) { 215 (void) setup_sectname(".line", MCS); 216 if (CHK_OPT(cmd_info, lFLAG) == 0) { 217 (void) setup_sectname(".debug", STRIP); 218 (void) setup_sectname(".stab", STRIP); 219 } 220 if (CHK_OPT(cmd_info, dFLAG) == 0) { 221 queue(ACT_DELETE, NULL); 222 cmd_info->flags |= MIGHT_CHG; 223 cmd_info->flags |= dFLAG; 224 } 225 } 226 227 (void) elf_version(EV_NONE); 228 if (elf_version(EV_CURRENT) == EV_NONE) { 229 error_message(ELFVER_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); 230 exit(FAILURE); 231 } 232 233 if (CHK_OPT(cmd_info, pFLAG) || CHK_OPT(cmd_info, MIGHT_CHG)) { 234 for (; optind < argc; optind++) { 235 error_count = error_count + 236 (each_file(argv[optind], cmd_info)); 237 } 238 } 239 240 if (Dflag) 241 check_swap(); 242 mcs_exit(error_count); 243 /*NOTREACHED*/ 244 return (0); 245 } 246 247 /* 248 * Supplementary functions 249 */ 250 static void 251 queue(int activity, char *string) 252 { 253 if (optcnt > optbufsz) { 254 optbufsz = optbufsz * 2; 255 if ((Action = realloc((struct action *)Action, 256 optbufsz * sizeof (struct action))) == NULL) { 257 error_message(MALLOC_ERROR, PLAIN_ERROR, (char *)0, prog); 258 mcs_exit(FAILURE); 259 } 260 } 261 Action[actmax].a_action = activity; 262 Action[actmax].a_cnt = 0; 263 Action[actmax].a_string = string; 264 actmax++; 265 } 266 267 /*ARGSUSED0*/ 268 static void 269 sigexit(int i) 270 { 271 (void) unlink(artmpfile); 272 (void) unlink(elftmpfile); 273 exit(100); 274 } 275 276 static void 277 usage(int me) 278 { 279 if (me == MCS) 280 (void) fprintf(stderr, gettext( 281 "usage: %s [-cdpVz] [-a string] [-n name] file ...\n"), prog); 282 else 283 (void) fprintf(stderr, gettext( 284 "usage: %s [-lVx] file ...\n"), prog); 285 mcs_exit(FAILURE); 286 } 287 288 void 289 mcs_exit(int val) 290 { 291 (void) unlink(artmpfile); 292 (void) unlink(elftmpfile); 293 exit(val); 294 } 295 296 /* 297 * Insert the section name 'name' into the 298 * section list. 299 */ 300 static int 301 setup_sectname(char *name, int whoami) 302 { 303 S_Name *new; 304 305 /* 306 * Check if the name is already specified or not. 307 */ 308 if ((whoami == MCS) && (sectcmp(name) == 0)) 309 return (0); 310 311 /* 312 * Allocate one 313 */ 314 if ((new = malloc(sizeof (S_Name))) == NULL) { 315 error_message(MALLOC_ERROR, PLAIN_ERROR, (char *)0, prog); 316 exit(FAILURE); 317 } 318 new->name = strdup(name); 319 if (new->name == NULL) { 320 error_message(USAGE_ERROR, PLAIN_ERROR, (char *)0, prog); 321 exit(FAILURE); 322 } 323 if (whoami == STRIP) 324 new->flags = SNAME_FLG_STRNCMP; 325 new->next = NULL; 326 327 /* 328 * Put this one in the list 329 */ 330 new->next = sect_head; 331 sect_head = new; 332 333 return (0); 334 } 335 336 /* 337 * Check if the 'name' exists in the section list. 338 * 339 * If found 340 * return 0; 341 * else 342 * return 1 343 */ 344 int 345 sectcmp(char *name) 346 { 347 /* 348 * Check if the name is already specified or not. 349 */ 350 if (sect_head != NULL) { 351 S_Name *p1 = sect_head; 352 while (p1 != NULL) { 353 if (p1->flags & SNAME_FLG_STRNCMP) { 354 if (strncmp(p1->name, 355 name, strlen(p1->name)) == 0) 356 return (0); 357 } else if (strcmp(p1->name, name) == 0) { 358 return (0); /* silently ignore */ 359 } 360 p1 = p1->next; 361 } 362 } 363 return (1); 364 } 365 366 static void 367 check_swap() 368 { 369 (void) system("/usr/sbin/swap -s"); 370 } 371