Skip to content
Draft
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
24 changes: 19 additions & 5 deletions include/unistd.h
Original file line number Diff line number Diff line change
Expand Up @@ -289,12 +289,19 @@
#define getdtablesize(f) ((int)sysconf(_SC_OPEN_MAX))
#define getpagesize(f) ((int)sysconf(_SC_PAGESIZE))

/* Accessor functions associated with getopt(). */
/* Accessor functions associated with getopt(). In the user space of a
* kernel build every process has its own copy of the C library data, so
* optarg, opterr, optind and optopt are the plain variables that POSIX
* specifies (see below). Programs that bring their own getopt() depend
* on that.
*/

#define optarg (*(getoptargp()))
#define opterr (*(getopterrp()))
#define optind (*(getoptindp()))
#define optopt (*(getoptoptp()))
#if !defined(CONFIG_BUILD_KERNEL) || defined(__KERNEL__)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kernel/flat should keep the same behavior. anyway, we have a similar and better fix, will provide soon.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, please link your PR here when it is ready and I will close this one. I can test it with a program that defines optarg itself.

# define optarg (*(getoptargp()))
# define opterr (*(getopterrp()))
# define optind (*(getoptindp()))
# define optopt (*(getoptoptp()))
#endif

#if defined(CONFIG_FS_LARGEFILE)
# define lseek64 lseek
Expand Down Expand Up @@ -481,6 +488,13 @@ FAR int *getopterrp(void); /* Print error message */
FAR int *getoptindp(void); /* Index into argv */
FAR int *getoptoptp(void); /* Unrecognized option character */

#if defined(CONFIG_BUILD_KERNEL) && !defined(__KERNEL__)
EXTERN FAR char *optarg; /* Optional argument following option */
EXTERN int opterr; /* Print error message */
EXTERN int optind; /* Index into argv */
EXTERN int optopt; /* Unrecognized option character */
#endif

int gethostname(FAR char *name, size_t namelen);
int sethostname(FAR const char *name, size_t namelen);

