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