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