|  | @@ -25,6 +25,7 @@
 | 
		
	
		
			
			| 25 | 25 |  #include <ipxe/settings.h>
 | 
		
	
		
			
			| 26 | 26 |  #include <ipxe/command.h>
 | 
		
	
		
			
			| 27 | 27 |  #include <ipxe/parseopt.h>
 | 
		
	
		
			
			|  | 28 | +#include <readline/readline.h>
 | 
		
	
		
			
			| 28 | 29 |  
 | 
		
	
		
			
			| 29 | 30 |  FILE_LICENCE ( GPL2_OR_LATER );
 | 
		
	
		
			
			| 30 | 31 |  
 | 
		
	
	
		
			
			|  | @@ -80,48 +81,54 @@ static int show_exec ( int argc, char **argv ) {
 | 
		
	
		
			
			| 80 | 81 |  	return 0;
 | 
		
	
		
			
			| 81 | 82 |  }
 | 
		
	
		
			
			| 82 | 83 |  
 | 
		
	
		
			
			| 83 |  | -/** "set" options */
 | 
		
	
		
			
			| 84 |  | -struct set_options {};
 | 
		
	
		
			
			|  | 84 | +/** "set", "clear", and "read" options */
 | 
		
	
		
			
			|  | 85 | +struct set_core_options {};
 | 
		
	
		
			
			| 85 | 86 |  
 | 
		
	
		
			
			| 86 |  | -/** "set" option list */
 | 
		
	
		
			
			| 87 |  | -static struct option_descriptor set_opts[] = {};
 | 
		
	
		
			
			|  | 87 | +/** "set", "clear", and "read" option list */
 | 
		
	
		
			
			|  | 88 | +static struct option_descriptor set_core_opts[] = {};
 | 
		
	
		
			
			| 88 | 89 |  
 | 
		
	
		
			
			| 89 | 90 |  /** "set" command descriptor */
 | 
		
	
		
			
			| 90 | 91 |  static struct command_descriptor set_cmd =
 | 
		
	
		
			
			| 91 |  | -	COMMAND_DESC ( struct set_options, set_opts, 1, MAX_ARGUMENTS,
 | 
		
	
		
			
			|  | 92 | +	COMMAND_DESC ( struct set_core_options, set_core_opts, 1, MAX_ARGUMENTS,
 | 
		
	
		
			
			| 92 | 93 |  		       "<setting> <value>" );
 | 
		
	
		
			
			| 93 | 94 |  
 | 
		
	
		
			
			|  | 95 | +/** "clear" and "read" command descriptor */
 | 
		
	
		
			
			|  | 96 | +static struct command_descriptor clear_read_cmd =
 | 
		
	
		
			
			|  | 97 | +	COMMAND_DESC ( struct set_core_options, set_core_opts, 1, 1,
 | 
		
	
		
			
			|  | 98 | +		       "<setting>" );
 | 
		
	
		
			
			|  | 99 | +
 | 
		
	
		
			
			| 94 | 100 |  /**
 | 
		
	
		
			
			| 95 |  | - * "set" command
 | 
		
	
		
			
			|  | 101 | + * "set", "clear", and "read" command
 | 
		
	
		
			
			| 96 | 102 |   *
 | 
		
	
		
			
			| 97 | 103 |   * @v argc		Argument count
 | 
		
	
		
			
			| 98 | 104 |   * @v argv		Argument list
 | 
		
	
		
			
			|  | 105 | + * @v cmd		Command descriptor
 | 
		
	
		
			
			|  | 106 | + * @v get_value		Method to obtain setting value
 | 
		
	
		
			
			| 99 | 107 |   * @ret rc		Return status code
 | 
		
	
		
			
			| 100 | 108 |   */
 | 
		
	
		
			
			| 101 |  | -static int set_exec ( int argc, char **argv ) {
 | 
		
	
		
			
			| 102 |  | -	struct set_options opts;
 | 
		
	
		
			
			|  | 109 | +static int set_core_exec ( int argc, char **argv,
 | 
		
	
		
			
			|  | 110 | +			   struct command_descriptor *cmd,
 | 
		
	
		
			
			|  | 111 | +			   int ( * get_value ) ( char **args, char **value ) ) {
 | 
		
	
		
			
			|  | 112 | +	struct set_core_options opts;
 | 
		
	
		
			
			| 103 | 113 |  	const char *name;
 | 
		
	
		
			
			| 104 | 114 |  	char *value;
 | 
		
	
		
			
			| 105 | 115 |  	int rc;
 | 
		
	
		
			
			| 106 | 116 |  
 | 
		
	
		
			
			| 107 | 117 |  	/* Parse options */
 | 
		
	
		
			
			| 108 |  | -	if ( ( rc = parse_options ( argc, argv, &set_cmd, &opts ) ) != 0 )
 | 
		
	
		
			
			|  | 118 | +	if ( ( rc = parse_options ( argc, argv, cmd, &opts ) ) != 0 )
 | 
		
	
		
			
			| 109 | 119 |  		goto err_parse_options;
 | 
		
	
		
			
			| 110 | 120 |  
 | 
		
	
		
			
			| 111 | 121 |  	/* Parse setting name */
 | 
		
	
		
			
			| 112 | 122 |  	name = argv[optind];
 | 
		
	
		
			
			| 113 | 123 |  
 | 
		
	
		
			
			| 114 | 124 |  	/* Parse setting value */
 | 
		
	
		
			
			| 115 |  | -	value = concat_args ( &argv[ optind + 1 ] );
 | 
		
	
		
			
			| 116 |  | -	if ( ! value ) {
 | 
		
	
		
			
			| 117 |  | -		rc = -ENOMEM;
 | 
		
	
		
			
			| 118 |  | -		goto err_concat_args;
 | 
		
	
		
			
			| 119 |  | -	}
 | 
		
	
		
			
			|  | 125 | +	if ( ( rc = get_value ( &argv[ optind + 1 ], &value ) ) != 0 )
 | 
		
	
		
			
			|  | 126 | +		goto err_get_value;
 | 
		
	
		
			
			| 120 | 127 |  
 | 
		
	
		
			
			| 121 | 128 |  	/* Determine total length of command line */
 | 
		
	
		
			
			| 122 | 129 |  	if ( ( rc = storef_named_setting ( name, value ) ) != 0 ) {
 | 
		
	
		
			
			| 123 |  | -		printf ( "Could not set \"%s\"=\"%s\": %s\n",
 | 
		
	
		
			
			| 124 |  | -			 name, value, strerror ( rc ) );
 | 
		
	
		
			
			|  | 130 | +		printf ( "Could not %s \"%s\": %s\n",
 | 
		
	
		
			
			|  | 131 | +			 argv[0], name, strerror ( rc ) );
 | 
		
	
		
			
			| 125 | 132 |  		goto err_store;
 | 
		
	
		
			
			| 126 | 133 |  	}
 | 
		
	
		
			
			| 127 | 134 |  
 | 
		
	
	
		
			
			|  | @@ -130,20 +137,50 @@ static int set_exec ( int argc, char **argv ) {
 | 
		
	
		
			
			| 130 | 137 |  
 | 
		
	
		
			
			| 131 | 138 |   err_store:
 | 
		
	
		
			
			| 132 | 139 |  	free ( value );
 | 
		
	
		
			
			| 133 |  | - err_concat_args:
 | 
		
	
		
			
			|  | 140 | + err_get_value:
 | 
		
	
		
			
			| 134 | 141 |   err_parse_options:
 | 
		
	
		
			
			| 135 | 142 |  	return rc;
 | 
		
	
		
			
			| 136 | 143 |  }
 | 
		
	
		
			
			| 137 | 144 |  
 | 
		
	
		
			
			| 138 |  | -/** "clear" options */
 | 
		
	
		
			
			| 139 |  | -struct clear_options {};
 | 
		
	
		
			
			|  | 145 | +/**
 | 
		
	
		
			
			|  | 146 | + * Get setting value for "set" command
 | 
		
	
		
			
			|  | 147 | + *
 | 
		
	
		
			
			|  | 148 | + * @v args		Remaining arguments
 | 
		
	
		
			
			|  | 149 | + * @ret value		Setting value
 | 
		
	
		
			
			|  | 150 | + * @ret rc		Return status code
 | 
		
	
		
			
			|  | 151 | + */
 | 
		
	
		
			
			|  | 152 | +static int set_value ( char **args, char **value ) {
 | 
		
	
		
			
			|  | 153 | +
 | 
		
	
		
			
			|  | 154 | +	*value = concat_args ( args );
 | 
		
	
		
			
			|  | 155 | +	if ( ! *value )
 | 
		
	
		
			
			|  | 156 | +		return -ENOMEM;
 | 
		
	
		
			
			|  | 157 | +
 | 
		
	
		
			
			|  | 158 | +	return 0;
 | 
		
	
		
			
			|  | 159 | +}
 | 
		
	
		
			
			|  | 160 | +
 | 
		
	
		
			
			|  | 161 | +/**
 | 
		
	
		
			
			|  | 162 | + * "set" command
 | 
		
	
		
			
			|  | 163 | + *
 | 
		
	
		
			
			|  | 164 | + * @v argc		Argument count
 | 
		
	
		
			
			|  | 165 | + * @v argv		Argument list
 | 
		
	
		
			
			|  | 166 | + * @ret rc		Return status code
 | 
		
	
		
			
			|  | 167 | + */
 | 
		
	
		
			
			|  | 168 | +static int set_exec ( int argc, char **argv ) {
 | 
		
	
		
			
			|  | 169 | +	return set_core_exec ( argc, argv, &set_cmd, set_value );
 | 
		
	
		
			
			|  | 170 | +}
 | 
		
	
		
			
			| 140 | 171 |  
 | 
		
	
		
			
			| 141 |  | -/** "clear" option list */
 | 
		
	
		
			
			| 142 |  | -static struct option_descriptor clear_opts[] = {};
 | 
		
	
		
			
			|  | 172 | +/**
 | 
		
	
		
			
			|  | 173 | + * Get setting value for "clear" command
 | 
		
	
		
			
			|  | 174 | + *
 | 
		
	
		
			
			|  | 175 | + * @v args		Remaining arguments
 | 
		
	
		
			
			|  | 176 | + * @ret value		Setting value
 | 
		
	
		
			
			|  | 177 | + * @ret rc		Return status code
 | 
		
	
		
			
			|  | 178 | + */
 | 
		
	
		
			
			|  | 179 | +static int clear_value ( char **args __unused, char **value ) {
 | 
		
	
		
			
			| 143 | 180 |  
 | 
		
	
		
			
			| 144 |  | -/** "clear" command descriptor */
 | 
		
	
		
			
			| 145 |  | -static struct command_descriptor clear_cmd =
 | 
		
	
		
			
			| 146 |  | -	COMMAND_DESC ( struct clear_options, clear_opts, 1, 1, "<setting>" );
 | 
		
	
		
			
			|  | 181 | +	*value = NULL;
 | 
		
	
		
			
			|  | 182 | +	return 0;
 | 
		
	
		
			
			|  | 183 | +}
 | 
		
	
		
			
			| 147 | 184 |  
 | 
		
	
		
			
			| 148 | 185 |  /**
 | 
		
	
		
			
			| 149 | 186 |   * "clear" command
 | 
		
	
	
		
			
			|  | @@ -153,27 +190,35 @@ static struct command_descriptor clear_cmd =
 | 
		
	
		
			
			| 153 | 190 |   * @ret rc		Return status code
 | 
		
	
		
			
			| 154 | 191 |   */
 | 
		
	
		
			
			| 155 | 192 |  static int clear_exec ( int argc, char **argv ) {
 | 
		
	
		
			
			| 156 |  | -	struct clear_options opts;
 | 
		
	
		
			
			| 157 |  | -	const char *name;
 | 
		
	
		
			
			| 158 |  | -	int rc;
 | 
		
	
		
			
			|  | 193 | +	return set_core_exec ( argc, argv, &clear_read_cmd, clear_value );
 | 
		
	
		
			
			|  | 194 | +}
 | 
		
	
		
			
			| 159 | 195 |  
 | 
		
	
		
			
			| 160 |  | -	/* Parse options */
 | 
		
	
		
			
			| 161 |  | -	if ( ( rc = parse_options ( argc, argv, &clear_cmd, &opts ) ) != 0 )
 | 
		
	
		
			
			| 162 |  | -		return rc;
 | 
		
	
		
			
			|  | 196 | +/**
 | 
		
	
		
			
			|  | 197 | + * Get setting value for "read" command
 | 
		
	
		
			
			|  | 198 | + *
 | 
		
	
		
			
			|  | 199 | + * @ret value		Setting value
 | 
		
	
		
			
			|  | 200 | + * @ret rc		Return status code
 | 
		
	
		
			
			|  | 201 | + */
 | 
		
	
		
			
			|  | 202 | +static int read_value ( char **args __unused, char **value ) {
 | 
		
	
		
			
			| 163 | 203 |  
 | 
		
	
		
			
			| 164 |  | -	/* Parse setting name */
 | 
		
	
		
			
			| 165 |  | -	name = argv[optind];
 | 
		
	
		
			
			|  | 204 | +	*value = readline ( NULL );
 | 
		
	
		
			
			|  | 205 | +	if ( ! *value )
 | 
		
	
		
			
			|  | 206 | +		return -ENOMEM;
 | 
		
	
		
			
			| 166 | 207 |  
 | 
		
	
		
			
			| 167 |  | -	/* Clear setting */
 | 
		
	
		
			
			| 168 |  | -	if ( ( rc = delete_named_setting ( name ) ) != 0 ) {
 | 
		
	
		
			
			| 169 |  | -		printf ( "Could not clear \"%s\": %s\n",
 | 
		
	
		
			
			| 170 |  | -			 name, strerror ( rc ) );
 | 
		
	
		
			
			| 171 |  | -		return rc;
 | 
		
	
		
			
			| 172 |  | -	}
 | 
		
	
		
			
			| 173 |  | -	
 | 
		
	
		
			
			| 174 | 208 |  	return 0;
 | 
		
	
		
			
			| 175 | 209 |  }
 | 
		
	
		
			
			| 176 | 210 |  
 | 
		
	
		
			
			|  | 211 | +/**
 | 
		
	
		
			
			|  | 212 | + * "read" command
 | 
		
	
		
			
			|  | 213 | + *
 | 
		
	
		
			
			|  | 214 | + * @v argc		Argument count
 | 
		
	
		
			
			|  | 215 | + * @v argv		Argument list
 | 
		
	
		
			
			|  | 216 | + * @ret rc		Return status code
 | 
		
	
		
			
			|  | 217 | + */
 | 
		
	
		
			
			|  | 218 | +static int read_exec ( int argc, char **argv ) {
 | 
		
	
		
			
			|  | 219 | +	return set_core_exec ( argc, argv, &clear_read_cmd, read_value );
 | 
		
	
		
			
			|  | 220 | +}
 | 
		
	
		
			
			|  | 221 | +
 | 
		
	
		
			
			| 177 | 222 |  /** Non-volatile option commands */
 | 
		
	
		
			
			| 178 | 223 |  struct command nvo_commands[] __command = {
 | 
		
	
		
			
			| 179 | 224 |  	{
 | 
		
	
	
		
			
			|  | @@ -188,4 +233,8 @@ struct command nvo_commands[] __command = {
 | 
		
	
		
			
			| 188 | 233 |  		.name = "clear",
 | 
		
	
		
			
			| 189 | 234 |  		.exec = clear_exec,
 | 
		
	
		
			
			| 190 | 235 |  	},
 | 
		
	
		
			
			|  | 236 | +	{
 | 
		
	
		
			
			|  | 237 | +		.name = "read",
 | 
		
	
		
			
			|  | 238 | +		.exec = read_exec,
 | 
		
	
		
			
			|  | 239 | +	},
 | 
		
	
		
			
			| 191 | 240 |  };
 |