Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions doc/services/shell/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -678,16 +678,16 @@ The shell module supports the following meta keys:

This feature is activated by :kconfig:option:`CONFIG_SHELL_METAKEYS` set to ``y``.

Getopt Feature
*****************
sys_getopt Feature
******************

Some shell users apart from subcommands might need to use options as well.
the arguments string, looking for supported options. Typically, this task
is accomplished by the ``getopt`` family functions.

For this purpose shell supports the getopt and getopt_long libraries available
in the FreeBSD project. This feature is activated by:
:kconfig:option:`CONFIG_POSIX_C_LIB_EXT` set to ``y`` and :kconfig:option:`CONFIG_GETOPT_LONG`
For this purpose shell supports a variant of the getopt and getopt_long libraries from
the FreeBSD project called sys_getopt and sys_getopt_long. This feature is activated by:
:kconfig:option:`CONFIG_GETOPT` set to ``y`` and :kconfig:option:`CONFIG_GETOPT_LONG`
set to ``y``.

This feature can be used in thread safe as well as non thread safe manner.
Expand All @@ -699,7 +699,7 @@ An example non-thread safe usage:
.. code-block:: c

char *cvalue = NULL;
while ((char c = getopt(argc, argv, "abhc:")) != -1) {
while ((char c = sys_getopt(argc, argv, "abhc:")) != -1) {
switch (c) {
case 'c':
cvalue = optarg;
Expand All @@ -714,9 +714,9 @@ An example thread safe usage:
.. code-block:: c

char *cvalue = NULL;
struct getopt_state *state;
while ((char c = getopt(argc, argv, "abhc:")) != -1) {
state = getopt_state_get();
struct sys_getopt_state *state;
while ((char c = sys_getopt(argc, argv, "abhc:")) != -1) {
state = sys_getopt_state_get();
switch (c) {
case 'c':
cvalue = state->optarg;
Expand All @@ -726,7 +726,7 @@ An example thread safe usage:
}
}

Thread safe getopt functionality is activated by
Thread safe sys_getopt functionality is activated by
:kconfig:option:`CONFIG_SHELL_GETOPT` set to ``y``.

Obscured Input Feature
Expand Down
4 changes: 2 additions & 2 deletions include/zephyr/shell/shell.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#include <zephyr/toolchain.h>

#if defined CONFIG_SHELL_GETOPT
#include <getopt.h>
#include <zephyr/sys/sys_getopt.h>
#endif

#ifdef __cplusplus
Expand Down Expand Up @@ -995,7 +995,7 @@ struct shell_ctx {

#if defined CONFIG_SHELL_GETOPT
/*!< getopt context for a shell backend. */
struct getopt_state getopt;
struct sys_getopt_state getopt;
#endif

uint16_t cmd_buff_len; /*!< Command length.*/
Expand Down
130 changes: 130 additions & 0 deletions include/zephyr/sys/sys_getopt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*
* Copyright (c) 2021 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef ZEPHYR_INCLUDE_SYS_GETOPT_H_
#define ZEPHYR_INCLUDE_SYS_GETOPT_H_

#ifdef __cplusplus
extern "C" {
#endif

#include <zephyr/kernel.h>

struct sys_getopt_state {
int opterr; /* if error message should be printed */
int optind; /* index into parent argv vector */
int optopt; /* character checked for validity */
int optreset; /* reset getopt */
char *optarg; /* argument associated with option */

char *place; /* option letter processing */

#if CONFIG_GETOPT_LONG
int nonopt_start;
int nonopt_end;
#endif
};

extern int sys_getopt_optreset; /* reset getopt */
extern char *sys_getopt_optarg;
extern int sys_getopt_opterr;
extern int sys_getopt_optind;
extern int sys_getopt_optopt;

#define sys_getopt_no_argument 0
#define sys_getopt_required_argument 1
#define sys_getopt_optional_argument 2

struct sys_getopt_option {
/* name of long option */
const char *name;
/*
* one of no_argument, required_argument, and optional_argument:
* whether option takes an argument
*/
int has_arg;
/* if not NULL, set *flag to val when option found */
int *flag;
/* if flag not NULL, value to set *flag to; else return value */
int val;
};

/* Function initializes getopt_state structure for current thread */
void sys_getopt_init(void);

/* Function returns getopt_state structure for the current thread. */
struct sys_getopt_state *sys_getopt_state_get(void);

/**
* @brief Parses the command-line arguments.
*
* @note This function is based on FreeBSD implementation but it does not
* support environment variable: POSIXLY_CORRECT.
*
* @param[in] nargc Arguments count.
* @param[in] nargv Arguments.
* @param[in] ostr String containing the legitimate option characters.
*
* @return If an option was successfully found, function returns
* the option character.
*/
int sys_getopt(int nargc, char *const nargv[], const char *ostr);

/**
* @brief Parses the command-line arguments.
*
* The sys_getopt_long() function works like @ref sys_getopt() except
* it also accepts long options, started with two dashes.
*
* @note This function is based on FreeBSD implementation but it does not
* support environment variable: POSIXLY_CORRECT.
*
* @param[in] nargc Arguments count.
* @param[in] nargv Arguments.
* @param[in] options String containing the legitimate option characters.
* @param[in] long_options Pointer to the first element of an array of
* @a struct sys_getopt_option.
* @param[in] idx If idx is not NULL, it points to a variable
* which is set to the index of the long option relative
* to @p long_options.
*
* @return If an option was successfully found, function returns
* the option character.
*/
int sys_getopt_long(int nargc, char *const *nargv, const char *options,
const struct sys_getopt_option *long_options, int *idx);

/**
* @brief Parses the command-line arguments.
*
* The sys_getopt_long_only() function works like @ref sys_getopt_long(),
* but '-' as well as "--" can indicate a long option. If an option that starts
* with '-' (not "--") doesn't match a long option, but does match a short
* option, it is parsed as a short option instead.
*
* @note This function is based on FreeBSD implementation but it does not
* support environment variable: POSIXLY_CORRECT.
*
* @param[in] nargc Arguments count.
* @param[in] nargv Arguments.
* @param[in] options String containing the legitimate option characters.
* @param[in] long_options Pointer to the first element of an array of
* @a struct sys_getopt_option.
* @param[in] idx If idx is not NULL, it points to a variable
* which is set to the index of the long option relative
* to @p long_options.
*
* @return If an option was successfully found, function returns
* the option character.
*/
int sys_getopt_long_only(int nargc, char *const *nargv, const char *options,
const struct sys_getopt_option *long_options, int *idx);

#ifdef __cplusplus
}
#endif

#endif /* ZEPHYR_INCLUDE_SYS_GETOPT_H_ */
5 changes: 1 addition & 4 deletions lib/posix/c_lib_ext/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,5 @@ zephyr_library()
zephyr_library_sources(
fnmatch.c
getentropy.c
getopt/getopt.c
getopt/getopt_common.c
getopt_shim.c
)

zephyr_library_sources_ifdef(CONFIG_GETOPT_LONG getopt/getopt_long.c)
18 changes: 2 additions & 16 deletions lib/posix/c_lib_ext/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
#
# SPDX-License-Identifier: Apache-2.0

menuconfig POSIX_C_LIB_EXT
config POSIX_C_LIB_EXT
bool "POSIX general C library extension"
select GETOPT
help
Select 'y' here and Zephyr will provide an implementation of the POSIX_C_LIB_EXT Option
Group, consisting of fnmatch(), getopt(), getsubopt(), optarg, opterr, optind, optopt,
Expand All @@ -12,18 +13,3 @@ menuconfig POSIX_C_LIB_EXT

For more information, please see
https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html

if POSIX_C_LIB_EXT

config GETOPT_LONG
bool "Getopt long library support"
help
This option adds support of the getopt long.
Different shell backends are using their own instance of getopt to
not interfere with each other.
All not shell threads share one global instance of getopt state, hence
apart from shell this library is not thread safe. User can add support
for other threads by extending function getopt_state_get in
getopt_common.c file.

endif # POSIX_C_LIB_EXT
106 changes: 14 additions & 92 deletions lib/posix/c_lib_ext/getopt/getopt.h
Original file line number Diff line number Diff line change
@@ -1,115 +1,37 @@
/*
* Copyright (c) 2021 Nordic Semiconductor ASA
* Copyright (c) 2025 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef _GETOPT_H__
#define _GETOPT_H__
#ifndef _GETOPT_H_
#define _GETOPT_H_

#include <zephyr/sys/sys_getopt.h>

#ifdef __cplusplus
extern "C" {
#endif

#include <zephyr/kernel.h>

struct getopt_state {
int opterr; /* if error message should be printed */
int optind; /* index into parent argv vector */
int optopt; /* character checked for validity */
int optreset; /* reset getopt */
char *optarg; /* argument associated with option */

char *place; /* option letter processing */

#if CONFIG_GETOPT_LONG
int nonopt_start;
int nonopt_end;
#endif
};
extern void getopt_init(void);

extern int optreset; /* reset getopt */
extern char *optarg;
extern int opterr;
extern int optind;
extern int optopt;
#define getopt_state sys_getopt_state
#define option sys_getopt_option

#define no_argument 0
#define required_argument 1
#define optional_argument 2

struct option {
/* name of long option */
const char *name;
/*
* one of no_argument, required_argument, and optional_argument:
* whether option takes an argument
*/
int has_arg;
/* if not NULL, set *flag to val when option found */
int *flag;
/* if flag not NULL, value to set *flag to; else return value */
int val;
};
extern struct sys_getopt_state *getopt_state_get(void);

/* Function initializes getopt_state structure for current thread */
void getopt_init(void);
extern int getopt_long(int nargc, char *const *nargv, const char *options,
const struct option *long_options, int *idx);

/* Function returns getopt_state structure for the current thread. */
struct getopt_state *getopt_state_get(void);

/**
* @brief Parses the command-line arguments.
*
* The getopt_long() function works like @ref getopt() except
* it also accepts long options, started with two dashes.
*
* @note This function is based on FreeBSD implementation but it does not
* support environment variable: POSIXLY_CORRECT.
*
* @param[in] argc Arguments count.
* @param[in] argv Arguments.
* @param[in] options String containing the legitimate option characters.
* @param[in] long_options Pointer to the first element of an array of
* @a struct z_option.
* @param[in] long_idx If long_idx is not NULL, it points to a variable
* which is set to the index of the long option relative
* to @p long_options.
*
* @return If an option was successfully found, function returns
* the option character.
*/
int getopt_long(int nargc, char *const *nargv, const char *options,
const struct option *long_options, int *idx);

/**
* @brief Parses the command-line arguments.
*
* The getopt_long_only() function works like @ref getopt_long(),
* but '-' as well as "--" can indicate a long option. If an option that starts
* with '-' (not "--") doesn't match a long option, but does match a short
* option, it is parsed as a short option instead.
*
* @note This function is based on FreeBSD implementation but it does not
* support environment variable: POSIXLY_CORRECT.
*
* @param[in] argc Arguments count.
* @param[in] argv Arguments.
* @param[in] options String containing the legitimate option characters.
* @param[in] long_options Pointer to the first element of an array of
* @a struct option.
* @param[in] long_idx If long_idx is not NULL, it points to a variable
* which is set to the index of the long option relative
* to @p long_options.
*
* @return If an option was successfully found, function returns
* the option character.
*/
int getopt_long_only(int nargc, char *const *nargv, const char *options,
const struct option *long_options, int *idx);
extern int getopt_long_only(int nargc, char *const *nargv, const char *options,
const struct option *long_options, int *idx);

#ifdef __cplusplus
}
#endif

#endif /* _GETOPT_H__ */
#endif /* _GETOPT_H_ */
Loading
Loading