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