xref: /onnv-gate/usr/src/cmd/sgs/elfedit/common/sys.c (revision 6206:6b0ed502a8e7)
15088Sab196087 /*
25088Sab196087  * CDDL HEADER START
35088Sab196087  *
45088Sab196087  * The contents of this file are subject to the terms of the
55088Sab196087  * Common Development and Distribution License (the "License").
65088Sab196087  * You may not use this file except in compliance with the License.
75088Sab196087  *
85088Sab196087  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95088Sab196087  * or http://www.opensolaris.org/os/licensing.
105088Sab196087  * See the License for the specific language governing permissions
115088Sab196087  * and limitations under the License.
125088Sab196087  *
135088Sab196087  * When distributing Covered Code, include this CDDL HEADER in each
145088Sab196087  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155088Sab196087  * If applicable, add the following below this CDDL HEADER, with the
165088Sab196087  * fields enclosed by brackets "[]" replaced with your own identifying
175088Sab196087  * information: Portions Copyright [yyyy] [name of copyright owner]
185088Sab196087  *
195088Sab196087  * CDDL HEADER END
205088Sab196087  */
215088Sab196087 
225088Sab196087 /*
23*6206Sab196087  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
245088Sab196087  * Use is subject to license terms.
255088Sab196087  */
265088Sab196087 #pragma ident	"%Z%%M%	%I%	%E% SMI"
275088Sab196087 
285088Sab196087 #include <fcntl.h>
295088Sab196087 #include <sys/types.h>
305088Sab196087 #include <sys/stat.h>
315088Sab196087 #include <unistd.h>
325088Sab196087 #include <strings.h>
335088Sab196087 #include <elfedit.h>
345088Sab196087 #include "_elfedit.h"
355088Sab196087 #include "msg.h"
365088Sab196087 
375088Sab196087 
385088Sab196087 
395088Sab196087 
405088Sab196087 /*
415088Sab196087  * This file provides the builtin sys module. It is similar to the
425088Sab196087  * other modules, but differs in several important ways:
435088Sab196087  *
445088Sab196087  *	- It is built as a static part of elfedit, and not
455088Sab196087  *		as a sharable object.
465088Sab196087  *	- It must be avaialble before the ELFCLASS of the object
475088Sab196087  *		is known, so it is not ELFCLASS specific. We don't build
48*6206Sab196087  *		it twice with <sys/machelf.h>, as we do for the loadable
49*6206Sab196087  *		modules. This means that commands need to test for the type
505088Sab196087  *		of their obj_state argument at runtime.
515088Sab196087  *	- The init function signature is different. We build an entire
525088Sab196087  *		module definition statically.
535088Sab196087  */
545088Sab196087 
555088Sab196087 
565088Sab196087 
575088Sab196087 /*
585088Sab196087  * This function is supplied to elfedit through our elfedit_module_t
595088Sab196087  * definition. It translates the opaque elfedit_i18nhdl_t handles
605088Sab196087  * in our module interface into the actual strings for elfedit to
615088Sab196087  * use.
625088Sab196087  *
635088Sab196087  * note:
645088Sab196087  *	This module uses Msg codes for its i18n handle type.
655088Sab196087  *	So the translation is simply to use MSG_INTL() to turn
665088Sab196087  *	it into a string and return it.
675088Sab196087  */
685088Sab196087 static const char *
mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl)695088Sab196087 mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl)
705088Sab196087 {
715088Sab196087 	Msg msg = (Msg)hdl;
725088Sab196087 
735088Sab196087 	return (MSG_INTL(msg));
745088Sab196087 }
755088Sab196087 
765088Sab196087 
775088Sab196087 
785088Sab196087 /*
795088Sab196087  * The sys_opt_t enum specifies a bit value for every optional argument
805088Sab196087  * allowed by a command in this module.
815088Sab196087  */
825088Sab196087 typedef enum {
835088Sab196087 	SYS_OPT_F_ALL =		1,	/* -a */
845088Sab196087 	SYS_OPT_F_FORCE =	2,	/* -f */
855088Sab196087 	SYS_OPT_F_SYNOPSIS =	4,	/* -s */
865088Sab196087 } dyn_opt_t;
875088Sab196087 
885088Sab196087 
895088Sab196087 /*
905088Sab196087  * Given a generic (void *) pointer to an obj_state argument, determine
915088Sab196087  * which type it is, and return the st_file, st_fd and st_elf fields.
925088Sab196087  */
935088Sab196087 static void
get_obj_state_info(void * obj_state,const char ** file,int * fd,Elf ** elf)945088Sab196087 get_obj_state_info(void *obj_state, const char **file, int *fd, Elf **elf)
955088Sab196087 {
965088Sab196087 	if (state.elf.elfclass == ELFCLASS32) {
975088Sab196087 		elfedit32_obj_state_t *s = (elfedit32_obj_state_t *)obj_state;
985088Sab196087 
995088Sab196087 		*file = s->os_file;
1005088Sab196087 		*fd = s->os_fd;
1015088Sab196087 		*elf = s->os_elf;
1025088Sab196087 	} else {
1035088Sab196087 		elfedit64_obj_state_t *s = (elfedit64_obj_state_t *)obj_state;
1045088Sab196087 
1055088Sab196087 		*file = s->os_file;
1065088Sab196087 		*fd = s->os_fd;
1075088Sab196087 		*elf = s->os_elf;
1085088Sab196087 	}
1095088Sab196087 }
1105088Sab196087 
1115088Sab196087 
1125088Sab196087 
1135088Sab196087 /*
1145088Sab196087  * Helper for cmd_help(). Displays synopsis information for one command.
1155088Sab196087  */
1165088Sab196087 static void
cmd_help_synopsis(elfeditGC_module_t * mod,elfeditGC_cmd_t * cmd)1175088Sab196087 cmd_help_synopsis(elfeditGC_module_t *mod, elfeditGC_cmd_t *cmd)
1185088Sab196087 {
1195088Sab196087 	char		name_buf[128];
1205088Sab196087 	const char	*name;
1215088Sab196087 	const char	**cmd_name;
1225088Sab196087 
1235088Sab196087 	if (cmd->cmd_name[1] == NULL) {   /* One name */
1245088Sab196087 		name = *cmd->cmd_name;
1255088Sab196087 	} else {
1265088Sab196087 		const char *cname;
1275088Sab196087 		int need_comma = 0;
1285088Sab196087 
1295088Sab196087 		name = name_buf;
1305088Sab196087 		(void) snprintf(name_buf, sizeof (name_buf),
1315088Sab196087 		    MSG_ORIG(MSG_HLPFMT_MULTNAM), cmd->cmd_name[0]);
1325088Sab196087 		for (cmd_name = cmd->cmd_name + 1;
1335088Sab196087 		    *cmd_name; cmd_name++) {
1345088Sab196087 			if (need_comma)
1355088Sab196087 				(void) strlcat(name_buf,
1365088Sab196087 				    MSG_ORIG(MSG_STR_COMMA_SP),
1375088Sab196087 				    sizeof (name_buf));
1385088Sab196087 			need_comma = 1;
1395088Sab196087 			cname = (cmd_name[0][0] == '\0') ?
1405088Sab196087 			    MSG_INTL(MSG_HLPFMT_MODDEFCMD) : *cmd_name;
1415088Sab196087 			(void) strlcat(name_buf, cname,
1425088Sab196087 			    sizeof (name_buf));
1435088Sab196087 		}
1445088Sab196087 		(void) strlcat(name_buf, MSG_ORIG(MSG_STR_CPAREN),
1455088Sab196087 		    sizeof (name_buf));
1465088Sab196087 	}
1475088Sab196087 	elfedit_printf(MSG_ORIG(MSG_HLPFMT_NAMSUMHDR), name,
1485088Sab196087 	    (* mod->mod_i18nhdl_to_str)(cmd->cmd_desc));
1495088Sab196087 	elfedit_printf(MSG_INTL(MSG_HLPFMT_SUMSYNOPSIS),
1505088Sab196087 	    elfedit_format_command_usage(mod, cmd,
1515088Sab196087 	    MSG_ORIG(MSG_STR_HLPSUMINDENT),
1525088Sab196087 	    strlen(MSG_ORIG(MSG_STR_HLPSUMINDENT))));
1535088Sab196087 }
1545088Sab196087 
1555088Sab196087 
1565088Sab196087 /*
1575088Sab196087  * Helper for cmd_help(). Displays synopsis information for one module.
1585088Sab196087  */
1595088Sab196087 static void
cmd_help_showmod(elfeditGC_module_t * mod)1605088Sab196087 cmd_help_showmod(elfeditGC_module_t *mod)
1615088Sab196087 {
1625088Sab196087 	elfeditGC_cmd_t	*cmd;
1635088Sab196087 
1645088Sab196087 	elfedit_printf(MSG_ORIG(MSG_HLPFMT_NAMDSCHDR),
1655088Sab196087 	    mod->mod_name, (* mod->mod_i18nhdl_to_str)(mod->mod_desc));
1665088Sab196087 	for (cmd = mod->mod_cmds; cmd->cmd_func != NULL; cmd++) {
1675088Sab196087 		if (cmd != mod->mod_cmds)
1685088Sab196087 			elfedit_printf(MSG_ORIG(MSG_STR_NL));
1695088Sab196087 		elfedit_printf(MSG_ORIG(MSG_STR_NL));
1705088Sab196087 		cmd_help_synopsis(mod, cmd);
1715088Sab196087 	}
1725088Sab196087 }
1735088Sab196087 
1745088Sab196087 
1755088Sab196087 /*
1765088Sab196087  * Given a string containing newline characters, break it into
1775088Sab196087  * individual lines, and output each line with the given
1785088Sab196087  * prefix string in front.
1795088Sab196087  */
1805088Sab196087 static void
write_help_str(const char * str,const char * prefix)1815088Sab196087 write_help_str(const char *str, const char *prefix)
1825088Sab196087 {
1835088Sab196087 	size_t i;
1845088Sab196087 
1855088Sab196087 	if (str == NULL)
1865088Sab196087 		return;
1875088Sab196087 	while (*str) {
1885088Sab196087 		i = strcspn(str, MSG_ORIG(MSG_STR_NL));
1895088Sab196087 		if (*(str + i) != '\0')
1905088Sab196087 			i++;
1915088Sab196087 		elfedit_printf(prefix);
1925088Sab196087 		elfedit_write(str, i);
1935088Sab196087 		str += i;
1945088Sab196087 	}
1955088Sab196087 }
1965088Sab196087 
1975088Sab196087 
1985088Sab196087 /*
1995088Sab196087  * Given a title, and a NULL terminated list of option/argument
2005088Sab196087  * descriptors, output the list contents.
2015088Sab196087  */
2025088Sab196087 static void
write_optarg(elfeditGC_module_t * mod,const char * title,elfedit_cmd_optarg_t * optarg)2035088Sab196087 write_optarg(elfeditGC_module_t *mod, const char *title,
2045088Sab196087     elfedit_cmd_optarg_t *optarg)
2055088Sab196087 {
2065088Sab196087 	int			cnt;
2075088Sab196087 	int			len;
2085088Sab196087 	const char		*help;
2095088Sab196087 	elfedit_optarg_item_t	item;
2105088Sab196087 
2115088Sab196087 	elfedit_printf(title);
2125088Sab196087 	for (cnt = 0; optarg->oa_name != NULL; cnt++) {
2135088Sab196087 		elfedit_next_optarg(&optarg, &item);
2145088Sab196087 
2155088Sab196087 		/* Insert a blank line between items */
2165088Sab196087 		if (cnt > 0)
2175088Sab196087 			elfedit_printf(MSG_ORIG(MSG_STR_NL));
2185088Sab196087 
2195088Sab196087 		/* Indentation */
2205088Sab196087 		elfedit_printf(MSG_ORIG(MSG_STR_HLPINDENT));
2215088Sab196087 		len = strlen(item.oai_name);
2225088Sab196087 		help = elfedit_optarg_helpstr(mod, &item);
2235088Sab196087 		if (item.oai_flags & ELFEDIT_CMDOA_F_VALUE) {
2245088Sab196087 			len += 1 + strlen(item.oai_vname);
2255088Sab196087 			elfedit_printf(MSG_ORIG(MSG_STR_HLPOPTARG2),
2265088Sab196087 			    item.oai_name, item.oai_vname);
2275088Sab196087 		} else {
2285088Sab196087 			elfedit_printf(MSG_ORIG(MSG_STR_HLPOPTARG),
2295088Sab196087 			    item.oai_name);
2305088Sab196087 		}
2315088Sab196087 
2325088Sab196087 		/*
2335088Sab196087 		 * If name is too long, inject a newline to avoid
2345088Sab196087 		 * crowding the help text.
2355088Sab196087 		 */
2365088Sab196087 		if (len > 3)
2375088Sab196087 			elfedit_printf(MSG_ORIG(MSG_STR_NL));
2385088Sab196087 
2395088Sab196087 		/* Output the help text with a tab prefix */
2405088Sab196087 		write_help_str(help, MSG_ORIG(MSG_STR_TAB));
2415088Sab196087 	}
2425088Sab196087 }
2435088Sab196087 
2445088Sab196087 
2455088Sab196087 /*
2465088Sab196087  * Implementation of sys:help
2475088Sab196087  */
2485088Sab196087 /*ARGSUSED*/
2495088Sab196087 static elfedit_cmdret_t
cmd_help(void * obj_state,int argc,const char * argv[])2505088Sab196087 cmd_help(void *obj_state, int argc, const char *argv[])
2515088Sab196087 {
2525088Sab196087 #define	INITIAL_ITEM_ALLOC 4
2535088Sab196087 
2545088Sab196087 
2555088Sab196087 	/*
2565088Sab196087 	 * An array of this type is used to collect the data needed to
2575088Sab196087 	 * generate help output.
2585088Sab196087 	 */
2595088Sab196087 	typedef struct {
2605088Sab196087 		elfeditGC_cmd_t		*cmd;
2615088Sab196087 		elfeditGC_module_t	*cmd_mod;	/* Used with cmd */
2625088Sab196087 		elfeditGC_module_t	*mod;
2635088Sab196087 	} ITEM;
2645088Sab196087 
2655088Sab196087 	static ITEM	*item;
2665088Sab196087 	static int	item_cnt;
2675088Sab196087 
2685088Sab196087 	MODLIST_T		*modlist;
2695088Sab196087 	int			dispcnt;
2705088Sab196087 	size_t			i;
2715088Sab196087 	elfeditGC_module_t	*mod;
2725088Sab196087 	elfeditGC_cmd_t		*cmd;
2735088Sab196087 	int			minus_s = 0;
2745088Sab196087 	elfedit_getopt_state_t	getopt_state;
2755088Sab196087 	ITEM			*cur_item;
2765088Sab196087 
2775088Sab196087 	/*
2785088Sab196087 	 * Process options. The only option accepted is -s, so we
2795088Sab196087 	 * don't even have to check the idmask to know.
2805088Sab196087 	 */
2815088Sab196087 	elfedit_getopt_init(&getopt_state, &argc, &argv);
2825088Sab196087 	while (elfedit_getopt(&getopt_state) != NULL)
2835088Sab196087 		minus_s = 1;
2845088Sab196087 
2855088Sab196087 	/*
2865088Sab196087 	 * This command can produce an arbitrary amount of output, so
2875088Sab196087 	 * run a pager.
2885088Sab196087 	 */
2895088Sab196087 	elfedit_pager_init();
2905088Sab196087 
2915088Sab196087 	if (argc == 0) {
2925088Sab196087 		if (minus_s) {
2935088Sab196087 			/* Force all modules to load so we have data */
2945088Sab196087 			elfedit_load_modpath();
2955088Sab196087 			for (modlist = state.modlist; modlist;
2965088Sab196087 			    modlist = modlist->ml_next) {
2975088Sab196087 				cmd_help_showmod(modlist->ml_mod);
2985088Sab196087 				if (modlist->ml_next != NULL) {
2995088Sab196087 					elfedit_printf(MSG_ORIG(MSG_STR_NL));
3005088Sab196087 					elfedit_printf(MSG_ORIG(MSG_STR_NL));
3015088Sab196087 				}
3025088Sab196087 			}
3035088Sab196087 			return (ELFEDIT_CMDRET_NONE);
3045088Sab196087 		}
3055088Sab196087 
3065088Sab196087 		/*
3075088Sab196087 		 * If no arguments are present, we display a simple
3085088Sab196087 		 * "how to use help" tutorial, which will hopefully
3095088Sab196087 		 * bootstrap the user into a position where they
3105088Sab196087 		 * know how to run the help command, and then find
3115088Sab196087 		 * what they're really after.
3125088Sab196087 		 */
3135088Sab196087 		elfedit_printf(MSG_INTL(MSG_SYS_HELP_HELP_NOARG));
3145088Sab196087 		return (ELFEDIT_CMDRET_NONE);
3155088Sab196087 	}
3165088Sab196087 
3175088Sab196087 
3185088Sab196087 	/*
3195088Sab196087 	 * As we process the arguments, we are willing to treat each
3205088Sab196087 	 * one as either a module or a command:
3215088Sab196087 	 *	1) An item without a colon can be a module,
3225088Sab196087 	 *		or a command from the sys: module.
3235088Sab196087 	 *	2) An item with a colon, and no command part is
3245088Sab196087 	 *		a module, and it can also be the default
3255088Sab196087 	 *		command for the module, if it has one. We choose
3265088Sab196087 	 *		to only display the module info in this case, since
3275088Sab196087 	 *		the use of "" to represent the default command is
3285088Sab196087 	 *		an implementation detail, not a user-facing concept.
3295088Sab196087 	 *	3) An item with a colon and a command part can only be
3305088Sab196087 	 *		a command.
3315088Sab196087 	 *
3325088Sab196087 	 * Note that there are cases where one argument can have two
3335088Sab196087 	 * valid interpretations. In this case, we display them both.
3345088Sab196087 	 *
3355088Sab196087 	 * Pass over the arguments and determine how many distinct
3365088Sab196087 	 * "things" we need to display. At the same time, force any
3375088Sab196087 	 * needed modules to load so that the debug load messages won't
3385088Sab196087 	 * show up in between the displayed items, and save the command
3395088Sab196087 	 * and module definitions we will need to generate the output.
3405088Sab196087 	 */
3415088Sab196087 	if (argc > item_cnt) {
3425088Sab196087 		int n = (item_cnt == 0) ? INITIAL_ITEM_ALLOC : item_cnt;
3435088Sab196087 
3445088Sab196087 		while (n < argc)
3455088Sab196087 			n *= 2;
3465088Sab196087 
3475088Sab196087 		item = elfedit_realloc(MSG_INTL(MSG_ALLOC_HELPITEM), item,
3485088Sab196087 		    n * sizeof (*item));
3495088Sab196087 		item_cnt = n;
3505088Sab196087 	}
3515088Sab196087 
3525088Sab196087 	dispcnt = 0;
3535088Sab196087 	for (i = 0; i < argc; i++) {
3545088Sab196087 		const char *colon = strchr(argv[i], ':');
3555088Sab196087 
3565088Sab196087 		if (colon == NULL) {	/* No colon: sys: cmd or module */
3575088Sab196087 			item[i].cmd =
3585088Sab196087 			    elfedit_find_command(argv[i], 0, &item[i].cmd_mod);
3595088Sab196087 			if (item[i].cmd != NULL)
3605088Sab196087 				dispcnt++;
3615088Sab196087 
3625088Sab196087 			/*
3635088Sab196087 			 * Also try to load it as a module. If a command
3645088Sab196087 			 * was found, then this need not succeed. Otherwise,
3655088Sab196087 			 * it has to be a module, and we cause an error
3665088Sab196087 			 * to be issued if not.
3675088Sab196087 			 */
3685088Sab196087 			item[i].mod = elfedit_load_module(argv[i],
3695088Sab196087 			    item[i].cmd == NULL, 0);
3705088Sab196087 			if (item[i].mod != NULL)
3715088Sab196087 				dispcnt++;
3725088Sab196087 		} else if (*(colon + 1) == '\0') {
3735088Sab196087 			/* Just colon: Module (and maybe default command) */
3745088Sab196087 			char buf[ELFEDIT_MAXMODNAM + 1];
3755088Sab196087 			const char *str = argv[i];
3765088Sab196087 			int len = colon - str;
3775088Sab196087 
3785088Sab196087 			item[i].cmd = NULL;
3795088Sab196087 			/* Strip off the colon */
3805088Sab196087 			if (len < sizeof (buf)) {
3815088Sab196087 				(void) strncpy(buf, str, len);
3825088Sab196087 				buf[len] = '\0';
3835088Sab196087 				str = buf;
3845088Sab196087 			}
3855088Sab196087 			item[i].mod = elfedit_load_module(str, 1, 0);
3865088Sab196087 			dispcnt++;
3875088Sab196087 		} else {	/* A command */
3885088Sab196087 			item[i].cmd =
3895088Sab196087 			    elfedit_find_command(argv[i], 1, &item[i].cmd_mod);
3905088Sab196087 			dispcnt++;
3915088Sab196087 			item[i].mod = NULL;
3925088Sab196087 		}
3935088Sab196087 	}
3945088Sab196087 
3955088Sab196087 	/*
3965088Sab196087 	 * Having validated the items, loop over them again and produce
3975088Sab196087 	 * the required help output.
3985088Sab196087 	 */
3995088Sab196087 	for (cur_item = item; argc--; argv++, cur_item++) {
4005088Sab196087 
4015088Sab196087 
4025088Sab196087 		/* Help for a module? */
4035088Sab196087 		if (cur_item->mod != NULL) {
4045088Sab196087 			if (dispcnt > 1)
4055088Sab196087 				elfedit_printf(MSG_ORIG(MSG_HLPFMT_MULTIHDR),
4065088Sab196087 				    *argv);
4075088Sab196087 			cmd_help_showmod(cur_item->mod);
4085088Sab196087 			if ((dispcnt > 1) && (argc > 0))
4095088Sab196087 				elfedit_printf(MSG_INTL(MSG_HLPFMT_MULTIEND),
4105088Sab196087 				    argv[0], argv[1]);
4115088Sab196087 			/* An empty line after the last line of output */
4125088Sab196087 			elfedit_printf(MSG_ORIG(MSG_STR_NL));
4135088Sab196087 		}
4145088Sab196087 
4155088Sab196087 		/* Help for a command? */
4165088Sab196087 		if (cur_item->cmd == NULL)
4175088Sab196087 			continue;
4185088Sab196087 		cmd = cur_item->cmd;
4195088Sab196087 		mod = cur_item->cmd_mod;
4205088Sab196087 		if (dispcnt > 1)
4215088Sab196087 			elfedit_printf(MSG_ORIG(MSG_HLPFMT_MULTIHDR), *argv);
4225088Sab196087 
4235088Sab196087 		/* If -s, display quick synopsis rather than the whole thing */
4245088Sab196087 		if (minus_s) {
4255088Sab196087 			cmd_help_synopsis(mod, cmd);
4265088Sab196087 			continue;
4275088Sab196087 		}
4285088Sab196087 
4295088Sab196087 		elfedit_printf(MSG_INTL(MSG_HLPFMT_MOD), mod->mod_name,
4305088Sab196087 		    (* mod->mod_i18nhdl_to_str)(mod->mod_desc));
4315088Sab196087 		elfedit_printf(MSG_INTL(MSG_HLPFMT_NAME),
4325088Sab196087 		    *cmd->cmd_name,
4335088Sab196087 		    (* mod->mod_i18nhdl_to_str)(cmd->cmd_desc));
4345088Sab196087 		elfedit_printf(MSG_INTL(MSG_HLPFMT_SYNOPSIS),
4355088Sab196087 		    elfedit_format_command_usage(mod, cmd,
4365088Sab196087 		    MSG_ORIG(MSG_STR_HLPUSEINDENT),
4375088Sab196087 		    strlen(MSG_ORIG(MSG_STR_HLPINDENT))));
4385088Sab196087 		/* If there are alias names, show them */
4395088Sab196087 		if (cmd->cmd_name[1] != NULL) {
4405088Sab196087 			const char **alias = cmd->cmd_name + 1;
4415088Sab196087 
4425088Sab196087 			elfedit_printf(MSG_INTL(MSG_HLPFMT_ALIASES));
4435088Sab196087 			do {
4445088Sab196087 				elfedit_printf(
4455088Sab196087 				    MSG_ORIG(MSG_STR_HLPINDENT));
4465088Sab196087 				elfedit_printf(
4475088Sab196087 				    MSG_ORIG(MSG_FMT_MODCMD),
4485088Sab196087 				    mod->mod_name, *alias);
4495088Sab196087 				if (**alias == '\0')
4505088Sab196087 					elfedit_printf(
4515088Sab196087 					    MSG_INTL(MSG_HLPFMT_DEFCMD));
4525088Sab196087 				elfedit_printf(MSG_ORIG(MSG_STR_NL));
4535088Sab196087 				alias++;
4545088Sab196087 			} while (*alias);
4555088Sab196087 		}
4565088Sab196087 		elfedit_printf(MSG_INTL(MSG_HLPFMT_DESC));
4575088Sab196087 		write_help_str(
4585088Sab196087 		    (* mod->mod_i18nhdl_to_str)(cmd->cmd_help),
4595088Sab196087 		    MSG_ORIG(MSG_STR_HLPINDENT));
4605088Sab196087 		if (cmd->cmd_args != NULL)
4615088Sab196087 			write_optarg(mod, MSG_INTL(MSG_HLPFMT_ARGS),
4625088Sab196087 			    cmd->cmd_args);
4635088Sab196087 		if (cmd->cmd_opt != NULL)
4645088Sab196087 			write_optarg(mod, MSG_INTL(MSG_HLPFMT_OPT),
4655088Sab196087 			    cmd->cmd_opt);
4665088Sab196087 		if ((dispcnt > 1) && (argc > 0))
4675088Sab196087 			elfedit_printf(MSG_INTL(MSG_HLPFMT_MULTIEND),
4685088Sab196087 			    argv[0], argv[1]);
4695088Sab196087 		/* An empty line after the last line of output */
4705088Sab196087 		elfedit_printf(MSG_ORIG(MSG_STR_NL));
4715088Sab196087 	}
4725088Sab196087 
4735088Sab196087 	return (ELFEDIT_CMDRET_NONE);
4745088Sab196087 
4755088Sab196087 #undef	INITIAL_ITEM_ALLOC
4765088Sab196087 }
4775088Sab196087 
4785088Sab196087 
4795088Sab196087 /*
4805088Sab196087  * Command completion function for sys:help
4815088Sab196087  */
4825088Sab196087 /*ARGSUSED*/
4835088Sab196087 static void
cpl_help(void * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)4845088Sab196087 cpl_help(void *obj_state, void *cpldata, int argc, const char *argv[],
4855088Sab196087     int num_opt)
4865088Sab196087 {
4875088Sab196087 	/*
4885088Sab196087 	 * The arguments can be any module or command. Supplying the
4895088Sab196087 	 * commands implicitly supplies the modules too.
4905088Sab196087 	 */
4915088Sab196087 	elfedit_cpl_command(cpldata);
4925088Sab196087 }
4935088Sab196087 
4945088Sab196087 
4955088Sab196087 /*
4965088Sab196087  * Implementation of sys:load
4975088Sab196087  */
4985088Sab196087 /*ARGSUSED*/
4995088Sab196087 static elfedit_cmdret_t
cmd_load(void * obj_state,int argc,const char * argv[])5005088Sab196087 cmd_load(void *obj_state, int argc, const char *argv[])
5015088Sab196087 {
5025088Sab196087 	elfedit_getopt_state_t	getopt_state;
5035088Sab196087 	elfedit_getopt_ret_t	*getopt_ret;
5045088Sab196087 	struct stat		statbuf;
5055088Sab196087 
5065088Sab196087 	elfedit_getopt_init(&getopt_state, &argc, &argv);
5075088Sab196087 	while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) {
5085088Sab196087 		switch (getopt_ret->gor_idmask) {
5095088Sab196087 		case SYS_OPT_F_ALL:
5105088Sab196087 			elfedit_load_modpath();
5115088Sab196087 			break;
5125088Sab196087 		}
5135088Sab196087 	}
5145088Sab196087 
5155088Sab196087 	/* For each remaining argument, load them individually */
5165088Sab196087 	for (; argc-- > 0; argv++) {
5175088Sab196087 		/* Is it a directory? Load everything in it */
5185088Sab196087 		if ((stat(*argv, &statbuf) == 0) &&
5195088Sab196087 		    (statbuf.st_mode & S_IFDIR)) {
5205088Sab196087 			elfedit_load_moddir(*argv, 1, 1);
5215088Sab196087 		} else {	/* Not a directory. Normal load */
5225088Sab196087 			(void) elfedit_load_module(*argv, 1, 1);
5235088Sab196087 		}
5245088Sab196087 	}
5255088Sab196087 
5265088Sab196087 	return (0);
5275088Sab196087 }
5285088Sab196087 
5295088Sab196087 
5305088Sab196087 /*
5315088Sab196087  * Command completion function for sys:load
5325088Sab196087  */
5335088Sab196087 /*ARGSUSED*/
5345088Sab196087 static void
cpl_load(void * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)5355088Sab196087 cpl_load(void *obj_state, void *cpldata, int argc, const char *argv[],
5365088Sab196087     int num_opt)
5375088Sab196087 {
5385088Sab196087 	/*
5395088Sab196087 	 * Module names. Note that this causes elfedit to load all
5405088Sab196087 	 * of the modules, which probably makes the current load
5415088Sab196087 	 * operation unnecessary. This could be improved, but I don't
5425088Sab196087 	 * see it as worth the complexity. Explicit load calls are
5435088Sab196087 	 * rare, and the user will usually not use command completion.
5445088Sab196087 	 */
5455088Sab196087 	elfedit_cpl_module(cpldata, 1);
5465088Sab196087 }
5475088Sab196087 
5485088Sab196087 
5495088Sab196087 /*
5505088Sab196087  * Implementation of sys:quit
5515088Sab196087  */
5525088Sab196087 /*ARGSUSED*/
5535088Sab196087 static elfedit_cmdret_t
cmd_quit(void * obj_state,int argc,const char * argv[])5545088Sab196087 cmd_quit(void *obj_state, int argc, const char *argv[])
5555088Sab196087 {
5565088Sab196087 	elfedit_getopt_state_t	getopt_state;
5575088Sab196087 	elfedit_getopt_ret_t	*getopt_ret;
5585088Sab196087 	int			force = 0;
5595088Sab196087 	const char		*file;
5605088Sab196087 	int			fd;
5615088Sab196087 	Elf			*elf;
5625088Sab196087 
5635088Sab196087 	elfedit_getopt_init(&getopt_state, &argc, &argv);
5645088Sab196087 	while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) {
5655088Sab196087 		switch (getopt_ret->gor_idmask) {
5665088Sab196087 		case SYS_OPT_F_FORCE:
5675088Sab196087 			force = 1;
5685088Sab196087 			break;
5695088Sab196087 		}
5705088Sab196087 	}
5715088Sab196087 	if (argc != 0)
5725088Sab196087 		elfedit_command_usage();
5735088Sab196087 
5745088Sab196087 	if (state.file.present) {
5755088Sab196087 		/*
5765088Sab196087 		 * If session is not READONLY, then refuse to quit if file
5775088Sab196087 		 * needs flushing and -f option was not used.
5785088Sab196087 		 */
5795088Sab196087 		if (!(state.flags & ELFEDIT_F_READONLY) && state.file.dirty &&
5805088Sab196087 		    !force)
5815088Sab196087 			elfedit_msg(ELFEDIT_MSG_ERR,
5825088Sab196087 			    MSG_INTL(MSG_ERR_NODIRTYQUIT));
5835088Sab196087 
5845088Sab196087 		get_obj_state_info(obj_state, &file, &fd, &elf);
5855088Sab196087 		(void) close(fd);
5865088Sab196087 		(void) elf_end(elf);
5875088Sab196087 		free(obj_state);
5885088Sab196087 	}
5895088Sab196087 
5905088Sab196087 	elfedit_exit(0);
5915088Sab196087 	/*NOTREACHED*/
5925088Sab196087 	return (0);
5935088Sab196087 }
5945088Sab196087 
5955088Sab196087 
5965088Sab196087 /*
5975088Sab196087  * Implementation of sys:status
5985088Sab196087  */
5995088Sab196087 /*ARGSUSED*/
6005088Sab196087 static elfedit_cmdret_t
cmd_status(void * obj_state,int argc,const char * argv[])6015088Sab196087 cmd_status(void *obj_state, int argc, const char *argv[])
6025088Sab196087 {
6035088Sab196087 	MODLIST_T	*modlist;
6045088Sab196087 	const char	*s;
6055088Sab196087 	size_t		i;
6065088Sab196087 
6075088Sab196087 	if (argc > 0)
6085088Sab196087 		elfedit_command_usage();
6095088Sab196087 
6105088Sab196087 	/*
6115088Sab196087 	 * This command can produce an arbitrary amount of output, so
6125088Sab196087 	 * run a pager.
6135088Sab196087 	 */
6145088Sab196087 	elfedit_pager_init();
6155088Sab196087 
6165088Sab196087 	/* Files */
6175088Sab196087 	if (state.file.present == 0) {
6185088Sab196087 		elfedit_printf(MSG_INTL(MSG_HLPFMT_INFILENONE));
6195088Sab196087 	} else if (state.flags & ELFEDIT_F_READONLY) {
6205088Sab196087 		elfedit_printf(MSG_INTL(MSG_HLPFMT_INFILERO),
6215088Sab196087 		    state.file.infile);
6225088Sab196087 	} else {
6235088Sab196087 		elfedit_printf(MSG_INTL(MSG_HLPFMT_INFILE), state.file.infile);
6245088Sab196087 		elfedit_printf(MSG_INTL(MSG_HLPFMT_OUTFILE),
6255088Sab196087 		    state.file.outfile);
6265088Sab196087 	}
6275088Sab196087 	if (state.file.dirty)
6285088Sab196087 		elfedit_printf(MSG_INTL(MSG_HLPFMT_CNGPENDING));
6295088Sab196087 
6305088Sab196087 	/* Option Variables */
6315088Sab196087 	elfedit_printf(MSG_INTL(MSG_HLPFMT_VARHDR));
6325088Sab196087 	elfedit_printf(MSG_INTL(MSG_HLPFMT_AFLG),
6335088Sab196087 	    (state.flags & ELFEDIT_F_AUTOPRINT) ? MSG_ORIG(MSG_STR_ON) :
6345088Sab196087 	    MSG_ORIG(MSG_STR_OFF));
6355088Sab196087 	elfedit_printf(MSG_INTL(MSG_HLPFMT_DFLG),
6365088Sab196087 	    (state.flags & ELFEDIT_F_DEBUG) ? MSG_ORIG(MSG_STR_ON) :
6375088Sab196087 	    MSG_ORIG(MSG_STR_OFF));
6385088Sab196087 	elfedit_printf(MSG_INTL(MSG_HLPFMT_OFLG),
6395088Sab196087 	    elfedit_atoconst_value_to_str(ELFEDIT_CONST_OUTSTYLE,
6405088Sab196087 	    state.outstyle, 1));
6415088Sab196087 
6425088Sab196087 	/* Module Load Path */
6435088Sab196087 	elfedit_printf(MSG_INTL(MSG_HLPFMT_PATHHDR));
6445088Sab196087 	for (i = 0; i < state.modpath.n; i++)
6455088Sab196087 		elfedit_printf(MSG_ORIG(MSG_HLPFMT_PATHELT),
6465088Sab196087 		    state.modpath.seg[i]);
6475088Sab196087 
6485088Sab196087 	/* Currently Loaded Modules */
6495088Sab196087 	elfedit_printf(MSG_INTL(MSG_HLPFMT_MODHDR));
6505088Sab196087 	for (modlist = state.modlist; modlist;
6515088Sab196087 	    modlist = modlist->ml_next) {
6525088Sab196087 		s = modlist->ml_path ? modlist->ml_path :
6535088Sab196087 		    MSG_INTL(MSG_FMT_BUILTIN);
6545088Sab196087 		elfedit_printf(MSG_ORIG(MSG_HLPFMT_NAMDSCCOL),
6555088Sab196087 		    modlist->ml_mod->mod_name, s);
6565088Sab196087 	}
6575088Sab196087 
6585088Sab196087 	return (ELFEDIT_CMDRET_NONE);
6595088Sab196087 }
6605088Sab196087 
6615088Sab196087 /*
6625088Sab196087  * Implementation of sys:set
6635088Sab196087  */
6645088Sab196087 /*ARGSUSED*/
6655088Sab196087 static elfedit_cmdret_t
cmd_set(void * obj_state,int argc,const char * argv[])6665088Sab196087 cmd_set(void *obj_state, int argc, const char *argv[])
6675088Sab196087 {
6685088Sab196087 	if ((argc != 2) || (strlen(argv[0]) > 1))
6695088Sab196087 		elfedit_command_usage();
6705088Sab196087 
6715088Sab196087 	switch (**argv) {
6725088Sab196087 	case 'a':
6735088Sab196087 	case 'A':
6745088Sab196087 		if (elfedit_atobool(argv[1], MSG_INTL(MSG_SYSSET_A)))
6755088Sab196087 			state.flags |= ELFEDIT_F_AUTOPRINT;
6765088Sab196087 		else
6775088Sab196087 			state.flags &= ~ELFEDIT_F_AUTOPRINT;
6785088Sab196087 		break;
6795088Sab196087 
6805088Sab196087 	case 'd':
6815088Sab196087 	case 'D':
6825088Sab196087 		if (elfedit_atobool(argv[1], MSG_INTL(MSG_SYSSET_D)))
6835088Sab196087 			state.flags |= ELFEDIT_F_DEBUG;
6845088Sab196087 		else
6855088Sab196087 			state.flags &= ~ELFEDIT_F_DEBUG;
6865088Sab196087 		break;
6875088Sab196087 
6885088Sab196087 	case 'o':
6895088Sab196087 	case 'O':
6905088Sab196087 		if (elfedit_atooutstyle(argv[1], &state.outstyle) == 0)
6915088Sab196087 			elfedit_msg(ELFEDIT_MSG_ERR,
6925088Sab196087 			    MSG_INTL(MSG_ERR_BADOSTYLE), argv[1]);
6935088Sab196087 		break;
6945088Sab196087 
6955088Sab196087 	default:
6965088Sab196087 		elfedit_command_usage();
6975088Sab196087 	}
6985088Sab196087 
6995088Sab196087 	return (0);
7005088Sab196087 }
7015088Sab196087 
7025088Sab196087 
7035088Sab196087 /*
7045088Sab196087  * Command completion function for sys:set
7055088Sab196087  */
7065088Sab196087 /*ARGSUSED*/
7075088Sab196087 static void
cpl_set(void * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)7085088Sab196087 cpl_set(void *obj_state, void *cpldata, int argc, const char *argv[],
7095088Sab196087     int num_opt)
7105088Sab196087 {
7115088Sab196087 	const char *s;
7125088Sab196087 
7135088Sab196087 	/*
7145088Sab196087 	 * This command doesn't accept options, so num_opt should be
7155088Sab196087 	 * 0. This is a defensive measure, in case that should change.
7165088Sab196087 	 */
7175088Sab196087 	argc -= num_opt;
7185088Sab196087 	argv += num_opt;
7195088Sab196087 
7205088Sab196087 	if ((argc < 1) || (argc > 2))
7215088Sab196087 		return;
7225088Sab196087 
7235088Sab196087 	if (argc == 1) {	/* The first argument is a variable letter */
7245088Sab196087 		elfedit_cpl_match(cpldata, MSG_ORIG(MSG_STR_A), 1);
7255088Sab196087 		elfedit_cpl_match(cpldata, MSG_ORIG(MSG_STR_D), 1);
7265088Sab196087 		elfedit_cpl_match(cpldata, MSG_ORIG(MSG_STR_O), 1);
7275088Sab196087 		elfedit_cpl_match(cpldata, MSG_ORIG(MSG_STR_W), 1);
7285088Sab196087 		return;
7295088Sab196087 	}
7305088Sab196087 
7315088Sab196087 	/* We're dealing with the second argument, the value */
7325088Sab196087 	s = argv[0];
7335088Sab196087 	if (strlen(s) > 1)	/* One letter variables */
7345088Sab196087 		return;
7355088Sab196087 	switch (*s) {
7365088Sab196087 	case 'a':		/* Booleans */
7375088Sab196087 	case 'A':
7385088Sab196087 	case 'd':
7395088Sab196087 	case 'D':
7405088Sab196087 	case 'w':
7415088Sab196087 	case 'W':
7425088Sab196087 		/* The second argument is a boolean */
7435088Sab196087 		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_BOOL);
7445088Sab196087 
7455088Sab196087 		/* The numbers are not symbolic, but we want them in the list */
7465088Sab196087 		elfedit_cpl_match(cpldata, MSG_ORIG(MSG_STR_0), 1);
7475088Sab196087 		elfedit_cpl_match(cpldata, MSG_ORIG(MSG_STR_1), 1);
7485088Sab196087 		break;
7495088Sab196087 
7505088Sab196087 	case 'o':		/* Output style */
7515088Sab196087 	case 'O':
7525088Sab196087 		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_OUTSTYLE);
7535088Sab196087 		break;
7545088Sab196087 	}
7555088Sab196087 }
7565088Sab196087 
7575088Sab196087 
7585088Sab196087 /*
7595088Sab196087  * Implementation of sys:unload
7605088Sab196087  */
7615088Sab196087 /*ARGSUSED*/
7625088Sab196087 static elfedit_cmdret_t
cmd_unload(void * obj_state,int argc,const char * argv[])7635088Sab196087 cmd_unload(void *obj_state, int argc, const char *argv[])
7645088Sab196087 {
7655088Sab196087 	elfedit_getopt_state_t	getopt_state;
7665088Sab196087 	elfedit_getopt_ret_t	*getopt_ret;
7675088Sab196087 	MODLIST_T		*moddef;
7685088Sab196087 	int			do_all = 0;
7695088Sab196087 
7705088Sab196087 	elfedit_getopt_init(&getopt_state, &argc, &argv);
7715088Sab196087 	while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) {
7725088Sab196087 		switch (getopt_ret->gor_idmask) {
7735088Sab196087 		case SYS_OPT_F_ALL:
7745088Sab196087 			do_all = 1;
7755088Sab196087 			break;
7765088Sab196087 		}
7775088Sab196087 	}
7785088Sab196087 
7795088Sab196087 	/*
7805088Sab196087 	 * If -a is specified, unload everything except builtins. Don't
7815088Sab196087 	 * allow plain arguments in this case because there is nothing
7825088Sab196087 	 * left to unload after -a.
7835088Sab196087 	 */
7845088Sab196087 	if (do_all) {
7855088Sab196087 		if (argc > 0)
7865088Sab196087 			elfedit_command_usage();
7875088Sab196087 		/*
7885088Sab196087 		 * Until we run out of non-builtin modules, take the first
7895088Sab196087 		 * one from the list and unload it. Each removal alters
7905088Sab196087 		 * the list, so we always start at the beginning, but this
7915088Sab196087 		 * is efficient since we always remove the first available item
7925088Sab196087 		 */
7935088Sab196087 		while (state.modlist != NULL) {
7945088Sab196087 			for (moddef = state.modlist; moddef != NULL;
7955088Sab196087 			    moddef = moddef->ml_next)
7965088Sab196087 				if (moddef->ml_dl_hdl != NULL) break;
7975088Sab196087 
7985088Sab196087 			/* If we made it to the end, then the list is empty */
7995088Sab196087 			if (moddef == NULL)
8005088Sab196087 				break;
8015088Sab196087 
8025088Sab196087 			elfedit_unload_module(moddef->ml_mod->mod_name);
8035088Sab196087 		}
8045088Sab196087 		return (0);
8055088Sab196087 	}
8065088Sab196087 
8075088Sab196087 	/* Unload each module individually */
8085088Sab196087 	for (; argc-- > 0; argv++)
8095088Sab196087 		elfedit_unload_module(*argv);
8105088Sab196087 
8115088Sab196087 	return (0);
8125088Sab196087 }
8135088Sab196087 
8145088Sab196087 
8155088Sab196087 /*
8165088Sab196087  * Command completion function for sys:unload
8175088Sab196087  */
8185088Sab196087 /*ARGSUSED*/
8195088Sab196087 static void
cpl_unload(void * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)8205088Sab196087 cpl_unload(void *obj_state, void *cpldata, int argc, const char *argv[],
8215088Sab196087     int num_opt)
8225088Sab196087 {
8235088Sab196087 	/*
8245088Sab196087 	 * Module names. Don't allow elfedit to load all the modules,
8255088Sab196087 	 * as the only modules we want to unload are those already
8265088Sab196087 	 * in memory.
8275088Sab196087 	 */
8285088Sab196087 	elfedit_cpl_module(cpldata, 0);
8295088Sab196087 }
8305088Sab196087 
8315088Sab196087 
8325088Sab196087 /*
8335088Sab196087  * Implementation of sys:write
8345088Sab196087  */
8355088Sab196087 /*ARGSUSED2*/
8365088Sab196087 static elfedit_cmdret_t
cmd_write(void * obj_state,int argc,const char * argv[])8375088Sab196087 cmd_write(void *obj_state, int argc, const char *argv[])
8385088Sab196087 {
8395088Sab196087 	const char	*file;
8405088Sab196087 	int		fd;
8415088Sab196087 	Elf		*elf;
8425088Sab196087 
8435088Sab196087 	if (argc != 0)
8445088Sab196087 		elfedit_command_usage();
8455088Sab196087 
8465088Sab196087 	if (state.file.present != 0) {
8475088Sab196087 		if (state.flags & ELFEDIT_F_READONLY)
8485088Sab196087 			elfedit_msg(ELFEDIT_MSG_ERR,
8495088Sab196087 			    MSG_INTL(MSG_ERR_READONLY));
8505088Sab196087 
8515088Sab196087 		get_obj_state_info(obj_state, &file, &fd, &elf);
8525088Sab196087 		if (elf_update(elf, ELF_C_WRITE) == -1)
8535088Sab196087 			elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_LIBELF),
8545088Sab196087 			    file, MSG_ORIG(MSG_ELF_UPDATE),
8555088Sab196087 			    elf_errmsg(elf_errno()));
8565088Sab196087 
8575088Sab196087 		/*
8585088Sab196087 		 * An update has succeeded for this file, so revoke the need
8595088Sab196087 		 * to unlink it on exit.
8605088Sab196087 		 */
8615088Sab196087 		state.file.unlink_on_exit = 0;
8625088Sab196087 	}
8635088Sab196087 
8645088Sab196087 	return (ELFEDIT_CMDRET_FLUSH);
8655088Sab196087 }
8665088Sab196087 
8675088Sab196087 
8685088Sab196087 
8695088Sab196087 
8705088Sab196087 
8715088Sab196087 /*ARGSUSED*/
8725088Sab196087 MODLIST_T *
elfedit_sys_init(elfedit_module_version_t version)8735088Sab196087 elfedit_sys_init(elfedit_module_version_t version)
8745088Sab196087 {
8755088Sab196087 	/* sys:help */
8765088Sab196087 	static const char *name_help[] = { MSG_ORIG(MSG_SYS_CMD_HELP),
8775088Sab196087 	    MSG_ORIG(MSG_SYS_CMD_HELP_A1), MSG_ORIG(MSG_SYS_CMD_HELP_A2),
8785088Sab196087 	    NULL };
8795088Sab196087 	static elfedit_cmd_optarg_t opt_help[] = {
8805088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_S),
8815088Sab196087 		    /* MSG_INTL(MSG_SYS_OPTDESC_HELP_S) */
8825088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_OPTDESC_HELP_S), 0,
8835088Sab196087 		    SYS_OPT_F_SYNOPSIS, 0 },
8845088Sab196087 		{ NULL }
8855088Sab196087 	};
8865088Sab196087 	static elfedit_cmd_optarg_t arg_help[] = {
8875088Sab196087 		{ MSG_ORIG(MSG_STR_ARG),
8885088Sab196087 		    /* MSG_INTL(MSG_ARGDESC_HELP_ARG) */
8895088Sab196087 		    ELFEDIT_I18NHDL(MSG_ARGDESC_HELP_ARG),
8905088Sab196087 		    ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT },
8915088Sab196087 		{ NULL }
8925088Sab196087 	};
8935088Sab196087 
8945088Sab196087 	/* sys:load */
8955088Sab196087 	static const char *name_load[] = {
8965088Sab196087 	    MSG_ORIG(MSG_SYS_CMD_LOAD), NULL };
8975088Sab196087 	static elfedit_cmd_optarg_t opt_load[] = {
8985088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_A),
8995088Sab196087 		    /* MSG_INTL(MSG_SYS_OPTDESC_LOAD_A) */
9005088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_OPTDESC_LOAD_A), 0,
9015088Sab196087 		    SYS_OPT_F_ALL, 0 },
9025088Sab196087 		{ NULL }
9035088Sab196087 	};
9045088Sab196087 	static elfedit_cmd_optarg_t arg_load[] = {
9055088Sab196087 		{ MSG_ORIG(MSG_STR_MODNAME),
9065088Sab196087 		    /* MSG_INTL(MSG_ARGDESC_LOAD_MODNAME) */
9075088Sab196087 		    ELFEDIT_I18NHDL(MSG_ARGDESC_LOAD_MODNAME),
9085088Sab196087 		    ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT },
9095088Sab196087 		{ NULL }
9105088Sab196087 	};
9115088Sab196087 
9125088Sab196087 	/* sys:quit */
9135088Sab196087 	static const char *name_quit[] = { MSG_ORIG(MSG_SYS_CMD_QUIT),
9145088Sab196087 	    MSG_ORIG(MSG_SYS_CMD_QUIT_A1), MSG_ORIG(MSG_SYS_CMD_QUIT_A2),
9155088Sab196087 	    NULL };
9165088Sab196087 	static elfedit_cmd_optarg_t opt_quit[] = {
9175088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_F),
9185088Sab196087 		    /* MSG_INTL(MSG_SYS_OPTDESC_QUIT_F) */
9195088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_OPTDESC_QUIT_F), 0,
9205088Sab196087 		    SYS_OPT_F_FORCE, 0 },
9215088Sab196087 		{ NULL }
9225088Sab196087 	};
9235088Sab196087 
9245088Sab196087 	/* sys:status */
9255088Sab196087 	static const char *name_status[] = {
9265088Sab196087 	    MSG_ORIG(MSG_SYS_CMD_STATUS), NULL };
9275088Sab196087 
9285088Sab196087 	/* sys:set */
9295088Sab196087 	static const char *name_set[] = {
9305088Sab196087 	    MSG_ORIG(MSG_SYS_CMD_SET), NULL };
9315088Sab196087 	static elfedit_cmd_optarg_t arg_set[] = {
9325088Sab196087 		{ MSG_ORIG(MSG_STR_OPTION),
9335088Sab196087 		    /* MSG_INTL(MSG_ARGDESC_SET_OPTION) */
9345088Sab196087 		    ELFEDIT_I18NHDL(MSG_ARGDESC_SET_OPTION), 0 },
9355088Sab196087 		{ MSG_ORIG(MSG_STR_VALUE),
9365088Sab196087 		    /* MSG_INTL(MSG_ARGDESC_SET_VALUE) */
9375088Sab196087 		    ELFEDIT_I18NHDL(MSG_ARGDESC_SET_VALUE), 0 },
9385088Sab196087 		{ NULL }
9395088Sab196087 	};
9405088Sab196087 
9415088Sab196087 	/* sys:unload */
9425088Sab196087 	static const char *name_unload[] = {
9435088Sab196087 	    MSG_ORIG(MSG_SYS_CMD_UNLOAD), NULL };
9445088Sab196087 	static elfedit_cmd_optarg_t opt_unload[] = {
9455088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_A),
9465088Sab196087 		    /* MSG_INTL(MSG_SYS_OPTDESC_UNLOAD_A) */
9475088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_OPTDESC_UNLOAD_A), 0,
9485088Sab196087 		    SYS_OPT_F_ALL, 0},
9495088Sab196087 		{ NULL }
9505088Sab196087 	};
9515088Sab196087 	static elfedit_cmd_optarg_t arg_unload[] = {
9525088Sab196087 		{ MSG_ORIG(MSG_STR_MODNAME),
9535088Sab196087 		    /* MSG_INTL(MSG_ARGDESC_UNLOAD_MODNAME) */
9545088Sab196087 		    ELFEDIT_I18NHDL(MSG_ARGDESC_UNLOAD_MODNAME),
9555088Sab196087 		    ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT },
9565088Sab196087 		{ NULL }
9575088Sab196087 	};
9585088Sab196087 
9595088Sab196087 	/* sys:write */
9605088Sab196087 	static const char *name_write[] = { MSG_ORIG(MSG_SYS_CMD_WRITE),
9615088Sab196087 	    MSG_ORIG(MSG_SYS_CMD_WRITE_A1), MSG_ORIG(MSG_SYS_CMD_WRITE_A2),
9625088Sab196087 	    NULL };
9635088Sab196087 
9645088Sab196087 	static elfedit_cmd_t cmds[] = {
9655088Sab196087 		/* sym:help */
9665088Sab196087 		{ (elfedit_cmd_func_t *)cmd_help,
9675088Sab196087 		    (elfedit_cmdcpl_func_t *)cpl_help, name_help,
9685088Sab196087 		    /* MSG_INTL(MSG_SYS_DESC_HELP) */
9695088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_DESC_HELP),
9705088Sab196087 		    /* MSG_INTL(MSG_SYS_HELP_HELP) */
9715088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_HELP_HELP),
9725088Sab196087 		    opt_help, arg_help },
9735088Sab196087 
9745088Sab196087 		/* sym:load */
9755088Sab196087 		{ (elfedit_cmd_func_t *)cmd_load,
9765088Sab196087 		    (elfedit_cmdcpl_func_t *)cpl_load, name_load,
9775088Sab196087 		    /* MSG_INTL(MSG_SYS_DESC_LOAD) */
9785088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_DESC_LOAD),
9795088Sab196087 		    /* MSG_INTL(MSG_SYS_HELP_LOAD) */
9805088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_HELP_LOAD),
9815088Sab196087 		    opt_load, arg_load },
9825088Sab196087 
9835088Sab196087 		/* sym:quit */
9845088Sab196087 		{ (elfedit_cmd_func_t *)cmd_quit, NULL, name_quit,
9855088Sab196087 		    /* MSG_INTL(MSG_SYS_DESC_QUIT) */
9865088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_DESC_QUIT),
9875088Sab196087 		    /* MSG_INTL(MSG_SYS_HELP_QUIT) */
9885088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_HELP_QUIT),
9895088Sab196087 		    opt_quit, NULL },
9905088Sab196087 
9915088Sab196087 		/* sym:status */
9925088Sab196087 		{ (elfedit_cmd_func_t *)cmd_status, NULL, name_status,
9935088Sab196087 		    /* MSG_INTL(MSG_SYS_DESC_STATUS) */
9945088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_DESC_STATUS),
9955088Sab196087 		    /* MSG_INTL(MSG_SYS_HELP_STATUS) */
9965088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_HELP_STATUS),
9975088Sab196087 		    NULL, NULL },
9985088Sab196087 
9995088Sab196087 		/* sym:set */
10005088Sab196087 		{ (elfedit_cmd_func_t *)cmd_set,
10015088Sab196087 		    (elfedit_cmdcpl_func_t *)cpl_set, name_set,
10025088Sab196087 		    /* MSG_INTL(MSG_SYS_DESC_SET) */
10035088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_DESC_SET),
10045088Sab196087 		    /* MSG_INTL(MSG_SYS_HELP_SET) */
10055088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_HELP_SET),
10065088Sab196087 		    NULL, arg_set },
10075088Sab196087 
10085088Sab196087 		/* sym:unload */
10095088Sab196087 		{ (elfedit_cmd_func_t *)cmd_unload,
10105088Sab196087 		    (elfedit_cmdcpl_func_t *)cpl_unload, name_unload,
10115088Sab196087 		    /* MSG_INTL(MSG_SYS_DESC_UNLOAD) */
10125088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_DESC_UNLOAD),
10135088Sab196087 		    /* MSG_INTL(MSG_SYS_HELP_UNLOAD) */
10145088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_HELP_UNLOAD),
10155088Sab196087 		    opt_unload, arg_unload },
10165088Sab196087 
10175088Sab196087 		/* sym:write */
10185088Sab196087 		{ (elfedit_cmd_func_t *)cmd_write, NULL, name_write,
10195088Sab196087 		    /* MSG_INTL(MSG_SYS_DESC_WRITE) */
10205088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_DESC_WRITE),
10215088Sab196087 		    /* MSG_INTL(MSG_SYS_HELP_WRITE) */
10225088Sab196087 		    ELFEDIT_I18NHDL(MSG_SYS_HELP_WRITE),
10235088Sab196087 		    NULL, NULL},
10245088Sab196087 
10255088Sab196087 		{ NULL }
10265088Sab196087 	};
10275088Sab196087 
10285088Sab196087 	static elfedit_module_t module = {
10295088Sab196087 	    ELFEDIT_VER_CURRENT, MSG_ORIG(MSG_MOD_SYS),
10305088Sab196087 	    /* MSG_INTL(MSG_MOD_SYS_DESC) */
10315088Sab196087 	    ELFEDIT_I18NHDL(MSG_MOD_SYS_DESC),
10325088Sab196087 	    cmds, mod_i18nhdl_to_str };
10335088Sab196087 
10345088Sab196087 	static MODLIST_T moddef = {
10355088Sab196087 		NULL,		/* next */
10365088Sab196087 		(elfeditGC_module_t *)&module,	/* Module definition */
10375088Sab196087 		NULL,		/* Didn't dlopen() it, so NULL handle */
10385088Sab196087 		NULL		/* Didn't dlopen() it, so no file path */
10395088Sab196087 	};
10405088Sab196087 
10415088Sab196087 	return (&moddef);
10425088Sab196087 }
1043