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