Expand Down
1 change: 1 addition & 0 deletions libs/libc/unistd/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ set(SRCS
lib_getopterrp.c
lib_getoptindp.c
lib_getoptoptp.c
lib_getoptpublic.c
lib_times.c
lib_alarm.c
lib_fstatvfs.c
Expand Down
2 changes: 1 addition & 1 deletion libs/libc/unistd/Make.defs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
CSRCS += lib_access.c lib_daemon.c lib_swab.c lib_pathconf.c lib_sysconf.c
CSRCS += lib_getcwd.c lib_getentropy.c lib_getopt_common.c lib_getopt.c
CSRCS += lib_getopt_long.c lib_getopt_longonly.c lib_getoptvars.c lib_getoptargp.c
CSRCS += lib_getopterrp.c lib_getoptindp.c lib_getoptoptp.c lib_times.c
CSRCS += lib_getopterrp.c lib_getoptindp.c lib_getoptoptp.c lib_getoptpublic.c lib_times.c
CSRCS += lib_alarm.c lib_fstatvfs.c lib_statvfs.c lib_sleep.c lib_nice.c
CSRCS += lib_getrusage.c lib_utime.c lib_utimes.c
CSRCS += lib_setrlimit.c lib_getrlimit.c lib_setpriority.c lib_getpriority.c
Expand Down
53 changes: 45 additions & 8 deletions libs/libc/unistd/lib_getopt_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,20 +167,20 @@ static int getopt_long_option(FAR struct getopt_s *go,
{
FAR char *next;

case no_argument:
/* No, no arguments. Just return the argument that we
* found.
*/
/* No, no arguments. Just return the argument that we
* found.
*/

case no_argument:
go->go_optptr = NULL;
go->go_optind++;
break;

case optional_argument:
/* Check if there is a following argument and if that
* following argument is another option.
*/
/* Check if there is a following argument and if that
* following argument is another option.
*/

case optional_argument:
next = argv[go->go_optind + 1];
if (next == NULL || next[0] == '-')
{
Expand Down Expand Up @@ -334,17 +334,26 @@ static int getopt_long_option(FAR struct getopt_s *go,
*
****************************************************************************/

#ifdef GETOPT_PUBLIC_VARIABLES
static int getopt_internal(int argc, FAR char * const argv[],
FAR const char *optstring,
FAR const struct option *longopts,
FAR int *longindex,
enum getopt_mode_e mode)
#else
int getopt_common(int argc, FAR char * const argv[],
FAR const char *optstring,
FAR const struct option *longopts,
FAR int *longindex,
enum getopt_mode_e mode)
#endif
{
int ret;

/* Get thread-specific getopt() variables */

FAR struct getopt_s *go = getoptvars();

if (go == NULL)
{
return '?';
Expand Down Expand Up @@ -640,3 +649,31 @@ int getopt_common(int argc, FAR char * const argv[],
go->go_binitialized = false;
return ERROR;
}

#ifdef GETOPT_PUBLIC_VARIABLES
int getopt_common(int argc, FAR char * const argv[],
FAR const char *optstring,
FAR const struct option *longopts,
FAR int *longindex,
enum getopt_mode_e mode)
{
FAR struct getopt_s *go = getoptvars();
int ret;

/* The program may have set optind (to restart) or opterr */

go->go_optarg = optarg;
go->go_opterr = opterr;
go->go_optind = optind;
go->go_optopt = optopt;

ret = getopt_internal(argc, argv, optstring, longopts, longindex, mode);

optarg = go->go_optarg;
opterr = go->go_opterr;
optind = go->go_optind;
optopt = go->go_optopt;

return ret;
}
#endif
5 changes: 5 additions & 0 deletions libs/libc/unistd/lib_getoptargp.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@

FAR char **getoptargp(void)
{
#ifdef GETOPT_PUBLIC_VARIABLES
return &optarg;
#else
FAR struct getopt_s *go = getoptvars();

return &go->go_optarg;
#endif
}
5 changes: 5 additions & 0 deletions libs/libc/unistd/lib_getopterrp.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@

FAR int *getopterrp(void)
{
#ifdef GETOPT_PUBLIC_VARIABLES
return &opterr;
#else
FAR struct getopt_s *go = getoptvars();

return &go->go_opterr;
#endif
}
5 changes: 5 additions & 0 deletions libs/libc/unistd/lib_getoptindp.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@

int *getoptindp(void)
{
#ifdef GETOPT_PUBLIC_VARIABLES
return &optind;
#else
FAR struct getopt_s *go = getoptvars();

return &go->go_optind;
#endif
}
5 changes: 5 additions & 0 deletions libs/libc/unistd/lib_getoptoptp.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@

int *getoptoptp(void)
{
#ifdef GETOPT_PUBLIC_VARIABLES
return &optopt;
#else
FAR struct getopt_s *go = getoptvars();

return &go->go_optopt;
#endif
}
52 changes: 52 additions & 0 deletions libs/libc/unistd/lib_getoptpublic.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/****************************************************************************
* libs/libc/unistd/lib_getoptpublic.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/

/****************************************************************************
* Included Files
****************************************************************************/

#include <nuttx/config.h>

#include "unistd.h"

#ifdef GETOPT_PUBLIC_VARIABLES

/****************************************************************************
* Public Data
****************************************************************************/

/* The public getopt() variables of a kernel-build process. They are in a
* file of their own, so that a program that defines its own does not get
* a second definition from the C library.
* getopt_common() copies them to and from its internal state.
*/

FAR char *optarg;
int opterr = 1;
int optind = 1;
int optopt = '?';

/****************************************************************************
* Public Functions
****************************************************************************/

#endif /* GETOPT_PUBLIC_VARIABLES */
8 changes: 8 additions & 0 deletions libs/libc/unistd/unistd.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ extern "C"
* getopt_long_only() that is being emulated by getopt_common().
*/

/* In the user space of a kernel build, the public getopt() variables are
* plain variables (see include/unistd.h).
*/

#if defined(CONFIG_BUILD_KERNEL) && !defined(__KERNEL__)
# define GETOPT_PUBLIC_VARIABLES 1
#endif

enum getopt_mode_e
{
GETOPT_MODE = 0,
Expand Down
Loading