xref: /onnv-gate/usr/src/cmd/sgs/elfedit/modules/common/cap.c (revision 12029:3202400f09a4)
15088Sab196087 /*
25088Sab196087  * CDDL HEADER START
35088Sab196087  *
45088Sab196087  * The contents of this file are subject to the terms of the
55088Sab196087  * Common Development and Distribution License (the "License").
65088Sab196087  * You may not use this file except in compliance with the License.
75088Sab196087  *
85088Sab196087  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95088Sab196087  * or http://www.opensolaris.org/os/licensing.
105088Sab196087  * See the License for the specific language governing permissions
115088Sab196087  * and limitations under the License.
125088Sab196087  *
135088Sab196087  * When distributing Covered Code, include this CDDL HEADER in each
145088Sab196087  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155088Sab196087  * If applicable, add the following below this CDDL HEADER, with the
165088Sab196087  * fields enclosed by brackets "[]" replaced with your own identifying
175088Sab196087  * information: Portions Copyright [yyyy] [name of copyright owner]
185088Sab196087  *
195088Sab196087  * CDDL HEADER END
205088Sab196087  */
215088Sab196087 
225088Sab196087 /*
2311827SRod.Evans@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
245088Sab196087  * Use is subject to license terms.
255088Sab196087  */
265088Sab196087 
275088Sab196087 #include	<ctype.h>
285088Sab196087 #include	<elfedit.h>
295088Sab196087 #include	<sys/elf_SPARC.h>
305088Sab196087 #include	<strings.h>
315088Sab196087 #include	<debug.h>
325088Sab196087 #include	<conv.h>
335088Sab196087 #include	<cap_msg.h>
345088Sab196087 
355088Sab196087 
365088Sab196087 /*
375088Sab196087  * Capabilities section
385088Sab196087  */
395088Sab196087 
405088Sab196087 
415088Sab196087 
425088Sab196087 
435088Sab196087 /*
445088Sab196087  * This module uses shared code for several of the commands.
455088Sab196087  * It is sometimes necessary to know which specific command
465088Sab196087  * is active.
475088Sab196087  */
485088Sab196087 typedef enum {
495088Sab196087 	/* Dump command, used as module default to display dynamic section */
505088Sab196087 	CAP_CMD_T_DUMP =	0,	/* cap:dump */
515088Sab196087 
525088Sab196087 	/* Commands that do not correspond directly to a specific DT tag */
535088Sab196087 	CAP_CMD_T_TAG =		1,	/* cap:tag */
545088Sab196087 	CAP_CMD_T_VALUE =	2,	/* cap:value */
555088Sab196087 	CAP_CMD_T_DELETE =	3,	/* cap:delete */
565088Sab196087 	CAP_CMD_T_MOVE =	4,	/* cap:shift */
575088Sab196087 
585088Sab196087 	/* Commands that embody tag specific knowledge */
595088Sab196087 	CAP_CMD_T_HW1 =		5,	/* cap:hw1 */
605088Sab196087 	CAP_CMD_T_SF1 =		6,	/* cap:sf1 */
6111827SRod.Evans@Sun.COM 	CAP_CMD_T_HW2 =		7,	/* cap:hw2 */
625088Sab196087 } CAP_CMD_T;
635088Sab196087 
645088Sab196087 
655088Sab196087 
665088Sab196087 #ifndef _ELF64
675088Sab196087 /*
685088Sab196087  * We supply this function for the msg module
695088Sab196087  */
705088Sab196087 const char *
_cap_msg(Msg mid)715088Sab196087 _cap_msg(Msg mid)
725088Sab196087 {
735088Sab196087 	return (gettext(MSG_ORIG(mid)));
745088Sab196087 }
755088Sab196087 #endif
765088Sab196087 
775088Sab196087 
785088Sab196087 /*
795088Sab196087  * This function is supplied to elfedit through our elfedit_module_t
805088Sab196087  * definition. It translates the opaque elfedit_i18nhdl_t handles
815088Sab196087  * in our module interface into the actual strings for elfedit to
825088Sab196087  * use.
835088Sab196087  *
845088Sab196087  * note:
855088Sab196087  *	This module uses Msg codes for its i18n handle type.
865088Sab196087  *	So the translation is simply to use MSG_INTL() to turn
875088Sab196087  *	it into a string and return it.
885088Sab196087  */
895088Sab196087 static const char *
mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl)905088Sab196087 mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl)
915088Sab196087 {
925088Sab196087 	Msg msg = (Msg)hdl;
935088Sab196087 
945088Sab196087 	return (MSG_INTL(msg));
955088Sab196087 }
965088Sab196087 
975088Sab196087 
985088Sab196087 
995088Sab196087 /*
1005088Sab196087  * The cap_opt_t enum specifies a bit value for every optional
1015088Sab196087  * argument allowed by a command in this module.
1025088Sab196087  */
1035088Sab196087 typedef enum {
1045088Sab196087 	CAP_OPT_F_AND =		1,	/* -and: AND (&) values to dest */
1055088Sab196087 	CAP_OPT_F_CMP =		2,	/* -cmp: Complement (~) values */
10611827SRod.Evans@Sun.COM 	CAP_OPT_F_CAPID =	4,	/* -capid id: elt limited to given */
10711827SRod.Evans@Sun.COM 					/*	capabilities group */
10811827SRod.Evans@Sun.COM 	CAP_OPT_F_CAPNDX =	8,	/* -capndx: elt is tag index, */
1095088Sab196087 					/*	not name */
11011827SRod.Evans@Sun.COM 	CAP_OPT_F_OR =		16,	/* -or: OR (|) values to dest */
11111827SRod.Evans@Sun.COM 	CAP_OPT_F_STRVAL =	32	/* -s: value is string, not integer */
1125088Sab196087 } cap_opt_t;
1135088Sab196087 
1145088Sab196087 
1155088Sab196087 /*
1165088Sab196087  * A variable of type ARGSTATE is used by each command to maintain
1175088Sab196087  * information about the arguments and related things. It is
1185088Sab196087  * initialized by process_args(), and used by the other routines.
1195088Sab196087  */
1205088Sab196087 typedef struct {
1215088Sab196087 	elfedit_obj_state_t	*obj_state;
1225088Sab196087 	struct {
1235088Sab196087 		elfedit_section_t *sec;	/* Capabilities section reference */
1245088Sab196087 		Cap	*data;		/* Start of capabilities section data */
1255088Sab196087 		Word	num;		/* # Capabilities elts */
12611827SRod.Evans@Sun.COM 		Boolean	grp_set;	/* TRUE when cap group is set */
12711827SRod.Evans@Sun.COM 		Word	grp_start_ndx;	/* capabilities group starting index */
12811827SRod.Evans@Sun.COM 		Word	grp_end_ndx;	/* capabilities group ending index */
1295088Sab196087 	} cap;
13011827SRod.Evans@Sun.COM 	struct {			/* String table */
13111827SRod.Evans@Sun.COM 		elfedit_section_t *sec;
13211827SRod.Evans@Sun.COM 	} str;
1335088Sab196087 	cap_opt_t	optmask;   	/* Mask of options used */
1345088Sab196087 	int		argc;		/* # of plain arguments */
1355088Sab196087 	const char	**argv;		/* Plain arguments */
1365088Sab196087 } ARGSTATE;
1375088Sab196087 
1385088Sab196087 
1395088Sab196087 
1405088Sab196087 /*
14111827SRod.Evans@Sun.COM  * Lookup the string table associated with the capabilities
14211827SRod.Evans@Sun.COM  * section.
14311827SRod.Evans@Sun.COM  *
14411827SRod.Evans@Sun.COM  * entry:
14511827SRod.Evans@Sun.COM  *	argstate - Argument state block
14611827SRod.Evans@Sun.COM  *	required - If TRUE, failure to obtain a string table should be
14711827SRod.Evans@Sun.COM  *		considered to be an error.
14811827SRod.Evans@Sun.COM  *
14911827SRod.Evans@Sun.COM  * exit:
15011827SRod.Evans@Sun.COM  *	If a string table is found, argstate->str is updated to reference it.
15111827SRod.Evans@Sun.COM  *	If no string table is found, and required is TRUE, an error is issued
15211827SRod.Evans@Sun.COM  *	and this routine does not return to the caller. Otherwise, this
15311827SRod.Evans@Sun.COM  *	routine returns quietly without modifying argstate->str.
15411827SRod.Evans@Sun.COM  */
15511827SRod.Evans@Sun.COM static void
argstate_add_str(ARGSTATE * argstate,Boolean required)15611827SRod.Evans@Sun.COM argstate_add_str(ARGSTATE *argstate, Boolean required)
15711827SRod.Evans@Sun.COM {
15811827SRod.Evans@Sun.COM 	/* String table already loaded? */
15911827SRod.Evans@Sun.COM 	if (argstate->str.sec != NULL)
16011827SRod.Evans@Sun.COM 		return;
16111827SRod.Evans@Sun.COM 
16211827SRod.Evans@Sun.COM 	/*
16311827SRod.Evans@Sun.COM 	 * We can't proceed if the capabilities section does not have
16411827SRod.Evans@Sun.COM 	 * an associated string table.
16511827SRod.Evans@Sun.COM 	 */
16611827SRod.Evans@Sun.COM 	if (argstate->cap.sec->sec_shdr->sh_info == 0) {
16711827SRod.Evans@Sun.COM 		/* Error if the operation requires a string table */
16811827SRod.Evans@Sun.COM 		if (required)
16911827SRod.Evans@Sun.COM 			elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOSTRTAB),
17011827SRod.Evans@Sun.COM 			    EC_WORD(argstate->cap.sec->sec_shndx),
17111827SRod.Evans@Sun.COM 			    argstate->cap.sec->sec_name);
17211827SRod.Evans@Sun.COM 		return;
17311827SRod.Evans@Sun.COM 	}
17411827SRod.Evans@Sun.COM 
17511827SRod.Evans@Sun.COM 	argstate->str.sec = elfedit_sec_getstr(argstate->obj_state,
17611827SRod.Evans@Sun.COM 	    argstate->cap.sec->sec_shdr->sh_info, 0);
17711827SRod.Evans@Sun.COM }
17811827SRod.Evans@Sun.COM 
17911827SRod.Evans@Sun.COM /*
18011827SRod.Evans@Sun.COM  * Given an index into the capabilities array, locate the index of the
18111827SRod.Evans@Sun.COM  * initial element in its capabilities group, and the number of elements
18211827SRod.Evans@Sun.COM  * in the group.
18311827SRod.Evans@Sun.COM  */
18411827SRod.Evans@Sun.COM static void
cap_group_extents(ARGSTATE * argstate,Word ndx,Word * ret_start_ndx,Word * ret_end_ndx)18511827SRod.Evans@Sun.COM cap_group_extents(ARGSTATE *argstate, Word ndx, Word *ret_start_ndx,
18611827SRod.Evans@Sun.COM     Word *ret_end_ndx)
18711827SRod.Evans@Sun.COM {
18811827SRod.Evans@Sun.COM 	*ret_end_ndx = ndx;
18911827SRod.Evans@Sun.COM 
19011827SRod.Evans@Sun.COM 	/*
19111827SRod.Evans@Sun.COM 	 * The group starts with a non-NULL tag that is either the
19211827SRod.Evans@Sun.COM 	 * first tag in the array, or is preceded by a NULL tag.
19311827SRod.Evans@Sun.COM 	 */
19411827SRod.Evans@Sun.COM 	while ((ndx > 0) && (argstate->cap.data[ndx].c_tag == CA_SUNW_NULL))
19511827SRod.Evans@Sun.COM 		ndx--;
19611827SRod.Evans@Sun.COM 	while ((ndx > 0) && (argstate->cap.data[ndx - 1].c_tag != CA_SUNW_NULL))
19711827SRod.Evans@Sun.COM 		ndx--;
19811827SRod.Evans@Sun.COM 	*ret_start_ndx = ndx;
19911827SRod.Evans@Sun.COM 
20011827SRod.Evans@Sun.COM 
20111827SRod.Evans@Sun.COM 	/*
20211827SRod.Evans@Sun.COM 	 * The group is terminated by a series of 1 or more NULL tags.
20311827SRod.Evans@Sun.COM 	 */
20411827SRod.Evans@Sun.COM 	ndx = *ret_end_ndx;
20511827SRod.Evans@Sun.COM 	while (((ndx + 1) < argstate->cap.num) &&
20611827SRod.Evans@Sun.COM 	    (argstate->cap.data[ndx].c_tag != CA_SUNW_NULL))
20711827SRod.Evans@Sun.COM 		ndx++;
20811827SRod.Evans@Sun.COM 	while (((ndx + 1) < argstate->cap.num) &&
20911827SRod.Evans@Sun.COM 	    (argstate->cap.data[ndx + 1].c_tag == CA_SUNW_NULL))
21011827SRod.Evans@Sun.COM 		ndx++;
21111827SRod.Evans@Sun.COM 	*ret_end_ndx = ndx;
21211827SRod.Evans@Sun.COM }
21311827SRod.Evans@Sun.COM 
21411827SRod.Evans@Sun.COM /*
21511827SRod.Evans@Sun.COM  * If a CA_SUNW_ID element exists within the current capabilities group
21611827SRod.Evans@Sun.COM  * in the given argument state, return the string pointer to the name.
21711827SRod.Evans@Sun.COM  * Otherwise return a pointer to a descriptive "noname" string.
21811827SRod.Evans@Sun.COM  */
21911827SRod.Evans@Sun.COM static const char *
cap_group_id(ARGSTATE * argstate)22011827SRod.Evans@Sun.COM cap_group_id(ARGSTATE *argstate)
22111827SRod.Evans@Sun.COM {
22211827SRod.Evans@Sun.COM 	Word		ndx = argstate->cap.grp_start_ndx;
22311827SRod.Evans@Sun.COM 	Cap		*cap = argstate->cap.data + ndx;
22411827SRod.Evans@Sun.COM 
22511827SRod.Evans@Sun.COM 	for (; ndx <= argstate->cap.grp_end_ndx; ndx++, cap++) {
22611827SRod.Evans@Sun.COM 		if (cap->c_tag == CA_SUNW_ID) {
22711827SRod.Evans@Sun.COM 			argstate_add_str(argstate, TRUE);
22811827SRod.Evans@Sun.COM 			return (elfedit_offset_to_str(argstate->str.sec,
22911827SRod.Evans@Sun.COM 			    cap->c_un.c_val, ELFEDIT_MSG_ERR, 0));
23011827SRod.Evans@Sun.COM 			break;
23111827SRod.Evans@Sun.COM 		}
23211827SRod.Evans@Sun.COM 
23311827SRod.Evans@Sun.COM 		if (cap->c_tag == CA_SUNW_NULL)
23411827SRod.Evans@Sun.COM 			break;
23511827SRod.Evans@Sun.COM 	}
23611827SRod.Evans@Sun.COM 
23711827SRod.Evans@Sun.COM 	return ((argstate->cap.grp_start_ndx == 0) ?
23811827SRod.Evans@Sun.COM 	    MSG_INTL(MSG_STR_OBJECT) : MSG_INTL(MSG_STR_NONAME));
23911827SRod.Evans@Sun.COM }
24011827SRod.Evans@Sun.COM 
24111827SRod.Evans@Sun.COM 
24211827SRod.Evans@Sun.COM /*
24311827SRod.Evans@Sun.COM  * Given an index into the capabilities array, set the argstate cap.grp_*
24411827SRod.Evans@Sun.COM  * fields to reflect the capabilities group containing the index.
24511827SRod.Evans@Sun.COM  *
24611827SRod.Evans@Sun.COM  * The group concept is used to limit operations to a related group
24711827SRod.Evans@Sun.COM  * of capabilities, and prevent insert/delete/move operations from
24811827SRod.Evans@Sun.COM  * spilling across groups.
24911827SRod.Evans@Sun.COM  */
25011827SRod.Evans@Sun.COM static void
argstate_cap_group(ARGSTATE * argstate,Word ndx)25111827SRod.Evans@Sun.COM argstate_cap_group(ARGSTATE *argstate, Word ndx)
25211827SRod.Evans@Sun.COM {
25311827SRod.Evans@Sun.COM 	if (argstate->cap.grp_set == TRUE)
25411827SRod.Evans@Sun.COM 		return;
25511827SRod.Evans@Sun.COM 
25611827SRod.Evans@Sun.COM 	cap_group_extents(argstate, ndx, &argstate->cap.grp_start_ndx,
25711827SRod.Evans@Sun.COM 	    &argstate->cap.grp_end_ndx);
25811827SRod.Evans@Sun.COM 
25911827SRod.Evans@Sun.COM 	argstate->cap.grp_set = TRUE;
26011827SRod.Evans@Sun.COM 	elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_CAPGRP),
26111827SRod.Evans@Sun.COM 	    EC_WORD(argstate->cap.sec->sec_shndx), argstate->cap.sec->sec_name,
26211827SRod.Evans@Sun.COM 	    EC_WORD(argstate->cap.grp_start_ndx),
26311827SRod.Evans@Sun.COM 	    EC_WORD(argstate->cap.grp_end_ndx), cap_group_id(argstate));
26411827SRod.Evans@Sun.COM }
26511827SRod.Evans@Sun.COM 
26611827SRod.Evans@Sun.COM /*
26711827SRod.Evans@Sun.COM  * Given an index into the capabilities array, issue a group title for
26811827SRod.Evans@Sun.COM  * the capabilities group that contains it.
26911827SRod.Evans@Sun.COM  */
27011827SRod.Evans@Sun.COM static void
group_title(ARGSTATE * argstate,Word ndx)27111827SRod.Evans@Sun.COM group_title(ARGSTATE *argstate, Word ndx)
27211827SRod.Evans@Sun.COM {
27311827SRod.Evans@Sun.COM 	ARGSTATE	loc_argstate;
27411827SRod.Evans@Sun.COM 
27511827SRod.Evans@Sun.COM 	loc_argstate = *argstate;
27611827SRod.Evans@Sun.COM 	cap_group_extents(argstate, ndx, &loc_argstate.cap.grp_start_ndx,
27711827SRod.Evans@Sun.COM 	    &loc_argstate.cap.grp_end_ndx);
27811827SRod.Evans@Sun.COM 	elfedit_printf(MSG_INTL(MSG_FMT_CAPGRP),
27911827SRod.Evans@Sun.COM 	    EC_WORD(loc_argstate.cap.grp_start_ndx),
28011827SRod.Evans@Sun.COM 	    EC_WORD(loc_argstate.cap.grp_end_ndx), cap_group_id(&loc_argstate));
28111827SRod.Evans@Sun.COM }
28211827SRod.Evans@Sun.COM 
28311827SRod.Evans@Sun.COM /*
2845088Sab196087  * Standard argument processing for cap module
2855088Sab196087  *
2865088Sab196087  * entry
2875088Sab196087  *	obj_state, argc, argv - Standard command arguments
2885088Sab196087  *	argstate - Address of ARGSTATE block to be initialized
2895088Sab196087  *
2905088Sab196087  * exit:
2915088Sab196087  *	On success, *argstate is initialized. On error,
2925088Sab196087  *	an error is issued and this routine does not return.
2935088Sab196087  */
2945088Sab196087 static void
process_args(elfedit_obj_state_t * obj_state,int argc,const char * argv[],ARGSTATE * argstate)2955088Sab196087 process_args(elfedit_obj_state_t *obj_state, int argc, const char *argv[],
2965088Sab196087     ARGSTATE *argstate)
2975088Sab196087 {
2985088Sab196087 	elfedit_getopt_state_t	getopt_state;
2995088Sab196087 	elfedit_getopt_ret_t	*getopt_ret;
30011827SRod.Evans@Sun.COM 	const char		*capid = NULL;
3015088Sab196087 
3025088Sab196087 	bzero(argstate, sizeof (*argstate));
3035088Sab196087 	argstate->obj_state = obj_state;
3045088Sab196087 
3055088Sab196087 	elfedit_getopt_init(&getopt_state, &argc, &argv);
3065088Sab196087 
3075088Sab196087 	/* Add each new option to the options mask */
30811827SRod.Evans@Sun.COM 	while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) {
3095088Sab196087 		argstate->optmask |= getopt_ret->gor_idmask;
3105088Sab196087 
31111827SRod.Evans@Sun.COM 		if (getopt_ret->gor_idmask == CAP_OPT_F_CAPID)
31211827SRod.Evans@Sun.COM 			capid = getopt_ret->gor_value;
31311827SRod.Evans@Sun.COM 	}
31411827SRod.Evans@Sun.COM 
3155088Sab196087 	/* If there may be an arbitrary amount of output, use a pager */
3165088Sab196087 	if (argc == 0)
3175088Sab196087 		elfedit_pager_init();
3185088Sab196087 
3195088Sab196087 	/* Return the updated values of argc/argv */
3205088Sab196087 	argstate->argc = argc;
3215088Sab196087 	argstate->argv = argv;
3225088Sab196087 
3235088Sab196087 	/* Locate the capabilities section */
3245088Sab196087 	argstate->cap.sec = elfedit_sec_getcap(obj_state, &argstate->cap.data,
3255088Sab196087 	    &argstate->cap.num);
32611827SRod.Evans@Sun.COM 
32711827SRod.Evans@Sun.COM 	/*
32811827SRod.Evans@Sun.COM 	 * If -capid was specified, locate the specified capabilities group,
32911827SRod.Evans@Sun.COM 	 * and narrow the section data to use only that group. Otherwise,
33011827SRod.Evans@Sun.COM 	 * use the whole array.
33111827SRod.Evans@Sun.COM 	 */
33211827SRod.Evans@Sun.COM 	if (capid != NULL) {
33311827SRod.Evans@Sun.COM 		Word	i;
33411827SRod.Evans@Sun.COM 		Cap	*cap = argstate->cap.data;
33511827SRod.Evans@Sun.COM 
33611827SRod.Evans@Sun.COM 		/*
33711827SRod.Evans@Sun.COM 		 * -capid requires the capability section to have an
33811827SRod.Evans@Sun.COM 		 * associated string table.
33911827SRod.Evans@Sun.COM 		 */
34011827SRod.Evans@Sun.COM 		argstate_add_str(argstate, TRUE);
34111827SRod.Evans@Sun.COM 
34211827SRod.Evans@Sun.COM 		for (i = 0; i < argstate->cap.num; i++, cap++)
34311827SRod.Evans@Sun.COM 			if ((cap->c_tag == CA_SUNW_ID) &&
34411827SRod.Evans@Sun.COM 			    (strcmp(capid, elfedit_offset_to_str(
34511827SRod.Evans@Sun.COM 			    argstate->str.sec, cap->c_un.c_val,
34611827SRod.Evans@Sun.COM 			    ELFEDIT_MSG_ERR, 0)) == 0))
34711827SRod.Evans@Sun.COM 				break;
34811827SRod.Evans@Sun.COM 
34911827SRod.Evans@Sun.COM 		if (i == argstate->cap.num)
35011827SRod.Evans@Sun.COM 			elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_BADCAPID),
35111827SRod.Evans@Sun.COM 			    EC_WORD(argstate->cap.sec->sec_shndx),
35211827SRod.Evans@Sun.COM 			    argstate->cap.sec->sec_name, capid);
35311827SRod.Evans@Sun.COM 		argstate_cap_group(argstate, i);
35411827SRod.Evans@Sun.COM 	} else {
35511827SRod.Evans@Sun.COM 		argstate->cap.grp_start_ndx = 0;
35611827SRod.Evans@Sun.COM 		argstate->cap.grp_end_ndx = argstate->cap.num - 1;
35711827SRod.Evans@Sun.COM 	}
3585088Sab196087 }
3595088Sab196087 
3605088Sab196087 
3615088Sab196087 
3625088Sab196087 /*
3635088Sab196087  * Print ELF capabilities values, taking the calling command, and output style
3645088Sab196087  * into account.
3655088Sab196087  *
3665088Sab196087  * entry:
3675088Sab196087  *	cmd - CAP_CMD_T_* value giving identify of caller
3685088Sab196087  *	autoprint - If True, output is only produced if the elfedit
3695088Sab196087  *		autoprint flag is set. If False, output is always produced.
3705088Sab196087  *	argstate - Argument state block
3715088Sab196087  *	print_type - Specifies which capabilities elements to display.
3725088Sab196087  *	ndx = If print_type is PRINT_CAP_T_NDX, displays the index specified.
3735088Sab196087  *		Otherwise ignored.
3745088Sab196087  */
3755088Sab196087 typedef enum {
3765088Sab196087 	PRINT_CAP_T_ALL =	0,	/* Show all indexes */
3775088Sab196087 	PRINT_CAP_T_NDX =	1,	/* Show capabilities[arg] only */
3785088Sab196087 	PRINT_CAP_T_TAG =	2	/* Show all elts with tag type */
3795088Sab196087 					/*	given by arg */
3805088Sab196087 } PRINT_CAP_T;
3815088Sab196087 
3825088Sab196087 static void
print_cap(CAP_CMD_T cmd,int autoprint,ARGSTATE * argstate,PRINT_CAP_T print_type,Word arg)3835088Sab196087 print_cap(CAP_CMD_T cmd, int autoprint, ARGSTATE *argstate,
3845088Sab196087     PRINT_CAP_T print_type, Word arg)
3855088Sab196087 {
3865088Sab196087 	elfedit_outstyle_t	outstyle;
387*12029SRod.Evans@Sun.COM 	Word		cnt, ndx, printed = 0;
388*12029SRod.Evans@Sun.COM 	Cap		*cap;
389*12029SRod.Evans@Sun.COM 	Boolean		header_done = FALSE, null_seen = FALSE;
390*12029SRod.Evans@Sun.COM 	const char	*str;
391*12029SRod.Evans@Sun.COM 	size_t		str_size;
3925088Sab196087 
3935088Sab196087 	if (autoprint && ((elfedit_flags() & ELFEDIT_F_AUTOPRINT) == 0))
3945088Sab196087 		return;
3955088Sab196087 
3965088Sab196087 	/*
3975088Sab196087 	 * Pick an output style. cap:dump is required to use the default
3985088Sab196087 	 * style. The other commands use the current output style.
3995088Sab196087 	 */
4005088Sab196087 	outstyle = (cmd == CAP_CMD_T_DUMP) ?
4015088Sab196087 	    ELFEDIT_OUTSTYLE_DEFAULT : elfedit_outstyle();
4025088Sab196087 
4035088Sab196087 	/* How many elements do we examine? */
4045088Sab196087 	if (print_type == PRINT_CAP_T_NDX) {
4055088Sab196087 		if (arg >= argstate->cap.num)
4065088Sab196087 			return;		/* Out of range */
4075088Sab196087 		ndx = arg;
4085088Sab196087 		cnt = 1;
4095088Sab196087 	} else {
41011827SRod.Evans@Sun.COM 		ndx = argstate->cap.grp_start_ndx;
41111827SRod.Evans@Sun.COM 		cnt = argstate->cap.grp_end_ndx - ndx + 1;
4125088Sab196087 	}
4135088Sab196087 
41411827SRod.Evans@Sun.COM 	/* Load string table if there is one */
41511827SRod.Evans@Sun.COM 	argstate_add_str(argstate, FALSE);
416*12029SRod.Evans@Sun.COM 	if (argstate->str.sec == NULL) {
417*12029SRod.Evans@Sun.COM 		str = NULL;
418*12029SRod.Evans@Sun.COM 		str_size = 0;
419*12029SRod.Evans@Sun.COM 	} else {
420*12029SRod.Evans@Sun.COM 		str = (const char *)argstate->str.sec->sec_data->d_buf;
421*12029SRod.Evans@Sun.COM 		str_size = argstate->str.sec->sec_data->d_size;
422*12029SRod.Evans@Sun.COM 	}
42311827SRod.Evans@Sun.COM 
4245088Sab196087 	cap = &argstate->cap.data[ndx];
4255088Sab196087 	for (; cnt--; cap++, ndx++) {
4265088Sab196087 		/*
4275088Sab196087 		 * If we are only displaying certain tag types and
4285088Sab196087 		 * this isn't one of those, move on to next element.
4295088Sab196087 		 */
43011827SRod.Evans@Sun.COM 		if ((print_type == PRINT_CAP_T_TAG) && (cap->c_tag != arg)) {
43111827SRod.Evans@Sun.COM 			if (cap->c_tag == CA_SUNW_NULL)
43211827SRod.Evans@Sun.COM 				null_seen = TRUE;
4335088Sab196087 			continue;
43411827SRod.Evans@Sun.COM 		}
43511827SRod.Evans@Sun.COM 
43611827SRod.Evans@Sun.COM 		/*
43711827SRod.Evans@Sun.COM 		 * If capability type requires a string table, and we don't
43811827SRod.Evans@Sun.COM 		 * have one, force an error.
43911827SRod.Evans@Sun.COM 		 */
44011827SRod.Evans@Sun.COM 		switch (cap->c_tag) {
44111827SRod.Evans@Sun.COM 		case CA_SUNW_PLAT:
44211827SRod.Evans@Sun.COM 		case CA_SUNW_MACH:
44311827SRod.Evans@Sun.COM 		case CA_SUNW_ID:
44411827SRod.Evans@Sun.COM 			if (argstate->str.sec == NULL)
44511827SRod.Evans@Sun.COM 				argstate_add_str(argstate, TRUE);
44611827SRod.Evans@Sun.COM 			break;
44711827SRod.Evans@Sun.COM 		}
4485088Sab196087 
4495088Sab196087 		if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) {
45011827SRod.Evans@Sun.COM 			if (null_seen && (cap->c_tag != CA_SUNW_NULL)) {
45111827SRod.Evans@Sun.COM 				null_seen = FALSE;
45211827SRod.Evans@Sun.COM 				if (header_done) {
45311827SRod.Evans@Sun.COM 					elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
45411827SRod.Evans@Sun.COM 					    MSG_ORIG(MSG_STR_EMPTY));
45511827SRod.Evans@Sun.COM 					header_done = FALSE;
45611827SRod.Evans@Sun.COM 				}
45711827SRod.Evans@Sun.COM 			}
45811827SRod.Evans@Sun.COM 
45911827SRod.Evans@Sun.COM 			if (header_done == FALSE) {
46011827SRod.Evans@Sun.COM 				header_done = TRUE;
46111827SRod.Evans@Sun.COM 				group_title(argstate, ndx);
4625088Sab196087 				Elf_cap_title(0);
4635088Sab196087 			}
464*12029SRod.Evans@Sun.COM 			Elf_cap_entry(NULL, cap, ndx, str, str_size,
4655088Sab196087 			    argstate->obj_state->os_ehdr->e_machine);
4665088Sab196087 		} else {
4675088Sab196087 			/*
46811827SRod.Evans@Sun.COM 			 * If CAP_CMD_T_TAG, and not in default output
46911827SRod.Evans@Sun.COM 			 * style, display the tag rather than the value.
4705088Sab196087 			 */
47111827SRod.Evans@Sun.COM 			if (cmd == CAP_CMD_T_TAG) {
47211827SRod.Evans@Sun.COM 				if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
47311827SRod.Evans@Sun.COM 					Conv_inv_buf_t	inv_buf;
47411827SRod.Evans@Sun.COM 
47511827SRod.Evans@Sun.COM 					elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
47611827SRod.Evans@Sun.COM 					    conv_cap_tag(cap->c_tag, 0,
47711827SRod.Evans@Sun.COM 					    &inv_buf));
47811827SRod.Evans@Sun.COM 				} else {
47911827SRod.Evans@Sun.COM 					elfedit_printf(
48011827SRod.Evans@Sun.COM 					    MSG_ORIG(MSG_FMT_WORDVALNL),
48111827SRod.Evans@Sun.COM 					    EC_WORD(cap->c_tag));
48211827SRod.Evans@Sun.COM 				}
48311827SRod.Evans@Sun.COM 				printed = 1;
4845088Sab196087 				continue;
48511827SRod.Evans@Sun.COM 			}
4865088Sab196087 
48711827SRod.Evans@Sun.COM 			/* Displaying the value in simple or numeric mode */
4885088Sab196087 			if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
48911827SRod.Evans@Sun.COM 				Conv_cap_val_buf_t	cap_val_buf;
49011827SRod.Evans@Sun.COM 
49111827SRod.Evans@Sun.COM 				if (print_type == PRINT_CAP_T_TAG) {
49211827SRod.Evans@Sun.COM 					elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
49311827SRod.Evans@Sun.COM 					    conv_cap_val_hw1(cap->c_un.c_val,
49411827SRod.Evans@Sun.COM 					    argstate->obj_state->os_ehdr->
49511827SRod.Evans@Sun.COM 					    e_machine, CONV_FMT_NOBKT,
49611827SRod.Evans@Sun.COM 					    &cap_val_buf.cap_val_hw1_buf));
49711827SRod.Evans@Sun.COM 					printed = 1;
49811827SRod.Evans@Sun.COM 					continue;
49911827SRod.Evans@Sun.COM 				}
5005088Sab196087 
5015088Sab196087 				switch (cap->c_tag) {
5025088Sab196087 				case CA_SUNW_HW_1:
5035088Sab196087 					elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
5045088Sab196087 					    conv_cap_val_hw1(cap->c_un.c_val,
5055088Sab196087 					    argstate->obj_state->os_ehdr->
50611827SRod.Evans@Sun.COM 					    e_machine, CONV_FMT_NOBKT,
50711827SRod.Evans@Sun.COM 					    &cap_val_buf.cap_val_hw1_buf));
5085088Sab196087 					printed = 1;
5095088Sab196087 					continue;
5105088Sab196087 				case CA_SUNW_SF_1:
5115088Sab196087 					elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
5125088Sab196087 					    conv_cap_val_sf1(cap->c_un.c_val,
5135088Sab196087 					    argstate->obj_state->os_ehdr->
51411827SRod.Evans@Sun.COM 					    e_machine, CONV_FMT_NOBKT,
51511827SRod.Evans@Sun.COM 					    &cap_val_buf.cap_val_sf1_buf));
51611827SRod.Evans@Sun.COM 					printed = 1;
51711827SRod.Evans@Sun.COM 					continue;
51811827SRod.Evans@Sun.COM 				case CA_SUNW_HW_2:
51911827SRod.Evans@Sun.COM 					elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
52011827SRod.Evans@Sun.COM 					    conv_cap_val_hw2(cap->c_un.c_val,
52111827SRod.Evans@Sun.COM 					    argstate->obj_state->os_ehdr->
52211827SRod.Evans@Sun.COM 					    e_machine, CONV_FMT_NOBKT,
52311827SRod.Evans@Sun.COM 					    &cap_val_buf.cap_val_hw2_buf));
52411827SRod.Evans@Sun.COM 					printed = 1;
52511827SRod.Evans@Sun.COM 					continue;
52611827SRod.Evans@Sun.COM 				case CA_SUNW_PLAT:
52711827SRod.Evans@Sun.COM 				case CA_SUNW_MACH:
52811827SRod.Evans@Sun.COM 				case CA_SUNW_ID:
52911827SRod.Evans@Sun.COM 					elfedit_printf(MSG_ORIG(MSG_FMT_STRNL),
53011827SRod.Evans@Sun.COM 					    elfedit_offset_to_str(
53111827SRod.Evans@Sun.COM 					    argstate->str.sec, cap->c_un.c_val,
53211827SRod.Evans@Sun.COM 					    ELFEDIT_MSG_ERR, 0));
5335088Sab196087 					printed = 1;
5345088Sab196087 					continue;
5355088Sab196087 				}
5365088Sab196087 			}
5375088Sab196087 			elfedit_printf(MSG_ORIG(MSG_FMT_HEXXWORDNL),
53811827SRod.Evans@Sun.COM 			    EC_XWORD(cap->c_un.c_val));
5395088Sab196087 		}
5405088Sab196087 		printed = 1;
54111827SRod.Evans@Sun.COM 		if (cap->c_tag == CA_SUNW_NULL)
54211827SRod.Evans@Sun.COM 			null_seen = TRUE;
5435088Sab196087 	}
5445088Sab196087 
5455088Sab196087 	/*
5465088Sab196087 	 * If nothing was output under the print types that are
5475088Sab196087 	 * based on tag type, issue an error saying it doesn't exist.
5485088Sab196087 	 */
5495088Sab196087 	if (!printed && (print_type == PRINT_CAP_T_TAG)) {
55011827SRod.Evans@Sun.COM 		Conv_inv_buf_t	inv_buf;
5515088Sab196087 
5525088Sab196087 		elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOCAELT),
5535088Sab196087 		    EC_WORD(argstate->cap.sec->sec_shndx),
55411827SRod.Evans@Sun.COM 		    argstate->cap.sec->sec_name, argstate->cap.grp_start_ndx,
55511827SRod.Evans@Sun.COM 		    argstate->cap.grp_end_ndx, cap_group_id(argstate),
5569273SAli.Bahrami@Sun.COM 		    conv_cap_tag(arg, 0, &inv_buf));
5575088Sab196087 	}
5585088Sab196087 }
5595088Sab196087 
5605088Sab196087 
5615088Sab196087 /*
5625088Sab196087  * Process the elt argument: This will be a tag type if -capndx is
5635088Sab196087  * not present and this is a print request. It will be an index otherwise.
5645088Sab196087  *
5655088Sab196087  * entry:
5665088Sab196087  *	argstate - Argument state block
5675088Sab196087  *	arg - Argument string to be converted into an index
5685088Sab196087  *	argname - String giving the name by which the argument is
5695088Sab196087  *		referred in the online help for the command.
5705088Sab196087  *	print_request - True if the command is to print the current
5715088Sab196087  *		value(s) and return without changing anything.
5725088Sab196087  *	print_type - Address of variable containing PRINT_CAP_T_
5735088Sab196087  *		code specifying how the elements will be displayed.
5745088Sab196087  *
5755088Sab196087  * exit:
5765088Sab196087  *	If print_request is False: arg is converted into an integer value.
5775088Sab196087  *	If -capndx was used, we convert it into an integer. If it was not
5785088Sab196087  *	used, then arg is a tag name --- we find the first capabilities entry
5795088Sab196087  *	that matches. If no entry matches, and there is an extra CA_NULL,
5805088Sab196087  *	it is added. Otherwise an error is issued. *print_type is set
5815088Sab196087  *	to PRINT_CAP_T_NDX.
5825088Sab196087  *
5835088Sab196087  *	If print_request is True: If -capndx was used, arg is converted into
5845088Sab196087  *	an integer value, *print_type is set to PRINT_CAP_T_NDX, and
5855088Sab196087  *	the value is returned. If -capndx was not used, *print_type is set to
5865088Sab196087  *	PRINT_CAP_T_TAG, and the tag value is returned.
5875088Sab196087  */
5885088Sab196087 static Word
arg_to_index(ARGSTATE * argstate,const char * arg,const char * argname,int print_request,PRINT_CAP_T * print_type)5895088Sab196087 arg_to_index(ARGSTATE *argstate, const char *arg, const char *argname,
5905088Sab196087     int print_request, PRINT_CAP_T *print_type)
5915088Sab196087 {
59211827SRod.Evans@Sun.COM 	Word		ndx, ca_value;
5935088Sab196087 
5945088Sab196087 
5955088Sab196087 	/* Assume we are returning an index, alter as needed below */
5965088Sab196087 	*print_type = PRINT_CAP_T_NDX;
5975088Sab196087 
59811827SRod.Evans@Sun.COM 	/*
59911827SRod.Evans@Sun.COM 	 * If -capndx was used, this is a simple numeric index.
60011827SRod.Evans@Sun.COM 	 * Determine its capability group because some operations
60111827SRod.Evans@Sun.COM 	 * (move, delete) are limited to operate within it.
60211827SRod.Evans@Sun.COM 	 */
60311827SRod.Evans@Sun.COM 	if ((argstate->optmask & CAP_OPT_F_CAPNDX) != 0) {
60411827SRod.Evans@Sun.COM 		ndx = (Word) elfedit_atoui_range(arg, argname, 0,
60511827SRod.Evans@Sun.COM 		    argstate->cap.num - 1, NULL);
60611827SRod.Evans@Sun.COM 		argstate_cap_group(argstate, ndx);
60711827SRod.Evans@Sun.COM 		return (ndx);
60811827SRod.Evans@Sun.COM 	}
6095088Sab196087 
6105088Sab196087 	/* The argument is a CA_ tag type, not a numeric index */
6115088Sab196087 	ca_value = (Word) elfedit_atoconst(arg, ELFEDIT_CONST_CA);
6125088Sab196087 
6135088Sab196087 	/*
6145088Sab196087 	 * If this is a printing request, then we let print_cap() show
6155088Sab196087 	 * all the items with this tag type.
6165088Sab196087 	 */
6175088Sab196087 	if (print_request) {
6185088Sab196087 		*print_type = PRINT_CAP_T_TAG;
6195088Sab196087 		return (ca_value);
6205088Sab196087 	}
6215088Sab196087 
62211827SRod.Evans@Sun.COM 	/*
62311827SRod.Evans@Sun.COM 	 * If we haven't determined a capability group yet, either via
62411827SRod.Evans@Sun.COM 	 * -capid, or -capndx, then make it the initial group, which
62511827SRod.Evans@Sun.COM 	 * represent the object capabilities.
62611827SRod.Evans@Sun.COM 	 */
62711827SRod.Evans@Sun.COM 	if (!argstate->cap.grp_set)
62811827SRod.Evans@Sun.COM 		argstate_cap_group(argstate, 0);
62911827SRod.Evans@Sun.COM 
63011827SRod.Evans@Sun.COM 	/*
63111827SRod.Evans@Sun.COM 	 * Locate the first entry with the given tag type within the
63211827SRod.Evans@Sun.COM 	 * capabilities group.
63311827SRod.Evans@Sun.COM 	 */
63411827SRod.Evans@Sun.COM 	for (ndx = argstate->cap.grp_start_ndx;
63511827SRod.Evans@Sun.COM 	    ndx <= argstate->cap.grp_end_ndx; ndx++) {
6365088Sab196087 		if (argstate->cap.data[ndx].c_tag == ca_value) {
6375088Sab196087 			elfedit_msg(ELFEDIT_MSG_DEBUG,
6385088Sab196087 			    MSG_INTL(MSG_DEBUG_CA2NDX),
6395088Sab196087 			    EC_WORD(argstate->cap.sec->sec_shndx),
6405088Sab196087 			    argstate->cap.sec->sec_name, EC_WORD(ndx), arg);
6415088Sab196087 			return (ndx);
6425088Sab196087 		}
64311827SRod.Evans@Sun.COM 
64411827SRod.Evans@Sun.COM 		/*
64511827SRod.Evans@Sun.COM 		 * If we hit a NULL, then only more NULLs can follow it and
64611827SRod.Evans@Sun.COM 		 * there's no need to look further. If there is more than
64711827SRod.Evans@Sun.COM 		 * one NULL, we can grab the first one and turn it into
64811827SRod.Evans@Sun.COM 		 * an element of the desired type.
64911827SRod.Evans@Sun.COM 		 */
65011827SRod.Evans@Sun.COM 		if (argstate->cap.data[ndx].c_tag == CA_SUNW_NULL) {
65111827SRod.Evans@Sun.COM 			if (ndx < argstate->cap.grp_end_ndx) {
65211827SRod.Evans@Sun.COM 				Conv_inv_buf_t	inv_buf;
65311827SRod.Evans@Sun.COM 
65411827SRod.Evans@Sun.COM 				elfedit_msg(ELFEDIT_MSG_DEBUG,
65511827SRod.Evans@Sun.COM 				    MSG_INTL(MSG_DEBUG_CONVNULL),
65611827SRod.Evans@Sun.COM 				    EC_WORD(argstate->cap.sec->sec_shndx),
65711827SRod.Evans@Sun.COM 				    argstate->cap.sec->sec_name, EC_WORD(ndx),
65811827SRod.Evans@Sun.COM 				    conv_cap_tag(ca_value, 0, &inv_buf));
65911827SRod.Evans@Sun.COM 				argstate->cap.data[ndx].c_tag = ca_value;
66011827SRod.Evans@Sun.COM 				bzero(&argstate->cap.data[ndx].c_un,
66111827SRod.Evans@Sun.COM 				    sizeof (argstate->cap.data[ndx].c_un));
66211827SRod.Evans@Sun.COM 				return (ndx);
66311827SRod.Evans@Sun.COM 			}
66411827SRod.Evans@Sun.COM 			break;
66511827SRod.Evans@Sun.COM 		}
6665088Sab196087 	}
6675088Sab196087 
6685088Sab196087 	/* No room to create one, so we're out of options and must fail */
6695088Sab196087 	elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOCAELT),
6705088Sab196087 	    EC_WORD(argstate->cap.sec->sec_shndx),
67111827SRod.Evans@Sun.COM 	    argstate->cap.sec->sec_name, argstate->cap.grp_start_ndx,
67211827SRod.Evans@Sun.COM 	    argstate->cap.grp_end_ndx, cap_group_id(argstate), arg);
6735088Sab196087 
6745088Sab196087 	/*NOTREACHED*/
6755088Sab196087 	return (0);		/* For lint */
6765088Sab196087 }
6775088Sab196087 
6785088Sab196087 
6795088Sab196087 /*
6805088Sab196087  * Argument processing for the bitmask commands. Convert the arguments
6815088Sab196087  * to integer form, apply -and/-cmp/-or, and return the resulting value.
6825088Sab196087  *
6835088Sab196087  * entry:
6845088Sab196087  *	argstate - Argument state block
6855088Sab196087  *	orig - Value of original bitmask
6865088Sab196087  *	const_sym - NULL, or array of name->integer mappings for
6875088Sab196087  *		applicable symbolic constant names.
6885088Sab196087  */
6895088Sab196087 static Word
flag_bitop(ARGSTATE * argstate,Word orig,const elfedit_atoui_sym_t * const_sym)6905088Sab196087 flag_bitop(ARGSTATE *argstate, Word orig, const elfedit_atoui_sym_t *const_sym)
6915088Sab196087 {
6925088Sab196087 	Word flags = 0;
6935088Sab196087 	int i;
6945088Sab196087 
6955088Sab196087 	/* Collect the arguments */
6965088Sab196087 	for (i = 0; i < argstate->argc; i++)
6975088Sab196087 		flags |= (Word) elfedit_atoui(argstate->argv[i], const_sym);
6985088Sab196087 
6995088Sab196087 	/* Complement the value? */
7005088Sab196087 	if (argstate->optmask & CAP_OPT_F_CMP)
7015088Sab196087 		flags = ~flags;
7025088Sab196087 
7035088Sab196087 	/* Perform any requested bit operations */
7045088Sab196087 	if (argstate->optmask & CAP_OPT_F_AND)
7055088Sab196087 		flags &= orig;
7065088Sab196087 	else if (argstate->optmask & CAP_OPT_F_OR)
7075088Sab196087 		flags |= orig;
7085088Sab196087 
7095088Sab196087 	return (flags);
7105088Sab196087 }
7115088Sab196087 
71211827SRod.Evans@Sun.COM /*
71311827SRod.Evans@Sun.COM  * Common processing for capabilities value setting.
71411827SRod.Evans@Sun.COM  *
71511827SRod.Evans@Sun.COM  * entry:
71611827SRod.Evans@Sun.COM  *	argstate - Argument state block
71711827SRod.Evans@Sun.COM  *	cap - capabilities data pointer
71811827SRod.Evans@Sun.COM  *	ndx - capabilities data index
71911827SRod.Evans@Sun.COM  *	cap_ndx - capabilities section index
72011827SRod.Evans@Sun.COM  *	cap_name - capabilities section name
72111827SRod.Evans@Sun.COM  *	cap_tag - capabilities tag
72211827SRod.Evans@Sun.COM  *	const_type - data conversion type
72311827SRod.Evans@Sun.COM  */
72411827SRod.Evans@Sun.COM 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)72511827SRod.Evans@Sun.COM cap_set(ARGSTATE *argstate, Cap *cap, Word ndx, Word cap_ndx,
72611827SRod.Evans@Sun.COM     const char *cap_name, Xword cap_tag, elfedit_const_t const_type)
72711827SRod.Evans@Sun.COM {
72811827SRod.Evans@Sun.COM 	Conv_cap_val_buf_t	buf1, buf2;
72911827SRod.Evans@Sun.COM 	Half			mach = argstate->obj_state->os_ehdr->e_machine;
73011827SRod.Evans@Sun.COM 	Xword			ncap, ocap;
7315088Sab196087 
73211827SRod.Evans@Sun.COM 	ncap = flag_bitop(argstate, cap[ndx].c_un.c_val,
73311827SRod.Evans@Sun.COM 	    elfedit_const_to_atoui(const_type));
73411827SRod.Evans@Sun.COM 
73511827SRod.Evans@Sun.COM 	/* Set the value */
73611827SRod.Evans@Sun.COM 	if ((ocap = cap[ndx].c_un.c_val) == ncap) {
73711827SRod.Evans@Sun.COM 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_BSB_OK),
73811827SRod.Evans@Sun.COM 		    cap_ndx, cap_name, EC_WORD(ndx),
73911827SRod.Evans@Sun.COM 		    conv_cap_val(cap_tag, ocap, mach, CONV_FMT_NOBKT, &buf1));
74011827SRod.Evans@Sun.COM 
74111827SRod.Evans@Sun.COM 		return (ELFEDIT_CMDRET_NONE);
74211827SRod.Evans@Sun.COM 	} else {
74311827SRod.Evans@Sun.COM 		elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_BSB_CHG),
74411827SRod.Evans@Sun.COM 		    cap_ndx, cap_name, EC_WORD(ndx),
74511827SRod.Evans@Sun.COM 		    conv_cap_val(cap_tag, ocap, mach, CONV_FMT_NOBKT, &buf1),
74611827SRod.Evans@Sun.COM 		    conv_cap_val(cap_tag, ncap, mach, CONV_FMT_NOBKT, &buf2));
74711827SRod.Evans@Sun.COM 
74811827SRod.Evans@Sun.COM 		cap[ndx].c_un.c_val = ncap;
74911827SRod.Evans@Sun.COM 		return (ELFEDIT_CMDRET_MOD);
75011827SRod.Evans@Sun.COM 	}
75111827SRod.Evans@Sun.COM }
7525088Sab196087 
7535088Sab196087 /*
7545088Sab196087  * Common body for the cap: module commands. These commands
7555088Sab196087  * share a large amount of common behavior, so it is convenient
7565088Sab196087  * to centralize things and use the cmd argument to handle the
7575088Sab196087  * small differences.
7585088Sab196087  *
7595088Sab196087  * entry:
7605088Sab196087  *	cmd - One of the CAP_CMD_T_* constants listed above, specifying
7615088Sab196087  *		which command to implement.
7625088Sab196087  *	obj_state, argc, argv - Standard command arguments
7635088Sab196087  */
7645088Sab196087 static elfedit_cmdret_t
cmd_body(CAP_CMD_T cmd,elfedit_obj_state_t * obj_state,int argc,const char * argv[])7655088Sab196087 cmd_body(CAP_CMD_T cmd, elfedit_obj_state_t *obj_state,
7665088Sab196087     int argc, const char *argv[])
7675088Sab196087 {
7685088Sab196087 	ARGSTATE		argstate;
7695088Sab196087 	Cap			*cap;
7705088Sab196087 	const char		*cap_name;
77111827SRod.Evans@Sun.COM 	Word			cap_ndx;
7725088Sab196087 	elfedit_cmdret_t	ret = ELFEDIT_CMDRET_NONE;
7735088Sab196087 	PRINT_CAP_T		print_type = PRINT_CAP_T_ALL;
7745088Sab196087 	Word			ndx;
7755088Sab196087 	int			print_only = 0;
7765088Sab196087 	int			do_autoprint = 1;
7775088Sab196087 
7785088Sab196087 	/* Process the optional arguments */
7795088Sab196087 	process_args(obj_state, argc, argv, &argstate);
7805088Sab196087 
7815088Sab196087 	cap = argstate.cap.data;
7825088Sab196087 	cap_name = argstate.cap.sec->sec_name;
7835088Sab196087 	cap_ndx = argstate.cap.sec->sec_shndx;
7845088Sab196087 
7855088Sab196087 	/* Check number of arguments, gather information */
7865088Sab196087 	switch (cmd) {
7875088Sab196087 	case CAP_CMD_T_DUMP:
7885088Sab196087 		/* cap:dump can accept an optional index argument */
7895088Sab196087 		if (argstate.argc > 1)
7905088Sab196087 			elfedit_command_usage();
7915088Sab196087 		print_only = 1;
7925088Sab196087 		if (argstate.argc == 1)
7935088Sab196087 			ndx = arg_to_index(&argstate, argstate.argv[0],
7945088Sab196087 			    MSG_ORIG(MSG_STR_ELT), print_only, &print_type);
7955088Sab196087 		break;
7965088Sab196087 
7975088Sab196087 	case CAP_CMD_T_TAG:
7985088Sab196087 	case CAP_CMD_T_VALUE:
7995088Sab196087 		print_only = (argstate.argc != 2);
8005088Sab196087 		if (argstate.argc > 0) {
8015088Sab196087 			if (argstate.argc > 2)
8025088Sab196087 				elfedit_command_usage();
8035088Sab196087 			ndx = arg_to_index(&argstate, argstate.argv[0],
8045088Sab196087 			    MSG_ORIG(MSG_STR_ELT), print_only, &print_type);
8055088Sab196087 		}
8065088Sab196087 		break;
8075088Sab196087 
8085088Sab196087 	case CAP_CMD_T_DELETE:
8095088Sab196087 		if ((argstate.argc < 1) || (argstate.argc > 2))
8105088Sab196087 			elfedit_command_usage();
8115088Sab196087 		ndx = arg_to_index(&argstate, argstate.argv[0],
8125088Sab196087 		    MSG_ORIG(MSG_STR_ELT),
8135088Sab196087 		    0, &print_type);
8145088Sab196087 		do_autoprint = 0;
8155088Sab196087 		break;
8165088Sab196087 
8175088Sab196087 	case CAP_CMD_T_MOVE:
8185088Sab196087 		if ((argstate.argc < 2) || (argstate.argc > 3))
8195088Sab196087 			elfedit_command_usage();
8205088Sab196087 		ndx = arg_to_index(&argstate, argstate.argv[0],
8215088Sab196087 		    MSG_ORIG(MSG_STR_ELT), 0, &print_type);
8225088Sab196087 		do_autoprint = 0;
8235088Sab196087 		break;
8245088Sab196087 
8255088Sab196087 	case CAP_CMD_T_HW1:
8265088Sab196087 		print_only = (argstate.argc == 0);
8275088Sab196087 		ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str(
8285088Sab196087 		    ELFEDIT_CONST_CA, CA_SUNW_HW_1, 1),
8295088Sab196087 		    MSG_ORIG(MSG_STR_VALUE), print_only, &print_type);
8305088Sab196087 		break;
8315088Sab196087 
8325088Sab196087 	case CAP_CMD_T_SF1:
8335088Sab196087 		print_only = (argstate.argc == 0);
8345088Sab196087 		ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str(
8355088Sab196087 		    ELFEDIT_CONST_CA, CA_SUNW_SF_1, 1),
8365088Sab196087 		    MSG_ORIG(MSG_STR_VALUE), print_only, &print_type);
8375088Sab196087 		break;
8385088Sab196087 
83911827SRod.Evans@Sun.COM 	case CAP_CMD_T_HW2:
84011827SRod.Evans@Sun.COM 		print_only = (argstate.argc == 0);
84111827SRod.Evans@Sun.COM 		ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str(
84211827SRod.Evans@Sun.COM 		    ELFEDIT_CONST_CA, CA_SUNW_HW_2, 1),
84311827SRod.Evans@Sun.COM 		    MSG_ORIG(MSG_STR_VALUE), print_only, &print_type);
84411827SRod.Evans@Sun.COM 		break;
84511827SRod.Evans@Sun.COM 
8465088Sab196087 	default:
8475088Sab196087 		/* Note expected: All commands should have been caught above */
8485088Sab196087 		elfedit_command_usage();
8495088Sab196087 		break;
8505088Sab196087 	}
8515088Sab196087 
8525088Sab196087 
8535088Sab196087 	/* If this is a request to print current values, do it and return */
8545088Sab196087 	if (print_only) {
8555088Sab196087 		print_cap(cmd, 0, &argstate, print_type, ndx);
8565088Sab196087 		return (ELFEDIT_CMDRET_NONE);
8575088Sab196087 	}
8585088Sab196087 
8595088Sab196087 
8605088Sab196087 	switch (cmd) {
8615088Sab196087 		/*
8625088Sab196087 		 * CAP_CMD_T_DUMP can't get here: It is a print-only
8635088Sab196087 		 * command.
8645088Sab196087 		 */
8655088Sab196087 
8665088Sab196087 	case CAP_CMD_T_TAG:
8675088Sab196087 		{
8685088Sab196087 			Conv_inv_buf_t	inv_buf1, inv_buf2;
8695088Sab196087 			Word c_tag = (Word) elfedit_atoconst(argstate.argv[1],
8705088Sab196087 			    ELFEDIT_CONST_CA);
8715088Sab196087 
8725088Sab196087 			if (cap[ndx].c_tag == c_tag) {
8735088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
8745088Sab196087 				    MSG_INTL(MSG_DEBUG_S_OK),
8755088Sab196087 				    cap_ndx, cap_name, EC_WORD(ndx),
8769273SAli.Bahrami@Sun.COM 				    conv_cap_tag(c_tag, 0, &inv_buf1));
8775088Sab196087 			} else {
8785088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
8795088Sab196087 				    MSG_INTL(MSG_DEBUG_S_CHG),
8805088Sab196087 				    cap_ndx, cap_name, EC_WORD(ndx),
8819273SAli.Bahrami@Sun.COM 				    conv_cap_tag(cap[ndx].c_tag, 0, &inv_buf1),
8829273SAli.Bahrami@Sun.COM 				    conv_cap_tag(c_tag, 0, &inv_buf2));
8835088Sab196087 				cap[ndx].c_tag = c_tag;
8845088Sab196087 				ret = ELFEDIT_CMDRET_MOD;
8855088Sab196087 			}
8865088Sab196087 		}
8875088Sab196087 		break;
8885088Sab196087 
8895088Sab196087 	case CAP_CMD_T_VALUE:
8905088Sab196087 		{
89111827SRod.Evans@Sun.COM 			Xword c_val;
89211827SRod.Evans@Sun.COM 
89311827SRod.Evans@Sun.COM 			if (argstate.optmask & CAP_OPT_F_STRVAL) {
89411827SRod.Evans@Sun.COM 				argstate_add_str(&argstate, TRUE);
89511827SRod.Evans@Sun.COM 				c_val = elfedit_strtab_insert(obj_state,
89611827SRod.Evans@Sun.COM 				    argstate.str.sec, NULL, argstate.argv[1]);
89711827SRod.Evans@Sun.COM 			} else {
89811827SRod.Evans@Sun.COM 				c_val = (Xword)
89911827SRod.Evans@Sun.COM 				    elfedit_atoui(argstate.argv[1], NULL);
90011827SRod.Evans@Sun.COM 			}
9015088Sab196087 
9025088Sab196087 			if (cap[ndx].c_un.c_val == c_val) {
9035088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
9045088Sab196087 				    MSG_INTL(MSG_DEBUG_X_OK),
9055088Sab196087 				    argstate.cap.sec->sec_shndx,
9065088Sab196087 				    argstate.cap.sec->sec_name,
9075088Sab196087 				    EC_WORD(ndx), EC_XWORD(c_val));
9085088Sab196087 			} else {
9095088Sab196087 				elfedit_msg(ELFEDIT_MSG_DEBUG,
9105088Sab196087 				    MSG_INTL(MSG_DEBUG_X_CHG),
9115088Sab196087 				    argstate.cap.sec->sec_shndx,
9125088Sab196087 				    argstate.cap.sec->sec_name,
9135088Sab196087 				    EC_WORD(ndx), EC_XWORD(cap[ndx].c_un.c_val),
9145088Sab196087 				    EC_XWORD(c_val));
9155088Sab196087 				cap[ndx].c_un.c_val = c_val;
9165088Sab196087 				ret = ELFEDIT_CMDRET_MOD;
9175088Sab196087 			}
9185088Sab196087 		}
9195088Sab196087 		break;
9205088Sab196087 
9215088Sab196087 	case CAP_CMD_T_DELETE:
9225088Sab196087 		{
9235088Sab196087 			Word cnt = (argstate.argc == 1) ? 1 :
9245088Sab196087 			    (Word) elfedit_atoui_range(argstate.argv[1],
92511827SRod.Evans@Sun.COM 			    MSG_ORIG(MSG_STR_COUNT), 1,
92611827SRod.Evans@Sun.COM 			    argstate.cap.grp_end_ndx - ndx + 1, NULL);
9275088Sab196087 			const char *msg_prefix =
9285088Sab196087 			    elfedit_sec_msgprefix(argstate.cap.sec);
9295088Sab196087 
93011827SRod.Evans@Sun.COM 			/*
93111827SRod.Evans@Sun.COM 			 * We want to limit the deleted elements to be
93211827SRod.Evans@Sun.COM 			 * in the range of the current capabilities group,
93311827SRod.Evans@Sun.COM 			 * and for the resulting NULL elements to be inserted
93411827SRod.Evans@Sun.COM 			 * at the end of the group, rather than at the end
93511827SRod.Evans@Sun.COM 			 * of the section. To do this, we set the array length
93611827SRod.Evans@Sun.COM 			 * in the call to the delete function so that it thinks
93711827SRod.Evans@Sun.COM 			 * the array ends with the current group.
93811827SRod.Evans@Sun.COM 			 *
93911827SRod.Evans@Sun.COM 			 * The delete function will catch attempts to delete
94011827SRod.Evans@Sun.COM 			 * past this virtual end, but the error message will
94111827SRod.Evans@Sun.COM 			 * not make sense to the user. In order to prevent that,
94211827SRod.Evans@Sun.COM 			 * we check for the condition here and provide a more
94311827SRod.Evans@Sun.COM 			 * useful error.
94411827SRod.Evans@Sun.COM 			 */
94511827SRod.Evans@Sun.COM 			if ((ndx + cnt - 1) > argstate.cap.grp_end_ndx)
94611827SRod.Evans@Sun.COM 				elfedit_msg(ELFEDIT_MSG_ERR,
94711827SRod.Evans@Sun.COM 				    MSG_INTL(MSG_ERR_GRPARRBNDS), msg_prefix,
94811827SRod.Evans@Sun.COM 				    argstate.cap.grp_start_ndx,
94911827SRod.Evans@Sun.COM 				    argstate.cap.grp_end_ndx,
95011827SRod.Evans@Sun.COM 				    cap_group_id(&argstate));
95111827SRod.Evans@Sun.COM 			elfedit_array_elts_delete(msg_prefix, cap, sizeof (Cap),
95211827SRod.Evans@Sun.COM 			    argstate.cap.grp_end_ndx + 1, ndx, cnt);
9535088Sab196087 			ret = ELFEDIT_CMDRET_MOD;
9545088Sab196087 		}
9555088Sab196087 		break;
9565088Sab196087 
9575088Sab196087 	case CAP_CMD_T_MOVE:
9585088Sab196087 		{
9595088Sab196087 			Cap	save;
9605088Sab196087 			Word	cnt;
9615088Sab196087 			Word	dstndx;
9625088Sab196087 			const char *msg_prefix =
9635088Sab196087 			    elfedit_sec_msgprefix(argstate.cap.sec);
9645088Sab196087 
9655088Sab196087 			dstndx = (Word)
9665088Sab196087 			    elfedit_atoui_range(argstate.argv[1],
96711827SRod.Evans@Sun.COM 			    MSG_ORIG(MSG_STR_DST_INDEX),
96811827SRod.Evans@Sun.COM 			    argstate.cap.grp_start_ndx,
96911827SRod.Evans@Sun.COM 			    argstate.cap.grp_end_ndx, NULL);
9705088Sab196087 			if (argstate.argc == 2) {
9715088Sab196087 				cnt = 1;
9725088Sab196087 			} else {
97311827SRod.Evans@Sun.COM 				Word max;
97411827SRod.Evans@Sun.COM 
97511827SRod.Evans@Sun.COM 				max = argstate.cap.grp_end_ndx -
97611827SRod.Evans@Sun.COM 				    ((ndx > dstndx) ? ndx : dstndx) + 1;
9775088Sab196087 				cnt = (Word) elfedit_atoui_range(
9785088Sab196087 				    argstate.argv[2], MSG_ORIG(MSG_STR_COUNT),
97911827SRod.Evans@Sun.COM 				    1, max, NULL);
9805088Sab196087 			}
98111827SRod.Evans@Sun.COM 
98211827SRod.Evans@Sun.COM 			/*
98311827SRod.Evans@Sun.COM 			 * Moves are required to be self contained within
98411827SRod.Evans@Sun.COM 			 * the bounds of the selected capability group.
98511827SRod.Evans@Sun.COM 			 * The move utility function contains bounds checking,
98611827SRod.Evans@Sun.COM 			 * but is not sub-array aware. Hence, we bounds check
98711827SRod.Evans@Sun.COM 			 * check it here, and then hand of the validated
98811827SRod.Evans@Sun.COM 			 * operation to the move utility function to execute.
98911827SRod.Evans@Sun.COM 			 */
99011827SRod.Evans@Sun.COM 			if ((ndx < argstate.cap.grp_start_ndx) ||
99111827SRod.Evans@Sun.COM 			    ((ndx + cnt) > argstate.cap.grp_end_ndx) ||
99211827SRod.Evans@Sun.COM 			    (dstndx < argstate.cap.grp_start_ndx) ||
99311827SRod.Evans@Sun.COM 			    ((dstndx + cnt) > argstate.cap.grp_end_ndx))
99411827SRod.Evans@Sun.COM 				elfedit_msg(ELFEDIT_MSG_ERR,
99511827SRod.Evans@Sun.COM 				    MSG_INTL(MSG_ERR_GRPARRBNDS), msg_prefix,
99611827SRod.Evans@Sun.COM 				    argstate.cap.grp_start_ndx,
99711827SRod.Evans@Sun.COM 				    argstate.cap.grp_end_ndx,
99811827SRod.Evans@Sun.COM 				    cap_group_id(&argstate));
99911827SRod.Evans@Sun.COM 			elfedit_array_elts_move(msg_prefix, cap, sizeof (save),
100011827SRod.Evans@Sun.COM 			    argstate.cap.grp_end_ndx + 1, ndx, dstndx,
100111827SRod.Evans@Sun.COM 			    cnt, &save);
10025088Sab196087 			ret = ELFEDIT_CMDRET_MOD;
10035088Sab196087 		}
10045088Sab196087 		break;
10055088Sab196087 
10065088Sab196087 
10075088Sab196087 	case CAP_CMD_T_HW1:
10085088Sab196087 		{
100911827SRod.Evans@Sun.COM 			ret = cap_set(&argstate, cap, ndx, cap_ndx, cap_name,
101011827SRod.Evans@Sun.COM 			    CA_SUNW_HW_1, ELFEDIT_CONST_HW1_SUNW);
10115088Sab196087 		}
10125088Sab196087 		break;
10135088Sab196087 
10145088Sab196087 	case CAP_CMD_T_SF1:
10155088Sab196087 		{
101611827SRod.Evans@Sun.COM 			ret = cap_set(&argstate, cap, ndx, cap_ndx, cap_name,
101711827SRod.Evans@Sun.COM 			    CA_SUNW_SF_1, ELFEDIT_CONST_SF1_SUNW);
101811827SRod.Evans@Sun.COM 		}
101911827SRod.Evans@Sun.COM 		break;
10205088Sab196087 
102111827SRod.Evans@Sun.COM 	case CAP_CMD_T_HW2:
102211827SRod.Evans@Sun.COM 		{
102311827SRod.Evans@Sun.COM 			ret = cap_set(&argstate, cap, ndx, cap_ndx, cap_name,
102411827SRod.Evans@Sun.COM 			    CA_SUNW_HW_2, ELFEDIT_CONST_HW2_SUNW);
10255088Sab196087 		}
10265088Sab196087 		break;
10275088Sab196087 	}
10285088Sab196087 
10295088Sab196087 	/*
10305088Sab196087 	 * If we modified the capabilities section header, tell libelf.
10315088Sab196087 	 */
10325088Sab196087 	if (ret == ELFEDIT_CMDRET_MOD)
10335088Sab196087 		elfedit_modified_data(argstate.cap.sec);
10345088Sab196087 
10355088Sab196087 	/* Do autoprint */
10365088Sab196087 	if (do_autoprint)
10375088Sab196087 		print_cap(cmd, 1, &argstate, print_type, ndx);
10385088Sab196087 
10395088Sab196087 	return (ret);
10405088Sab196087 }
10415088Sab196087 
10425088Sab196087 
10435088Sab196087 
10445088Sab196087 /*
10455088Sab196087  * Command completion functions for the commands
10465088Sab196087  */
10475088Sab196087 
10485088Sab196087 /*
104911827SRod.Evans@Sun.COM  * -capid command completion: Supply all CA_SUNW_ID names found in the object.
105011827SRod.Evans@Sun.COM  */
105111827SRod.Evans@Sun.COM static void
cpl_capid_opt(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)105211827SRod.Evans@Sun.COM cpl_capid_opt(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
105311827SRod.Evans@Sun.COM     const char *argv[], int num_opt)
105411827SRod.Evans@Sun.COM {
105511827SRod.Evans@Sun.COM 	elfedit_section_t	*cap_sec, *str_sec;
105611827SRod.Evans@Sun.COM 	Cap			*cap;
105711827SRod.Evans@Sun.COM 	Word			num;
105811827SRod.Evans@Sun.COM 
105911827SRod.Evans@Sun.COM 	if (obj_state == NULL)	 /* No object available */
106011827SRod.Evans@Sun.COM 		return;
106111827SRod.Evans@Sun.COM 
106211827SRod.Evans@Sun.COM 	if ((argc > num_opt) || (argc < 2) ||
106311827SRod.Evans@Sun.COM 	    (strcmp(argv[argc - 2], MSG_ORIG(MSG_STR_MINUS_CAPID)) != 0))
106411827SRod.Evans@Sun.COM 		return;
106511827SRod.Evans@Sun.COM 
106611827SRod.Evans@Sun.COM 	cap_sec = elfedit_sec_getcap(obj_state, &cap, &num);
106711827SRod.Evans@Sun.COM 
106811827SRod.Evans@Sun.COM 	/* If no associated string table, we have no strings to complete */
106911827SRod.Evans@Sun.COM 	if (cap_sec->sec_shdr->sh_info == 0)
107011827SRod.Evans@Sun.COM 		return;
107111827SRod.Evans@Sun.COM 
107211827SRod.Evans@Sun.COM 	str_sec = elfedit_sec_getstr(obj_state, cap_sec->sec_shdr->sh_info, 0);
107311827SRod.Evans@Sun.COM 
107411827SRod.Evans@Sun.COM 	for (; num--; cap++)
107511827SRod.Evans@Sun.COM 		if (cap->c_tag == CA_SUNW_ID)
107611827SRod.Evans@Sun.COM 			elfedit_cpl_match(cpldata, elfedit_offset_to_str(
107711827SRod.Evans@Sun.COM 			    str_sec, cap->c_un.c_val, ELFEDIT_MSG_ERR, 0), 0);
107811827SRod.Evans@Sun.COM }
107911827SRod.Evans@Sun.COM 
108011827SRod.Evans@Sun.COM /*
10815088Sab196087  * Command completion for the first argument, which specifies
10825088Sab196087  * the capabilities element to use. Examines the options to see if
10835088Sab196087  * -capndx is present, and if not, supplies the completion
10845088Sab196087  * strings for argument 1.
10855088Sab196087  */
10865088Sab196087 /*ARGSUSED*/
10875088Sab196087 static void
cpl_eltarg(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)10885088Sab196087 cpl_eltarg(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
10895088Sab196087     const char *argv[], int num_opt)
10905088Sab196087 {
109111827SRod.Evans@Sun.COM 	Word	i;
109211827SRod.Evans@Sun.COM 
109311827SRod.Evans@Sun.COM 	/* -capid id_name */
109411827SRod.Evans@Sun.COM 	if (argc <= num_opt) {
109511827SRod.Evans@Sun.COM 		cpl_capid_opt(obj_state, cpldata, argc, argv, num_opt);
109611827SRod.Evans@Sun.COM 		return;
109711827SRod.Evans@Sun.COM 	}
10985088Sab196087 
10995088Sab196087 	/* Make sure it's the first argument */
11005088Sab196087 	if ((argc - num_opt) != 1)
11015088Sab196087 		return;
11025088Sab196087 
11035088Sab196087 	/* Is -capndx present? If so, we don't complete tag types */
11045088Sab196087 	for (i = 0; i < num_opt; i++)
11055088Sab196087 		if (strcmp(argv[i], MSG_ORIG(MSG_STR_MINUS_CAPNDX)) == 0)
11065088Sab196087 			return;
11075088Sab196087 
11085088Sab196087 	/*
11095088Sab196087 	 * Supply capability tag names. There are very few of these, so
11105088Sab196087 	 * rather than worry about whether a given tag exists in the
11115088Sab196087 	 * file or not, we simply serve up all the possibilities.
11125088Sab196087 	 */
11135088Sab196087 	elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_CA);
11145088Sab196087 }
11155088Sab196087 
11165088Sab196087 /*ARGSUSED*/
11175088Sab196087 static void
cpl_tag(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)11185088Sab196087 cpl_tag(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
11195088Sab196087     const char *argv[], int num_opt)
11205088Sab196087 {
112111827SRod.Evans@Sun.COM 	/* -capid id_name */
112211827SRod.Evans@Sun.COM 	if (argc <= num_opt) {
112311827SRod.Evans@Sun.COM 		cpl_capid_opt(obj_state, cpldata, argc, argv, num_opt);
112411827SRod.Evans@Sun.COM 		return;
112511827SRod.Evans@Sun.COM 	}
112611827SRod.Evans@Sun.COM 
112711827SRod.Evans@Sun.COM 	/* First plain argument */
11285088Sab196087 	if ((argc - num_opt) == 1) {
11295088Sab196087 		cpl_eltarg(obj_state, cpldata, argc, argv, num_opt);
11305088Sab196087 		return;
11315088Sab196087 	}
11325088Sab196087 
11335088Sab196087 	/* The second argument is always a tag value */
11345088Sab196087 	if ((argc - num_opt) == 2)
11355088Sab196087 		elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_CA);
11365088Sab196087 }
11375088Sab196087 
11385088Sab196087 /*ARGSUSED*/
11395088Sab196087 static void
cpl_hw1(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)11405088Sab196087 cpl_hw1(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
11415088Sab196087     const char *argv[], int num_opt)
11425088Sab196087 {
114311827SRod.Evans@Sun.COM 	/* -capid id_name */
114411827SRod.Evans@Sun.COM 	if (argc <= num_opt) {
114511827SRod.Evans@Sun.COM 		cpl_capid_opt(obj_state, cpldata, argc, argv, num_opt);
114611827SRod.Evans@Sun.COM 		return;
114711827SRod.Evans@Sun.COM 	}
11485088Sab196087 
114911827SRod.Evans@Sun.COM 	/* This routine allows multiple flags to be specified */
115011827SRod.Evans@Sun.COM 	elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_HW1_SUNW);
11515088Sab196087 }
11525088Sab196087 
11535088Sab196087 /*ARGSUSED*/
11545088Sab196087 static void
cpl_sf1(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)11555088Sab196087 cpl_sf1(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
11565088Sab196087     const char *argv[], int num_opt)
11575088Sab196087 {
115811827SRod.Evans@Sun.COM 	/* -capid id_name */
115911827SRod.Evans@Sun.COM 	if (argc <= num_opt) {
116011827SRod.Evans@Sun.COM 		cpl_capid_opt(obj_state, cpldata, argc, argv, num_opt);
116111827SRod.Evans@Sun.COM 		return;
116211827SRod.Evans@Sun.COM 	}
116311827SRod.Evans@Sun.COM 
11645088Sab196087 	/* This routine allows multiple flags to be specified */
11655088Sab196087 	elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_SF1_SUNW);
11665088Sab196087 }
11675088Sab196087 
116811827SRod.Evans@Sun.COM /*ARGSUSED*/
116911827SRod.Evans@Sun.COM static void
cpl_hw2(elfedit_obj_state_t * obj_state,void * cpldata,int argc,const char * argv[],int num_opt)117011827SRod.Evans@Sun.COM cpl_hw2(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
117111827SRod.Evans@Sun.COM     const char *argv[], int num_opt)
117211827SRod.Evans@Sun.COM {
117311827SRod.Evans@Sun.COM 	/* -capid id_name */
117411827SRod.Evans@Sun.COM 	if (argc <= num_opt) {
117511827SRod.Evans@Sun.COM 		cpl_capid_opt(obj_state, cpldata, argc, argv, num_opt);
117611827SRod.Evans@Sun.COM 		return;
117711827SRod.Evans@Sun.COM 	}
117811827SRod.Evans@Sun.COM 
117911827SRod.Evans@Sun.COM 	/* This routine allows multiple flags to be specified */
118011827SRod.Evans@Sun.COM 	elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_HW2_SUNW);
118111827SRod.Evans@Sun.COM }
11825088Sab196087 
11835088Sab196087 /*
11845088Sab196087  * Implementation functions for the commands
11855088Sab196087  */
11865088Sab196087 static elfedit_cmdret_t
cmd_dump(elfedit_obj_state_t * obj_state,int argc,const char * argv[])11875088Sab196087 cmd_dump(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
11885088Sab196087 {
11895088Sab196087 	return (cmd_body(CAP_CMD_T_DUMP, obj_state, argc, argv));
11905088Sab196087 }
11915088Sab196087 
11925088Sab196087 static elfedit_cmdret_t
cmd_tag(elfedit_obj_state_t * obj_state,int argc,const char * argv[])11935088Sab196087 cmd_tag(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
11945088Sab196087 {
11955088Sab196087 	return (cmd_body(CAP_CMD_T_TAG, obj_state, argc, argv));
11965088Sab196087 }
11975088Sab196087 
11985088Sab196087 static elfedit_cmdret_t
cmd_value(elfedit_obj_state_t * obj_state,int argc,const char * argv[])11995088Sab196087 cmd_value(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
12005088Sab196087 {
12015088Sab196087 	return (cmd_body(CAP_CMD_T_VALUE, obj_state, argc, argv));
12025088Sab196087 }
12035088Sab196087 
12045088Sab196087 static elfedit_cmdret_t
cmd_delete(elfedit_obj_state_t * obj_state,int argc,const char * argv[])12055088Sab196087 cmd_delete(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
12065088Sab196087 {
12075088Sab196087 	return (cmd_body(CAP_CMD_T_DELETE, obj_state, argc, argv));
12085088Sab196087 }
12095088Sab196087 
12105088Sab196087 static elfedit_cmdret_t
cmd_move(elfedit_obj_state_t * obj_state,int argc,const char * argv[])12115088Sab196087 cmd_move(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
12125088Sab196087 {
12135088Sab196087 	return (cmd_body(CAP_CMD_T_MOVE, obj_state, argc, argv));
12145088Sab196087 }
12155088Sab196087 
12165088Sab196087 static elfedit_cmdret_t
cmd_hw1(elfedit_obj_state_t * obj_state,int argc,const char * argv[])12175088Sab196087 cmd_hw1(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
12185088Sab196087 {
12195088Sab196087 	return (cmd_body(CAP_CMD_T_HW1, obj_state, argc, argv));
12205088Sab196087 }
12215088Sab196087 
12225088Sab196087 static elfedit_cmdret_t
cmd_sf1(elfedit_obj_state_t * obj_state,int argc,const char * argv[])12235088Sab196087 cmd_sf1(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
12245088Sab196087 {
12255088Sab196087 	return (cmd_body(CAP_CMD_T_SF1, obj_state, argc, argv));
12265088Sab196087 }
12275088Sab196087 
122811827SRod.Evans@Sun.COM static elfedit_cmdret_t
cmd_hw2(elfedit_obj_state_t * obj_state,int argc,const char * argv[])122911827SRod.Evans@Sun.COM cmd_hw2(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
123011827SRod.Evans@Sun.COM {
123111827SRod.Evans@Sun.COM 	return (cmd_body(CAP_CMD_T_HW2, obj_state, argc, argv));
123211827SRod.Evans@Sun.COM }
12335088Sab196087 
12345088Sab196087 /*ARGSUSED*/
12355088Sab196087 elfedit_module_t *
elfedit_init(elfedit_module_version_t version)12365088Sab196087 elfedit_init(elfedit_module_version_t version)
12375088Sab196087 {
123811827SRod.Evans@Sun.COM 	/* For commands that only accept -capid, -and, -cmp, -o, and -or */
123911827SRod.Evans@Sun.COM 	static elfedit_cmd_optarg_t opt_ostyle_capid_bitop[] = {
12405088Sab196087 		{ ELFEDIT_STDOA_OPT_AND, NULL,
12415088Sab196087 		    ELFEDIT_CMDOA_F_INHERIT, CAP_OPT_F_AND, CAP_OPT_F_OR },
124211827SRod.Evans@Sun.COM 		{ MSG_ORIG(MSG_STR_MINUS_CAPID),
124311827SRod.Evans@Sun.COM 		    /* MSG_INTL(MSG_OPTDESC_CAPID) */
124411827SRod.Evans@Sun.COM 		    ELFEDIT_I18NHDL(MSG_OPTDESC_CAPID), ELFEDIT_CMDOA_F_VALUE,
124511827SRod.Evans@Sun.COM 		    CAP_OPT_F_CAPID, CAP_OPT_F_CAPNDX },
124611827SRod.Evans@Sun.COM 		{ MSG_ORIG(MSG_STR_IDNAME), NULL, 0 },
12475088Sab196087 		{ ELFEDIT_STDOA_OPT_CMP, NULL,
12485088Sab196087 		    ELFEDIT_CMDOA_F_INHERIT, CAP_OPT_F_CMP, 0 },
12495088Sab196087 		{ ELFEDIT_STDOA_OPT_O, NULL,
12505088Sab196087 		    ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
12515088Sab196087 		{ ELFEDIT_STDOA_OPT_OR, NULL,
12525088Sab196087 		    ELFEDIT_CMDOA_F_INHERIT, CAP_OPT_F_OR, CAP_OPT_F_AND },
12535088Sab196087 		{ NULL }
12545088Sab196087 	};
12555088Sab196087 
125611827SRod.Evans@Sun.COM 	/* For commands that only accept -capid and -capndx */
125711827SRod.Evans@Sun.COM 	static elfedit_cmd_optarg_t opt_capid_capndx[] = {
125811827SRod.Evans@Sun.COM 		{ MSG_ORIG(MSG_STR_MINUS_CAPID),
125911827SRod.Evans@Sun.COM 		    /* MSG_INTL(MSG_OPTDESC_CAPID) */
126011827SRod.Evans@Sun.COM 		    ELFEDIT_I18NHDL(MSG_OPTDESC_CAPID), ELFEDIT_CMDOA_F_VALUE,
126111827SRod.Evans@Sun.COM 		    CAP_OPT_F_CAPID, CAP_OPT_F_CAPNDX },
126211827SRod.Evans@Sun.COM 		{ MSG_ORIG(MSG_STR_IDNAME), NULL, 0 },
12635088Sab196087 		{ MSG_ORIG(MSG_STR_MINUS_CAPNDX),
12645088Sab196087 		    /* MSG_INTL(MSG_OPTDESC_CAPNDX) */
12655088Sab196087 		    ELFEDIT_I18NHDL(MSG_OPTDESC_CAPNDX), 0,
126611827SRod.Evans@Sun.COM 		    CAP_OPT_F_CAPNDX, CAP_OPT_F_CAPID },
12675088Sab196087 		{ NULL }
12685088Sab196087 	};
12695088Sab196087 
12705088Sab196087 
12715088Sab196087 	/* cap:dump */
12725088Sab196087 	static const char *name_dump[] = {
12735088Sab196087 	    MSG_ORIG(MSG_CMD_DUMP),
12745088Sab196087 	    MSG_ORIG(MSG_STR_EMPTY),	/* "" makes this the default command */
12755088Sab196087 	    NULL
12765088Sab196087 	};
12775088Sab196087 	static elfedit_cmd_optarg_t arg_dump[] = {
12785088Sab196087 		{ MSG_ORIG(MSG_STR_ELT),
12795088Sab196087 		    /* MSG_INTL(MSG_ARGDESC_ELT) */
12805088Sab196087 		    ELFEDIT_I18NHDL(MSG_ARGDESC_ELT),
12815088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
12825088Sab196087 		{ NULL }
12835088Sab196087 	};
12845088Sab196087 
12855088Sab196087 
12865088Sab196087 	/* cap:tag */
12875088Sab196087 	static const char *name_tag[] = { MSG_ORIG(MSG_CMD_TAG), NULL };
128811827SRod.Evans@Sun.COM 	static elfedit_cmd_optarg_t opt_tag[] = {
128911827SRod.Evans@Sun.COM 		{ MSG_ORIG(MSG_STR_MINUS_CAPID),
129011827SRod.Evans@Sun.COM 		    /* MSG_INTL(MSG_OPTDESC_CAPID) */
129111827SRod.Evans@Sun.COM 		    ELFEDIT_I18NHDL(MSG_OPTDESC_CAPID), ELFEDIT_CMDOA_F_VALUE,
129211827SRod.Evans@Sun.COM 		    CAP_OPT_F_CAPID, CAP_OPT_F_CAPNDX },
129311827SRod.Evans@Sun.COM 		{ MSG_ORIG(MSG_STR_IDNAME), NULL, 0 },
129411827SRod.Evans@Sun.COM 		{ MSG_ORIG(MSG_STR_MINUS_CAPNDX),
129511827SRod.Evans@Sun.COM 		    /* MSG_INTL(MSG_OPTDESC_CAPNDX) */
129611827SRod.Evans@Sun.COM 		    ELFEDIT_I18NHDL(MSG_OPTDESC_CAPNDX), 0,
129711827SRod.Evans@Sun.COM 		    CAP_OPT_F_CAPNDX, 0 },
129811827SRod.Evans@Sun.COM 		{ ELFEDIT_STDOA_OPT_O, NULL,
129911827SRod.Evans@Sun.COM 		    ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
130011827SRod.Evans@Sun.COM 		{ NULL }
130111827SRod.Evans@Sun.COM 	};
13025088Sab196087 	static elfedit_cmd_optarg_t arg_tag[] = {
13035088Sab196087 		{ MSG_ORIG(MSG_STR_ELT),
13045088Sab196087 		    /* MSG_INTL(MSG_A1_TAG_ELT) */
13055088Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_TAG_ELT),
13065088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
13075088Sab196087 		{ MSG_ORIG(MSG_STR_VALUE),
13085088Sab196087 		    /* MSG_INTL(MSG_A2_TAG_VALUE) */
13095088Sab196087 		    ELFEDIT_I18NHDL(MSG_A2_TAG_VALUE),
13105088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
13115088Sab196087 		{ NULL }
13125088Sab196087 	};
13135088Sab196087 
13145088Sab196087 
13155088Sab196087 	/* cap:value */
13165088Sab196087 	static const char *name_value[] = { MSG_ORIG(MSG_CMD_VALUE), NULL };
131711827SRod.Evans@Sun.COM 	static elfedit_cmd_optarg_t opt_value[] = {
131811827SRod.Evans@Sun.COM 		{ MSG_ORIG(MSG_STR_MINUS_CAPID),
131911827SRod.Evans@Sun.COM 		    /* MSG_INTL(MSG_OPTDESC_CAPID) */
132011827SRod.Evans@Sun.COM 		    ELFEDIT_I18NHDL(MSG_OPTDESC_CAPID), ELFEDIT_CMDOA_F_VALUE,
132111827SRod.Evans@Sun.COM 		    CAP_OPT_F_CAPID, CAP_OPT_F_CAPNDX },
132211827SRod.Evans@Sun.COM 		{ MSG_ORIG(MSG_STR_IDNAME), NULL, 0 },
132311827SRod.Evans@Sun.COM 		{ MSG_ORIG(MSG_STR_MINUS_CAPNDX),
132411827SRod.Evans@Sun.COM 		    /* MSG_INTL(MSG_OPTDESC_CAPNDX) */
132511827SRod.Evans@Sun.COM 		    ELFEDIT_I18NHDL(MSG_OPTDESC_CAPNDX), 0,
132611827SRod.Evans@Sun.COM 		    CAP_OPT_F_CAPNDX, 0 },
132711827SRod.Evans@Sun.COM 		{ ELFEDIT_STDOA_OPT_O, NULL,
132811827SRod.Evans@Sun.COM 		    ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
132911827SRod.Evans@Sun.COM 		{ MSG_ORIG(MSG_STR_MINUS_S),
133011827SRod.Evans@Sun.COM 		    /* MSG_INTL(MSG_OPTDESC_S) */
133111827SRod.Evans@Sun.COM 		    ELFEDIT_I18NHDL(MSG_OPTDESC_S), 0,
133211827SRod.Evans@Sun.COM 		    CAP_OPT_F_STRVAL, 0 },
133311827SRod.Evans@Sun.COM 		{ NULL }
133411827SRod.Evans@Sun.COM 	};
13355088Sab196087 	static elfedit_cmd_optarg_t arg_value[] = {
13365088Sab196087 		{ MSG_ORIG(MSG_STR_ELT),
13375088Sab196087 		    /* MSG_INTL(MSG_ARGDESC_ELT) */
13385088Sab196087 		    ELFEDIT_I18NHDL(MSG_ARGDESC_ELT),
13395088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
13405088Sab196087 		{ MSG_ORIG(MSG_STR_VALUE),
13415088Sab196087 		    /* MSG_INTL(MSG_A2_VALUE_VALUE) */
13425088Sab196087 		    ELFEDIT_I18NHDL(MSG_A2_VALUE_VALUE),
13435088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
13445088Sab196087 		{ NULL }
13455088Sab196087 	};
13465088Sab196087 
13475088Sab196087 	/* cap:delete */
13485088Sab196087 	static const char *name_delete[] = { MSG_ORIG(MSG_CMD_DELETE), NULL };
13495088Sab196087 	static elfedit_cmd_optarg_t arg_delete[] = {
13505088Sab196087 		{ MSG_ORIG(MSG_STR_ELT),
13515088Sab196087 		    /* MSG_INTL(MSG_ARGDESC_ELT) */
13525088Sab196087 		    ELFEDIT_I18NHDL(MSG_ARGDESC_ELT),
13535088Sab196087 		    0 },
13545088Sab196087 		{ MSG_ORIG(MSG_STR_COUNT),
13555088Sab196087 		    /* MSG_INTL(MSG_A2_DELETE_COUNT) */
13565088Sab196087 		    ELFEDIT_I18NHDL(MSG_A2_DELETE_COUNT),
13575088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
13585088Sab196087 		{ NULL }
13595088Sab196087 	};
13605088Sab196087 
13615088Sab196087 	/* cap:move */
13625088Sab196087 	static const char *name_move[] = { MSG_ORIG(MSG_CMD_MOVE), NULL };
13635088Sab196087 	static elfedit_cmd_optarg_t arg_move[] = {
13645088Sab196087 		{ MSG_ORIG(MSG_STR_ELT),
13655088Sab196087 		    /* MSG_INTL(MSG_ARGDESC_ELT) */
13665088Sab196087 		    ELFEDIT_I18NHDL(MSG_ARGDESC_ELT),
13675088Sab196087 		    0 },
13685088Sab196087 		{ MSG_ORIG(MSG_STR_DST_INDEX),
13695088Sab196087 		    /* MSG_INTL(MSG_A2_MOVE_DST_INDEX) */
13705088Sab196087 		    ELFEDIT_I18NHDL(MSG_A2_MOVE_DST_INDEX),
13715088Sab196087 		    0 },
13725088Sab196087 		{ MSG_ORIG(MSG_STR_COUNT),
13735088Sab196087 		    /* MSG_INTL(MSG_A3_MOVE_COUNT) */
13745088Sab196087 		    ELFEDIT_I18NHDL(MSG_A3_MOVE_COUNT),
13755088Sab196087 		    ELFEDIT_CMDOA_F_OPT },
13765088Sab196087 		{ NULL }
13775088Sab196087 	};
13785088Sab196087 
13795088Sab196087 	/* cap:hw1 */
13805088Sab196087 	static const char *name_hw1[] = { MSG_ORIG(MSG_CMD_HW1), NULL };
13815088Sab196087 	static elfedit_cmd_optarg_t arg_hw1[] = {
13825088Sab196087 		{ MSG_ORIG(MSG_STR_VALUE),
13835088Sab196087 		    /* MSG_INTL(MSG_A1_HW1_VALUE) */
13845088Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_HW1_VALUE),
13855088Sab196087 		    ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT },
13865088Sab196087 		{ NULL }
13875088Sab196087 	};
13885088Sab196087 
13895088Sab196087 	/* cap:sf1 */
13905088Sab196087 	static const char *name_sf1[] = { MSG_ORIG(MSG_CMD_SF1), NULL };
13915088Sab196087 	static elfedit_cmd_optarg_t arg_sf1[] = {
13925088Sab196087 		{ MSG_ORIG(MSG_STR_VALUE),
13935088Sab196087 		    /* MSG_INTL(MSG_A1_SF1_VALUE) */
13945088Sab196087 		    ELFEDIT_I18NHDL(MSG_A1_SF1_VALUE),
13955088Sab196087 		    ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT },
13965088Sab196087 		{ NULL }
13975088Sab196087 	};
13985088Sab196087 
139911827SRod.Evans@Sun.COM 	/* cap:hw2 */
140011827SRod.Evans@Sun.COM 	static const char *name_hw2[] = { MSG_ORIG(MSG_CMD_HW2), NULL };
140111827SRod.Evans@Sun.COM 	static elfedit_cmd_optarg_t arg_hw2[] = {
140211827SRod.Evans@Sun.COM 		{ MSG_ORIG(MSG_STR_VALUE),
140311827SRod.Evans@Sun.COM 		    /* MSG_INTL(MSG_A1_HW2_VALUE) */
140411827SRod.Evans@Sun.COM 		    ELFEDIT_I18NHDL(MSG_A1_HW2_VALUE),
140511827SRod.Evans@Sun.COM 		    ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT },
140611827SRod.Evans@Sun.COM 		{ NULL }
140711827SRod.Evans@Sun.COM 	};
14085088Sab196087 
14095088Sab196087 
14105088Sab196087 	static elfedit_cmd_t cmds[] = {
14115088Sab196087 		/* cap:dump */
14125088Sab196087 		{ cmd_dump, cpl_eltarg, name_dump,
14135088Sab196087 		    /* MSG_INTL(MSG_DESC_DUMP) */
14145088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_DUMP),
14155088Sab196087 		    /* MSG_INTL(MSG_HELP_DUMP) */
14165088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_DUMP),
141711827SRod.Evans@Sun.COM 		    opt_capid_capndx, arg_dump },
14185088Sab196087 
14195088Sab196087 		/* cap:tag */
14205088Sab196087 		{ cmd_tag, cpl_tag, name_tag,
14215088Sab196087 		    /* MSG_INTL(MSG_DESC_TAG) */
14225088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_TAG),
14235088Sab196087 		    /* MSG_INTL(MSG_HELP_TAG) */
14245088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_TAG),
142511827SRod.Evans@Sun.COM 		    opt_tag, arg_tag },
14265088Sab196087 
14275088Sab196087 		/* cap:value */
14285088Sab196087 		{ cmd_value, cpl_eltarg, name_value,
14295088Sab196087 		    /* MSG_INTL(MSG_DESC_VALUE) */
14305088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_VALUE),
14315088Sab196087 		    /* MSG_INTL(MSG_HELP_VALUE) */
14325088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_VALUE),
143311827SRod.Evans@Sun.COM 		    opt_value, arg_value },
14345088Sab196087 
14355088Sab196087 		/* cap:delete */
14365088Sab196087 		{ cmd_delete, cpl_eltarg, name_delete,
14375088Sab196087 		    /* MSG_INTL(MSG_DESC_DELETE) */
14385088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_DELETE),
14395088Sab196087 		    /* MSG_INTL(MSG_HELP_DELETE) */
14405088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_DELETE),
144111827SRod.Evans@Sun.COM 		    opt_capid_capndx, arg_delete },
14425088Sab196087 
14435088Sab196087 		/* cap:move */
14445088Sab196087 		{ cmd_move, cpl_eltarg, name_move,
14455088Sab196087 		    /* MSG_INTL(MSG_DESC_MOVE) */
14465088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_MOVE),
14475088Sab196087 		    /* MSG_INTL(MSG_HELP_MOVE) */
14485088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_MOVE),
144911827SRod.Evans@Sun.COM 		    opt_capid_capndx, arg_move },
14505088Sab196087 
14515088Sab196087 		/* cap:hw1 */
14525088Sab196087 		{ cmd_hw1, cpl_hw1, name_hw1,
14535088Sab196087 		    /* MSG_INTL(MSG_DESC_HW1) */
14545088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_HW1),
14555088Sab196087 		    /* MSG_INTL(MSG_HELP_HW1) */
14565088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_HW1),
145711827SRod.Evans@Sun.COM 		    opt_ostyle_capid_bitop, arg_hw1 },
14585088Sab196087 
14595088Sab196087 		/* cap:sf1 */
14605088Sab196087 		{ cmd_sf1, cpl_sf1, name_sf1,
14615088Sab196087 		    /* MSG_INTL(MSG_DESC_SF1) */
14625088Sab196087 		    ELFEDIT_I18NHDL(MSG_DESC_SF1),
14635088Sab196087 		    /* MSG_INTL(MSG_HELP_SF1) */
14645088Sab196087 		    ELFEDIT_I18NHDL(MSG_HELP_SF1),
146511827SRod.Evans@Sun.COM 		    opt_ostyle_capid_bitop, arg_sf1 },
146611827SRod.Evans@Sun.COM 
146711827SRod.Evans@Sun.COM 		/* cap:hw2 */
146811827SRod.Evans@Sun.COM 		{ cmd_hw2, cpl_hw2, name_hw2,
146911827SRod.Evans@Sun.COM 		    /* MSG_INTL(MSG_DESC_HW2) */
147011827SRod.Evans@Sun.COM 		    ELFEDIT_I18NHDL(MSG_DESC_HW2),
147111827SRod.Evans@Sun.COM 		    /* MSG_INTL(MSG_HELP_HW2) */
147211827SRod.Evans@Sun.COM 		    ELFEDIT_I18NHDL(MSG_HELP_HW2),
147311827SRod.Evans@Sun.COM 		    opt_ostyle_capid_bitop, arg_hw2 },
14745088Sab196087 
14755088Sab196087 		{ NULL }
14765088Sab196087 	};
14775088Sab196087 
14785088Sab196087 	static elfedit_module_t module = {
14795088Sab196087 	    ELFEDIT_VER_CURRENT, MSG_ORIG(MSG_MOD_NAME),
14805088Sab196087 	    /* MSG_INTL(MSG_MOD_DESC) */
14815088Sab196087 	    ELFEDIT_I18NHDL(MSG_MOD_DESC),
14825088Sab196087 	    cmds, mod_i18nhdl_to_str };
14835088Sab196087 
14845088Sab196087 	return (&module);
14855088Sab196087 }
1486