xref: /illumos-gate/usr/src/cmd/sgs/mcs/common/main.c (revision 03100a6332bd4edc7a53091fcf7c9a7131bcdaa7)
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 2006 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 	(void) 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