1d29b2c44Sab /*
2d29b2c44Sab  * CDDL HEADER START
3d29b2c44Sab  *
4d29b2c44Sab  * The contents of this file are subject to the terms of the
5d29b2c44Sab  * Common Development and Distribution License (the "License").
6d29b2c44Sab  * You may not use this file except in compliance with the License.
7d29b2c44Sab  *
8d29b2c44Sab  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9d29b2c44Sab  * or http://www.opensolaris.org/os/licensing.
10d29b2c44Sab  * See the License for the specific language governing permissions
11d29b2c44Sab  * and limitations under the License.
12d29b2c44Sab  *
13d29b2c44Sab  * When distributing Covered Code, include this CDDL HEADER in each
14d29b2c44Sab  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15d29b2c44Sab  * If applicable, add the following below this CDDL HEADER, with the
16d29b2c44Sab  * fields enclosed by brackets "[]" replaced with your own identifying
17d29b2c44Sab  * information: Portions Copyright [yyyy] [name of copyright owner]
18d29b2c44Sab  *
19d29b2c44Sab  * CDDL HEADER END
20d29b2c44Sab  */
21d29b2c44Sab 
22d29b2c44Sab /*
2308278a5eSRod Evans  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24d29b2c44Sab  * Use is subject to license terms.
2533f5ff17SMilan Jurik  * Copyright 2012 Milan Jurik. All rights reserved.
26*56726c7eSRobert Mustacchi  * Copyright 2022 Oxide Computer Company
27d29b2c44Sab  */
28d29b2c44Sab 
29d29b2c44Sab #include	<ctype.h>
30d29b2c44Sab #include	<elfedit.h>
31d29b2c44Sab #include	<sys/elf_SPARC.h>
32d29b2c44Sab #include	<strings.h>
33d29b2c44Sab #include	<debug.h>
34d29b2c44Sab #include	<conv.h>
35d29b2c44Sab #include	<cap_msg.h>
36d29b2c44Sab 
37d29b2c44Sab 
38d29b2c44Sab /*
39d29b2c44Sab  * Capabilities section
40d29b2c44Sab  */
41d29b2c44Sab 
42d29b2c44Sab 
43d29b2c44Sab 
44d29b2c44Sab 
45d29b2c44Sab /*
46d29b2c44Sab  * This module uses shared code for several of the commands.
47d29b2c44Sab  * It is sometimes necessary to know which specific command
48d29b2c44Sab  * is active.
49d29b2c44Sab  */
50d29b2c44Sab typedef enum {
51d29b2c44Sab 	/* Dump command, used as module default to display dynamic section */
52d29b2c44Sab 	CAP_CMD_T_DUMP =	0,	/* cap:dump */
53d29b2c44Sab 
54d29b2c44Sab 	/* Commands that do not correspond directly to a specific DT tag */
55d29b2c44Sab 	CAP_CMD_T_TAG =		1,	/* cap:tag */
56d29b2c44Sab 	CAP_CMD_T_VALUE =	2,	/* cap:value */
57d29b2c44Sab 	CAP_CMD_T_DELETE =	3,	/* cap:delete */
58d29b2c44Sab 	CAP_CMD_T_MOVE =	4,	/* cap:shift */
59d29b2c44Sab 
60d29b2c44Sab 	/* Commands that embody tag specific knowledge */
61d29b2c44Sab 	CAP_CMD_T_HW1 =		5,	/* cap:hw1 */
62d29b2c44Sab 	CAP_CMD_T_SF1 =		6,	/* cap:sf1 */
6308278a5eSRod Evans 	CAP_CMD_T_HW2 =		7,	/* cap:hw2 */
64*56726c7eSRobert Mustacchi 	CAP_CMD_T_HW3 =		8,	/* cap:hw3 */
65d29b2c44Sab } CAP_CMD_T;
66d29b2c44Sab 
67d29b2c44Sab 
68d29b2c44Sab 
69d29b2c44Sab #ifndef _ELF64
70d29b2c44Sab /*
71d29b2c44Sab  * We supply this function for the msg module
72d29b2c44Sab  */
73d29b2c44Sab const char *
_cap_msg(Msg mid)74d29b2c44Sab _cap_msg(Msg mid)
75d29b2c44Sab {
76d29b2c44Sab 	return (gettext(MSG_ORIG(mid)));
77d29b2c44Sab }
78d29b2c44Sab #endif
79d29b2c44Sab 
80d29b2c44Sab 
81d29b2c44Sab /*
82d29b2c44Sab  * This function is supplied to elfedit through our elfedit_module_t
83d29b2c44Sab  * definition. It translates the opaque elfedit_i18nhdl_t handles
84d29b2c44Sab  * in our module interface into the actual strings for elfedit to
85d29b2c44Sab  * use.
86d29b2c44Sab  *
87d29b2c44Sab  * note:
88d29b2c44Sab  *	This module uses Msg codes for its i18n handle type.
89d29b2c44Sab  *	So the translation is simply to use MSG_INTL() to turn
90d29b2c44Sab  *	it into a string and return it.
91d29b2c44Sab  */
92d29b2c44Sab static const char *
mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl)93d29b2c44Sab mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl)
94d29b2c44Sab {
95d29b2c44Sab 	Msg msg = (Msg)hdl;
96d29b2c44Sab 
97d29b2c44Sab 	return (MSG_INTL(msg));
98d29b2c44Sab }
99d29b2c44Sab 
100d29b2c44Sab 
101d29b2c44Sab 
102d29b2c44Sab /*
103d29b2c44Sab  * The cap_opt_t enum specifies a bit value for every optional
104d29b2c44Sab  * argument allowed by a command in this module.
105d29b2c44Sab  */
106d29b2c44Sab typedef enum {
107d29b2c44Sab 	CAP_OPT_F_AND =		1,	/* -and: AND (&) values to dest */
108d29b2c44Sab 	CAP_OPT_F_CMP =		2,	/* -cmp: Complement (~) values */
10908278a5eSRod Evans 	CAP_OPT_F_CAPID =	4,	/* -capid id: elt limited to given */
11008278a5eSRod Evans 					/*	capabilities group */
11108278a5eSRod Evans 	CAP_OPT_F_CAPNDX =	8,	/* -capndx: elt is tag index, */
112d29b2c44Sab 					/*	not name */
11308278a5eSRod Evans 	CAP_OPT_F_OR =		16,	/* -or: OR (|) values to dest */
11408278a5eSRod Evans 	CAP_OPT_F_STRVAL =	32	/* -s: value is string, not integer */
115d29b2c44Sab } cap_opt_t;
116d29b2c44Sab 
117d29b2c44Sab 
118d29b2c44Sab /*
119d29b2c44Sab  * A variable of type ARGSTATE is used by each command to maintain
120d29b2c44Sab  * information about the arguments and related things. It is
121d29b2c44Sab  * initialized by process_args(), and used by the other routines.
122d29b2c44Sab  */
123d29b2c44Sab typedef struct {
124d29b2c44Sab 	elfedit_obj_state_t	*obj_state;
125d29b2c44Sab 	struct {
126d29b2c44Sab 		elfedit_section_t *sec;	/* Capabilities section reference */
127d29b2c44Sab 		Cap	*data;		/* Start of capabilities section data */
128d29b2c44Sab 		Word	num;		/* # Capabilities elts */
12908278a5eSRod Evans 		Boolean	grp_set;	/* TRUE when cap group is set */
13008278a5eSRod Evans 		Word	grp_start_ndx;	/* capabilities group starting index */
13108278a5eSRod Evans 		Word	grp_end_ndx;	/* capabilities group ending index */
132d29b2c44Sab 	} cap;
13308278a5eSRod Evans 	struct {			/* String table */
13408278a5eSRod Evans 		elfedit_section_t *sec;
13508278a5eSRod Evans 	} str;
1369320f495SToomas Soome 	cap_opt_t	optmask;	/* Mask of options used */
137d29b2c44Sab 	int		argc;		/* # of plain arguments */
138d29b2c44Sab 	const char	**argv;		/* Plain arguments */
139d29b2c44Sab } ARGSTATE;
140d29b2c44Sab 
141d29b2c44Sab 
142d29b2c44Sab 
14308278a5eSRod Evans /*
14408278a5eSRod Evans  * Lookup the string table associated with the capabilities
14508278a5eSRod Evans  * section.
14608278a5eSRod Evans  *
14708278a5eSRod Evans  * entry:
14808278a5eSRod Evans  *	argstate - Argument state block
14908278a5eSRod Evans  *	required - If TRUE, failure to obtain a string table should be
15008278a5eSRod Evans  *		considered to be an error.
15108278a5eSRod Evans  *
15208278a5eSRod Evans  * exit:
15308278a5eSRod Evans  *	If a string table is found, argstate->str is updated to reference it.
15408278a5eSRod Evans  *	If no string table is found, and required is TRUE, an error is issued
15508278a5eSRod Evans  *	and this routine does not return to the caller. Otherwise, this
15608278a5eSRod Evans  *	routine returns quietly without modifying argstate->str.
15708278a5eSRod Evans  */
15808278a5eSRod Evans static void
argstate_add_str(ARGSTATE * argstate,Boolean required)15908278a5eSRod Evans argstate_add_str(ARGSTATE *argstate, Boolean required)
16008278a5eSRod Evans {
16108278a5eSRod Evans 	/* String table already loaded? */
16208278a5eSRod Evans 	if (argstate->str.sec != NULL)
16308278a5eSRod Evans 		return;
16408278a5eSRod Evans 
16508278a5eSRod Evans 	/*
16608278a5eSRod Evans 	 * We can't proceed if the capabilities section does not have
16708278a5eSRod Evans 	 * an associated string table.
16808278a5eSRod Evans 	 */
16908278a5eSRod Evans 	if (argstate->cap.sec->sec_shdr->sh_info == 0) {
17008278a5eSRod Evans 		/* Error if the operation requires a string table */
17108278a5eSRod Evans 		if (required)
17208278a5eSRod Evans 			elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSTRTAB),
17308278a5eSRod Evans 			    EC_WORD(argstate->cap.sec->sec_shndx),
17408278a5eSRod Evans 			    argstate->cap.sec->sec_name);
17508278a5eSRod Evans 		return;
17608278a5eSRod Evans 	}
17708278a5eSRod Evans 
17808278a5eSRod Evans 	argstate->str.sec = elfedit_sec_getstr(argstate->obj_state,
17908278a5eSRod Evans 	    argstate->cap.sec->sec_shdr->sh_info, 0);
18008278a5eSRod Evans }
18108278a5eSRod Evans 
18208278a5eSRod Evans /*
18308278a5eSRod Evans  * Given an index into the capabilities array, locate the index of the
18408278a5eSRod Evans  * initial element in its capabilities group, and the number of elements
18508278a5eSRod Evans  * in the group.
18608278a5eSRod Evans  */
18708278a5eSRod Evans static void
cap_group_extents(ARGSTATE * argstate,Word ndx,Word * ret_start_ndx,Word * ret_end_ndx)18808278a5eSRod Evans cap_group_extents(ARGSTATE *argstate, Word ndx, Word *ret_start_ndx,
18908278a5eSRod Evans     Word *ret_end_ndx)
19008278a5eSRod Evans {
19108278a5eSRod Evans 	*ret_end_ndx = ndx;
19208278a5eSRod Evans 
19308278a5eSRod Evans 	/*
19408278a5eSRod Evans 	 * The group starts with a non-NULL tag that is either the
19508278a5eSRod Evans 	 * first tag in the array, or is preceded by a NULL tag.
19608278a5eSRod Evans 	 */
19708278a5eSRod Evans 	while ((ndx > 0) && (argstate->cap.data[ndx].c_tag == CA_SUNW_NULL))
19808278a5eSRod Evans 		ndx--;
19908278a5eSRod Evans 	while ((ndx > 0) && (argstate->cap.data[ndx - 1].c_tag != CA_SUNW_NULL))
20008278a5eSRod Evans 		ndx--;
20108278a5eSRod Evans 	*ret_start_ndx = ndx;
20208278a5eSRod Evans 
20308278a5eSRod Evans 
20408278a5eSRod Evans 	/*
20508278a5eSRod Evans 	 * The group is terminated by a series of 1 or more NULL tags.
20608278a5eSRod Evans 	 */
20708278a5eSRod Evans 	ndx = *ret_end_ndx;
20808278a5eSRod Evans 	while (((ndx + 1) < argstate->cap.num) &&
20908278a5eSRod Evans 	    (argstate->cap.data[ndx].c_tag != CA_SUNW_NULL))
21008278a5eSRod Evans 		ndx++;
21108278a5eSRod Evans 	while (((ndx + 1) < argstate->cap.num) &&
21208278a5eSRod Evans 	    (argstate->cap.data[ndx + 1].c_tag == CA_SUNW_NULL))
21308278a5eSRod Evans 		ndx++;
21408278a5eSRod Evans 	*ret_end_ndx = ndx;
21508278a5eSRod Evans }
21608278a5eSRod Evans 
21708278a5eSRod Evans /*
21808278a5eSRod Evans  * If a CA_SUNW_ID element exists within the current capabilities group
21908278a5eSRod Evans  * in the given argument state, return the string pointer to the name.
22008278a5eSRod Evans  * Otherwise return a pointer to a descriptive "noname" string.
22108278a5eSRod Evans  */
22208278a5eSRod Evans static const char *
cap_group_id(ARGSTATE * argstate)22308278a5eSRod Evans cap_group_id(ARGSTATE *argstate)
22408278a5eSRod Evans {
22508278a5eSRod Evans 	Word		ndx = argstate->cap.grp_start_ndx;
22608278a5eSRod Evans 	Cap		*cap = argstate->cap.data + ndx;
22708278a5eSRod Evans 
22808278a5eSRod Evans 	for (; ndx <= argstate->cap.grp_end_ndx; ndx++, cap++) {
22908278a5eSRod Evans 		if (cap->c_tag == CA_SUNW_ID) {
23008278a5eSRod Evans 			argstate_add_str(argstate, TRUE);
23108278a5eSRod Evans 			return (elfedit_offset_to_str(argstate->str.sec,
23208278a5eSRod Evans 			    cap->c_un.c_val, ELFEDIT_MSG_ERR, 0));
23308278a5eSRod Evans 		}
23408278a5eSRod Evans 
23508278a5eSRod Evans 		if (cap->c_tag == CA_SUNW_NULL)
23608278a5eSRod Evans 			break;
23708278a5eSRod Evans 	}
23808278a5eSRod Evans 
23908278a5eSRod Evans 	return ((argstate->cap.grp_start_ndx == 0) ?
24008278a5eSRod Evans 	    MSG_INTL(MSG_STR_OBJECT) : MSG_INTL(MSG_STR_NONAME));
24108278a5eSRod Evans }
24208278a5eSRod Evans 
24308278a5eSRod Evans 
24408278a5eSRod Evans /*
24508278a5eSRod Evans  * Given an index into the capabilities array, set the argstate cap.grp_*
24608278a5eSRod Evans  * fields to reflect the capabilities group containing the index.
24708278a5eSRod Evans  *
24808278a5eSRod Evans  * The group concept is used to limit operations to a related group
24908278a5eSRod Evans  * of capabilities, and prevent insert/delete/move operations from
25008278a5eSRod Evans  * spilling across groups.
25108278a5eSRod Evans  */
25208278a5eSRod Evans static void
argstate_cap_group(ARGSTATE * argstate,Word ndx)25308278a5eSRod Evans argstate_cap_group(ARGSTATE *argstate, Word ndx)
25408278a5eSRod Evans {
25508278a5eSRod Evans 	if (argstate->cap.grp_set == TRUE)
25608278a5eSRod Evans 		return;
25708278a5eSRod Evans 
25808278a5eSRod Evans 	cap_group_extents(argstate, ndx, &argstate->cap.grp_start_ndx,
25908278a5eSRod Evans 	    &argstate->cap.grp_end_ndx);
26008278a5eSRod Evans 
26108278a5eSRod Evans 	argstate->cap.grp_set = TRUE;
26208278a5eSRod Evans 	elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_CAPGRP),
26308278a5eSRod Evans 	    EC_WORD(argstate->cap.sec->sec_shndx), argstate->cap.sec->sec_name,
26408278a5eSRod Evans 	    EC_WORD(argstate->cap.grp_start_ndx),
26508278a5eSRod Evans 	    EC_WORD(argstate->cap.grp_end_ndx), cap_group_id(argstate));
26608278a5eSRod Evans }
26708278a5eSRod Evans 
26808278a5eSRod Evans /*
26908278a5eSRod Evans  * Given an index into the capabilities array, issue a group title for
27008278a5eSRod Evans  * the capabilities group that contains it.
27108278a5eSRod Evans  */
27208278a5eSRod Evans static void
group_title(ARGSTATE * argstate,Word ndx)27308278a5eSRod Evans group_title(ARGSTATE *argstate, Word ndx)
27408278a5eSRod Evans {
27508278a5eSRod Evans 	ARGSTATE	loc_argstate;
27608278a5eSRod Evans 
27708278a5eSRod Evans 	loc_argstate = *argstate;
27808278a5eSRod Evans 	cap_group_extents(argstate, ndx, &loc_argstate.cap.grp_start_ndx,
27908278a5eSRod Evans 	    &loc_argstate.cap.grp_end_ndx);
28008278a5eSRod Evans 	elfedit_printf(MSG_INTL(MSG_FMT_CAPGRP),
28108278a5eSRod Evans 	    EC_WORD(loc_argstate.cap.grp_start_ndx),
28208278a5eSRod Evans 	    EC_WORD(loc_argstate.cap.grp_end_ndx), cap_group_id(&loc_argstate));
28308278a5eSRod Evans }
28408278a5eSRod Evans 
285d29b2c44Sab /*
286d29b2c44Sab  * Standard argument processing for cap module
287d29b2c44Sab  *
288d29b2c44Sab  * entry
289d29b2c44Sab  *	obj_state, argc, argv - Standard command arguments
290d29b2c44Sab  *	argstate - Address of ARGSTATE block to be initialized
291d29b2c44Sab  *
292d29b2c44Sab  * exit:
293d29b2c44Sab  *	On success, *argstate is initialized. On error,
294d29b2c44Sab  *	an error is issued and this routine does not return.
295d29b2c44Sab  */
296d29b2c44Sab static void
process_args(elfedit_obj_state_t * obj_state,int argc,const char * argv[],ARGSTATE * argstate)297d29b2c44Sab process_args(elfedit_obj_state_t *obj_state, int argc, const char *argv[],
298d29b2c44Sab     ARGSTATE *argstate)
299d29b2c44Sab {
300d29b2c44Sab 	elfedit_getopt_state_t	getopt_state;
301d29b2c44Sab 	elfedit_getopt_ret_t	*getopt_ret;
30208278a5eSRod Evans 	const char		*capid = NULL;
303d29b2c44Sab 
304d29b2c44Sab 	bzero(argstate, sizeof (*argstate));
305d29b2c44Sab 	argstate->obj_state = obj_state;
306d29b2c44Sab 
307d29b2c44Sab 	elfedit_getopt_init(&getopt_state, &argc, &argv);
308d29b2c44Sab 
309d29b2c44Sab 	/* Add each new option to the options mask */
31008278a5eSRod Evans 	while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) {
311d29b2c44Sab 		argstate->optmask |= getopt_ret->gor_idmask;
312d29b2c44Sab 
31308278a5eSRod Evans 		if (getopt_ret->gor_idmask == CAP_OPT_F_CAPID)
31408278a5eSRod Evans 			capid = getopt_ret->gor_value;
31508278a5eSRod Evans 	}
31608278a5eSRod Evans 
317d29b2c44Sab 	/* If there may be an arbitrary amount of output, use a pager */
318d29b2c44Sab 	if (argc == 0)
319d29b2c44Sab 		elfedit_pager_init();
320d29b2c44Sab 
321d29b2c44Sab 	/* Return the updated values of argc/argv */
322d29b2c44Sab 	argstate->argc = argc;
323d29b2c44Sab 	argstate->argv = argv;
324d29b2c44Sab 
325d29b2c44Sab 	/* Locate the capabilities section */
326d29b2c44Sab 	argstate->cap.sec = elfedit_sec_getcap(obj_state, &argstate->cap.data,
327d29b2c44Sab 	    &argstate->cap.num);
32808278a5eSRod Evans 
32908278a5eSRod Evans 	/*
33008278a5eSRod Evans 	 * If -capid was specified, locate the specified capabilities group,
33108278a5eSRod Evans 	 * and narrow the section data to use only that group. Otherwise,
33208278a5eSRod Evans 	 * use the whole array.
33308278a5eSRod Evans 	 */
33408278a5eSRod Evans 	if (capid != NULL) {
33508278a5eSRod Evans 		Word	i;
33608278a5eSRod Evans 		Cap	*cap = argstate->cap.data;
33708278a5eSRod Evans 
33808278a5eSRod Evans 		/*
33908278a5eSRod Evans 		 * -capid requires the capability section to have an
34008278a5eSRod Evans 		 * associated string table.
34108278a5eSRod Evans 		 */
34208278a5eSRod Evans 		argstate_add_str(argstate, TRUE);
34308278a5eSRod Evans 
34408278a5eSRod Evans 		for (i = 0; i < argstate->cap.num; i++, cap++)
34508278a5eSRod Evans 			if ((cap->c_tag == CA_SUNW_ID) &&
34608278a5eSRod Evans 			    (strcmp(capid, elfedit_offset_to_str(
34708278a5eSRod Evans 			    argstate->str.sec, cap->c_un.c_val,
34808278a5eSRod Evans 			    ELFEDIT_MSG_ERR, 0)) == 0))
34908278a5eSRod Evans 				break;
35008278a5eSRod Evans 
35108278a5eSRod Evans 		if (i == argstate->cap.num)
35208278a5eSRod Evans 			elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_BADCAPID),
35308278a5eSRod Evans 			    EC_WORD(argstate->cap.sec->sec_shndx),
35408278a5eSRod Evans 			    argstate->cap.sec->sec_name, capid);
35508278a5eSRod Evans 		argstate_cap_group(argstate, i);
35608278a5eSRod Evans 	} else {
35708278a5eSRod Evans 		argstate->cap.grp_start_ndx = 0;
35808278a5eSRod Evans 		argstate->cap.grp_end_ndx = argstate->cap.num - 1;
35908278a5eSRod Evans 	}
360d29b2c44Sab }
361d29b2c44Sab 
362d29b2c44Sab 
363d29b2c44Sab 
364d29b2c44Sab /*
365d29b2c44Sab  * Print ELF capabilities values, taking the calling command, and output style
366d29b2c44Sab  * into account.
367d29b2c44Sab  *
368d29b2c44Sab  * entry:
369d29b2c44Sab  *	cmd - CAP_CMD_T_* value giving identify of caller
370d29b2c44Sab  *	autoprint - If True, output is only produced if the elfedit
371d29b2c44Sab  *		autoprint flag is set. If False, output is always produced.
372d29b2c44Sab  *	argstate - Argument state block
373d29b2c44Sab  *	print_type - Specifies which capabilities elements to display.
374d29b2c44Sab  *	ndx = If print_type is PRINT_CAP_T_NDX, displays the index specified.
375d29b2c44Sab  *		Otherwise ignored.
376d29b2c44Sab  */
377d29b2c44Sab typedef enum {
378d29b2c44Sab 	PRINT_CAP_T_ALL =	0,	/* Show all indexes */
379d29b2c44Sab 	PRINT_CAP_T_NDX =	1,	/* Show capabilities[arg] only */
380d29b2c44Sab 	PRINT_CAP_T_TAG =	2	/* Show all elts with tag type */
381d29b2c44Sab 					/*	given by arg */
382d29b2c44Sab } PRINT_CAP_T;
383d29b2c44Sab 
384d29b2c44Sab static void
print_cap(CAP_CMD_T cmd,int autoprint,ARGSTATE * argstate,PRINT_CAP_T print_type,Word arg)385d29b2c44Sab print_cap(CAP_CMD_T cmd, int autoprint, ARGSTATE *argstate,
386d29b2c44Sab     PRINT_CAP_T print_type, Word arg)
387d29b2c44Sab {
388d29b2c44Sab 	elfedit_outstyle_t	outstyle;
38998c080d5SRod Evans 	Word		cnt, ndx, printed = 0;
39098c080d5SRod Evans 	Cap		*cap;
39198c080d5SRod Evans 	Boolean		header_done = FALSE, null_seen = FALSE;
39298c080d5SRod Evans 	const char	*str;
39398c080d5SRod Evans 	size_t		str_size;
394d29b2c44Sab 
395d29b2c44Sab 	if (autoprint && ((elfedit_flags() & ELFEDIT_F_AUTOPRINT) == 0))
396d29b2c44Sab 		return;
397d29b2c44Sab 
398d29b2c44Sab 	/*
399d29b2c44Sab 	 * Pick an output style. cap:dump is required to use the default
400d29b2c44Sab 	 * style. The other commands use the current output style.
401d29b2c44Sab 	 */
402d29b2c44Sab 	outstyle = (cmd == CAP_CMD_T_DUMP) ?
403d29b2c44Sab 	    ELFEDIT_OUTSTYLE_DEFAULT : elfedit_outstyle();
404d29b2c44Sab 
405d29b2c44Sab 	/* How many elements do we examine? */
406d29b2c44Sab 	if (print_type == PRINT_CAP_T_NDX) {
407d29b2c44Sab 		if (arg >= argstate->cap.num)
408d29b2c44Sab 			return;		/* Out of range */
409d29b2c44Sab 		ndx = arg;
410d29b2c44Sab 		cnt = 1;
411d29b2c44Sab 	} else {
41208278a5eSRod Evans 		ndx = argstate->cap.grp_start_ndx;
41308278a5eSRod Evans 		cnt = argstate->cap.grp_end_ndx - ndx + 1;
414d29b2c44Sab 	}
415d29b2c44Sab 
41608278a5eSRod Evans 	/* Load string table if there is one */
41708278a5eSRod Evans 	argstate_add_str(argstate, FALSE);
41898c080d5SRod Evans 	if (argstate->str.sec == NULL) {
41998c080d5SRod Evans 		str = NULL;
42098c080d5SRod Evans 		str_size = 0;
42198c080d5SRod Evans 	} else {
42298c080d5SRod Evans 		str = (const char *)argstate->str.sec->sec_data->d_buf;
42398c080d5SRod Evans 		str_size = argstate->str.sec->sec_data->d_size;
42498c080d5SRod Evans 	}
42508278a5eSRod Evans 
426d29b2c44Sab 	cap = &argstate->cap.data[ndx];
427d29b2c44Sab 	for (; cnt--; cap++, ndx++) {
428d29b2c44Sab 		/*
429d29b2c44Sab 		 * If we are only displaying certain tag types and
430d29b2c44Sab 		 * this isn't one of those, move on to next element.
431d29b2c44Sab 		 */
43208278a5eSRod Evans 		if ((print_type == PRINT_CAP_T_TAG) && (cap->c_tag != arg)) {
43308278a5eSRod Evans 			if (cap->c_tag == CA_SUNW_NULL)
43408278a5eSRod Evans 				null_seen = TRUE;
435d29b2c44Sab 			continue;
43608278a5eSRod Evans 		}
43708278a5eSRod Evans 
43808278a5eSRod Evans 		/*
43908278a5eSRod Evans 		 * If capability type requires a string table, and we don't
44008278a5eSRod Evans 		 * have one, force an error.
44108278a5eSRod Evans 		 */
44208278a5eSRod Evans 		switch (cap->c_tag) {
44308278a5eSRod Evans 		case CA_SUNW_PLAT:
44408278a5eSRod Evans 		case CA_SUNW_MACH:
44508278a5eSRod Evans 		case CA_SUNW_ID:
44608278a5eSRod Evans 			if (argstate->str.sec == NULL)
44708278a5eSRod Evans 				argstate_add_str(argstate, TRUE);
44808278a5eSRod Evans 			break;
44908278a5eSRod Evans 		}
450d29b2c44Sab 
451d29b2c44Sab 		if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) {
45208278a5eSRod Evans 			if (null_seen && (cap->c_tag != CA_SUNW_NULL)) {
45308278a5eSRod Evans 				null_seen = FALSE;
45408278a5eSRod Evans 				if (header_done) {
45508278a5eSRod Evans 					elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
45608278a5eSRod Evans 					    MSG_ORIG(MSG_STR_EMPTY));
45708278a5eSRod Evans 					header_done = FALSE;
45808278a5eSRod Evans 				}
45908278a5eSRod Evans 			}
46008278a5eSRod Evans 
46108278a5eSRod Evans 			if (header_done == FALSE) {
46208278a5eSRod Evans 				header_done = TRUE;
46308278a5eSRod Evans 				group_title(argstate, ndx);
464d29b2c44Sab 				Elf_cap_title(0);
465d29b2c44Sab 			}
46698c080d5SRod Evans 			Elf_cap_entry(NULL, cap, ndx, str, str_size,
467d29b2c44Sab 			    argstate->obj_state->os_ehdr->e_machine);
468d29b2c44Sab 		} else {
469d29b2c44Sab 			/*
47008278a5eSRod Evans 			 * If CAP_CMD_T_TAG, and not in default output
47108278a5eSRod Evans 			 * style, display the tag rather than the value.
472d29b2c44Sab 			 */
47308278a5eSRod Evans 			if (cmd == CAP_CMD_T_TAG) {
47408278a5eSRod Evans 				if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
47508278a5eSRod Evans 					Conv_inv_buf_t	inv_buf;
47608278a5eSRod Evans 
47708278a5eSRod Evans 					elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
47808278a5eSRod Evans 					    conv_cap_tag(cap->c_tag, 0,
47908278a5eSRod Evans 					    &inv_buf));
48008278a5eSRod Evans 				} else {
48108278a5eSRod Evans 					elfedit_printf(
48208278a5eSRod Evans 					    MSG_ORIG(MSG_FMT_WORDVALNL),
48308278a5eSRod Evans 					    EC_WORD(cap->c_tag));
48408278a5eSRod Evans 				}
48508278a5eSRod Evans 				printed = 1;
486d29b2c44Sab 				continue;
48708278a5eSRod Evans 			}
488d29b2c44Sab 
48908278a5eSRod Evans 			/* Displaying the value in simple or numeric mode */
490d29b2c44Sab 			if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
49108278a5eSRod Evans 				Conv_cap_val_buf_t	cap_val_buf;
49208278a5eSRod Evans 
49308278a5eSRod Evans 				if (print_type == PRINT_CAP_T_TAG) {
49408278a5eSRod Evans 					elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
49508278a5eSRod Evans 					    conv_cap_val_hw1(cap->c_un.c_val,
49608278a5eSRod Evans 					    argstate->obj_state->os_ehdr->
49708278a5eSRod Evans 					    e_machine, CONV_FMT_NOBKT,
49808278a5eSRod Evans 					    &cap_val_buf.cap_val_hw1_buf));
49908278a5eSRod Evans 					printed = 1;
50008278a5eSRod Evans 					continue;
50108278a5eSRod Evans 				}
502d29b2c44Sab 
503d29b2c44Sab 				switch (cap->c_tag) {
504d29b2c44Sab 				case CA_SUNW_HW_1:
505d29b2c44Sab 					elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
506d29b2c44Sab 					    conv_cap_val_hw1(cap->c_un.c_val,
507d29b2c44Sab 					    argstate->obj_state->os_ehdr->
50808278a5eSRod Evans 					    e_machine, CONV_FMT_NOBKT,
50908278a5eSRod Evans 					    &cap_val_buf.cap_val_hw1_buf));
510d29b2c44Sab 					printed = 1;
511d29b2c44Sab 					continue;
512d29b2c44Sab 				case CA_SUNW_SF_1:
513d29b2c44Sab 					elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
514d29b2c44Sab 					    conv_cap_val_sf1(cap->c_un.c_val,
515d29b2c44Sab 					    argstate->obj_state->os_ehdr->
51608278a5eSRod Evans 					    e_machine, CONV_FMT_NOBKT,
51708278a5eSRod Evans 					    &cap_val_buf.cap_val_sf1_buf));
51808278a5eSRod Evans 					printed = 1;
51908278a5eSRod Evans 					continue;
52008278a5eSRod Evans 				case CA_SUNW_HW_2:
52108278a5eSRod Evans 					elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
52208278a5eSRod Evans 					    conv_cap_val_hw2(cap->c_un.c_val,
52308278a5eSRod Evans 					    argstate->obj_state->os_ehdr->
52408278a5eSRod Evans 					    e_machine, CONV_FMT_NOBKT,
52508278a5eSRod Evans 					    &cap_val_buf.cap_val_hw2_buf));
52608278a5eSRod Evans 					printed = 1;
52708278a5eSRod Evans 					continue;
52808278a5eSRod Evans 				case CA_SUNW_PLAT:
52908278a5eSRod Evans 				case CA_SUNW_MACH:
53008278a5eSRod Evans 				case CA_SUNW_ID:
53108278a5eSRod Evans 					elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
53208278a5eSRod Evans 					    elfedit_offset_to_str(
53308278a5eSRod Evans 					    argstate->str.sec, cap->c_un.c_val,
53408278a5eSRod Evans 					    ELFEDIT_MSG_ERR, 0));
535d29b2c44Sab 					printed = 1;
536d29b2c44Sab 					continue;
537*56726c7eSRobert Mustacchi 				case CA_SUNW_HW_3:
538*56726c7eSRobert Mustacchi 					elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
539*56726c7eSRobert Mustacchi 					    conv_cap_val_hw3(cap->c_un.c_val,
540*56726c7eSRobert Mustacchi 					    argstate->obj_state->os_ehdr->
541*56726c7eSRobert Mustacchi 					    e_machine, CONV_FMT_NOBKT,
542*56726c7eSRobert Mustacchi 					    &cap_val_buf.cap_val_hw3_buf));
543*56726c7eSRobert Mustacchi 					printed = 1;
544*56726c7eSRobert Mustacchi 					continue;
545d29b2c44Sab 				}
546d29b2c44Sab 			}
547d29b2c44Sab 			elfedit_printf(MSG_ORIG(MSG_FMT_HEXXWORDNL),
54808278a5eSRod Evans 			    EC_XWORD(cap->c_un.c_val));
549d29b2c44Sab 		}
550d29b2c44Sab 		printed = 1;
55108278a5eSRod Evans 		if (cap->c_tag == CA_SUNW_NULL)
55208278a5eSRod Evans 			null_seen = TRUE;
553d29b2c44Sab 	}
554d29b2c44Sab 
555d29b2c44Sab 	/*
556d29b2c44Sab 	 * If nothing was output under the print types that are
557d29b2c44Sab 	 * based on tag type, issue an error saying it doesn't exist.
558d29b2c44Sab 	 */
559d29b2c44Sab 	if (!printed && (print_type == PRINT_CAP_T_TAG)) {
56008278a5eSRod Evans 		Conv_inv_buf_t	inv_buf;
561d29b2c44Sab 
562d29b2c44Sab 		elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOCAELT),
563d29b2c44Sab 		    EC_WORD(argstate->cap.sec->sec_shndx),
56408278a5eSRod Evans 		    argstate->cap.sec->sec_name, argstate->cap.grp_start_ndx,
56508278a5eSRod Evans 		    argstate->cap.grp_end_ndx, cap_group_id(argstate),
5664f680cc6SAli Bahrami 		    conv_cap_tag(arg, 0, &inv_buf));
567d29b2c44Sab 	}
568d29b2c44Sab }
569d29b2c44Sab 
570d29b2c44Sab 
571d29b2c44Sab /*
572d29b2c44Sab  * Process the elt argument: This will be a tag type if -capndx is
573d29b2c44Sab  * not present and this is a print request. It will be an index otherwise.
574d29b2c44Sab  *
575d29b2c44Sab  * entry:
576d29b2c44Sab  *	argstate - Argument state block
577d29b2c44Sab  *	arg - Argument string to be converted into an index
578d29b2c44Sab  *	argname - String giving the name by which the argument is
579d29b2c44Sab  *		referred in the online help for the command.
580d29b2c44Sab  *	print_request - True if the command is to print the current
581d29b2c44Sab  *		value(s) and return without changing anything.
582d29b2c44Sab  *	print_type - Address of variable containing PRINT_CAP_T_
583d29b2c44Sab  *		code specifying how the elements will be displayed.
584d29b2c44Sab  *
585d29b2c44Sab  * exit:
586d29b2c44Sab  *	If print_request is False: arg is converted into an integer value.
587d29b2c44Sab  *	If -capndx was used, we convert it into an integer. If it was not
588d29b2c44Sab  *	used, then arg is a tag name --- we find the first capabilities entry
589d29b2c44Sab  *	that matches. If no entry matches, and there is an extra CA_NULL,
590d29b2c44Sab  *	it is added. Otherwise an error is issued. *print_type is set
591d29b2c44Sab  *	to PRINT_CAP_T_NDX.
592d29b2c44Sab  *
593d29b2c44Sab  *	If print_request is True: If -capndx was used, arg is converted into
594d29b2c44Sab  *	an integer value, *print_type is set to PRINT_CAP_T_NDX, and
595d29b2c44Sab  *	the value is returned. If -capndx was not used, *print_type is set to
596d29b2c44Sab  *	PRINT_CAP_T_TAG, and the tag value is returned.
597d29b2c44Sab  */
598d29b2c44Sab static Word
arg_to_index(ARGSTATE * argstate,const char * arg,const char * argname,int print_request,PRINT_CAP_T * print_type)599d29b2c44Sab arg_to_index(ARGSTATE *argstate, const char *arg, const char *argname,
600d29b2c44Sab     int print_request, PRINT_CAP_T *print_type)
601d29b2c44Sab {
60208278a5eSRod Evans 	Word		ndx, ca_value;
603d29b2c44Sab 
604d29b2c44Sab 
605d29b2c44Sab 	/* Assume we are returning an index, alter as needed below */
606d29b2c44Sab 	*print_type = PRINT_CAP_T_NDX;
607d29b2c44Sab 
60808278a5eSRod Evans 	/*
60908278a5eSRod Evans 	 * If -capndx was used, this is a simple numeric index.
61008278a5eSRod Evans 	 * Determine its capability group because some operations
61108278a5eSRod Evans 	 * (move, delete) are limited to operate within it.
61208278a5eSRod Evans 	 */
61308278a5eSRod Evans 	if ((argstate->optmask & CAP_OPT_F_CAPNDX) != 0) {
61408278a5eSRod Evans 		ndx = (Word) elfedit_atoui_range(arg, argname, 0,
61508278a5eSRod Evans 		    argstate->cap.num - 1, NULL);
61608278a5eSRod Evans 		argstate_cap_group(argstate, ndx);
61708278a5eSRod Evans 		return (ndx);
61808278a5eSRod Evans 	}
619d29b2c44Sab 
620d29b2c44Sab 	/* The argument is a CA_ tag type, not a numeric index */
621d29b2c44Sab 	ca_value = (Word) elfedit_atoconst(arg, ELFEDIT_CONST_CA);
622d29b2c44Sab 
623d29b2c44Sab 	/*
624d29b2c44Sab 	 * If this is a printing request, then we let print_cap() show
625d29b2c44Sab 	 * all the items with this tag type.
626d29b2c44Sab 	 */
627d29b2c44Sab 	if (print_request) {
628d29b2c44Sab 		*print_type = PRINT_CAP_T_TAG;
629d29b2c44Sab 		return (ca_value);
630d29b2c44Sab 	}
631d29b2c44Sab 
63208278a5eSRod Evans 	/*
63308278a5eSRod Evans 	 * If we haven't determined a capability group yet, either via
63408278a5eSRod Evans 	 * -capid, or -capndx, then make it the initial group, which
63508278a5eSRod Evans 	 * represent the object capabilities.
63608278a5eSRod Evans 	 */
63708278a5eSRod Evans 	if (!argstate->cap.grp_set)
63808278a5eSRod Evans 		argstate_cap_group(argstate, 0);
63908278a5eSRod Evans 
64008278a5eSRod Evans 	/*
64108278a5eSRod Evans 	 * Locate the first entry with the given tag type within the
64208278a5eSRod Evans 	 * capabilities group.
64308278a5eSRod Evans 	 */
64408278a5eSRod Evans 	for (ndx = argstate->cap.grp_start_ndx;
64508278a5eSRod Evans 	    ndx <= argstate->cap.grp_end_ndx; ndx++) {
646d29b2c44Sab 		if (argstate->cap.data[ndx].c_tag == ca_value) {
647d29b2c44Sab 			elfedit_msg(ELFEDIT_MSG_DEBUG,
648d29b2c44Sab 			    MSG_INTL(MSG_DEBUG_CA2NDX),
649d29b2c44Sab 			    EC_WORD(argstate->cap.sec->sec_shndx),
650d29b2c44Sab 			    argstate->cap.sec->sec_name, EC_WORD(ndx), arg);
651d29b2c44Sab 			return (ndx);
652d29b2c44Sab 		}
65308278a5eSRod Evans 
65408278a5eSRod Evans 		/*
65508278a5eSRod Evans 		 * If we hit a NULL, then only more NULLs can follow it and
65608278a5eSRod Evans 		 * there's no need to look further. If there is more than
65708278a5eSRod Evans 		 * one NULL, we can grab the first one and turn it into
65808278a5eSRod Evans 		 * an element of the desired type.
65908278a5eSRod Evans 		 */
66008278a5eSRod Evans 		if (argstate->cap.data[ndx].c_tag == CA_SUNW_NULL) {
66108278a5eSRod Evans 			if (ndx < argstate->cap.grp_end_ndx) {
66208278a5eSRod Evans 				Conv_inv_buf_t	inv_buf;
66308278a5eSRod Evans 
66408278a5eSRod Evans 				elfedit_msg(ELFEDIT_MSG_DEBUG,
66508278a5eSRod Evans 				    MSG_INTL(MSG_DEBUG_CONVNULL),
66608278a5eSRod Evans 				    EC_WORD(argstate->cap.sec->sec_shndx),
66708278a5eSRod Evans 				    argstate->cap.sec->sec_name, EC_WORD(ndx),
66808278a5eSRod Evans 				    conv_cap_tag(ca_value, 0, &inv_buf));
66908278a5eSRod Evans 				argstate->cap.data[ndx].c_tag = ca_value;
67008278a5eSRod Evans 				bzero(&argstate->cap.data[ndx].c_un,
67108278a5eSRod Evans 				    sizeof (argstate->cap.data[ndx].c_un));
67208278a5eSRod Evans 				return (ndx);
67308278a5eSRod Evans 			}
67408278a5eSRod Evans 			break;
67508278a5eSRod Evans 		}
676d29b2c44Sab 	}
677d29b2c44Sab 
678d29b2c44Sab 	/* No room to create one, so we're out of options and must fail */
679d29b2c44Sab 	elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOCAELT),
680d29b2c44Sab 	    EC_WORD(argstate->cap.sec->sec_shndx),
68108278a5eSRod Evans 	    argstate->cap.sec->sec_name, argstate->cap.grp_start_ndx,
68208278a5eSRod Evans 	    argstate->cap.grp_end_ndx, cap_group_id(argstate), arg);
683d29b2c44Sab 
684d29b2c44Sab 	/*NOTREACHED*/
685d29b2c44Sab 	return (0);		/* For lint */
686d29b2c44Sab }
687d29b2c44Sab 
688d29b2c44Sab 
689d29b2c44Sab /*
690d29b2c44Sab  * Argument processing for the bitmask commands. Convert the arguments
691d29b2c44Sab  * to integer form, apply -and/-cmp/-or, and return the resulting value.
692d29b2c44Sab  *
693d29b2c44Sab  * entry:
694d29b2c44Sab  *	argstate - Argument state block
695d29b2c44Sab  *	orig - Value of original bitmask
696d29b2c44Sab  *	const_sym - NULL, or array of name->integer mappings for
697d29b2c44Sab  *		applicable symbolic constant names.
698d29b2c44Sab  */
699d29b2c44Sab static Word
flag_bitop(ARGSTATE * argstate,Word orig,const elfedit_atoui_sym_t * const_sym)700d29b2c44Sab flag_bitop(ARGSTATE *argstate, Word orig, const elfedit_atoui_sym_t *const_sym)
701d29b2c44Sab {
702d29b2c44Sab 	Word flags = 0;
703d29b2c44Sab 	int i;
704d29b2c44Sab 
705d29b2c44Sab 	/* Collect the arguments */
706d29b2c44Sab 	for (i = 0; i < argstate->argc; i++)
707d29b2c44Sab 		flags |= (Word) elfedit_atoui(argstate->argv[i], const_sym);
708d29b2c44Sab 
709d29b2c44Sab 	/* Complement the value? */
710d29b2c44Sab 	if (argstate->optmask & CAP_OPT_F_CMP)
711d29b2c44Sab 		flags = ~flags;
712d29b2c44Sab 
713d29b2c44Sab 	/* Perform any requested bit operations */
714d29b2c44Sab 	if (argstate->optmask & CAP_OPT_F_AND)
715d29b2c44Sab 		flags &= orig;
716d29b2c44Sab 	else if (argstate->optmask & CAP_OPT_F_OR)
717d29b2c44Sab 		flags |= orig;
718d29b2c44Sab 
719d29b2c44Sab 	return (flags);
720d29b2c44Sab }
721d29b2c44Sab 
72208278a5eSRod Evans /*
72308278a5eSRod Evans  * Common processing for capabilities value setting.
72408278a5eSRod Evans  *
72508278a5eSRod Evans  * entry:
72608278a5eSRod Evans  *	argstate - Argument state block
72708278a5eSRod Evans  *	cap - capabilities data pointer
72808278a5eSRod Evans  *	ndx - capabilities data index
72908278a5eSRod Evans  *	cap_ndx - capabilities section index
73008278a5eSRod Evans  *	cap_name - capabilities section name
73108278a5eSRod Evans  *	cap_tag - capabilities tag
73208278a5eSRod Evans  *	const_type - data conversion type
73308278a5eSRod Evans  */
73408278a5eSRod Evans static elfedit_cmdret_t
cap_set(ARGSTATE * argstate,Cap * cap,Word ndx,Word cap_ndx,const char * cap_name,Xword cap_tag,elfedit_const_t const_type)73508278a5eSRod Evans cap_set(ARGSTATE *argstate, Cap *cap, Word ndx, Word cap_ndx,
73608278a5eSRod Evans     const char *cap_name, Xword cap_tag, elfedit_const_t const_type)
73708278a5eSRod Evans {
73808278a5eSRod Evans 	Conv_cap_val_buf_t	buf1, buf2;
73908278a5eSRod Evans 	Half			mach = argstate->obj_state->os_ehdr->e_machine;
74008278a5eSRod Evans 	Xword			ncap, ocap;
74108278a5eSRod Evans 
74208278a5eSRod Evans 	ncap = flag_bitop(argstate, cap[ndx].c_un.c_val,
74308278a5eSRod Evans 	    elfedit_const_to_atoui(const_type));
74408278a5eSRod Evans 
74508278a5eSRod Evans 	/* Set the value */
74608278a5eSRod Evans 	if ((ocap = cap[ndx].c_un.c_val) == ncap) {
74708278a5eSRod Evans 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_BSB_OK),
74808278a5eSRod Evans 		    cap_ndx, cap_name, EC_WORD(ndx),
74908278a5eSRod Evans 		    conv_cap_val(cap_tag, ocap, mach, CONV_FMT_NOBKT, &buf1));
750d29b2c44Sab 
75108278a5eSRod Evans 		return (ELFEDIT_CMDRET_NONE);
75208278a5eSRod Evans 	} else {
75308278a5eSRod Evans 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_BSB_CHG),
75408278a5eSRod Evans 		    cap_ndx, cap_name, EC_WORD(ndx),
75508278a5eSRod Evans 		    conv_cap_val(cap_tag, ocap, mach, CONV_FMT_NOBKT, &buf1),
75608278a5eSRod Evans 		    conv_cap_val(cap_tag, ncap, mach, CONV_FMT_NOBKT, &buf2));
75708278a5eSRod Evans 
75808278a5eSRod Evans 		cap[ndx].c_un.c_val = ncap;
75908278a5eSRod Evans 		return (ELFEDIT_CMDRET_MOD);
76008278a5eSRod Evans 	}
76108278a5eSRod Evans }
762d29b2c44Sab 
763d29b2c44Sab /*
764d29b2c44Sab  * Common body for the cap: module commands. These commands
765d29b2c44Sab  * share a large amount of common behavior, so it is convenient
766d29b2c44Sab  * to centralize things and use the cmd argument to handle the
767d29b2c44Sab  * small differences.
768d29b2c44Sab  *
769d29b2c44Sab  * entry:
770d29b2c44Sab  *	cmd - One of the CAP_CMD_T_* constants listed above, specifying
771d29b2c44Sab  *		which command to implement.
772d29b2c44Sab  *	obj_state, argc, argv - Standard command arguments
773d29b2c44Sab  */
774d29b2c44Sab static elfedit_cmdret_t
cmd_body(CAP_CMD_T cmd,elfedit_obj_state_t * obj_state,int argc,const char * argv[])775d29b2c44Sab cmd_body(CAP_CMD_T cmd, elfedit_obj_state_t *obj_state,
776d29b2c44Sab     int argc, const char *argv[])
777d29b2c44Sab {
778d29b2c44Sab 	ARGSTATE		argstate;
779d29b2c44Sab 	Cap			*cap;
780d29b2c44Sab 	const char		*cap_name;
78108278a5eSRod Evans 	Word			cap_ndx;
782d29b2c44Sab 	elfedit_cmdret_t	ret = ELFEDIT_CMDRET_NONE;
783d29b2c44Sab 	PRINT_CAP_T		print_type = PRINT_CAP_T_ALL;
784d29b2c44Sab 	Word			ndx;
785d29b2c44Sab 	int			print_only = 0;
786d29b2c44Sab 	int			do_autoprint = 1;
787d29b2c44Sab 
788d29b2c44Sab 	/* Process the optional arguments */
789d29b2c44Sab 	process_args(obj_state, argc, argv, &argstate);
790d29b2c44Sab 
791d29b2c44Sab 	cap = argstate.cap.data;
792d29b2c44Sab 	cap_name = argstate.cap.sec->sec_name;
793d29b2c44Sab 	cap_ndx = argstate.cap.sec->sec_shndx;
794d29b2c44Sab 
795d29b2c44Sab 	/* Check number of arguments, gather information */
796d29b2c44Sab 	switch (cmd) {
797d29b2c44Sab 	case CAP_CMD_T_DUMP:
798d29b2c44Sab 		/* cap:dump can accept an optional index argument */
799d29b2c44Sab 		if (argstate.argc > 1)
800d29b2c44Sab 			elfedit_command_usage();
801d29b2c44Sab 		print_only = 1;
802d29b2c44Sab 		if (argstate.argc == 1)
803d29b2c44Sab 			ndx = arg_to_index(&argstate, argstate.argv[0],
804d29b2c44Sab 			    MSG_ORIG(MSG_STR_ELT), print_only, &print_type);
805d29b2c44Sab 		break;
806d29b2c44Sab 
807d29b2c44Sab 	case CAP_CMD_T_TAG:
808d29b2c44Sab 	case CAP_CMD_T_VALUE:
809d29b2c44Sab 		print_only = (argstate.argc != 2);
810d29b2c44Sab 		if (argstate.argc > 0) {
811d29b2c44Sab 			if (argstate.argc > 2)
812d29b2c44Sab 				elfedit_command_usage();
813d29b2c44Sab 			ndx = arg_to_index(&argstate, argstate.argv[0],
814d29b2c44Sab 			    MSG_ORIG(MSG_STR_ELT), print_only, &print_type);
815d29b2c44Sab 		}
816d29b2c44Sab 		break;
817d29b2c44Sab 
818d29b2c44Sab 	case CAP_CMD_T_DELETE:
819d29b2c44Sab 		if ((argstate.argc < 1) || (argstate.argc > 2))
820d29b2c44Sab 			elfedit_command_usage();
821d29b2c44Sab 		ndx = arg_to_index(&argstate, argstate.argv[0],
822d29b2c44Sab 		    MSG_ORIG(MSG_STR_ELT),
823d29b2c44Sab 		    0, &print_type);
824d29b2c44Sab 		do_autoprint = 0;
825d29b2c44Sab 		break;
826d29b2c44Sab 
827d29b2c44Sab 	case CAP_CMD_T_MOVE:
828d29b2c44Sab 		if ((argstate.argc < 2) || (argstate.argc > 3))
829d29b2c44Sab 			elfedit_command_usage();
830d29b2c44Sab 		ndx = arg_to_index(&argstate, argstate.argv[0],
831d29b2c44Sab 		    MSG_ORIG(MSG_STR_ELT), 0, &print_type);
832d29b2c44Sab 		do_autoprint = 0;
833d29b2c44Sab 		break;
834d29b2c44Sab 
835d29b2c44Sab 	case CAP_CMD_T_HW1:
836d29b2c44Sab 		print_only = (argstate.argc == 0);
837d29b2c44Sab 		ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str(
838d29b2c44Sab 		    ELFEDIT_CONST_CA, CA_SUNW_HW_1, 1),
839d29b2c44Sab 		    MSG_ORIG(MSG_STR_VALUE), print_only, &print_type);
840d29b2c44Sab 		break;
841d29b2c44Sab 
842d29b2c44Sab 	case CAP_CMD_T_SF1:
843d29b2c44Sab 		print_only = (argstate.argc == 0);
844d29b2c44Sab 		ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str(
845d29b2c44Sab 		    ELFEDIT_CONST_CA, CA_SUNW_SF_1, 1),
846d29b2c44Sab 		    MSG_ORIG(MSG_STR_VALUE), print_only, &print_type);
847d29b2c44Sab 		break;
848d29b2c44Sab 
84908278a5eSRod Evans 	case CAP_CMD_T_HW2:
85008278a5eSRod Evans 		print_only = (argstate.argc == 0);
85108278a5eSRod Evans 		ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str(
85208278a5eSRod Evans 		    ELFEDIT_CONST_CA, CA_SUNW_HW_2, 1),
85308278a5eSRod Evans 		    MSG_ORIG(MSG_STR_VALUE), print_only, &print_type);
85408278a5eSRod Evans 		break;
85508278a5eSRod Evans 
856*56726c7eSRobert Mustacchi 	case CAP_CMD_T_HW3:
857*56726c7eSRobert Mustacchi 		print_only = (argstate.argc == 0);
858*56726c7eSRobert Mustacchi 		ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str(
859*56726c7eSRobert Mustacchi 		    ELFEDIT_CONST_CA, CA_SUNW_HW_3, 1),
860*56726c7eSRobert Mustacchi 		    MSG_ORIG(MSG_STR_VALUE), print_only, &print_type);
861*56726c7eSRobert Mustacchi 		break;
862*56726c7eSRobert Mustacchi 
863d29b2c44Sab 	default:
864d29b2c44Sab 		/* Note expected: All commands should have been caught above */
865d29b2c44Sab 		elfedit_command_usage();
866d29b2c44Sab 		break;
867d29b2c44Sab 	}
868d29b2c44Sab 
869d29b2c44Sab 
870d29b2c44Sab 	/* If this is a request to print current values, do it and return */
871d29b2c44Sab 	if (print_only) {
872d29b2c44Sab 		print_cap(cmd, 0, &argstate, print_type, ndx);
873d29b2c44Sab 		return (ELFEDIT_CMDRET_NONE);
874d29b2c44Sab 	}
875d29b2c44Sab 
876d29b2c44Sab 
877d29b2c44Sab 	switch (cmd) {
878d29b2c44Sab 		/*
879d29b2c44Sab 		 * CAP_CMD_T_DUMP can't get here: It is a print-only
880d29b2c44Sab 		 * command.
881d29b2c44Sab 		 */
882d29b2c44Sab 
883d29b2c44Sab 	case CAP_CMD_T_TAG:
884d29b2c44Sab 		{
885d29b2c44Sab 			Conv_inv_buf_t	inv_buf1, inv_buf2;
886d29b2c44Sab 			Word c_tag = (Word) elfedit_atoconst(argstate.argv[1],
887d29b2c44Sab 			    ELFEDIT_CONST_CA);
888d29b2c44Sab 
889d29b2c44Sab 			if (cap[ndx].c_tag == c_tag) {
890d29b2c44Sab 				elfedit_msg(ELFEDIT_MSG_DEBUG,
891d29b2c44Sab 				    MSG_INTL(MSG_DEBUG_S_OK),
892d29b2c44Sab 				    cap_ndx, cap_name, EC_WORD(ndx),
8934f680cc6SAli Bahrami 				    conv_cap_tag(c_tag, 0, &inv_buf1));
894d29b2c44Sab 			} else {
895d29b2c44Sab 				elfedit_msg(ELFEDIT_MSG_DEBUG,
896d29b2c44Sab 				    MSG_INTL(MSG_DEBUG_S_CHG),
897d29b2c44Sab 				    cap_ndx, cap_name, EC_WORD(ndx),
8984f680cc6SAli Bahrami 				    conv_cap_tag(cap[ndx].c_tag, 0, &inv_buf1),
8994f680cc6SAli Bahrami 				    conv_cap_tag(c_tag, 0, &inv_buf2));
900d29b2c44Sab 				cap[ndx].c_tag = c_tag;
901d29b2c44Sab 				ret = ELFEDIT_CMDRET_MOD;
902d29b2c44Sab 			}
903d29b2c44Sab 		}
904d29b2c44Sab 		break;
905d29b2c44Sab 
906d29b2c44Sab 	case CAP_CMD_T_VALUE:
907d29b2c44Sab 		{
90808278a5eSRod Evans 			Xword c_val;
90908278a5eSRod Evans 
91008278a5eSRod Evans 			if (argstate.optmask & CAP_OPT_F_STRVAL) {
91108278a5eSRod Evans 				argstate_add_str(&argstate, TRUE);
91208278a5eSRod Evans 				c_val = elfedit_strtab_insert(obj_state,
91308278a5eSRod Evans 				    argstate.str.sec, NULL, argstate.argv[1]);
91408278a5eSRod Evans 			} else {
91508278a5eSRod Evans 				c_val = (Xword)
91608278a5eSRod Evans 				    elfedit_atoui(argstate.argv[1], NULL);
91708278a5eSRod Evans 			}
918d29b2c44Sab 
919d29b2c44Sab 			if (cap[ndx].c_un.c_val == c_val) {
920d29b2c44Sab 				elfedit_msg(ELFEDIT_MSG_DEBUG,
921d29b2c44Sab 				    MSG_INTL(MSG_DEBUG_X_OK),
922d29b2c44Sab 				    argstate.cap.sec->sec_shndx,
923d29b2c44Sab 				    argstate.cap.sec->sec_name,
924d29b2c44Sab 				    EC_WORD(ndx), EC_XWORD(c_val));
925d29b2c44Sab 			} else {
926d29b2c44Sab 				elfedit_msg(ELFEDIT_MSG_DEBUG,
927d29b2c44Sab 				    MSG_INTL(MSG_DEBUG_X_CHG),
928d29b2c44Sab 				    argstate.cap.sec->sec_shndx,
929d29b2c44Sab 				    argstate.cap.sec->sec_name,
930d29b2c44Sab 				    EC_WORD(ndx), EC_XWORD(cap[ndx].c_un.c_val),
931d29b2c44Sab 				    EC_XWORD(c_val));
932d29b2c44Sab 				cap[ndx].c_un.c_val = c_val;
933d29b2c44Sab 				ret = ELFEDIT_CMDRET_MOD;
934d29b2c44Sab 			}
935d29b2c44Sab 		}
936d29b2c44Sab 		break;
937d29b2c44Sab 
938d29b2c44Sab 	case CAP_CMD_T_DELETE:
939d29b2c44Sab 		{
940d29b2c44Sab 			Word cnt = (argstate.argc == 1) ? 1 :
941d29b2c44Sab 			    (Word) elfedit_atoui_range(argstate.argv[1],
94208278a5eSRod Evans 			    MSG_ORIG(MSG_STR_COUNT), 1,
94308278a5eSRod Evans 			    argstate.cap.grp_end_ndx - ndx + 1, NULL);
944d29b2c44Sab 			const char *msg_prefix =
945d29b2c44Sab 			    elfedit_sec_msgprefix(argstate.cap.sec);
946d29b2c44Sab 
94708278a5eSRod Evans 			/*
94808278a5eSRod Evans 			 * We want to limit the deleted elements to be
94908278a5eSRod Evans 			 * in the range of the current capabilities group,
95008278a5eSRod Evans 			 * and for the resulting NULL elements to be inserted
95108278a5eSRod Evans 			 * at the end of the group, rather than at the end
95208278a5eSRod Evans 			 * of the section. To do this, we set the array length
95308278a5eSRod Evans 			 * in the call to the delete function so that it thinks
95408278a5eSRod Evans 			 * the array ends with the current group.
95508278a5eSRod Evans 			 *
95608278a5eSRod Evans 			 * The delete function will catch attempts to delete
95708278a5eSRod Evans 			 * past this virtual end, but the error message will
95808278a5eSRod Evans 			 * not make sense to the user. In order to prevent that,
95908278a5eSRod Evans 			 * we check for the condition here and provide a more
96008278a5eSRod Evans 			 * useful error.
96108278a5eSRod Evans 			 */
96208278a5eSRod Evans 			if ((ndx + cnt - 1) > argstate.cap.grp_end_ndx)
96308278a5eSRod Evans 				elfedit_msg(ELFEDIT_MSG_ERR,
96408278a5eSRod Evans 				    MSG_INTL(MSG_ERR_GRPARRBNDS), msg_prefix,
96508278a5eSRod Evans 				    argstate.cap.grp_start_ndx,
96608278a5eSRod Evans 				    argstate.cap.grp_end_ndx,
96708278a5eSRod Evans 				    cap_group_id(&argstate));
96808278a5eSRod Evans 			elfedit_array_elts_delete(msg_prefix, cap, sizeof (Cap),
96908278a5eSRod Evans 			    argstate.cap.grp_end_ndx + 1, ndx, cnt);
970d29b2c44Sab 			ret = ELFEDIT_CMDRET_MOD;
971d29b2c44Sab 		}
972d29b2c44Sab 		break;
973d29b2c44Sab 
974d29b2c44Sab 	case CAP_CMD_T_MOVE:
975d29b2c44Sab 		{
976d29b2c44Sab 			Cap	save;
977d29b2c44Sab 			Word	cnt;
978d29b2c44Sab 			Word	dstndx;
979d29b2c44Sab 			const char *msg_prefix =
980d29b2c44Sab 			    elfedit_sec_msgprefix(argstate.cap.sec);
981d29b2c44Sab 
982d29b2c44Sab 			dstndx = (Word)
983d29b2c44Sab 			    elfedit_atoui_range(argstate.argv[1],
98408278a5eSRod Evans 			    MSG_ORIG(MSG_STR_DST_INDEX),
98508278a5eSRod Evans 			    argstate.cap.grp_start_ndx,
98608278a5eSRod Evans 			    argstate.cap.grp_end_ndx, NULL);
987d29b2c44Sab 			if (argstate.argc == 2) {
988d29b2c44Sab 				cnt = 1;
989d29b2c44Sab 			} else {
99008278a5eSRod Evans 				Word max;
99108278a5eSRod Evans 
99208278a5eSRod Evans 				max = argstate.cap.grp_end_ndx -
99308278a5eSRod Evans 				    ((ndx > dstndx) ? ndx : dstndx) + 1;
994d29b2c44Sab 				cnt = (Word) elfedit_atoui_range(
995d29b2c44Sab 				    argstate.argv[2], MSG_ORIG(MSG_STR_COUNT),
99608278a5eSRod Evans 				    1, max, NULL);
997d29b2c44Sab 			}
99808278a5eSRod Evans 
99908278a5eSRod Evans 			/*
100008278a5eSRod Evans 			 * Moves are required to be self contained within
100108278a5eSRod Evans 			 * the bounds of the selected capability group.
100208278a5eSRod Evans 			 * The move utility function contains bounds checking,
100308278a5eSRod Evans 			 * but is not sub-array aware. Hence, we bounds check
100408278a5eSRod Evans 			 * check it here, and then hand of the validated
100508278a5eSRod Evans 			 * operation to the move utility function to execute.
100608278a5eSRod Evans 			 */
100708278a5eSRod Evans 			if ((ndx < argstate.cap.grp_start_ndx) ||
100808278a5eSRod Evans 			    ((ndx + cnt) > argstate.cap.grp_end_ndx) ||
100908278a5eSRod Evans 			    (dstndx < argstate.cap.grp_start_ndx) ||
101008278a5eSRod Evans 			    ((dstndx + cnt) > argstate.cap.grp_end_ndx))
101108278a5eSRod Evans 				elfedit_msg(ELFEDIT_MSG_ERR,
101208278a5eSRod Evans 				    MSG_INTL(MSG_ERR_GRPARRBNDS), msg_prefix,
101308278a5eSRod Evans 				    argstate.cap.grp_start_ndx,
101408278a5eSRod Evans 				    argstate.cap.grp_end_ndx,
101508278a5eSRod Evans 				    cap_group_id(&argstate));
101608278a5eSRod Evans 			elfedit_array_elts_move(msg_prefix, cap, sizeof (save),
101708278a5eSRod Evans 			    argstate.cap.grp_end_ndx + 1, ndx, dstndx,
101808278a5eSRod Evans 			    cnt, &save);
1019d29b2c44Sab 			ret = ELFEDIT_CMDRET_MOD;
1020d29b2c44Sab 		}
1021d29b2c44Sab 		break;
1022d29b2c44Sab 
1023d29b2c44Sab 
1024d29b2c44Sab 	case CAP_CMD_T_HW1:
1025d29b2c44Sab 		{
102608278a5eSRod Evans 			ret = cap_set(&argstate, cap, ndx, cap_ndx, cap_name,
102708278a5eSRod Evans 			    CA_SUNW_HW_1, ELFEDIT_CONST_HW1_SUNW);
1028d29b2c44Sab 		}
1029d29b2c44Sab 		break;
1030d29b2c44Sab 
1031d29b2c44Sab 	case CAP_CMD_T_SF1:
1032d29b2c44Sab 		{
103308278a5eSRod Evans 			ret = cap_set(&argstate, cap, ndx, cap_ndx, cap_name,
103408278a5eSRod Evans 			    CA_SUNW_SF_1, ELFEDIT_CONST_SF1_SUNW);
103508278a5eSRod Evans 		}
103608278a5eSRod Evans 		break;
1037d29b2c44Sab 
103808278a5eSRod Evans 	case CAP_CMD_T_HW2:
103908278a5eSRod Evans 		{
104008278a5eSRod Evans 			ret = cap_set(&argstate, cap, ndx, cap_ndx, cap_name,
104108278a5eSRod Evans 			    CA_SUNW_HW_2, ELFEDIT_CONST_HW2_SUNW);
1042d29b2c44Sab 		}
1043d29b2c44Sab 		break;
1044*56726c7eSRobert Mustacchi 
1045*56726c7eSRobert Mustacchi 	case CAP_CMD_T_HW3:
1046*56726c7eSRobert Mustacchi 		{
1047*56726c7eSRobert Mustacchi 			ret = cap_set(&argstate, cap, ndx, cap_ndx, cap_name,
1048*56726c7eSRobert Mustacchi 			    CA_SUNW_HW_3, ELFEDIT_CONST_HW3_SUNW);
1049*56726c7eSRobert Mustacchi 		}
1050*56726c7eSRobert Mustacchi 		break;
1051*56726c7eSRobert Mustacchi 
1052d29b2c44Sab 	}
1053d29b2c44Sab 
1054d29b2c44Sab 	/*
1055d29b2c44Sab 	 * If we modified the capabilities section header, tell libelf.
1056d29b2c44Sab 	 */
1057d29b2c44Sab 	if (ret == ELFEDIT_CMDRET_MOD)
1058d29b2c44Sab 		elfedit_modified_data(argstate.cap.sec);
1059d29b2c44Sab 
1060d29b2c44Sab 	/* Do autoprint */
1061d29b2c44Sab 	if (do_autoprint)
1062d29b2c44Sab 		print_cap(cmd, 1, &argstate, print_type, ndx);
1063d29b2c44Sab 
1064d29b2c44Sab 	return (ret);
1065d29b2c44Sab }
1066d29b2c44Sab 
1067d29b2c44Sab 
1068d29b2c44Sab 
1069d29b2c44Sab /*
1070d29b2c44Sab  * Command completion functions for the commands
1071d29b2c44Sab  */
1072d29b2c44Sab 
107308278a5eSRod Evans /*
107408278a5eSRod Evans  * -capid command completion: Supply all CA_SUNW_ID names found in the object.
107508278a5eSRod Evans  */
107608278a5eSRod Evans static void
cpl_capid_opt(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)107708278a5eSRod Evans cpl_capid_opt(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
107808278a5eSRod Evans     const char *argv[], int num_opt)
107908278a5eSRod Evans {
108008278a5eSRod Evans 	elfedit_section_t	*cap_sec, *str_sec;
108108278a5eSRod Evans 	Cap			*cap;
108208278a5eSRod Evans 	Word			num;
108308278a5eSRod Evans 
108408278a5eSRod Evans 	if (obj_state == NULL)	 /* No object available */
108508278a5eSRod Evans 		return;
108608278a5eSRod Evans 
108708278a5eSRod Evans 	if ((argc > num_opt) || (argc < 2) ||
108808278a5eSRod Evans 	    (strcmp(argv[argc - 2], MSG_ORIG(MSG_STR_MINUS_CAPID)) != 0))
108908278a5eSRod Evans 		return;
109008278a5eSRod Evans 
109108278a5eSRod Evans 	cap_sec = elfedit_sec_getcap(obj_state, &cap, &num);
109208278a5eSRod Evans 
109308278a5eSRod Evans 	/* If no associated string table, we have no strings to complete */
109408278a5eSRod Evans 	if (cap_sec->sec_shdr->sh_info == 0)
109508278a5eSRod Evans 		return;
109608278a5eSRod Evans 
109708278a5eSRod Evans 	str_sec = elfedit_sec_getstr(obj_state, cap_sec->sec_shdr->sh_info, 0);
109808278a5eSRod Evans 
109908278a5eSRod Evans 	for (; num--; cap++)
110008278a5eSRod Evans 		if (cap->c_tag == CA_SUNW_ID)
110108278a5eSRod Evans 			elfedit_cpl_match(cpldata, elfedit_offset_to_str(
110208278a5eSRod Evans 			    str_sec, cap->c_un.c_val, ELFEDIT_MSG_ERR, 0), 0);
110308278a5eSRod Evans }
110408278a5eSRod Evans 
1105d29b2c44Sab /*
1106d29b2c44Sab  * Command completion for the first argument, which specifies
1107d29b2c44Sab  * the capabilities element to use. Examines the options to see if
1108d29b2c44Sab  * -capndx is present, and if not, supplies the completion
1109d29b2c44Sab  * strings for argument 1.
1110d29b2c44Sab  */
1111d29b2c44Sab /*ARGSUSED*/
1112d29b2c44Sab static void
cpl_eltarg(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)1113d29b2c44Sab cpl_eltarg(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
1114d29b2c44Sab     const char *argv[], int num_opt)
1115d29b2c44Sab {
111608278a5eSRod Evans 	Word	i;
111708278a5eSRod Evans 
111808278a5eSRod Evans 	/* -capid id_name */
111908278a5eSRod Evans 	if (argc <= num_opt) {
112008278a5eSRod Evans 		cpl_capid_opt(obj_state, cpldata, argc, argv, num_opt);
112108278a5eSRod Evans 		return;
112208278a5eSRod Evans 	}
1123d29b2c44Sab 
1124d29b2c44Sab 	/* Make sure it's the first argument */
1125d29b2c44Sab 	if ((argc - num_opt) != 1)
1126d29b2c44Sab 		return;
1127d29b2c44Sab 
1128d29b2c44Sab 	/* Is -capndx present? If so, we don't complete tag types */
1129d29b2c44Sab 	for (i = 0; i < num_opt; i++)
1130d29b2c44Sab 		if (strcmp(argv[i], MSG_ORIG(MSG_STR_MINUS_CAPNDX)) == 0)
1131d29b2c44Sab 			return;
1132d29b2c44Sab 
1133d29b2c44Sab 	/*
1134d29b2c44Sab 	 * Supply capability tag names. There are very few of these, so
1135d29b2c44Sab 	 * rather than worry about whether a given tag exists in the
1136d29b2c44Sab 	 * file or not, we simply serve up all the possibilities.
1137d29b2c44Sab 	 */
1138d29b2c44Sab 	elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_CA);
1139d29b2c44Sab }
1140d29b2c44Sab 
1141d29b2c44Sab /*ARGSUSED*/
1142d29b2c44Sab static void
cpl_tag(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)1143d29b2c44Sab cpl_tag(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
1144d29b2c44Sab     const char *argv[], int num_opt)
1145d29b2c44Sab {
114608278a5eSRod Evans 	/* -capid id_name */
114708278a5eSRod Evans 	if (argc <= num_opt) {
114808278a5eSRod Evans 		cpl_capid_opt(obj_state, cpldata, argc, argv, num_opt);
114908278a5eSRod Evans 		return;
115008278a5eSRod Evans 	}
115108278a5eSRod Evans 
115208278a5eSRod Evans 	/* First plain argument */
1153d29b2c44Sab 	if ((argc - num_opt) == 1) {
1154d29b2c44Sab 		cpl_eltarg(obj_state, cpldata, argc, argv, num_opt);
1155d29b2c44Sab 		return;
1156d29b2c44Sab 	}
1157d29b2c44Sab 
1158d29b2c44Sab 	/* The second argument is always a tag value */
1159d29b2c44Sab 	if ((argc - num_opt) == 2)
1160d29b2c44Sab 		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_CA);
1161d29b2c44Sab }
1162d29b2c44Sab 
1163d29b2c44Sab /*ARGSUSED*/
1164d29b2c44Sab static void
cpl_hw1(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)1165d29b2c44Sab cpl_hw1(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
1166d29b2c44Sab     const char *argv[], int num_opt)
1167d29b2c44Sab {
116808278a5eSRod Evans 	/* -capid id_name */
116908278a5eSRod Evans 	if (argc <= num_opt) {
117008278a5eSRod Evans 		cpl_capid_opt(obj_state, cpldata, argc, argv, num_opt);
117108278a5eSRod Evans 		return;
117208278a5eSRod Evans 	}
1173d29b2c44Sab 
117408278a5eSRod Evans 	/* This routine allows multiple flags to be specified */
117508278a5eSRod Evans 	elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_HW1_SUNW);
1176d29b2c44Sab }
1177d29b2c44Sab 
1178d29b2c44Sab /*ARGSUSED*/
1179d29b2c44Sab static void
cpl_sf1(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)1180d29b2c44Sab cpl_sf1(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
1181d29b2c44Sab     const char *argv[], int num_opt)
1182d29b2c44Sab {
118308278a5eSRod Evans 	/* -capid id_name */
118408278a5eSRod Evans 	if (argc <= num_opt) {
118508278a5eSRod Evans 		cpl_capid_opt(obj_state, cpldata, argc, argv, num_opt);
118608278a5eSRod Evans 		return;
118708278a5eSRod Evans 	}
118808278a5eSRod Evans 
1189d29b2c44Sab 	/* This routine allows multiple flags to be specified */
1190d29b2c44Sab 	elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_SF1_SUNW);
1191d29b2c44Sab }
1192d29b2c44Sab 
119308278a5eSRod Evans /*ARGSUSED*/
119408278a5eSRod Evans static void
cpl_hw2(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)119508278a5eSRod Evans cpl_hw2(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
119608278a5eSRod Evans     const char *argv[], int num_opt)
119708278a5eSRod Evans {
119808278a5eSRod Evans 	/* -capid id_name */
119908278a5eSRod Evans 	if (argc <= num_opt) {
120008278a5eSRod Evans 		cpl_capid_opt(obj_state, cpldata, argc, argv, num_opt);
120108278a5eSRod Evans 		return;
120208278a5eSRod Evans 	}
120308278a5eSRod Evans 
120408278a5eSRod Evans 	/* This routine allows multiple flags to be specified */
120508278a5eSRod Evans 	elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_HW2_SUNW);
120608278a5eSRod Evans }
1207d29b2c44Sab 
1208*56726c7eSRobert Mustacchi static void
cpl_hw3(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)1209*56726c7eSRobert Mustacchi cpl_hw3(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
1210*56726c7eSRobert Mustacchi     const char *argv[], int num_opt)
1211*56726c7eSRobert Mustacchi {
1212*56726c7eSRobert Mustacchi 	/* -capid id_name */
1213*56726c7eSRobert Mustacchi 	if (argc <= num_opt) {
1214*56726c7eSRobert Mustacchi 		cpl_capid_opt(obj_state, cpldata, argc, argv, num_opt);
1215*56726c7eSRobert Mustacchi 		return;
1216*56726c7eSRobert Mustacchi 	}
1217*56726c7eSRobert Mustacchi 
1218*56726c7eSRobert Mustacchi 	/* This routine allows multiple flags to be specified */
1219*56726c7eSRobert Mustacchi 	elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_HW3_SUNW);
1220*56726c7eSRobert Mustacchi }
1221d29b2c44Sab /*
1222d29b2c44Sab  * Implementation functions for the commands
1223d29b2c44Sab  */
1224d29b2c44Sab static elfedit_cmdret_t
cmd_dump(elfedit_obj_state_t * obj_state,int argc,const char * argv[])1225d29b2c44Sab cmd_dump(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1226d29b2c44Sab {
1227d29b2c44Sab 	return (cmd_body(CAP_CMD_T_DUMP, obj_state, argc, argv));
1228d29b2c44Sab }
1229d29b2c44Sab 
1230d29b2c44Sab static elfedit_cmdret_t
cmd_tag(elfedit_obj_state_t * obj_state,int argc,const char * argv[])1231d29b2c44Sab cmd_tag(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1232d29b2c44Sab {
1233d29b2c44Sab 	return (cmd_body(CAP_CMD_T_TAG, obj_state, argc, argv));
1234d29b2c44Sab }
1235d29b2c44Sab 
1236d29b2c44Sab static elfedit_cmdret_t
cmd_value(elfedit_obj_state_t * obj_state,int argc,const char * argv[])1237d29b2c44Sab cmd_value(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1238d29b2c44Sab {
1239d29b2c44Sab 	return (cmd_body(CAP_CMD_T_VALUE, obj_state, argc, argv));
1240d29b2c44Sab }
1241d29b2c44Sab 
1242d29b2c44Sab static elfedit_cmdret_t
cmd_delete(elfedit_obj_state_t * obj_state,int argc,const char * argv[])1243d29b2c44Sab cmd_delete(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1244d29b2c44Sab {
1245d29b2c44Sab 	return (cmd_body(CAP_CMD_T_DELETE, obj_state, argc, argv));
1246d29b2c44Sab }
1247d29b2c44Sab 
1248d29b2c44Sab static elfedit_cmdret_t
cmd_move(elfedit_obj_state_t * obj_state,int argc,const char * argv[])1249d29b2c44Sab cmd_move(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1250d29b2c44Sab {
1251d29b2c44Sab 	return (cmd_body(CAP_CMD_T_MOVE, obj_state, argc, argv));
1252d29b2c44Sab }
1253d29b2c44Sab 
1254d29b2c44Sab static elfedit_cmdret_t
cmd_hw1(elfedit_obj_state_t * obj_state,int argc,const char * argv[])1255d29b2c44Sab cmd_hw1(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1256d29b2c44Sab {
1257d29b2c44Sab 	return (cmd_body(CAP_CMD_T_HW1, obj_state, argc, argv));
1258d29b2c44Sab }
1259d29b2c44Sab 
1260d29b2c44Sab static elfedit_cmdret_t
cmd_sf1(elfedit_obj_state_t * obj_state,int argc,const char * argv[])1261d29b2c44Sab cmd_sf1(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1262d29b2c44Sab {
1263d29b2c44Sab 	return (cmd_body(CAP_CMD_T_SF1, obj_state, argc, argv));
1264d29b2c44Sab }
1265d29b2c44Sab 
126608278a5eSRod Evans static elfedit_cmdret_t
cmd_hw2(elfedit_obj_state_t * obj_state,int argc,const char * argv[])126708278a5eSRod Evans cmd_hw2(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
126808278a5eSRod Evans {
126908278a5eSRod Evans 	return (cmd_body(CAP_CMD_T_HW2, obj_state, argc, argv));
127008278a5eSRod Evans }
1271d29b2c44Sab 
1272*56726c7eSRobert Mustacchi static elfedit_cmdret_t
cmd_hw3(elfedit_obj_state_t * obj_state,int argc,const char * argv[])1273*56726c7eSRobert Mustacchi cmd_hw3(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
1274*56726c7eSRobert Mustacchi {
1275*56726c7eSRobert Mustacchi 	return (cmd_body(CAP_CMD_T_HW3, obj_state, argc, argv));
1276*56726c7eSRobert Mustacchi }
1277*56726c7eSRobert Mustacchi 
1278d29b2c44Sab /*ARGSUSED*/
1279d29b2c44Sab elfedit_module_t *
elfedit_init(elfedit_module_version_t version)1280d29b2c44Sab elfedit_init(elfedit_module_version_t version)
1281d29b2c44Sab {
128208278a5eSRod Evans 	/* For commands that only accept -capid, -and, -cmp, -o, and -or */
128308278a5eSRod Evans 	static elfedit_cmd_optarg_t opt_ostyle_capid_bitop[] = {
12849320f495SToomas Soome 		{ ELFEDIT_STDOA_OPT_AND, 0,
1285d29b2c44Sab 		    ELFEDIT_CMDOA_F_INHERIT, CAP_OPT_F_AND, CAP_OPT_F_OR },
128608278a5eSRod Evans 		{ MSG_ORIG(MSG_STR_MINUS_CAPID),
128708278a5eSRod Evans 		    /* MSG_INTL(MSG_OPTDESC_CAPID) */
128808278a5eSRod Evans 		    ELFEDIT_I18NHDL(MSG_OPTDESC_CAPID), ELFEDIT_CMDOA_F_VALUE,
128908278a5eSRod Evans 		    CAP_OPT_F_CAPID, CAP_OPT_F_CAPNDX },
12909320f495SToomas Soome 		{ MSG_ORIG(MSG_STR_IDNAME), 0, 0 },
12919320f495SToomas Soome 		{ ELFEDIT_STDOA_OPT_CMP, 0,
1292d29b2c44Sab 		    ELFEDIT_CMDOA_F_INHERIT, CAP_OPT_F_CMP, 0 },
12939320f495SToomas Soome 		{ ELFEDIT_STDOA_OPT_O, 0,
1294d29b2c44Sab 		    ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
12959320f495SToomas Soome 		{ ELFEDIT_STDOA_OPT_OR, 0,
1296d29b2c44Sab 		    ELFEDIT_CMDOA_F_INHERIT, CAP_OPT_F_OR, CAP_OPT_F_AND },
1297d29b2c44Sab 		{ NULL }
1298d29b2c44Sab 	};
1299d29b2c44Sab 
130008278a5eSRod Evans 	/* For commands that only accept -capid and -capndx */
130108278a5eSRod Evans 	static elfedit_cmd_optarg_t opt_capid_capndx[] = {
130208278a5eSRod Evans 		{ MSG_ORIG(MSG_STR_MINUS_CAPID),
130308278a5eSRod Evans 		    /* MSG_INTL(MSG_OPTDESC_CAPID) */
130408278a5eSRod Evans 		    ELFEDIT_I18NHDL(MSG_OPTDESC_CAPID), ELFEDIT_CMDOA_F_VALUE,
130508278a5eSRod Evans 		    CAP_OPT_F_CAPID, CAP_OPT_F_CAPNDX },
13069320f495SToomas Soome 		{ MSG_ORIG(MSG_STR_IDNAME), 0, 0 },
1307d29b2c44Sab 		{ MSG_ORIG(MSG_STR_MINUS_CAPNDX),
1308d29b2c44Sab 		    /* MSG_INTL(MSG_OPTDESC_CAPNDX) */
1309d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_OPTDESC_CAPNDX), 0,
131008278a5eSRod Evans 		    CAP_OPT_F_CAPNDX, CAP_OPT_F_CAPID },
1311d29b2c44Sab 		{ NULL }
1312d29b2c44Sab 	};
1313d29b2c44Sab 
1314d29b2c44Sab 
1315d29b2c44Sab 	/* cap:dump */
1316d29b2c44Sab 	static const char *name_dump[] = {
1317d29b2c44Sab 	    MSG_ORIG(MSG_CMD_DUMP),
1318d29b2c44Sab 	    MSG_ORIG(MSG_STR_EMPTY),	/* "" makes this the default command */
1319d29b2c44Sab 	    NULL
1320d29b2c44Sab 	};
1321d29b2c44Sab 	static elfedit_cmd_optarg_t arg_dump[] = {
1322d29b2c44Sab 		{ MSG_ORIG(MSG_STR_ELT),
1323d29b2c44Sab 		    /* MSG_INTL(MSG_ARGDESC_ELT) */
1324d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_ARGDESC_ELT),
1325d29b2c44Sab 		    ELFEDIT_CMDOA_F_OPT },
1326d29b2c44Sab 		{ NULL }
1327d29b2c44Sab 	};
1328d29b2c44Sab 
1329d29b2c44Sab 
1330d29b2c44Sab 	/* cap:tag */
1331d29b2c44Sab 	static const char *name_tag[] = { MSG_ORIG(MSG_CMD_TAG), NULL };
133208278a5eSRod Evans 	static elfedit_cmd_optarg_t opt_tag[] = {
133308278a5eSRod Evans 		{ MSG_ORIG(MSG_STR_MINUS_CAPID),
133408278a5eSRod Evans 		    /* MSG_INTL(MSG_OPTDESC_CAPID) */
133508278a5eSRod Evans 		    ELFEDIT_I18NHDL(MSG_OPTDESC_CAPID), ELFEDIT_CMDOA_F_VALUE,
133608278a5eSRod Evans 		    CAP_OPT_F_CAPID, CAP_OPT_F_CAPNDX },
13379320f495SToomas Soome 		{ MSG_ORIG(MSG_STR_IDNAME), 0, 0 },
133808278a5eSRod Evans 		{ MSG_ORIG(MSG_STR_MINUS_CAPNDX),
133908278a5eSRod Evans 		    /* MSG_INTL(MSG_OPTDESC_CAPNDX) */
134008278a5eSRod Evans 		    ELFEDIT_I18NHDL(MSG_OPTDESC_CAPNDX), 0,
134108278a5eSRod Evans 		    CAP_OPT_F_CAPNDX, 0 },
13429320f495SToomas Soome 		{ ELFEDIT_STDOA_OPT_O, 0,
134308278a5eSRod Evans 		    ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
134408278a5eSRod Evans 		{ NULL }
134508278a5eSRod Evans 	};
1346d29b2c44Sab 	static elfedit_cmd_optarg_t arg_tag[] = {
1347d29b2c44Sab 		{ MSG_ORIG(MSG_STR_ELT),
1348d29b2c44Sab 		    /* MSG_INTL(MSG_A1_TAG_ELT) */
1349d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_A1_TAG_ELT),
1350d29b2c44Sab 		    ELFEDIT_CMDOA_F_OPT },
1351d29b2c44Sab 		{ MSG_ORIG(MSG_STR_VALUE),
1352d29b2c44Sab 		    /* MSG_INTL(MSG_A2_TAG_VALUE) */
1353d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_A2_TAG_VALUE),
1354d29b2c44Sab 		    ELFEDIT_CMDOA_F_OPT },
1355d29b2c44Sab 		{ NULL }
1356d29b2c44Sab 	};
1357d29b2c44Sab 
1358d29b2c44Sab 
1359d29b2c44Sab 	/* cap:value */
1360d29b2c44Sab 	static const char *name_value[] = { MSG_ORIG(MSG_CMD_VALUE), NULL };
136108278a5eSRod Evans 	static elfedit_cmd_optarg_t opt_value[] = {
136208278a5eSRod Evans 		{ MSG_ORIG(MSG_STR_MINUS_CAPID),
136308278a5eSRod Evans 		    /* MSG_INTL(MSG_OPTDESC_CAPID) */
136408278a5eSRod Evans 		    ELFEDIT_I18NHDL(MSG_OPTDESC_CAPID), ELFEDIT_CMDOA_F_VALUE,
136508278a5eSRod Evans 		    CAP_OPT_F_CAPID, CAP_OPT_F_CAPNDX },
13669320f495SToomas Soome 		{ MSG_ORIG(MSG_STR_IDNAME), 0, 0 },
136708278a5eSRod Evans 		{ MSG_ORIG(MSG_STR_MINUS_CAPNDX),
136808278a5eSRod Evans 		    /* MSG_INTL(MSG_OPTDESC_CAPNDX) */
136908278a5eSRod Evans 		    ELFEDIT_I18NHDL(MSG_OPTDESC_CAPNDX), 0,
137008278a5eSRod Evans 		    CAP_OPT_F_CAPNDX, 0 },
13719320f495SToomas Soome 		{ ELFEDIT_STDOA_OPT_O, 0,
137208278a5eSRod Evans 		    ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
137308278a5eSRod Evans 		{ MSG_ORIG(MSG_STR_MINUS_S),
137408278a5eSRod Evans 		    /* MSG_INTL(MSG_OPTDESC_S) */
137508278a5eSRod Evans 		    ELFEDIT_I18NHDL(MSG_OPTDESC_S), 0,
137608278a5eSRod Evans 		    CAP_OPT_F_STRVAL, 0 },
137708278a5eSRod Evans 		{ NULL }
137808278a5eSRod Evans 	};
1379d29b2c44Sab 	static elfedit_cmd_optarg_t arg_value[] = {
1380d29b2c44Sab 		{ MSG_ORIG(MSG_STR_ELT),
1381d29b2c44Sab 		    /* MSG_INTL(MSG_ARGDESC_ELT) */
1382d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_ARGDESC_ELT),
1383d29b2c44Sab 		    ELFEDIT_CMDOA_F_OPT },
1384d29b2c44Sab 		{ MSG_ORIG(MSG_STR_VALUE),
1385d29b2c44Sab 		    /* MSG_INTL(MSG_A2_VALUE_VALUE) */
1386d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_A2_VALUE_VALUE),
1387d29b2c44Sab 		    ELFEDIT_CMDOA_F_OPT },
1388d29b2c44Sab 		{ NULL }
1389d29b2c44Sab 	};
1390d29b2c44Sab 
1391d29b2c44Sab 	/* cap:delete */
1392d29b2c44Sab 	static const char *name_delete[] = { MSG_ORIG(MSG_CMD_DELETE), NULL };
1393d29b2c44Sab 	static elfedit_cmd_optarg_t arg_delete[] = {
1394d29b2c44Sab 		{ MSG_ORIG(MSG_STR_ELT),
1395d29b2c44Sab 		    /* MSG_INTL(MSG_ARGDESC_ELT) */
1396d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_ARGDESC_ELT),
1397d29b2c44Sab 		    0 },
1398d29b2c44Sab 		{ MSG_ORIG(MSG_STR_COUNT),
1399d29b2c44Sab 		    /* MSG_INTL(MSG_A2_DELETE_COUNT) */
1400d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_A2_DELETE_COUNT),
1401d29b2c44Sab 		    ELFEDIT_CMDOA_F_OPT },
1402d29b2c44Sab 		{ NULL }
1403d29b2c44Sab 	};
1404d29b2c44Sab 
1405d29b2c44Sab 	/* cap:move */
1406d29b2c44Sab 	static const char *name_move[] = { MSG_ORIG(MSG_CMD_MOVE), NULL };
1407d29b2c44Sab 	static elfedit_cmd_optarg_t arg_move[] = {
1408d29b2c44Sab 		{ MSG_ORIG(MSG_STR_ELT),
1409d29b2c44Sab 		    /* MSG_INTL(MSG_ARGDESC_ELT) */
1410d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_ARGDESC_ELT),
1411d29b2c44Sab 		    0 },
1412d29b2c44Sab 		{ MSG_ORIG(MSG_STR_DST_INDEX),
1413d29b2c44Sab 		    /* MSG_INTL(MSG_A2_MOVE_DST_INDEX) */
1414d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_A2_MOVE_DST_INDEX),
1415d29b2c44Sab 		    0 },
1416d29b2c44Sab 		{ MSG_ORIG(MSG_STR_COUNT),
1417d29b2c44Sab 		    /* MSG_INTL(MSG_A3_MOVE_COUNT) */
1418d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_A3_MOVE_COUNT),
1419d29b2c44Sab 		    ELFEDIT_CMDOA_F_OPT },
1420d29b2c44Sab 		{ NULL }
1421d29b2c44Sab 	};
1422d29b2c44Sab 
1423d29b2c44Sab 	/* cap:hw1 */
1424d29b2c44Sab 	static const char *name_hw1[] = { MSG_ORIG(MSG_CMD_HW1), NULL };
1425d29b2c44Sab 	static elfedit_cmd_optarg_t arg_hw1[] = {
1426d29b2c44Sab 		{ MSG_ORIG(MSG_STR_VALUE),
1427d29b2c44Sab 		    /* MSG_INTL(MSG_A1_HW1_VALUE) */
1428d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_A1_HW1_VALUE),
1429d29b2c44Sab 		    ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT },
1430d29b2c44Sab 		{ NULL }
1431d29b2c44Sab 	};
1432d29b2c44Sab 
1433d29b2c44Sab 	/* cap:sf1 */
1434d29b2c44Sab 	static const char *name_sf1[] = { MSG_ORIG(MSG_CMD_SF1), NULL };
1435d29b2c44Sab 	static elfedit_cmd_optarg_t arg_sf1[] = {
1436d29b2c44Sab 		{ MSG_ORIG(MSG_STR_VALUE),
1437d29b2c44Sab 		    /* MSG_INTL(MSG_A1_SF1_VALUE) */
1438d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_A1_SF1_VALUE),
1439d29b2c44Sab 		    ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT },
1440d29b2c44Sab 		{ NULL }
1441d29b2c44Sab 	};
1442d29b2c44Sab 
144308278a5eSRod Evans 	/* cap:hw2 */
144408278a5eSRod Evans 	static const char *name_hw2[] = { MSG_ORIG(MSG_CMD_HW2), NULL };
144508278a5eSRod Evans 	static elfedit_cmd_optarg_t arg_hw2[] = {
144608278a5eSRod Evans 		{ MSG_ORIG(MSG_STR_VALUE),
144708278a5eSRod Evans 		    /* MSG_INTL(MSG_A1_HW2_VALUE) */
144808278a5eSRod Evans 		    ELFEDIT_I18NHDL(MSG_A1_HW2_VALUE),
144908278a5eSRod Evans 		    ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT },
145008278a5eSRod Evans 		{ NULL }
145108278a5eSRod Evans 	};
1452d29b2c44Sab 
1453*56726c7eSRobert Mustacchi 	/* cap:hw3 */
1454*56726c7eSRobert Mustacchi 	static const char *name_hw3[] = { MSG_ORIG(MSG_CMD_HW3), NULL };
1455*56726c7eSRobert Mustacchi 	static elfedit_cmd_optarg_t arg_hw3[] = {
1456*56726c7eSRobert Mustacchi 		{ MSG_ORIG(MSG_STR_VALUE),
1457*56726c7eSRobert Mustacchi 		    /* MSG_INTL(MSG_A1_HW3_VALUE) */
1458*56726c7eSRobert Mustacchi 		    ELFEDIT_I18NHDL(MSG_A1_HW3_VALUE),
1459*56726c7eSRobert Mustacchi 		    ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT },
1460*56726c7eSRobert Mustacchi 		{ NULL }
1461*56726c7eSRobert Mustacchi 	};
1462d29b2c44Sab 
1463d29b2c44Sab 	static elfedit_cmd_t cmds[] = {
1464d29b2c44Sab 		/* cap:dump */
1465d29b2c44Sab 		{ cmd_dump, cpl_eltarg, name_dump,
1466d29b2c44Sab 		    /* MSG_INTL(MSG_DESC_DUMP) */
1467d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_DESC_DUMP),
1468d29b2c44Sab 		    /* MSG_INTL(MSG_HELP_DUMP) */
1469d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_HELP_DUMP),
147008278a5eSRod Evans 		    opt_capid_capndx, arg_dump },
1471d29b2c44Sab 
1472d29b2c44Sab 		/* cap:tag */
1473d29b2c44Sab 		{ cmd_tag, cpl_tag, name_tag,
1474d29b2c44Sab 		    /* MSG_INTL(MSG_DESC_TAG) */
1475d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_DESC_TAG),
1476d29b2c44Sab 		    /* MSG_INTL(MSG_HELP_TAG) */
1477d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_HELP_TAG),
147808278a5eSRod Evans 		    opt_tag, arg_tag },
1479d29b2c44Sab 
1480d29b2c44Sab 		/* cap:value */
1481d29b2c44Sab 		{ cmd_value, cpl_eltarg, name_value,
1482d29b2c44Sab 		    /* MSG_INTL(MSG_DESC_VALUE) */
1483d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_DESC_VALUE),
1484d29b2c44Sab 		    /* MSG_INTL(MSG_HELP_VALUE) */
1485d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_HELP_VALUE),
148608278a5eSRod Evans 		    opt_value, arg_value },
1487d29b2c44Sab 
1488d29b2c44Sab 		/* cap:delete */
1489d29b2c44Sab 		{ cmd_delete, cpl_eltarg, name_delete,
1490d29b2c44Sab 		    /* MSG_INTL(MSG_DESC_DELETE) */
1491d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_DESC_DELETE),
1492d29b2c44Sab 		    /* MSG_INTL(MSG_HELP_DELETE) */
1493d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_HELP_DELETE),
149408278a5eSRod Evans 		    opt_capid_capndx, arg_delete },
1495d29b2c44Sab 
1496d29b2c44Sab 		/* cap:move */
1497d29b2c44Sab 		{ cmd_move, cpl_eltarg, name_move,
1498d29b2c44Sab 		    /* MSG_INTL(MSG_DESC_MOVE) */
1499d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_DESC_MOVE),
1500d29b2c44Sab 		    /* MSG_INTL(MSG_HELP_MOVE) */
1501d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_HELP_MOVE),
150208278a5eSRod Evans 		    opt_capid_capndx, arg_move },
1503d29b2c44Sab 
1504d29b2c44Sab 		/* cap:hw1 */
1505d29b2c44Sab 		{ cmd_hw1, cpl_hw1, name_hw1,
1506d29b2c44Sab 		    /* MSG_INTL(MSG_DESC_HW1) */
1507d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_DESC_HW1),
1508d29b2c44Sab 		    /* MSG_INTL(MSG_HELP_HW1) */
1509d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_HELP_HW1),
151008278a5eSRod Evans 		    opt_ostyle_capid_bitop, arg_hw1 },
1511d29b2c44Sab 
1512d29b2c44Sab 		/* cap:sf1 */
1513d29b2c44Sab 		{ cmd_sf1, cpl_sf1, name_sf1,
1514d29b2c44Sab 		    /* MSG_INTL(MSG_DESC_SF1) */
1515d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_DESC_SF1),
1516d29b2c44Sab 		    /* MSG_INTL(MSG_HELP_SF1) */
1517d29b2c44Sab 		    ELFEDIT_I18NHDL(MSG_HELP_SF1),
151808278a5eSRod Evans 		    opt_ostyle_capid_bitop, arg_sf1 },
151908278a5eSRod Evans 
152008278a5eSRod Evans 		/* cap:hw2 */
152108278a5eSRod Evans 		{ cmd_hw2, cpl_hw2, name_hw2,
152208278a5eSRod Evans 		    /* MSG_INTL(MSG_DESC_HW2) */
152308278a5eSRod Evans 		    ELFEDIT_I18NHDL(MSG_DESC_HW2),
152408278a5eSRod Evans 		    /* MSG_INTL(MSG_HELP_HW2) */
152508278a5eSRod Evans 		    ELFEDIT_I18NHDL(MSG_HELP_HW2),
152608278a5eSRod Evans 		    opt_ostyle_capid_bitop, arg_hw2 },
1527d29b2c44Sab 
1528*56726c7eSRobert Mustacchi 		/* cap:hw3 */
1529*56726c7eSRobert Mustacchi 		{ cmd_hw3, cpl_hw3, name_hw3,
1530*56726c7eSRobert Mustacchi 		    /* MSG_INTL(MSG_DESC_HW3) */
1531*56726c7eSRobert Mustacchi 		    ELFEDIT_I18NHDL(MSG_DESC_HW3),
1532*56726c7eSRobert Mustacchi 		    /* MSG_INTL(MSG_HELP_HW3) */
1533*56726c7eSRobert Mustacchi 		    ELFEDIT_I18NHDL(MSG_HELP_HW3),
1534*56726c7eSRobert Mustacchi 		    opt_ostyle_capid_bitop, arg_hw3 },
1535*56726c7eSRobert Mustacchi 
1536d29b2c44Sab 		{ NULL }
1537d29b2c44Sab 	};
1538d29b2c44Sab 
1539d29b2c44Sab 	static elfedit_module_t module = {
1540d29b2c44Sab 	    ELFEDIT_VER_CURRENT, MSG_ORIG(MSG_MOD_NAME),
1541d29b2c44Sab 	    /* MSG_INTL(MSG_MOD_DESC) */
1542d29b2c44Sab 	    ELFEDIT_I18NHDL(MSG_MOD_DESC),
1543d29b2c44Sab 	    cmds, mod_i18nhdl_to_str };
1544d29b2c44Sab 
1545d29b2c44Sab 	return (&module);
1546d29b2c44Sab }
1547