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