/*
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/*
* fbc_getargs - Program command line processing
*/
#include <stdio.h> /* fprintf(), fputs() */
#include <stdlib.h> /* exit(), malloc(), strtof(), strtol() */
#include <string.h> /* strchr(), strcmp(), strlen() */
#include <unistd.h> /* issetugid() */
#include "fbc.h" /* Common fbconf_xorg(1M) definitions */
#include "fbc_error.h" /* Error reporting */
#include "fbc_getargs.h" /* Program command line processing */
#include "fbc_keywds.h" /* Command line keyword look-up */
#include "fbc_properties.h" /* fbconf_xorg(1M) program properties */
#include "fbc_res.h" /* Video modes/resolutions (-res option) */
#include "fbc_xorg.h" /* Edit config file data representations */
/*
* fbc_search_optvals()
*
* Look up the keyword that has been provided as the value for a
* command line option.
*/
void
const char * const option_name, /* Command line option name */
const char * const option_value, /* Keyword string to look up */
{
int i; /* Loop counter / array index */
/*
* Look up the option value keyword
*/
sizeof (keywd_int_t),
(const void **)match_ent_ptr);
if (error_code != FBC_SUCCESS) {
if (error_code == FBC_ERR_KWD_INVALID) {
/*
*/
fbc_errormsg("Invalid value for -%s option: %s\n",
keywd_table[i].argv_name);
}
} else {
/*
* Handle an ambiguous abbreviation of a value keyword
*/
fbc_errormsg("Ambiguous value for -%s option.\n",
fbc_print_matching_keywds((void *)keywd_table,
sizeof (keywd_int_t),
}
}
} /* fbc_search_optvals() */
/*
* fbc_add_Option_mod()
*
* Add a config Option entry description to the .Option_mods[] array.
*
* Reject conflicting Option values and consolidate duplicate
* descriptions. (Among other things, duplicates raise the
* possibility overfilling the .Option_mods[] array).
*
* Currently supported are Option entries having no value or a single
* value.
*
* Use fbvar->modify_config to show that the specified section of
* the configuration file is to be modified.
*/
int
const char *option_name, /* Option entry name string */
const char *option_value, /* Option entry value string */
/* strcmp(), strcasecmp(), etc. */
{
int i; /* Loop counter / array subscript */
/*
* A NULL Option description pointer can be returned in case of error
*/
if (option_mod_p == NULL) {
/*
* If the caller doesn't want this result, discard it someplace
*/
}
*option_mod_p = NULL;
/*
* Taking this code path shows intent to modify a config file section
*/
/*
* See if this Option was specified already and if the values conflict
*/
/*
* Compare the config sections and Option names
*
* Differences in alphabetic case aren't expected,
* but are possible if our tables are constructed
* carelessly. XFree86-style insensitivity to
* whitespace and underscores could be supported,
* should that become an issue.
*/
/*
* Compare the Option values or absence thereof
*
* Our caller has provided strcmp_fn that
* does case-insensitive comparisons for
* keywords, or that does case sensitive
* comparisons for other values such as
* pathnames. Whitespace- and underscore-
* sensitivity could also be controlled in
* this way.
*/
if ((option_value != NULL) ||
if ((option_value == NULL) ||
/* NULL and non-NULL conflict */
return (FBC_ERR_OPT_CONFLICT);
}
!= 0) {
/* Value strings don't match */
return (FBC_ERR_OPT_CONFLICT);
}
}
/*
* Option name and value have been specified already
*/
return (FBC_SUCCESS);
}
}
/*
* Point to the next available Option entry description slot
*
* Leave space for the array terminator element.
*/
fbc_errormsg("Internal error; array bound exceeded\n");
}
/*
* Fill in the Option entry description
*/
return (FBC_SUCCESS);
} /* fbc_add_Option_mod() */
/*
* fbc_add_radio_Option_mod()
*
* Add a config Option entry description to the .Option_mods[] array.
* If this and other Options are ganged together in radio button
* fashion (e.g., if one's value is set to True then all others' must
* be False) then reset the values of the other Options when
* necesary. Note that these Options are all assumed to belong to
* the same, single section of the configuration file.
*
* If the Option value is a keyword, look up the command line
* argument and convert it to its config file form.
*
* For all Option descriptions that are to be added, reject
* conflicting Option values and consolidate duplicate descriptions.
*/
void
const char *option_reset_value, /* Opt reset keyword, else NULL */
char * const argv[], /* Program argument vector */
int arg, /* Program argument subscript */
const void *fbopt_descr, /* Ptr to cmd line option descr */
{
/* strcmp(), strcasecmp(), etc. */
/*
* See whether the config Option value involves a keyword look-up
*/
if (keywd_table != NULL) {
/*
* Validate the config Option's keyword value
*/
/*
* Get the Option value as it will appear in the config file
*
* If the .conf_name hasn't been provided (e.g.,
* fbc_keywds_Samples[]), use the .argv_name.
*/
if (option_value == NULL) {
}
}
/*
* Set up the Option description for the config file
*/
if (fbc_add_Option_mod(
option_mod_p) != FBC_SUCCESS) {
fbc_errormsg("Conflicting option, %s %s\n",
}
/*
* See whether setting this value should reset related Option values
*
* The values of related Options should be reset (in radio
* button fashion) if:
* * A reset value (option_reset_value) has been provided
* * The value of this Option isn't the reset value
* * Related Options exist
*/
if ((option_reset_value != NULL) &&
/*
* Reset each related Option value
*/
for (;;) {
if (*option_name == '\0') {
break;
}
/*
* Set up the Option description for the config file
*/
if (fbc_add_Option_mod(
((const fbopt_descr_t *)fbopt_descr)->
NULL) != FBC_SUCCESS) {
"Conflicting associated option, %s %s\n",
}
}
}
} /* fbc_add_radio_Option_mod() */
#ifdef FBC_FUTURE
/*
* fbc_Option_none()
*
* Handle a configuration Option entry having no Option value.
*
* Note: This is a fbc_getopt_fn_t typed function.
*/
void
char * const argv[], /* Program argument vector */
int *arg, /* Program argument subscript */
const void *fbopt_descr) /* Ptr to cmd line option descr */
{
NULL, /* Option entry has no value */
&strcmp, /* Not used; there's no value */
NULL) != FBC_SUCCESS) {
}
} /* fbc_Option_none() */
#endif /* FBC_FUTURE */
/*
* Keyword tables for command line options having keyword arguments
*
* The zeroth keywd_int_t array element contains the "radio button"
* reset value in its .conf_name member. The zeroth element is not
* part of the keyword look-up table. The keyword look-up table
* begins at array element [1].
*/
/* True | False */
};
/* Enable | Disable */
};
/* -outputs Swapped | Direct */
};
/* -slave Disable | Multiview | ... */
#ifdef U22only
#endif
};
/* -multisample Disable | Available | ForceOn */
};
/* -samples */
};
/*
* fbc_Option_keyword()
*
* Handle an configuration Option entry having a keyword value (that
* is independent of other Option entries),
*
* Option "Clone" "Enable"|"Disable" # -clone
*
* Option "MultiviewMode" "Disable"|"Multiview" # -slave
*
* Option "Multisample" "Disable"|"Available"|"ForceOn"
*
* Option "Samples" "1"|"4"|"8"|"16" # -samples
*
* Option "StereoEnable" "Enable"|"Disable" # -stereo
*
* or multiple such configuration Option entries that are ganged
* together in radio-button fashion.
*
* Option "DefLinear" "True"|"False" # -deflinear
* Option "DefOverlay" "True"|"False" # -defoverlay
* Option "DefTransparent" "True"|"False" # -deftransparent
*
* Option "DoubleWide" "Enable"|"Disable" # -doublewide
* Option "DoubleHigh" "Enable"|"Disable" # -doublehigh
*
* If this and other Options are ganged together in radio button
* fashion (e.g., if one's value is set to True then all others' must
* be False) then reset the values of the other Options when
* necessary.
*
* Note: This is a fbc_getopt_fn_t typed function.
*/
void
char * const argv[], /* Program argument vector */
int *arg, /* Program argument subscript */
const void *fbopt_descr) /* Ptr to cmd line option descr */
{
/*
* Prepare an Option entry having a Boolean-style keyword value
*/
keywd_table[0].conf_name,
argv,
*arg,
NULL);
} /* fbc_Option_keyword() */
#ifndef FBC_FUTURE
/*
* fbc_Option_int()
*
* Handle a configuration Option entry having an integer value.
*
* Note: This is a fbc_getopt_fn_t typed function.
*/
void
char * const argv[], /* Program argument vector */
int *arg, /* Program argument subscript */
const void *fbopt_descr) /* Ptr to cmd line option descr */
{
/*
* Validate the integer value string
*/
fbc_errormsg("Invalid integer value, %s %s\n",
}
/*
* Initialize the config Option descriptor
*/
&strcasecmp, /* Hexadecimal is case insensitive */
NULL) != FBC_SUCCESS) {
fbc_errormsg("Conflicting option, %s %s\n",
}
} /* fbc_Option_int() */
#endif /* FBC_FUTURE */
/*
* fbc_Option_Stream_Offset()
*
* Handle the configuration Option entries:
* Option "StreamXOffset" <int>
* Option "StreamYOffset" <int>
*
* This function handles a single command line option, -offset, that
* takes two integer arguments. Retrieving two config Option names
* from one fbopt_descr_t table entry is atypical, and involves an
* embedded Nul character in the Option name(s) string. Config
* Option entry descriptors are produced for StreamXOffset &
* StreamYOffset.
*
* Note: This is a fbc_getopt_fn_t typed function.
*/
void
char * const argv[], /* Program argument vector */
int *arg, /* Program argument subscript */
const void *fbopt_descr) /* Ptr to cmd line option descriptor */
{
int i; /* Loop counter / argv[] index */
/*
* Validate the signed integer offset value strings
*/
for (i = 1; i <= 2; i += 1) {
fbc_errormsg("Invalid offset value #%d, %s %s %s\n",
}
}
/*
* Initialize StreamXOffset & StreamYOffset config Option descriptors
*/
for (i = 1; i <= 2; i += 1) {
if (fbc_add_Option_mod(
&strcasecmp, /* Hex is case insensitive */
NULL) != FBC_SUCCESS) {
fbc_errormsg("Conflicting option, %s %s %s\n",
}
}
} /* fbc_Option_Stream_Offset() */
#ifdef FBC_FUTURE
/*
* fbc_Option_real()
*
* Handle a configuration Option entry having a floating point value.
*
* Note: This is a fbc_getopt_fn_t typed function.
*/
void
char * const argv[], /* Program argument vector */
int *arg, /* Program argument subscript */
const void *fbopt_descr) /* Ptr to cmd line option descriptor */
{
/*
* Validate the floating point value string
*/
fbc_errormsg("Invalid floating point value, %s %s\n",
}
/*
* Initialize the config Option entry descriptor
*/
strcasecmp, /* Floating point is insensitive */
NULL) != FBC_SUCCESS) {
fbc_errormsg("Conflicting option, %s %s\n",
}
} /* fbc_Option_real() */
#endif /* FBC_FUTURE */
#ifdef FBC_FUTURE
/*
* fbc_Option_string()
*
* Handle a configuration Option entry having a string value.
*
* Note: This is a fbc_getopt_fn_t typed function.
*/
void
char * const argv[], /* Program argument vector */
int *arg, /* Program argument subscript */
const void *fbopt_descr) /* Ptr to cmd line option descriptor */
{
&strcasecmp, /* Ummm ... */
NULL) != FBC_SUCCESS) {
fbc_errormsg("Conflicting option, %s %s\n",
}
} /* fbc_Option_string() */
#endif /* FBC_FUTURE */
#ifdef FBC_FUTURE /* or past */
/*
* fbc_opt_DefaultDepth()
*
* Set the DefaultDepth entry of a Screen section (-defdepth):
*
* DefaultDepth 8|24
*
* (Had been implemented for kfbconfig OS release 5.9.)
*
* Note: This is a fbc_getopt_fn_t typed function.
*/
};
void
char * const argv[], /* Program argument vector */
int *arg, /* Program argument subscript */
const void *fbopt_descr) /* Ptr to cmd line option descriptor */
{
/*
* Get the option's keyword value
*/
/*
* Convert the keyword value to the corresponding depth value
*/
/*
* The -defdepth option shows intent to modify the Screen section
*/
} /* fbc_opt_DefaultDepth() */
#endif
/*
* fbc_opt_defaults()
*
* Establish the default configuration for the specified device
* (-defaults).
*
* Note: This is a fbc_getopt_fn_t typed function.
*/
void
char * const argv[], /* Program argument vector */
int *arg, /* Program argument subscript */
const void *fbopt_descr) /* Ptr to cmd line option descr */
{
/*
* For each command line option descriptor, set any -defaults values
*/
fbopt_dsc += 1) {
/*
* See if this command line option has any -defaults values
*/
continue; /* Nope */
}
/*
* Avoid infinite recursion; disallow defaults for -defaults
*/
"Internal error; recursive -defaults encountered and ignored\n");
continue; /* Let's not find out what that does */
}
/*
* Set the default(s) for this implied command line option
*/
defaults_arg = 0;
}
} /* fbc_opt_defaults() */
/*
* fbc_opt_dev()
*
* Needn't get the frame buffer device name (-dev).
*
* The frame buffer device name should have been determined already
* (by fbc_get_device_arg() and fbc_get_device_name()), so it could
* be established what command line options to support.
*
* Note: This is a fbc_getopt_fn_t typed function.
*/
void
char * const argv[], /* Program argument vector */
int *arg, /* Program argument subscript */
const void *fbopt_descr) /* Ptr to cmd line option descr */
{
/* void */
} /* fbc_opt_dev() */
/*
* fbc_opt_file()
*
* Specify the configuration file (-file)
*
* Note: This is a fbc_getopt_fn_t typed function.
*/
/*
* Note: Initialization code in main() assumes that the
* fbc_keywds_file[0] entry contains the default values.
*/
};
void
char * const argv[], /* Program argument vector */
int *arg, /* Program argument subscript */
const void *fbopt_descr) /* Ptr to cmd line option descr */
{
/*
* Distinguish between keywords and pathnames
*
* Pathnames ought to be absolute ("%A"), which means the
* first character must be a slash. Otherwise, it's assumed
* that the argument is a keyword.
*/
/*
??? Allow this? * Save the fully qualified configuration file pathname
*/
if (issetugid()) {
fbc_errormsg("%s %s not allowed with added privileges\n",
}
} else {
/*
* Look up the configuration file location keyword
*/
/*
* Normalize the location keyword, to be used in -propt output
*/
/*
* Establish the configuration file pathname
*/
}
/*
* Establish the configuration file search path
*/
} /* fbc_opt_file() */
/*
* fbc_opt_Gamma()
*
* Set the Gamma entry of a Monitor section (-g <gamma_value>):
*
* Gamma <gamma_value>
*
* Note: This is a fbc_getopt_fn_t typed function.
*/
void
char * const argv[], /* Program argument vector */
int *arg, /* Program argument subscript */
const void *fbopt_descr) /* Ptr to cmd line option descr */
{
/*
* Process the gamma correction value argument
*/
(*end_ptr != '\0') ||
fbc_errormsg("Invalid gamma value, %s %s\n",
}
/*
* Add the "#Gamma" pseudo-Option and reset any "GFile" Option
*
* If no config entries are ganged with -g ("#Gamma"), we
* don't need to do anything. This is indicated by having no
* config Option entry names (.conf_name is NULL).
*
* If this device has any config entries that are ganged with
* "#Gamma" then they should also be pseudo-Options, or real
* Options for which the empty pathname value, "", is the
* correct reset value. Pseudo-options are flagged with a
* "#" name prefix. These fake Options will be eliminated
* from the .Option_mods[] array before the array is used to
* update the config file, so the choice of a reset value is
* unimportant in such cases.
*
* The point of all this is to permit these two (more in the
* future?) config entries to be manipulated in radio-button
* fashion, when one is an Option entry and the other is not.
*/
"", /* No gamma table pathname */
argv,
*arg,
NULL);
}
} /* fbc_opt_Gamma() */
/*
* fbc_Option_GFile()
*
* Handle a gamma table file pathname configuration Option entry
* (-gfile):
* Option "GFile" "[<gfile_path>]"
*
* Note: This is a fbc_getopt_fn_t typed function.
*/
void
char * const argv[], /* Program argument vector */
int *arg, /* Program argument subscript */
const void *fbopt_descr) /* Ptr to cmd line option descriptor */
{
/*
* Save the gamma table input file pathname (or empty string)
*/
/*
* Add the "GFile" Option and reset the "#Gamma" pseudo-Option, if any
*
* If this device has any config entries that are ganged with
* "GFile" then they should be pseudo-Options, such as
* "#Gamma", or be real Options for which the arbitrarily
* chosen FBC_GAMMA_DEFAULT_STR is the correct reset value.
* Pseudo-options are flagged with a "#" name prefix. These
* fake Options will be eliminated from the .Option_mods[]
* array before the array is used to update the config file,
* so the choice of a reset value is unimportant.
*
* The point of all this is to permit these two (more in the
* future?) config entries to be manipulated in radio-button
* fashion, when one is an Option entry and the other is not.
*/
FBC_GAMMA_DEFAULT_STR, /* A "don't care" arg */
argv,
*arg,
&option_mod);
/*
* Arrange to delete any Gamma entry
*/
/*
* Note where the pointer for the gamma table pathname has been stored
*
* The description for the "GFile" Option entry has just been
* initialized using a pointer to the input gamma table
* pathname. Before the actual Option entry is created, this
* must be replaced by a pointer to the output pathname (e.g.
* "/etc/X11/kfb0.gamma"), which is based on the config file
* directory and the device name. We don't necessarily know
* the config file directory yet.
*
* A further wrinkle is that the Option description needs the
* input pathname during command line processing so that
* conflicting -gfile argument strings can be detected.
*
* If this -gfile option has a non-empty pathname argument
* and no other -gfile option has been seen, remember the
* address of the pathname pointer so it can be changed
* later, after the command line processing has been
* completed, and once the output pathname components are
* known.
*/
}
} /* fbc_Option_GFile() */
/*
* fbc_opt_help()
*
* Handle a request for help with the current varient of
* fbconf_xorg(1M) (-help).
*
* Note: This is a fbc_getopt_fn_t typed function.
*/
void
char * const argv[], /* Program argument vector */
int *arg, /* Program argument subscript */
const void *fbopt_descr) /* Ptr to cmd line option descr */
{
/*
* Remember to be helpful later on
*/
} /* fbc_opt_help() */
/*
* fbc_opt_prconf()
*
* Print hardware configuration (-prconf).
*
* Note: This is a fbc_getopt_fn_t typed function.
*/
void
char * const argv[], /* Program argument vector */
int *arg, /* Program argument subscript */
const void *fbopt_descr) /* Ptr to cmd line option descr */
{
} /* fbc_opt_prconf() */
/*
* fbc_opt_predid()
*
* Print EDID data (-predid [raw] [parsed]).
*
* Note: This is a fbc_getopt_fn_t typed function.
*/
enum {
};
};
void
char * const argv[], /* Program argument vector */
int *arg, /* Program argument subscript */
const void *fbopt_descr) /* Ptr to cmd line option descr */
{
/*
* Redundant but safe
*/
/*
* Repeat for each argv[] string that looks like an argument
*/
/*
* Look up the keyword (and exit if it isn't found)
*/
&fbc_keywds_predid[0],
switch (match_ent_ptr->value) {
case FBC_PrEDID_Raw: /* 10-sec video mode trial */
break;
case FBC_PrEDID_Parsed: /* Apply new video mode now */
break;
default:
"Internal error; unimplemented keyword, %s\n",
break;
}
/*
* Include this keyword argument in the count
*/
*arg += 1;
}
/*
* The default is "-predid parsed"
*/
}
} /* fbc_opt_predid() */
/*
* fbc_opt_propt()
*
* Print configuration options (-propt).
*
* Note: This is a fbc_getopt_fn_t typed function.
*/
void
char * const argv[], /* Program argument vector */
int *arg, /* Program argument subscript */
const void *fbopt_descr) /* Ptr to cmd line option descr */
{
} /* fbc_opt_propt() */
/*
* fbc_opt_res()
*
* Video mode/resolution:
* -res ?
* -res <video_mode> [noconfirm|nocheck]
* -res <video_mode> [noconfirm|nocheck] [try|now]
*
* Note: This is a fbc_getopt_fn_t typed function.
*/
enum {
};
};
};
void
char * const argv[], /* Program argument vector */
int *arg, /* Program argument subscript */
const void *fbopt_descr) /* Ptr to cmd line option descr */
{
/*
* Redundant but safe
*/
/*
* Handle -res ? as the special directive for listing video modes
*/
return;
}
/*
* Save the video mode / resolution name
*/
/*
* Handle any keyword arguments
*/
/*
* Repeat for each argv[] string that looks like an argument
*/
/*
* Look up the keyword (and exit if it isn't found)
*/
switch (match_ent_ptr->value) {
case FBC_ResMode_NoCheck:
/* Don't check the video mode argument */
/* "nocheck" implies "noconfirm" */
/*FALLTHROUGH*/
case FBC_ResMode_NoConfirm:
/* Check without confirmation */
break;
case FBC_ResMode_Try:
/* 10-second video mode trial */
break;
case FBC_ResMode_Now:
/* Apply the new video mode now */
break;
default:
"Internal error; unimplemented keyword, %s\n",
break;
}
/*
* Include this keyword argument in the count
*/
*arg += 1;
}
}
/*
* Taking this code path shows intent to modify a config file section
*/
} /* fbc_opt_res() */
/*
* fbc_getargs()
*
* Process the fbconf_xorg(1M) program command line options. There
* are no legal program command line arguments.
*
* In the event of an error this function or one of its subordinate
* functions is expected to report the error and exit the program.
*/
int
const int argc, /* Program argument count */
char *const argv[], /* Program argument vector */
{
/*
* Fill in "not set" values for the explicitly named xorg.conf entries
*/
/*
* Allocate a descriptor array of config Option entries to be modified
*
* This includes space for the descriptor array's terminator
* element.
*/
* sizeof (xf86_opt_mod_t));
fbc_errormsg("Insufficient memory, Option_mods\n");
}
/*
* Process the program command line options
*/
/*
* Look up the command line option by name
*/
break; /* This looks more like an argument */
}
sizeof (fbopt_descr_t),
(void *)&fbopt_descr);
if (error_code != FBC_SUCCESS) {
if (error_code == FBC_ERR_KWD_INVALID) {
fbc_errormsg("Unknown option, %s\n",
} else {
fbc_errormsg("Option %s is ambiguous.\n",
sizeof (fbopt_descr_t),
}
}
/*
* Make sure the final cmd line option isn't missing an arg
*/
fbc_errormsg("Option requires an argument, %s\n",
}
/*
* Process the command line option and any argument(s)
*/
/*
* Advance to the next option, if any
*
* If the current option accepted a variable number
* of arguments, the "fbc_getopt_fn" function should
* have incremented the "arg" index by the number of
* optional arguments that were encountered. Here
* the "arg" index is incremented by the number of
* required arguments.
*/
}
/*
* Disallow program command line arguments
*/
}
/*
* Mark the end of the array of config Option entries to be modified
*/
option_mod->section = 0;
/*
* Return without incident
*/
return (FBC_EXIT_SUCCESS);
} /* fbc_getargs() */
/* End of fbc_getargs.c */