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