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.
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.
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]
23 * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
25 * Copyright (c) 1988 AT&T
29 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
30 * Use is subject to license terms.
39 static size_t optcnt
= 0;
40 static size_t optbufsz
= OPTUNIT
;
43 * Function prototypes.
45 static void usage(int);
46 static void sigexit(int);
47 static int setup_sectname(char *, int);
48 static void queue(int, char *);
51 main(int argc
, char ** argv
, char ** envp
)
55 int error_count
= 0, num_sect
= 0, errflag
= 0;
60 * Check for a binary that better fits this architecture.
62 (void) conv_check_native(argv
, envp
);
65 * mcs(1) and strip() are hard linked together, determine which command
69 if ((str
= strrchr(prog
, '/')) != NULL
)
74 if (strcmp(str
, "mcs") == 0) {
77 } else if (strcmp(str
, "strip") == 0) {
83 (void) setlocale(LC_ALL
, "");
84 #if !defined(TEXT_DOMAIN)
85 #define TEXT_DOMAIN "SYS_TEST"
87 (void) textdomain(TEXT_DOMAIN
);
89 for (i
= 0; signum
[i
]; i
++)
90 if (signal(signum
[i
], SIG_IGN
) != SIG_IGN
)
91 (void) signal(signum
[i
], sigexit
);
94 malloc(optbufsz
* sizeof (struct action
))) == NULL
) {
95 error_message(MALLOC_ERROR
, PLAIN_ERROR
, (char *)0, prog
);
100 * Allocate command info structure
102 cmd_info
= (Cmd_Info
*) calloc(1, sizeof (Cmd_Info
));
103 if (cmd_info
== NULL
) {
104 error_message(MALLOC_ERROR
, PLAIN_ERROR
, (char *)0, prog
);
107 if (my_prog
== STRIP
)
108 cmd_info
->flags
|= I_AM_STRIP
;
110 while ((c
= getopt(argc
, argv
, (char *)opt
)) != EOF
) {
114 queue(ACT_APPEND
, optarg
);
115 cmd_info
->flags
|= (MIGHT_CHG
| aFLAG
);
116 cmd_info
->str_size
+= strlen(optarg
) + 1;
120 queue(ACT_COMPRESS
, NULL
);
121 cmd_info
->flags
|= (MIGHT_CHG
| cFLAG
);
125 if (CHK_OPT(cmd_info
, dFLAG
) == 0)
126 queue(ACT_DELETE
, NULL
);
127 cmd_info
->flags
|= (MIGHT_CHG
| dFLAG
);
131 queue(ACT_ZAP
, NULL
);
132 cmd_info
->flags
|= (MIGHT_CHG
| zFLAG
);
135 (void) setup_sectname(optarg
, my_prog
);
140 cmd_info
->flags
|= lFLAG
;
144 queue(ACT_PRINT
, NULL
);
145 cmd_info
->flags
|= pFLAG
;
149 cmd_info
->flags
|= xFLAG
;
152 cmd_info
->flags
|= VFLAG
;
153 (void) fprintf(stderr
, "%s: %s %s\n", prog
,
154 (const char *)SGU_PKG
, (const char *)SGU_REL
);
170 * strip command may not take any options.
172 if (my_prog
!= STRIP
) {
173 if (argc
== optind
&&
174 (CHK_OPT(cmd_info
, MIGHT_CHG
) || CHK_OPT(cmd_info
, pFLAG
) ||
177 else if (!CHK_OPT(cmd_info
, MIGHT_CHG
) &&
178 !CHK_OPT(cmd_info
, pFLAG
) && !CHK_OPT(cmd_info
, VFLAG
))
183 * This version only allows multiple section names
184 * only for -d option.
186 if ((num_sect
>= 2) && (CHK_OPT(cmd_info
, pFLAG
) ||
187 CHK_OPT(cmd_info
, aFLAG
) ||
188 CHK_OPT(cmd_info
, cFLAG
))) {
189 error_message(USAGE_ERROR
, PLAIN_ERROR
, (char *)0, prog
);
194 * If no -n was specified,
195 * set the default, ".comment".
196 * This is for mcs only.
198 if (num_sect
== 0 && my_prog
== MCS
) {
199 (void) setup_sectname(".comment", MCS
);
203 * If I am strip command, then add needed
206 if (my_prog
== STRIP
) {
207 (void) setup_sectname(".line", MCS
);
208 if (CHK_OPT(cmd_info
, lFLAG
) == 0) {
209 (void) setup_sectname(".debug", STRIP
);
210 (void) setup_sectname(".stab", STRIP
);
212 if (CHK_OPT(cmd_info
, dFLAG
) == 0) {
213 queue(ACT_DELETE
, NULL
);
214 cmd_info
->flags
|= MIGHT_CHG
;
215 cmd_info
->flags
|= dFLAG
;
219 (void) elf_version(EV_NONE
);
220 if (elf_version(EV_CURRENT
) == EV_NONE
) {
221 error_message(ELFVER_ERROR
, LIBelf_ERROR
, elf_errmsg(-1), prog
);
225 if (CHK_OPT(cmd_info
, pFLAG
) || CHK_OPT(cmd_info
, MIGHT_CHG
)) {
226 for (; optind
< argc
; optind
++) {
227 error_count
= error_count
+
228 (each_file(argv
[optind
], cmd_info
));
232 mcs_exit(error_count
);
238 * Supplementary functions
241 queue(int activity
, char *string
)
243 if (optcnt
> optbufsz
) {
244 optbufsz
= optbufsz
* 2;
245 if ((Action
= realloc((struct action
*)Action
,
246 optbufsz
* sizeof (struct action
))) == NULL
) {
247 error_message(MALLOC_ERROR
, PLAIN_ERROR
, (char *)0, prog
);
251 Action
[actmax
].a_action
= activity
;
252 Action
[actmax
].a_cnt
= 0;
253 Action
[actmax
].a_string
= string
;
258 * Reset a temporary file descriptor for reuse.
259 * If the file requires unlinking, that is done first.
262 free_tempfile(Tmp_File
*temp_file
)
264 if ((temp_file
->tmp_name
!= NULL
) && (temp_file
->tmp_unlink
))
265 (void) unlink(temp_file
->tmp_name
);
266 (void) memset(temp_file
, 0, sizeof (*temp_file
));
273 free_tempfile(&artmpfile
);
274 free_tempfile(&elftmpfile
);
282 (void) fprintf(stderr
, gettext(
283 "usage: %s [-cdpVz] [-a string] [-n name] file ...\n"), prog
);
285 (void) fprintf(stderr
, gettext(
286 "usage: %s [-lVx] file ...\n"), prog
);
293 free_tempfile(&artmpfile
);
294 free_tempfile(&elftmpfile
);
299 * Insert the section name 'name' into the
303 setup_sectname(char *name
, int whoami
)
308 * Check if the name is already specified or not.
310 if ((whoami
== MCS
) && (sectcmp(name
) == 0))
316 if ((new = malloc(sizeof (S_Name
))) == NULL
) {
317 error_message(MALLOC_ERROR
, PLAIN_ERROR
, (char *)0, prog
);
320 new->name
= strdup(name
);
321 if (new->name
== NULL
) {
322 error_message(USAGE_ERROR
, PLAIN_ERROR
, (char *)0, prog
);
326 new->flags
= SNAME_FLG_STRNCMP
;
330 * Put this one in the list
332 new->next
= sect_head
;
339 * Check if the 'name' exists in the section list.
350 * Check if the name is already specified or not.
352 if (sect_head
!= NULL
) {
353 S_Name
*p1
= sect_head
;
355 if (p1
->flags
& SNAME_FLG_STRNCMP
) {
356 if (strncmp(p1
->name
,
357 name
, strlen(p1
->name
)) == 0)
359 } else if (strcmp(p1
->name
, name
) == 0) {
360 return (0); /* silently ignore */