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