xref: /onnv-gate/usr/src/cmd/sgs/elfedit/common/sys.c (revision 5088:26c540f30cd3)
1*5088Sab196087 /*
2*5088Sab196087  * CDDL HEADER START
3*5088Sab196087  *
4*5088Sab196087  * The contents of this file are subject to the terms of the
5*5088Sab196087  * Common Development and Distribution License (the "License").
6*5088Sab196087  * You may not use this file except in compliance with the License.
7*5088Sab196087  *
8*5088Sab196087  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*5088Sab196087  * or http://www.opensolaris.org/os/licensing.
10*5088Sab196087  * See the License for the specific language governing permissions
11*5088Sab196087  * and limitations under the License.
12*5088Sab196087  *
13*5088Sab196087  * When distributing Covered Code, include this CDDL HEADER in each
14*5088Sab196087  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*5088Sab196087  * If applicable, add the following below this CDDL HEADER, with the
16*5088Sab196087  * fields enclosed by brackets "[]" replaced with your own identifying
17*5088Sab196087  * information: Portions Copyright [yyyy] [name of copyright owner]
18*5088Sab196087  *
19*5088Sab196087  * CDDL HEADER END
20*5088Sab196087  */
21*5088Sab196087 
22*5088Sab196087 /*
23*5088Sab196087  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24*5088Sab196087  * Use is subject to license terms.
25*5088Sab196087  */
26*5088Sab196087 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*5088Sab196087 
28*5088Sab196087 #include <fcntl.h>
29*5088Sab196087 #include <sys/types.h>
30*5088Sab196087 #include <sys/stat.h>
31*5088Sab196087 #include <unistd.h>
32*5088Sab196087 #include <strings.h>
33*5088Sab196087 #include <elfedit.h>
34*5088Sab196087 #include "_elfedit.h"
35*5088Sab196087 #include "msg.h"
36*5088Sab196087 
37*5088Sab196087 
38*5088Sab196087 
39*5088Sab196087 
40*5088Sab196087 /*
41*5088Sab196087  * This file provides the builtin sys module. It is similar to the
42*5088Sab196087  * other modules, but differs in several important ways:
43*5088Sab196087  *
44*5088Sab196087  *	- It is built as a static part of elfedit, and not
45*5088Sab196087  *		as a sharable object.
46*5088Sab196087  *	- It must be avaialble before the ELFCLASS of the object
47*5088Sab196087  *		is known, so it is not ELFCLASS specific. We don't build
48*5088Sab196087  *		it twice with machdep.h, as we do for the loadable modules.
49*5088Sab196087  *		This means that commands need to test for the type
50*5088Sab196087  *		of their obj_state argument at runtime.
51*5088Sab196087  *	- The init function signature is different. We build an entire
52*5088Sab196087  *		module definition statically.
53*5088Sab196087  */
54*5088Sab196087 
55*5088Sab196087 
56*5088Sab196087 
57*5088Sab196087 /*
58*5088Sab196087  * This function is supplied to elfedit through our elfedit_module_t
59*5088Sab196087  * definition. It translates the opaque elfedit_i18nhdl_t handles
60*5088Sab196087  * in our module interface into the actual strings for elfedit to
61*5088Sab196087  * use.
62*5088Sab196087  *
63*5088Sab196087  * note:
64*5088Sab196087  *	This module uses Msg codes for its i18n handle type.
65*5088Sab196087  *	So the translation is simply to use MSG_INTL() to turn
66*5088Sab196087  *	it into a string and return it.
67*5088Sab196087  */
68*5088Sab196087 static const char *
69*5088Sab196087 mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl)
70*5088Sab196087 {
71*5088Sab196087 	Msg msg = (Msg)hdl;
72*5088Sab196087 
73*5088Sab196087 	return (MSG_INTL(msg));
74*5088Sab196087 }
75*5088Sab196087 
76*5088Sab196087 
77*5088Sab196087 
78*5088Sab196087 /*
79*5088Sab196087  * The sys_opt_t enum specifies a bit value for every optional argument
80*5088Sab196087  * allowed by a command in this module.
81*5088Sab196087  */
82*5088Sab196087 typedef enum {
83*5088Sab196087 	SYS_OPT_F_ALL =		1,	/* -a */
84*5088Sab196087 	SYS_OPT_F_FORCE =	2,	/* -f */
85*5088Sab196087 	SYS_OPT_F_SYNOPSIS =	4,	/* -s */
86*5088Sab196087 } dyn_opt_t;
87*5088Sab196087 
88*5088Sab196087 
89*5088Sab196087 /*
90*5088Sab196087  * Given a generic (void *) pointer to an obj_state argument, determine
91*5088Sab196087  * which type it is, and return the st_file, st_fd and st_elf fields.
92*5088Sab196087  */
93*5088Sab196087 static void
94*5088Sab196087 get_obj_state_info(void *obj_state, const char **file, int *fd, Elf **elf)
95*5088Sab196087 {
96*5088Sab196087 	if (state.elf.elfclass == ELFCLASS32) {
97*5088Sab196087 		elfedit32_obj_state_t *s = (elfedit32_obj_state_t *)obj_state;
98*5088Sab196087 
99*5088Sab196087 		*file = s->os_file;
100*5088Sab196087 		*fd = s->os_fd;
101*5088Sab196087 		*elf = s->os_elf;
102*5088Sab196087 	} else {
103*5088Sab196087 		elfedit64_obj_state_t *s = (elfedit64_obj_state_t *)obj_state;
104*5088Sab196087 
105*5088Sab196087 		*file = s->os_file;
106*5088Sab196087 		*fd = s->os_fd;
107*5088Sab196087 		*elf = s->os_elf;
108*5088Sab196087 	}
109*5088Sab196087 }
110*5088Sab196087 
111*5088Sab196087 
112*5088Sab196087 
113*5088Sab196087 /*
114*5088Sab196087  * Helper for cmd_help(). Displays synopsis information for one command.
115*5088Sab196087  */
116*5088Sab196087 static void
117*5088Sab196087 cmd_help_synopsis(elfeditGC_module_t *mod, elfeditGC_cmd_t *cmd)
118*5088Sab196087 {
119*5088Sab196087 	char		name_buf[128];
120*5088Sab196087 	const char	*name;
121*5088Sab196087 	const char	**cmd_name;
122*5088Sab196087 
123*5088Sab196087 	if (cmd->cmd_name[1] == NULL) {   /* One name */
124*5088Sab196087 		name = *cmd->cmd_name;
125*5088Sab196087 	} else {
126*5088Sab196087 		const char *cname;
127*5088Sab196087 		int need_comma = 0;
128*5088Sab196087 
129*5088Sab196087 		name = name_buf;
130*5088Sab196087 		(void) snprintf(name_buf, sizeof (name_buf),
131*5088Sab196087 		    MSG_ORIG(MSG_HLPFMT_MULTNAM), cmd->cmd_name[0]);
132*5088Sab196087 		for (cmd_name = cmd->cmd_name + 1;
133*5088Sab196087 		    *cmd_name; cmd_name++) {
134*5088Sab196087 			if (need_comma)
135*5088Sab196087 				(void) strlcat(name_buf,
136*5088Sab196087 				    MSG_ORIG(MSG_STR_COMMA_SP),
137*5088Sab196087 				    sizeof (name_buf));
138*5088Sab196087 			need_comma = 1;
139*5088Sab196087 			cname = (cmd_name[0][0] == '\0') ?
140*5088Sab196087 			    MSG_INTL(MSG_HLPFMT_MODDEFCMD) : *cmd_name;
141*5088Sab196087 			(void) strlcat(name_buf, cname,
142*5088Sab196087 			    sizeof (name_buf));
143*5088Sab196087 		}
144*5088Sab196087 		(void) strlcat(name_buf, MSG_ORIG(MSG_STR_CPAREN),
145*5088Sab196087 		    sizeof (name_buf));
146*5088Sab196087 	}
147*5088Sab196087 	elfedit_printf(MSG_ORIG(MSG_HLPFMT_NAMSUMHDR), name,
148*5088Sab196087 	    (* mod->mod_i18nhdl_to_str)(cmd->cmd_desc));
149*5088Sab196087 	elfedit_printf(MSG_INTL(MSG_HLPFMT_SUMSYNOPSIS),
150*5088Sab196087 	    elfedit_format_command_usage(mod, cmd,
151*5088Sab196087 	    MSG_ORIG(MSG_STR_HLPSUMINDENT),
152*5088Sab196087 	    strlen(MSG_ORIG(MSG_STR_HLPSUMINDENT))));
153*5088Sab196087 }
154*5088Sab196087 
155*5088Sab196087 
156*5088Sab196087 /*
157*5088Sab196087  * Helper for cmd_help(). Displays synopsis information for one module.
158*5088Sab196087  */
159*5088Sab196087 static void
160*5088Sab196087 cmd_help_showmod(elfeditGC_module_t *mod)
161*5088Sab196087 {
162*5088Sab196087 	elfeditGC_cmd_t	*cmd;
163*5088Sab196087 
164*5088Sab196087 	elfedit_printf(MSG_ORIG(MSG_HLPFMT_NAMDSCHDR),
165*5088Sab196087 	    mod->mod_name, (* mod->mod_i18nhdl_to_str)(mod->mod_desc));
166*5088Sab196087 	for (cmd = mod->mod_cmds; cmd->cmd_func != NULL; cmd++) {
167*5088Sab196087 		if (cmd != mod->mod_cmds)
168*5088Sab196087 			elfedit_printf(MSG_ORIG(MSG_STR_NL));
169*5088Sab196087 		elfedit_printf(MSG_ORIG(MSG_STR_NL));
170*5088Sab196087 		cmd_help_synopsis(mod, cmd);
171*5088Sab196087 	}
172*5088Sab196087 }
173*5088Sab196087 
174*5088Sab196087 
175*5088Sab196087 /*
176*5088Sab196087  * Given a string containing newline characters, break it into
177*5088Sab196087  * individual lines, and output each line with the given
178*5088Sab196087  * prefix string in front.
179*5088Sab196087  */
180*5088Sab196087 static void
181*5088Sab196087 write_help_str(const char *str, const char *prefix)
182*5088Sab196087 {
183*5088Sab196087 	size_t i;
184*5088Sab196087 
185*5088Sab196087 	if (str == NULL)
186*5088Sab196087 		return;
187*5088Sab196087 	while (*str) {
188*5088Sab196087 		i = strcspn(str, MSG_ORIG(MSG_STR_NL));
189*5088Sab196087 		if (*(str + i) != '\0')
190*5088Sab196087 			i++;
191*5088Sab196087 		elfedit_printf(prefix);
192*5088Sab196087 		elfedit_write(str, i);
193*5088Sab196087 		str += i;
194*5088Sab196087 	}
195*5088Sab196087 }
196*5088Sab196087 
197*5088Sab196087 
198*5088Sab196087 /*
199*5088Sab196087  * Given a title, and a NULL terminated list of option/argument
200*5088Sab196087  * descriptors, output the list contents.
201*5088Sab196087  */
202*5088Sab196087 static void
203*5088Sab196087 write_optarg(elfeditGC_module_t *mod, const char *title,
204*5088Sab196087     elfedit_cmd_optarg_t *optarg)
205*5088Sab196087 {
206*5088Sab196087 	int			cnt;
207*5088Sab196087 	int			len;
208*5088Sab196087 	const char		*help;
209*5088Sab196087 	elfedit_optarg_item_t	item;
210*5088Sab196087 
211*5088Sab196087 	elfedit_printf(title);
212*5088Sab196087 	for (cnt = 0; optarg->oa_name != NULL; cnt++) {
213*5088Sab196087 		elfedit_next_optarg(&optarg, &item);
214*5088Sab196087 
215*5088Sab196087 		/* Insert a blank line between items */
216*5088Sab196087 		if (cnt > 0)
217*5088Sab196087 			elfedit_printf(MSG_ORIG(MSG_STR_NL));
218*5088Sab196087 
219*5088Sab196087 		/* Indentation */
220*5088Sab196087 		elfedit_printf(MSG_ORIG(MSG_STR_HLPINDENT));
221*5088Sab196087 		len = strlen(item.oai_name);
222*5088Sab196087 		help = elfedit_optarg_helpstr(mod, &item);
223*5088Sab196087 		if (item.oai_flags & ELFEDIT_CMDOA_F_VALUE) {
224*5088Sab196087 			len += 1 + strlen(item.oai_vname);
225*5088Sab196087 			elfedit_printf(MSG_ORIG(MSG_STR_HLPOPTARG2),
226*5088Sab196087 			    item.oai_name, item.oai_vname);
227*5088Sab196087 		} else {
228*5088Sab196087 			elfedit_printf(MSG_ORIG(MSG_STR_HLPOPTARG),
229*5088Sab196087 			    item.oai_name);
230*5088Sab196087 		}
231*5088Sab196087 
232*5088Sab196087 		/*
233*5088Sab196087 		 * If name is too long, inject a newline to avoid
234*5088Sab196087 		 * crowding the help text.
235*5088Sab196087 		 */
236*5088Sab196087 		if (len > 3)
237*5088Sab196087 			elfedit_printf(MSG_ORIG(MSG_STR_NL));
238*5088Sab196087 
239*5088Sab196087 		/* Output the help text with a tab prefix */
240*5088Sab196087 		write_help_str(help, MSG_ORIG(MSG_STR_TAB));
241*5088Sab196087 	}
242*5088Sab196087 }
243*5088Sab196087 
244*5088Sab196087 
245*5088Sab196087 /*
246*5088Sab196087  * Implementation of sys:help
247*5088Sab196087  */
248*5088Sab196087 /*ARGSUSED*/
249*5088Sab196087 static elfedit_cmdret_t
250*5088Sab196087 cmd_help(void *obj_state, int argc, const char *argv[])
251*5088Sab196087 {
252*5088Sab196087 #define	INITIAL_ITEM_ALLOC 4
253*5088Sab196087 
254*5088Sab196087 
255*5088Sab196087 	/*
256*5088Sab196087 	 * An array of this type is used to collect the data needed to
257*5088Sab196087 	 * generate help output.
258*5088Sab196087 	 */
259*5088Sab196087 	typedef struct {
260*5088Sab196087 		elfeditGC_cmd_t		*cmd;
261*5088Sab196087 		elfeditGC_module_t	*cmd_mod;	/* Used with cmd */
262*5088Sab196087 		elfeditGC_module_t	*mod;
263*5088Sab196087 	} ITEM;
264*5088Sab196087 
265*5088Sab196087 	static ITEM	*item;
266*5088Sab196087 	static int	item_cnt;
267*5088Sab196087 
268*5088Sab196087 	MODLIST_T		*modlist;
269*5088Sab196087 	int			dispcnt;
270*5088Sab196087 	size_t			i;
271*5088Sab196087 	elfeditGC_module_t	*mod;
272*5088Sab196087 	elfeditGC_cmd_t		*cmd;
273*5088Sab196087 	int			minus_s = 0;
274*5088Sab196087 	elfedit_getopt_state_t	getopt_state;
275*5088Sab196087 	ITEM			*cur_item;
276*5088Sab196087 
277*5088Sab196087 	/*
278*5088Sab196087 	 * Process options. The only option accepted is -s, so we
279*5088Sab196087 	 * don't even have to check the idmask to know.
280*5088Sab196087 	 */
281*5088Sab196087 	elfedit_getopt_init(&getopt_state, &argc, &argv);
282*5088Sab196087 	while (elfedit_getopt(&getopt_state) != NULL)
283*5088Sab196087 		minus_s = 1;
284*5088Sab196087 
285*5088Sab196087 	/*
286*5088Sab196087 	 * This command can produce an arbitrary amount of output, so
287*5088Sab196087 	 * run a pager.
288*5088Sab196087 	 */
289*5088Sab196087 	elfedit_pager_init();
290*5088Sab196087 
291*5088Sab196087 	if (argc == 0) {
292*5088Sab196087 		if (minus_s) {
293*5088Sab196087 			/* Force all modules to load so we have data */
294*5088Sab196087 			elfedit_load_modpath();
295*5088Sab196087 			for (modlist = state.modlist; modlist;
296*5088Sab196087 			    modlist = modlist->ml_next) {
297*5088Sab196087 				cmd_help_showmod(modlist->ml_mod);
298*5088Sab196087 				if (modlist->ml_next != NULL) {
299*5088Sab196087 					elfedit_printf(MSG_ORIG(MSG_STR_NL));
300*5088Sab196087 					elfedit_printf(MSG_ORIG(MSG_STR_NL));
301*5088Sab196087 				}
302*5088Sab196087 			}
303*5088Sab196087 			return (ELFEDIT_CMDRET_NONE);
304*5088Sab196087 		}
305*5088Sab196087 
306*5088Sab196087 		/*
307*5088Sab196087 		 * If no arguments are present, we display a simple
308*5088Sab196087 		 * "how to use help" tutorial, which will hopefully
309*5088Sab196087 		 * bootstrap the user into a position where they
310*5088Sab196087 		 * know how to run the help command, and then find
311*5088Sab196087 		 * what they're really after.
312*5088Sab196087 		 */
313*5088Sab196087 		elfedit_printf(MSG_INTL(MSG_SYS_HELP_HELP_NOARG));
314*5088Sab196087 		return (ELFEDIT_CMDRET_NONE);
315*5088Sab196087 	}
316*5088Sab196087 
317*5088Sab196087 
318*5088Sab196087 	/*
319*5088Sab196087 	 * As we process the arguments, we are willing to treat each
320*5088Sab196087 	 * one as either a module or a command:
321*5088Sab196087 	 *	1) An item without a colon can be a module,
322*5088Sab196087 	 *		or a command from the sys: module.
323*5088Sab196087 	 *	2) An item with a colon, and no command part is
324*5088Sab196087 	 *		a module, and it can also be the default
325*5088Sab196087 	 *		command for the module, if it has one. We choose
326*5088Sab196087 	 *		to only display the module info in this case, since
327*5088Sab196087 	 *		the use of "" to represent the default command is
328*5088Sab196087 	 *		an implementation detail, not a user-facing concept.
329*5088Sab196087 	 *	3) An item with a colon and a command part can only be
330*5088Sab196087 	 *		a command.
331*5088Sab196087 	 *
332*5088Sab196087 	 * Note that there are cases where one argument can have two
333*5088Sab196087 	 * valid interpretations. In this case, we display them both.
334*5088Sab196087 	 *
335*5088Sab196087 	 * Pass over the arguments and determine how many distinct
336*5088Sab196087 	 * "things" we need to display. At the same time, force any
337*5088Sab196087 	 * needed modules to load so that the debug load messages won't
338*5088Sab196087 	 * show up in between the displayed items, and save the command
339*5088Sab196087 	 * and module definitions we will need to generate the output.
340*5088Sab196087 	 */
341*5088Sab196087 	if (argc > item_cnt) {
342*5088Sab196087 		int n = (item_cnt == 0) ? INITIAL_ITEM_ALLOC : item_cnt;
343*5088Sab196087 
344*5088Sab196087 		while (n < argc)
345*5088Sab196087 			n *= 2;
346*5088Sab196087 
347*5088Sab196087 		item = elfedit_realloc(MSG_INTL(MSG_ALLOC_HELPITEM), item,
348*5088Sab196087 		    n * sizeof (*item));
349*5088Sab196087 		item_cnt = n;
350*5088Sab196087 	}
351*5088Sab196087 
352*5088Sab196087 	dispcnt = 0;
353*5088Sab196087 	for (i = 0; i < argc; i++) {
354*5088Sab196087 		const char *colon = strchr(argv[i], ':');
355*5088Sab196087 
356*5088Sab196087 		if (colon == NULL) {	/* No colon: sys: cmd or module */
357*5088Sab196087 			item[i].cmd =
358*5088Sab196087 			    elfedit_find_command(argv[i], 0, &item[i].cmd_mod);
359*5088Sab196087 			if (item[i].cmd != NULL)
360*5088Sab196087 				dispcnt++;
361*5088Sab196087 
362*5088Sab196087 			/*
363*5088Sab196087 			 * Also try to load it as a module. If a command
364*5088Sab196087 			 * was found, then this need not succeed. Otherwise,
365*5088Sab196087 			 * it has to be a module, and we cause an error
366*5088Sab196087 			 * to be issued if not.
367*5088Sab196087 			 */
368*5088Sab196087 			item[i].mod = elfedit_load_module(argv[i],
369*5088Sab196087 			    item[i].cmd == NULL, 0);
370*5088Sab196087 			if (item[i].mod != NULL)
371*5088Sab196087 				dispcnt++;
372*5088Sab196087 		} else if (*(colon + 1) == '\0') {
373*5088Sab196087 			/* Just colon: Module (and maybe default command) */
374*5088Sab196087 			char buf[ELFEDIT_MAXMODNAM + 1];
375*5088Sab196087 			const char *str = argv[i];
376*5088Sab196087 			int len = colon - str;
377*5088Sab196087 
378*5088Sab196087 			item[i].cmd = NULL;
379*5088Sab196087 			/* Strip off the colon */
380*5088Sab196087 			if (len < sizeof (buf)) {
381*5088Sab196087 				(void) strncpy(buf, str, len);
382*5088Sab196087 				buf[len] = '\0';
383*5088Sab196087 				str = buf;
384*5088Sab196087 			}
385*5088Sab196087 			item[i].mod = elfedit_load_module(str, 1, 0);
386*5088Sab196087 			dispcnt++;
387*5088Sab196087 		} else {	/* A command */
388*5088Sab196087 			item[i].cmd =
389*5088Sab196087 			    elfedit_find_command(argv[i], 1, &item[i].cmd_mod);
390*5088Sab196087 			dispcnt++;
391*5088Sab196087 			item[i].mod = NULL;
392*5088Sab196087 		}
393*5088Sab196087 	}
394*5088Sab196087 
395*5088Sab196087 	/*
396*5088Sab196087 	 * Having validated the items, loop over them again and produce
397*5088Sab196087 	 * the required help output.
398*5088Sab196087 	 */
399*5088Sab196087 	for (cur_item = item; argc--; argv++, cur_item++) {
400*5088Sab196087 
401*5088Sab196087 
402*5088Sab196087 		/* Help for a module? */
403*5088Sab196087 		if (cur_item->mod != NULL) {
404*5088Sab196087 			if (dispcnt > 1)
405*5088Sab196087 				elfedit_printf(MSG_ORIG(MSG_HLPFMT_MULTIHDR),
406*5088Sab196087 				    *argv);
407*5088Sab196087 			cmd_help_showmod(cur_item->mod);
408*5088Sab196087 			if ((dispcnt > 1) && (argc > 0))
409*5088Sab196087 				elfedit_printf(MSG_INTL(MSG_HLPFMT_MULTIEND),
410*5088Sab196087 				    argv[0], argv[1]);
411*5088Sab196087 			/* An empty line after the last line of output */
412*5088Sab196087 			elfedit_printf(MSG_ORIG(MSG_STR_NL));
413*5088Sab196087 		}
414*5088Sab196087 
415*5088Sab196087 		/* Help for a command? */
416*5088Sab196087 		if (cur_item->cmd == NULL)
417*5088Sab196087 			continue;
418*5088Sab196087 		cmd = cur_item->cmd;
419*5088Sab196087 		mod = cur_item->cmd_mod;
420*5088Sab196087 		if (dispcnt > 1)
421*5088Sab196087 			elfedit_printf(MSG_ORIG(MSG_HLPFMT_MULTIHDR), *argv);
422*5088Sab196087 
423*5088Sab196087 		/* If -s, display quick synopsis rather than the whole thing */
424*5088Sab196087 		if (minus_s) {
425*5088Sab196087 			cmd_help_synopsis(mod, cmd);
426*5088Sab196087 			continue;
427*5088Sab196087 		}
428*5088Sab196087 
429*5088Sab196087 		elfedit_printf(MSG_INTL(MSG_HLPFMT_MOD), mod->mod_name,
430*5088Sab196087 		    (* mod->mod_i18nhdl_to_str)(mod->mod_desc));
431*5088Sab196087 		elfedit_printf(MSG_INTL(MSG_HLPFMT_NAME),
432*5088Sab196087 		    *cmd->cmd_name,
433*5088Sab196087 		    (* mod->mod_i18nhdl_to_str)(cmd->cmd_desc));
434*5088Sab196087 		elfedit_printf(MSG_INTL(MSG_HLPFMT_SYNOPSIS),
435*5088Sab196087 		    elfedit_format_command_usage(mod, cmd,
436*5088Sab196087 		    MSG_ORIG(MSG_STR_HLPUSEINDENT),
437*5088Sab196087 		    strlen(MSG_ORIG(MSG_STR_HLPINDENT))));
438*5088Sab196087 		/* If there are alias names, show them */
439*5088Sab196087 		if (cmd->cmd_name[1] != NULL) {
440*5088Sab196087 			const char **alias = cmd->cmd_name + 1;
441*5088Sab196087 
442*5088Sab196087 			elfedit_printf(MSG_INTL(MSG_HLPFMT_ALIASES));
443*5088Sab196087 			do {
444*5088Sab196087 				elfedit_printf(
445*5088Sab196087 				    MSG_ORIG(MSG_STR_HLPINDENT));
446*5088Sab196087 				elfedit_printf(
447*5088Sab196087 				    MSG_ORIG(MSG_FMT_MODCMD),
448*5088Sab196087 				    mod->mod_name, *alias);
449*5088Sab196087 				if (**alias == '\0')
450*5088Sab196087 					elfedit_printf(
451*5088Sab196087 					    MSG_INTL(MSG_HLPFMT_DEFCMD));
452*5088Sab196087 				elfedit_printf(MSG_ORIG(MSG_STR_NL));
453*5088Sab196087 				alias++;
454*5088Sab196087 			} while (*alias);
455*5088Sab196087 		}
456*5088Sab196087 		elfedit_printf(MSG_INTL(MSG_HLPFMT_DESC));
457*5088Sab196087 		write_help_str(
458*5088Sab196087 		    (* mod->mod_i18nhdl_to_str)(cmd->cmd_help),
459*5088Sab196087 		    MSG_ORIG(MSG_STR_HLPINDENT));
460*5088Sab196087 		if (cmd->cmd_args != NULL)
461*5088Sab196087 			write_optarg(mod, MSG_INTL(MSG_HLPFMT_ARGS),
462*5088Sab196087 			    cmd->cmd_args);
463*5088Sab196087 		if (cmd->cmd_opt != NULL)
464*5088Sab196087 			write_optarg(mod, MSG_INTL(MSG_HLPFMT_OPT),
465*5088Sab196087 			    cmd->cmd_opt);
466*5088Sab196087 		if ((dispcnt > 1) && (argc > 0))
467*5088Sab196087 			elfedit_printf(MSG_INTL(MSG_HLPFMT_MULTIEND),
468*5088Sab196087 			    argv[0], argv[1]);
469*5088Sab196087 		/* An empty line after the last line of output */
470*5088Sab196087 		elfedit_printf(MSG_ORIG(MSG_STR_NL));
471*5088Sab196087 	}
472*5088Sab196087 
473*5088Sab196087 	return (ELFEDIT_CMDRET_NONE);
474*5088Sab196087 
475*5088Sab196087 #undef	INITIAL_ITEM_ALLOC
476*5088Sab196087 }
477*5088Sab196087 
478*5088Sab196087 
479*5088Sab196087 /*
480*5088Sab196087  * Command completion function for sys:help
481*5088Sab196087  */
482*5088Sab196087 /*ARGSUSED*/
483*5088Sab196087 static void
484*5088Sab196087 cpl_help(void *obj_state, void *cpldata, int argc, const char *argv[],
485*5088Sab196087     int num_opt)
486*5088Sab196087 {
487*5088Sab196087 	/*
488*5088Sab196087 	 * The arguments can be any module or command. Supplying the
489*5088Sab196087 	 * commands implicitly supplies the modules too.
490*5088Sab196087 	 */
491*5088Sab196087 	elfedit_cpl_command(cpldata);
492*5088Sab196087 }
493*5088Sab196087 
494*5088Sab196087 
495*5088Sab196087 /*
496*5088Sab196087  * Implementation of sys:load
497*5088Sab196087  */
498*5088Sab196087 /*ARGSUSED*/
499*5088Sab196087 static elfedit_cmdret_t
500*5088Sab196087 cmd_load(void *obj_state, int argc, const char *argv[])
501*5088Sab196087 {
502*5088Sab196087 	elfedit_getopt_state_t	getopt_state;
503*5088Sab196087 	elfedit_getopt_ret_t	*getopt_ret;
504*5088Sab196087 	struct stat		statbuf;
505*5088Sab196087 
506*5088Sab196087 	elfedit_getopt_init(&getopt_state, &argc, &argv);
507*5088Sab196087 	while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) {
508*5088Sab196087 		switch (getopt_ret->gor_idmask) {
509*5088Sab196087 		case SYS_OPT_F_ALL:
510*5088Sab196087 			elfedit_load_modpath();
511*5088Sab196087 			break;
512*5088Sab196087 		}
513*5088Sab196087 	}
514*5088Sab196087 
515*5088Sab196087 	/* For each remaining argument, load them individually */
516*5088Sab196087 	for (; argc-- > 0; argv++) {
517*5088Sab196087 		/* Is it a directory? Load everything in it */
518*5088Sab196087 		if ((stat(*argv, &statbuf) == 0) &&
519*5088Sab196087 		    (statbuf.st_mode & S_IFDIR)) {
520*5088Sab196087 			elfedit_load_moddir(*argv, 1, 1);
521*5088Sab196087 		} else {	/* Not a directory. Normal load */
522*5088Sab196087 			(void) elfedit_load_module(*argv, 1, 1);
523*5088Sab196087 		}
524*5088Sab196087 	}
525*5088Sab196087 
526*5088Sab196087 	return (0);
527*5088Sab196087 }
528*5088Sab196087 
529*5088Sab196087 
530*5088Sab196087 /*
531*5088Sab196087  * Command completion function for sys:load
532*5088Sab196087  */
533*5088Sab196087 /*ARGSUSED*/
534*5088Sab196087 static void
535*5088Sab196087 cpl_load(void *obj_state, void *cpldata, int argc, const char *argv[],
536*5088Sab196087     int num_opt)
537*5088Sab196087 {
538*5088Sab196087 	/*
539*5088Sab196087 	 * Module names. Note that this causes elfedit to load all
540*5088Sab196087 	 * of the modules, which probably makes the current load
541*5088Sab196087 	 * operation unnecessary. This could be improved, but I don't
542*5088Sab196087 	 * see it as worth the complexity. Explicit load calls are
543*5088Sab196087 	 * rare, and the user will usually not use command completion.
544*5088Sab196087 	 */
545*5088Sab196087 	elfedit_cpl_module(cpldata, 1);
546*5088Sab196087 }
547*5088Sab196087 
548*5088Sab196087 
549*5088Sab196087 /*
550*5088Sab196087  * Implementation of sys:quit
551*5088Sab196087  */
552*5088Sab196087 /*ARGSUSED*/
553*5088Sab196087 static elfedit_cmdret_t
554*5088Sab196087 cmd_quit(void *obj_state, int argc, const char *argv[])
555*5088Sab196087 {
556*5088Sab196087 	elfedit_getopt_state_t	getopt_state;
557*5088Sab196087 	elfedit_getopt_ret_t	*getopt_ret;
558*5088Sab196087 	int			force = 0;
559*5088Sab196087 	const char		*file;
560*5088Sab196087 	int			fd;
561*5088Sab196087 	Elf			*elf;
562*5088Sab196087 
563*5088Sab196087 	elfedit_getopt_init(&getopt_state, &argc, &argv);
564*5088Sab196087 	while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) {
565*5088Sab196087 		switch (getopt_ret->gor_idmask) {
566*5088Sab196087 		case SYS_OPT_F_FORCE:
567*5088Sab196087 			force = 1;
568*5088Sab196087 			break;
569*5088Sab196087 		}
570*5088Sab196087 	}
571*5088Sab196087 	if (argc != 0)
572*5088Sab196087 		elfedit_command_usage();
573*5088Sab196087 
574*5088Sab196087 	if (state.file.present) {
575*5088Sab196087 		/*
576*5088Sab196087 		 * If session is not READONLY, then refuse to quit if file
577*5088Sab196087 		 * needs flushing and -f option was not used.
578*5088Sab196087 		 */
579*5088Sab196087 		if (!(state.flags & ELFEDIT_F_READONLY) && state.file.dirty &&
580*5088Sab196087 		    !force)
581*5088Sab196087 			elfedit_msg(ELFEDIT_MSG_ERR,
582*5088Sab196087 			    MSG_INTL(MSG_ERR_NODIRTYQUIT));
583*5088Sab196087 
584*5088Sab196087 		get_obj_state_info(obj_state, &file, &fd, &elf);
585*5088Sab196087 		(void) close(fd);
586*5088Sab196087 		(void) elf_end(elf);
587*5088Sab196087 		free(obj_state);
588*5088Sab196087 	}
589*5088Sab196087 
590*5088Sab196087 	elfedit_exit(0);
591*5088Sab196087 	/*NOTREACHED*/
592*5088Sab196087 	return (0);
593*5088Sab196087 }
594*5088Sab196087 
595*5088Sab196087 
596*5088Sab196087 /*
597*5088Sab196087  * Implementation of sys:status
598*5088Sab196087  */
599*5088Sab196087 /*ARGSUSED*/
600*5088Sab196087 static elfedit_cmdret_t
601*5088Sab196087 cmd_status(void *obj_state, int argc, const char *argv[])
602*5088Sab196087 {
603*5088Sab196087 	MODLIST_T	*modlist;
604*5088Sab196087 	const char	*s;
605*5088Sab196087 	size_t		i;
606*5088Sab196087 
607*5088Sab196087 	if (argc > 0)
608*5088Sab196087 		elfedit_command_usage();
609*5088Sab196087 
610*5088Sab196087 	/*
611*5088Sab196087 	 * This command can produce an arbitrary amount of output, so
612*5088Sab196087 	 * run a pager.
613*5088Sab196087 	 */
614*5088Sab196087 	elfedit_pager_init();
615*5088Sab196087 
616*5088Sab196087 	/* Files */
617*5088Sab196087 	if (state.file.present == 0) {
618*5088Sab196087 		elfedit_printf(MSG_INTL(MSG_HLPFMT_INFILENONE));
619*5088Sab196087 	} else if (state.flags & ELFEDIT_F_READONLY) {
620*5088Sab196087 		elfedit_printf(MSG_INTL(MSG_HLPFMT_INFILERO),
621*5088Sab196087 		    state.file.infile);
622*5088Sab196087 	} else {
623*5088Sab196087 		elfedit_printf(MSG_INTL(MSG_HLPFMT_INFILE), state.file.infile);
624*5088Sab196087 		elfedit_printf(MSG_INTL(MSG_HLPFMT_OUTFILE),
625*5088Sab196087 		    state.file.outfile);
626*5088Sab196087 	}
627*5088Sab196087 	if (state.file.dirty)
628*5088Sab196087 		elfedit_printf(MSG_INTL(MSG_HLPFMT_CNGPENDING));
629*5088Sab196087 
630*5088Sab196087 	/* Option Variables */
631*5088Sab196087 	elfedit_printf(MSG_INTL(MSG_HLPFMT_VARHDR));
632*5088Sab196087 	elfedit_printf(MSG_INTL(MSG_HLPFMT_AFLG),
633*5088Sab196087 	    (state.flags & ELFEDIT_F_AUTOPRINT) ? MSG_ORIG(MSG_STR_ON) :
634*5088Sab196087 	    MSG_ORIG(MSG_STR_OFF));
635*5088Sab196087 	elfedit_printf(MSG_INTL(MSG_HLPFMT_DFLG),
636*5088Sab196087 	    (state.flags & ELFEDIT_F_DEBUG) ? MSG_ORIG(MSG_STR_ON) :
637*5088Sab196087 	    MSG_ORIG(MSG_STR_OFF));
638*5088Sab196087 	elfedit_printf(MSG_INTL(MSG_HLPFMT_OFLG),
639*5088Sab196087 	    elfedit_atoconst_value_to_str(ELFEDIT_CONST_OUTSTYLE,
640*5088Sab196087 	    state.outstyle, 1));
641*5088Sab196087 
642*5088Sab196087 	/* Module Load Path */
643*5088Sab196087 	elfedit_printf(MSG_INTL(MSG_HLPFMT_PATHHDR));
644*5088Sab196087 	for (i = 0; i < state.modpath.n; i++)
645*5088Sab196087 		elfedit_printf(MSG_ORIG(MSG_HLPFMT_PATHELT),
646*5088Sab196087 		    state.modpath.seg[i]);
647*5088Sab196087 
648*5088Sab196087 	/* Currently Loaded Modules */
649*5088Sab196087 	elfedit_printf(MSG_INTL(MSG_HLPFMT_MODHDR));
650*5088Sab196087 	for (modlist = state.modlist; modlist;
651*5088Sab196087 	    modlist = modlist->ml_next) {
652*5088Sab196087 		s = modlist->ml_path ? modlist->ml_path :
653*5088Sab196087 		    MSG_INTL(MSG_FMT_BUILTIN);
654*5088Sab196087 		elfedit_printf(MSG_ORIG(MSG_HLPFMT_NAMDSCCOL),
655*5088Sab196087 		    modlist->ml_mod->mod_name, s);
656*5088Sab196087 	}
657*5088Sab196087 
658*5088Sab196087 	return (ELFEDIT_CMDRET_NONE);
659*5088Sab196087 }
660*5088Sab196087 
661*5088Sab196087 /*
662*5088Sab196087  * Implementation of sys:set
663*5088Sab196087  */
664*5088Sab196087 /*ARGSUSED*/
665*5088Sab196087 static elfedit_cmdret_t
666*5088Sab196087 cmd_set(void *obj_state, int argc, const char *argv[])
667*5088Sab196087 {
668*5088Sab196087 	if ((argc != 2) || (strlen(argv[0]) > 1))
669*5088Sab196087 		elfedit_command_usage();
670*5088Sab196087 
671*5088Sab196087 	switch (**argv) {
672*5088Sab196087 	case 'a':
673*5088Sab196087 	case 'A':
674*5088Sab196087 		if (elfedit_atobool(argv[1], MSG_INTL(MSG_SYSSET_A)))
675*5088Sab196087 			state.flags |= ELFEDIT_F_AUTOPRINT;
676*5088Sab196087 		else
677*5088Sab196087 			state.flags &= ~ELFEDIT_F_AUTOPRINT;
678*5088Sab196087 		break;
679*5088Sab196087 
680*5088Sab196087 	case 'd':
681*5088Sab196087 	case 'D':
682*5088Sab196087 		if (elfedit_atobool(argv[1], MSG_INTL(MSG_SYSSET_D)))
683*5088Sab196087 			state.flags |= ELFEDIT_F_DEBUG;
684*5088Sab196087 		else
685*5088Sab196087 			state.flags &= ~ELFEDIT_F_DEBUG;
686*5088Sab196087 		break;
687*5088Sab196087 
688*5088Sab196087 	case 'o':
689*5088Sab196087 	case 'O':
690*5088Sab196087 		if (elfedit_atooutstyle(argv[1], &state.outstyle) == 0)
691*5088Sab196087 			elfedit_msg(ELFEDIT_MSG_ERR,
692*5088Sab196087 			    MSG_INTL(MSG_ERR_BADOSTYLE), argv[1]);
693*5088Sab196087 		break;
694*5088Sab196087 
695*5088Sab196087 	default:
696*5088Sab196087 		elfedit_command_usage();
697*5088Sab196087 	}
698*5088Sab196087 
699*5088Sab196087 	return (0);
700*5088Sab196087 }
701*5088Sab196087 
702*5088Sab196087 
703*5088Sab196087 /*
704*5088Sab196087  * Command completion function for sys:set
705*5088Sab196087  */
706*5088Sab196087 /*ARGSUSED*/
707*5088Sab196087 static void
708*5088Sab196087 cpl_set(void *obj_state, void *cpldata, int argc, const char *argv[],
709*5088Sab196087     int num_opt)
710*5088Sab196087 {
711*5088Sab196087 	const char *s;
712*5088Sab196087 
713*5088Sab196087 	/*
714*5088Sab196087 	 * This command doesn't accept options, so num_opt should be
715*5088Sab196087 	 * 0. This is a defensive measure, in case that should change.
716*5088Sab196087 	 */
717*5088Sab196087 	argc -= num_opt;
718*5088Sab196087 	argv += num_opt;
719*5088Sab196087 
720*5088Sab196087 	if ((argc < 1) || (argc > 2))
721*5088Sab196087 		return;
722*5088Sab196087 
723*5088Sab196087 	if (argc == 1) {	/* The first argument is a variable letter */
724*5088Sab196087 		elfedit_cpl_match(cpldata, MSG_ORIG(MSG_STR_A), 1);
725*5088Sab196087 		elfedit_cpl_match(cpldata, MSG_ORIG(MSG_STR_D), 1);
726*5088Sab196087 		elfedit_cpl_match(cpldata, MSG_ORIG(MSG_STR_O), 1);
727*5088Sab196087 		elfedit_cpl_match(cpldata, MSG_ORIG(MSG_STR_W), 1);
728*5088Sab196087 		return;
729*5088Sab196087 	}
730*5088Sab196087 
731*5088Sab196087 	/* We're dealing with the second argument, the value */
732*5088Sab196087 	s = argv[0];
733*5088Sab196087 	if (strlen(s) > 1)	/* One letter variables */
734*5088Sab196087 		return;
735*5088Sab196087 	switch (*s) {
736*5088Sab196087 	case 'a':		/* Booleans */
737*5088Sab196087 	case 'A':
738*5088Sab196087 	case 'd':
739*5088Sab196087 	case 'D':
740*5088Sab196087 	case 'w':
741*5088Sab196087 	case 'W':
742*5088Sab196087 		/* The second argument is a boolean */
743*5088Sab196087 		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_BOOL);
744*5088Sab196087 
745*5088Sab196087 		/* The numbers are not symbolic, but we want them in the list */
746*5088Sab196087 		elfedit_cpl_match(cpldata, MSG_ORIG(MSG_STR_0), 1);
747*5088Sab196087 		elfedit_cpl_match(cpldata, MSG_ORIG(MSG_STR_1), 1);
748*5088Sab196087 		break;
749*5088Sab196087 
750*5088Sab196087 	case 'o':		/* Output style */
751*5088Sab196087 	case 'O':
752*5088Sab196087 		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_OUTSTYLE);
753*5088Sab196087 		break;
754*5088Sab196087 	}
755*5088Sab196087 }
756*5088Sab196087 
757*5088Sab196087 
758*5088Sab196087 /*
759*5088Sab196087  * Implementation of sys:unload
760*5088Sab196087  */
761*5088Sab196087 /*ARGSUSED*/
762*5088Sab196087 static elfedit_cmdret_t
763*5088Sab196087 cmd_unload(void *obj_state, int argc, const char *argv[])
764*5088Sab196087 {
765*5088Sab196087 	elfedit_getopt_state_t	getopt_state;
766*5088Sab196087 	elfedit_getopt_ret_t	*getopt_ret;
767*5088Sab196087 	MODLIST_T		*moddef;
768*5088Sab196087 	int			do_all = 0;
769*5088Sab196087 
770*5088Sab196087 	elfedit_getopt_init(&getopt_state, &argc, &argv);
771*5088Sab196087 	while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) {
772*5088Sab196087 		switch (getopt_ret->gor_idmask) {
773*5088Sab196087 		case SYS_OPT_F_ALL:
774*5088Sab196087 			do_all = 1;
775*5088Sab196087 			break;
776*5088Sab196087 		}
777*5088Sab196087 	}
778*5088Sab196087 
779*5088Sab196087 	/*
780*5088Sab196087 	 * If -a is specified, unload everything except builtins. Don't
781*5088Sab196087 	 * allow plain arguments in this case because there is nothing
782*5088Sab196087 	 * left to unload after -a.
783*5088Sab196087 	 */
784*5088Sab196087 	if (do_all) {
785*5088Sab196087 		if (argc > 0)
786*5088Sab196087 			elfedit_command_usage();
787*5088Sab196087 		/*
788*5088Sab196087 		 * Until we run out of non-builtin modules, take the first
789*5088Sab196087 		 * one from the list and unload it. Each removal alters
790*5088Sab196087 		 * the list, so we always start at the beginning, but this
791*5088Sab196087 		 * is efficient since we always remove the first available item
792*5088Sab196087 		 */
793*5088Sab196087 		while (state.modlist != NULL) {
794*5088Sab196087 			for (moddef = state.modlist; moddef != NULL;
795*5088Sab196087 			    moddef = moddef->ml_next)
796*5088Sab196087 				if (moddef->ml_dl_hdl != NULL) break;
797*5088Sab196087 
798*5088Sab196087 			/* If we made it to the end, then the list is empty */
799*5088Sab196087 			if (moddef == NULL)
800*5088Sab196087 				break;
801*5088Sab196087 
802*5088Sab196087 			elfedit_unload_module(moddef->ml_mod->mod_name);
803*5088Sab196087 		}
804*5088Sab196087 		return (0);
805*5088Sab196087 	}
806*5088Sab196087 
807*5088Sab196087 	/* Unload each module individually */
808*5088Sab196087 	for (; argc-- > 0; argv++)
809*5088Sab196087 		elfedit_unload_module(*argv);
810*5088Sab196087 
811*5088Sab196087 	return (0);
812*5088Sab196087 }
813*5088Sab196087 
814*5088Sab196087 
815*5088Sab196087 /*
816*5088Sab196087  * Command completion function for sys:unload
817*5088Sab196087  */
818*5088Sab196087 /*ARGSUSED*/
819*5088Sab196087 static void
820*5088Sab196087 cpl_unload(void *obj_state, void *cpldata, int argc, const char *argv[],
821*5088Sab196087     int num_opt)
822*5088Sab196087 {
823*5088Sab196087 	/*
824*5088Sab196087 	 * Module names. Don't allow elfedit to load all the modules,
825*5088Sab196087 	 * as the only modules we want to unload are those already
826*5088Sab196087 	 * in memory.
827*5088Sab196087 	 */
828*5088Sab196087 	elfedit_cpl_module(cpldata, 0);
829*5088Sab196087 }
830*5088Sab196087 
831*5088Sab196087 
832*5088Sab196087 /*
833*5088Sab196087  * Implementation of sys:write
834*5088Sab196087  */
835*5088Sab196087 /*ARGSUSED2*/
836*5088Sab196087 static elfedit_cmdret_t
837*5088Sab196087 cmd_write(void *obj_state, int argc, const char *argv[])
838*5088Sab196087 {
839*5088Sab196087 	const char	*file;
840*5088Sab196087 	int		fd;
841*5088Sab196087 	Elf		*elf;
842*5088Sab196087 
843*5088Sab196087 	if (argc != 0)
844*5088Sab196087 		elfedit_command_usage();
845*5088Sab196087 
846*5088Sab196087 	if (state.file.present != 0) {
847*5088Sab196087 		if (state.flags & ELFEDIT_F_READONLY)
848*5088Sab196087 			elfedit_msg(ELFEDIT_MSG_ERR,
849*5088Sab196087 			    MSG_INTL(MSG_ERR_READONLY));
850*5088Sab196087 
851*5088Sab196087 		get_obj_state_info(obj_state, &file, &fd, &elf);
852*5088Sab196087 		if (elf_update(elf, ELF_C_WRITE) == -1)
853*5088Sab196087 			elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_LIBELF),
854*5088Sab196087 			    file, MSG_ORIG(MSG_ELF_UPDATE),
855*5088Sab196087 			    elf_errmsg(elf_errno()));
856*5088Sab196087 
857*5088Sab196087 		/*
858*5088Sab196087 		 * An update has succeeded for this file, so revoke the need
859*5088Sab196087 		 * to unlink it on exit.
860*5088Sab196087 		 */
861*5088Sab196087 		state.file.unlink_on_exit = 0;
862*5088Sab196087 	}
863*5088Sab196087 
864*5088Sab196087 	return (ELFEDIT_CMDRET_FLUSH);
865*5088Sab196087 }
866*5088Sab196087 
867*5088Sab196087 
868*5088Sab196087 
869*5088Sab196087 
870*5088Sab196087 
871*5088Sab196087 /*ARGSUSED*/
872*5088Sab196087 MODLIST_T *
873*5088Sab196087 elfedit_sys_init(elfedit_module_version_t version)
874*5088Sab196087 {
875*5088Sab196087 	/* sys:help */
876*5088Sab196087 	static const char *name_help[] = { MSG_ORIG(MSG_SYS_CMD_HELP),
877*5088Sab196087 	    MSG_ORIG(MSG_SYS_CMD_HELP_A1), MSG_ORIG(MSG_SYS_CMD_HELP_A2),
878*5088Sab196087 	    NULL };
879*5088Sab196087 	static elfedit_cmd_optarg_t opt_help[] = {
880*5088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_S),
881*5088Sab196087 		    /* MSG_INTL(MSG_SYS_OPTDESC_HELP_S) */
882*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_OPTDESC_HELP_S), 0,
883*5088Sab196087 		    SYS_OPT_F_SYNOPSIS, 0 },
884*5088Sab196087 		{ NULL }
885*5088Sab196087 	};
886*5088Sab196087 	static elfedit_cmd_optarg_t arg_help[] = {
887*5088Sab196087 		{ MSG_ORIG(MSG_STR_ARG),
888*5088Sab196087 		    /* MSG_INTL(MSG_ARGDESC_HELP_ARG) */
889*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_ARGDESC_HELP_ARG),
890*5088Sab196087 		    ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT },
891*5088Sab196087 		{ NULL }
892*5088Sab196087 	};
893*5088Sab196087 
894*5088Sab196087 	/* sys:load */
895*5088Sab196087 	static const char *name_load[] = {
896*5088Sab196087 	    MSG_ORIG(MSG_SYS_CMD_LOAD), NULL };
897*5088Sab196087 	static elfedit_cmd_optarg_t opt_load[] = {
898*5088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_A),
899*5088Sab196087 		    /* MSG_INTL(MSG_SYS_OPTDESC_LOAD_A) */
900*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_OPTDESC_LOAD_A), 0,
901*5088Sab196087 		    SYS_OPT_F_ALL, 0 },
902*5088Sab196087 		{ NULL }
903*5088Sab196087 	};
904*5088Sab196087 	static elfedit_cmd_optarg_t arg_load[] = {
905*5088Sab196087 		{ MSG_ORIG(MSG_STR_MODNAME),
906*5088Sab196087 		    /* MSG_INTL(MSG_ARGDESC_LOAD_MODNAME) */
907*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_ARGDESC_LOAD_MODNAME),
908*5088Sab196087 		    ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT },
909*5088Sab196087 		{ NULL }
910*5088Sab196087 	};
911*5088Sab196087 
912*5088Sab196087 	/* sys:quit */
913*5088Sab196087 	static const char *name_quit[] = { MSG_ORIG(MSG_SYS_CMD_QUIT),
914*5088Sab196087 	    MSG_ORIG(MSG_SYS_CMD_QUIT_A1), MSG_ORIG(MSG_SYS_CMD_QUIT_A2),
915*5088Sab196087 	    NULL };
916*5088Sab196087 	static elfedit_cmd_optarg_t opt_quit[] = {
917*5088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_F),
918*5088Sab196087 		    /* MSG_INTL(MSG_SYS_OPTDESC_QUIT_F) */
919*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_OPTDESC_QUIT_F), 0,
920*5088Sab196087 		    SYS_OPT_F_FORCE, 0 },
921*5088Sab196087 		{ NULL }
922*5088Sab196087 	};
923*5088Sab196087 
924*5088Sab196087 	/* sys:status */
925*5088Sab196087 	static const char *name_status[] = {
926*5088Sab196087 	    MSG_ORIG(MSG_SYS_CMD_STATUS), NULL };
927*5088Sab196087 
928*5088Sab196087 	/* sys:set */
929*5088Sab196087 	static const char *name_set[] = {
930*5088Sab196087 	    MSG_ORIG(MSG_SYS_CMD_SET), NULL };
931*5088Sab196087 	static elfedit_cmd_optarg_t arg_set[] = {
932*5088Sab196087 		{ MSG_ORIG(MSG_STR_OPTION),
933*5088Sab196087 		    /* MSG_INTL(MSG_ARGDESC_SET_OPTION) */
934*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_ARGDESC_SET_OPTION), 0 },
935*5088Sab196087 		{ MSG_ORIG(MSG_STR_VALUE),
936*5088Sab196087 		    /* MSG_INTL(MSG_ARGDESC_SET_VALUE) */
937*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_ARGDESC_SET_VALUE), 0 },
938*5088Sab196087 		{ NULL }
939*5088Sab196087 	};
940*5088Sab196087 
941*5088Sab196087 	/* sys:unload */
942*5088Sab196087 	static const char *name_unload[] = {
943*5088Sab196087 	    MSG_ORIG(MSG_SYS_CMD_UNLOAD), NULL };
944*5088Sab196087 	static elfedit_cmd_optarg_t opt_unload[] = {
945*5088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_A),
946*5088Sab196087 		    /* MSG_INTL(MSG_SYS_OPTDESC_UNLOAD_A) */
947*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_OPTDESC_UNLOAD_A), 0,
948*5088Sab196087 		    SYS_OPT_F_ALL, 0},
949*5088Sab196087 		{ NULL }
950*5088Sab196087 	};
951*5088Sab196087 	static elfedit_cmd_optarg_t arg_unload[] = {
952*5088Sab196087 		{ MSG_ORIG(MSG_STR_MODNAME),
953*5088Sab196087 		    /* MSG_INTL(MSG_ARGDESC_UNLOAD_MODNAME) */
954*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_ARGDESC_UNLOAD_MODNAME),
955*5088Sab196087 		    ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT },
956*5088Sab196087 		{ NULL }
957*5088Sab196087 	};
958*5088Sab196087 
959*5088Sab196087 	/* sys:write */
960*5088Sab196087 	static const char *name_write[] = { MSG_ORIG(MSG_SYS_CMD_WRITE),
961*5088Sab196087 	    MSG_ORIG(MSG_SYS_CMD_WRITE_A1), MSG_ORIG(MSG_SYS_CMD_WRITE_A2),
962*5088Sab196087 	    NULL };
963*5088Sab196087 
964*5088Sab196087 	static elfedit_cmd_t cmds[] = {
965*5088Sab196087 		/* sym:help */
966*5088Sab196087 		{ (elfedit_cmd_func_t *)cmd_help,
967*5088Sab196087 		    (elfedit_cmdcpl_func_t *)cpl_help, name_help,
968*5088Sab196087 		    /* MSG_INTL(MSG_SYS_DESC_HELP) */
969*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_DESC_HELP),
970*5088Sab196087 		    /* MSG_INTL(MSG_SYS_HELP_HELP) */
971*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_HELP_HELP),
972*5088Sab196087 		    opt_help, arg_help },
973*5088Sab196087 
974*5088Sab196087 		/* sym:load */
975*5088Sab196087 		{ (elfedit_cmd_func_t *)cmd_load,
976*5088Sab196087 		    (elfedit_cmdcpl_func_t *)cpl_load, name_load,
977*5088Sab196087 		    /* MSG_INTL(MSG_SYS_DESC_LOAD) */
978*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_DESC_LOAD),
979*5088Sab196087 		    /* MSG_INTL(MSG_SYS_HELP_LOAD) */
980*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_HELP_LOAD),
981*5088Sab196087 		    opt_load, arg_load },
982*5088Sab196087 
983*5088Sab196087 		/* sym:quit */
984*5088Sab196087 		{ (elfedit_cmd_func_t *)cmd_quit, NULL, name_quit,
985*5088Sab196087 		    /* MSG_INTL(MSG_SYS_DESC_QUIT) */
986*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_DESC_QUIT),
987*5088Sab196087 		    /* MSG_INTL(MSG_SYS_HELP_QUIT) */
988*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_HELP_QUIT),
989*5088Sab196087 		    opt_quit, NULL },
990*5088Sab196087 
991*5088Sab196087 		/* sym:status */
992*5088Sab196087 		{ (elfedit_cmd_func_t *)cmd_status, NULL, name_status,
993*5088Sab196087 		    /* MSG_INTL(MSG_SYS_DESC_STATUS) */
994*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_DESC_STATUS),
995*5088Sab196087 		    /* MSG_INTL(MSG_SYS_HELP_STATUS) */
996*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_HELP_STATUS),
997*5088Sab196087 		    NULL, NULL },
998*5088Sab196087 
999*5088Sab196087 		/* sym:set */
1000*5088Sab196087 		{ (elfedit_cmd_func_t *)cmd_set,
1001*5088Sab196087 		    (elfedit_cmdcpl_func_t *)cpl_set, name_set,
1002*5088Sab196087 		    /* MSG_INTL(MSG_SYS_DESC_SET) */
1003*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_DESC_SET),
1004*5088Sab196087 		    /* MSG_INTL(MSG_SYS_HELP_SET) */
1005*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_HELP_SET),
1006*5088Sab196087 		    NULL, arg_set },
1007*5088Sab196087 
1008*5088Sab196087 		/* sym:unload */
1009*5088Sab196087 		{ (elfedit_cmd_func_t *)cmd_unload,
1010*5088Sab196087 		    (elfedit_cmdcpl_func_t *)cpl_unload, name_unload,
1011*5088Sab196087 		    /* MSG_INTL(MSG_SYS_DESC_UNLOAD) */
1012*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_DESC_UNLOAD),
1013*5088Sab196087 		    /* MSG_INTL(MSG_SYS_HELP_UNLOAD) */
1014*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_HELP_UNLOAD),
1015*5088Sab196087 		    opt_unload, arg_unload },
1016*5088Sab196087 
1017*5088Sab196087 		/* sym:write */
1018*5088Sab196087 		{ (elfedit_cmd_func_t *)cmd_write, NULL, name_write,
1019*5088Sab196087 		    /* MSG_INTL(MSG_SYS_DESC_WRITE) */
1020*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_DESC_WRITE),
1021*5088Sab196087 		    /* MSG_INTL(MSG_SYS_HELP_WRITE) */
1022*5088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_HELP_WRITE),
1023*5088Sab196087 		    NULL, NULL},
1024*5088Sab196087 
1025*5088Sab196087 		{ NULL }
1026*5088Sab196087 	};
1027*5088Sab196087 
1028*5088Sab196087 	static elfedit_module_t module = {
1029*5088Sab196087 	    ELFEDIT_VER_CURRENT, MSG_ORIG(MSG_MOD_SYS),
1030*5088Sab196087 	    /* MSG_INTL(MSG_MOD_SYS_DESC) */
1031*5088Sab196087 	    ELFEDIT_I18NHDL(MSG_MOD_SYS_DESC),
1032*5088Sab196087 	    cmds, mod_i18nhdl_to_str };
1033*5088Sab196087 
1034*5088Sab196087 	static MODLIST_T moddef = {
1035*5088Sab196087 		NULL,		/* next */
1036*5088Sab196087 		(elfeditGC_module_t *)&module,	/* Module definition */
1037*5088Sab196087 		NULL,		/* Didn't dlopen() it, so NULL handle */
1038*5088Sab196087 		NULL		/* Didn't dlopen() it, so no file path */
1039*5088Sab196087 	};
1040*5088Sab196087 
1041*5088Sab196087 	return (&moddef);
1042*5088Sab196087 }
1043