summaryrefslogtreecommitdiff
path: root/libc/unistd
diff options
context:
space:
mode:
Diffstat (limited to 'libc/unistd')
-rw-r--r--libc/unistd/Makefile.in50
-rw-r--r--libc/unistd/confstr.c26
-rw-r--r--libc/unistd/daemon.c109
-rw-r--r--libc/unistd/exec.c58
-rw-r--r--libc/unistd/execvpe.c7
-rw-r--r--libc/unistd/fpathconf.c10
-rw-r--r--libc/unistd/getlogin.c4
-rw-r--r--libc/unistd/getopt-susv3.c12
-rw-r--r--libc/unistd/getopt.c54
-rw-r--r--libc/unistd/getopt_int.h5
-rw-r--r--libc/unistd/getopt_long-simple.c1
-rw-r--r--libc/unistd/getpass.c70
-rw-r--r--libc/unistd/getsubopt-susv3.c3
-rw-r--r--libc/unistd/getsubopt.c8
-rw-r--r--libc/unistd/pathconf.c8
-rw-r--r--libc/unistd/sleep.c159
-rw-r--r--libc/unistd/sysconf.c146
-rw-r--r--libc/unistd/ualarm.c1
-rw-r--r--libc/unistd/usershell.c184
-rw-r--r--libc/unistd/usleep.c16
20 files changed, 509 insertions, 422 deletions
diff --git a/libc/unistd/Makefile.in b/libc/unistd/Makefile.in
index 8095aa641..659008d4d 100644
--- a/libc/unistd/Makefile.in
+++ b/libc/unistd/Makefile.in
@@ -1,48 +1,40 @@
# Makefile for uClibc
#
-# Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org>
#
# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
#
+subdirs += libc/unistd
+
UNISTD_DIR := $(top_srcdir)libc/unistd
UNISTD_OUT := $(top_builddir)libc/unistd
-CSRC := $(notdir $(wildcard $(UNISTD_DIR)/*.c))
-# multi source
-CSRC := $(filter-out exec.c,$(CSRC))
-
-ifeq ($(ARCH_USE_MMU),y)
-CSRC := $(filter-out __exec_alloc.c,$(CSRC))
-else
-CSRC := $(filter-out daemon.c,$(CSRC))
-endif
+CSRC-y := $(notdir $(wildcard $(UNISTD_DIR)/*.c))
+OMIT-y := exec.c # multi source
+OMIT-$(ARCH_USE_MMU) += __exec_alloc.c
+OMIT-$(if $(UCLIBC_SUSV3_LEGACY),,y) += ualarm.c usleep.c
+#OMIT-$(UCLIBC_HAS_THREADS_NATIVE) += sleep.c
ifeq ($(UCLIBC_HAS_GNU_GETOPT),y)
-CSRC := $(filter-out getopt-susv3.c getopt_long-simple.c,$(CSRC))
+# GNU getopt family
+OMIT-y += getopt-susv3.c getopt_long-simple.c getsubopt-susv3.c
+OMIT-y += $(if $(UCLIBC_HAS_GNU_GETSUBOPT),,getsubopt.c)
else
-CSRC := $(filter-out getopt.c,$(CSRC))
-ifneq ($(UCLIBC_HAS_GETOPT_LONG),y)
-CSRC := $(filter-out getopt_long-simple.c,$(CSRC))
-endif
+# SuS getopt family
+OMIT-y += getopt.c getsubopt.c
+OMIT-y += $(if $(UCLIBC_HAS_GETOPT_LONG),,getopt_long-simple.c)
+OMIT-y += $(if $(UCLIBC_HAS_GNU_GETSUBOPT),,getsubopt-susv3.c)
endif
-ifeq ($(UCLIBC_HAS_GNU_GETSUBOPT),y)
-CSRC := $(filter-out getsubopt-susv3.c,$(CSRC))
-else
-CSRC := $(filter-out getsubopt.c,$(CSRC))
-endif
-
-ifeq ($(UCLIBC_HAS_THREADS_NATIVE),y)
-CSRC := $(filter-out sleep.c,$(CSRC))
-endif
+CSRC-y := $(filter-out $(OMIT-y),$(CSRC-y))
-UNISTD_SRC := $(patsubst %.c,$(UNISTD_DIR)/%.c,$(CSRC))
-UNISTD_OBJ := $(patsubst %.c,$(UNISTD_OUT)/%.o,$(CSRC))
+UNISTD_SRC := $(patsubst %.c,$(UNISTD_DIR)/%.c,$(CSRC-y))
+UNISTD_OBJ := $(patsubst %.c,$(UNISTD_OUT)/%.o,$(CSRC-y))
libc-y += $(UNISTD_OBJ)
-objclean-y += unistd_objclean
+objclean-y += CLEAN_libc/unistd
-unistd_objclean:
- $(RM) $(UNISTD_OUT)/*.{o,os}
+CLEAN_libc/unistd:
+ $(do_rm) $(addprefix $(UNISTD_OUT)/*., o os)
diff --git a/libc/unistd/confstr.c b/libc/unistd/confstr.c
index 67a9d585a..373644265 100644
--- a/libc/unistd/confstr.c
+++ b/libc/unistd/confstr.c
@@ -13,16 +13,14 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#include <stddef.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
-/* Experimentally off - libc_hidden_proto(memcpy) */
#define CS_PATH "/bin:/usr/bin"
@@ -43,6 +41,26 @@ size_t confstr (int name, char *buf, size_t len)
string_len = sizeof (cs_path);
}
break;
+#ifdef __UCLIBC_HAS_THREADS__
+ case _CS_GNU_LIBPTHREAD_VERSION:
+# if defined __LINUXTHREADS_OLD__
+ string = "linuxthreads-0.01";
+ string_len = sizeof("linuxthreads-x.xx");
+# elif defined __LINUXTHREADS_NEW__
+ string = "linuxthreads-0.10";
+ string_len = sizeof("linuxthreads-x.xx");
+# elif defined __UCLIBC_HAS_THREADS_NATIVE__
+# define __NPTL_VERSION ("NPTL " \
+ __stringify(__UCLIBC_MAJOR__) "." \
+ __stringify(__UCLIBC_MINOR__) "." \
+ __stringify(__UCLIBC_SUBLEVEL__))
+ string = __NPTL_VERSION;
+ string_len = sizeof(__NPTL_VERSION);
+# else
+# error unable to determine thread impl
+# endif
+ break;
+#endif
default:
__set_errno (EINVAL);
return 0;
diff --git a/libc/unistd/daemon.c b/libc/unistd/daemon.c
index d565ed41d..8fa292850 100644
--- a/libc/unistd/daemon.c
+++ b/libc/unistd/daemon.c
@@ -44,49 +44,100 @@
#include <features.h>
#include <fcntl.h>
#include <paths.h>
+#include <signal.h>
#include <unistd.h>
+#include <not-cancel.h>
+#include <errno.h>
+
+#ifdef __UCLIBC_HAS_THREADS_NATIVE__
+#include <sys/stat.h>
+#endif
+
+#ifdef __UCLIBC_HAS_LFS__
+#define STAT stat64
+#define FSTAT fstat64
+#else
+#define STAT stat
+#define FSTAT fstat
+#endif
#if defined __USE_BSD || (defined __USE_XOPEN && !defined __USE_UNIX98)
-libc_hidden_proto(open)
-libc_hidden_proto(close)
-libc_hidden_proto(_exit)
-libc_hidden_proto(dup2)
-libc_hidden_proto(setsid)
-libc_hidden_proto(chdir)
-libc_hidden_proto(fork)
+#ifndef __ARCH_USE_MMU__
+#include <sys/syscall.h>
+#include <sched.h>
+/* use clone() to get fork() like behavior here -- we just want to disassociate
+ * from the controlling terminal
+ */
+pid_t _fork_parent(void)
+{
+ INTERNAL_SYSCALL_DECL(err);
+ register long ret = INTERNAL_SYSCALL(clone, err, 2, CLONE_VM, 0);
+ if (ret > 0)
+ /* parent needs to die now w/out touching stack */
+ INTERNAL_SYSCALL(exit, err, 1, 0);
+ return ret;
+}
+static inline pid_t fork_parent(void)
+{
+ /* Block all signals to keep the parent from using the stack */
+ pid_t ret;
+ sigset_t new_set, old_set;
+ sigfillset(&new_set);
+ sigprocmask(SIG_BLOCK, &new_set, &old_set);
+ ret = _fork_parent();
+ sigprocmask(SIG_SETMASK, &old_set, NULL);
+ return ret;
+}
+#else
+static inline pid_t fork_parent(void)
+{
+ switch (fork()) {
+ case -1: return -1;
+ case 0: return 0;
+ default: _exit(0);
+ }
+}
+#endif
-int daemon( int nochdir, int noclose )
+int daemon(int nochdir, int noclose)
{
int fd;
- switch (fork()) {
- case -1:
- return(-1);
- case 0:
- break;
- default:
- _exit(0);
- }
+ if (fork_parent() == -1)
+ return -1;
if (setsid() == -1)
- return(-1);
-
- /* Make certain we are not a session leader, or else we
- * might reacquire a controlling terminal */
- if (fork())
- _exit(0);
+ return -1;
if (!nochdir)
chdir("/");
- if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
- dup2(fd, STDIN_FILENO);
- dup2(fd, STDOUT_FILENO);
- dup2(fd, STDERR_FILENO);
- if (fd > 2)
- close(fd);
+ if (!noclose)
+ {
+ struct STAT st;
+
+ if ((fd = open_not_cancel_2(_PATH_DEVNULL, O_RDWR)) != -1
+ && (__builtin_expect (FSTAT (fd, &st), 0) == 0))
+ {
+ if (__builtin_expect (S_ISCHR (st.st_mode), 1) != 0) {
+ dup2(fd, STDIN_FILENO);
+ dup2(fd, STDOUT_FILENO);
+ dup2(fd, STDERR_FILENO);
+ if (fd > 2)
+ close(fd);
+ } else {
+ /* We must set an errno value since no
+ function call actually failed. */
+ close_not_cancel_no_status (fd);
+ __set_errno (ENODEV);
+ return -1;
+ }
+ } else {
+ close_not_cancel_no_status (fd);
+ return -1;
+ }
}
- return(0);
+ return 0;
}
#endif
diff --git a/libc/unistd/exec.c b/libc/unistd/exec.c
index 9134e4370..9be856d4f 100644
--- a/libc/unistd/exec.c
+++ b/libc/unistd/exec.c
@@ -20,6 +20,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include <paths.h>
#include <string.h>
#include <errno.h>
#include <stdarg.h>
@@ -27,23 +28,13 @@
#include <unistd.h>
#include <sys/mman.h>
-libc_hidden_proto(execl)
-libc_hidden_proto(execle)
-libc_hidden_proto(execlp)
-libc_hidden_proto(execv)
-libc_hidden_proto(execvp)
-/* Experimentally off - libc_hidden_proto(memcpy) */
-/* Experimentally off - libc_hidden_proto(strchr) */
-/* Experimentally off - libc_hidden_proto(strlen) */
-libc_hidden_proto(execve)
-libc_hidden_proto(mmap)
-libc_hidden_proto(munmap)
-libc_hidden_proto(getenv)
/**********************************************************************/
#define EXEC_FUNC_COMMON 0
#define EXEC_FUNC_EXECVP 1
+#define EXEC_FUNC_EXECVPE 2
+
#if defined(__ARCH_USE_MMU__)
/* We have an MMU, so use alloca() to grab space for buffers and arg lists. */
@@ -70,6 +61,7 @@ libc_hidden_proto(getenv)
* execle(a) -> execve(-)
* execv(-) -> execve(-)
* execvp(a) -> execve(-)
+ * execvpe(a) -> execve(-)
*/
# define EXEC_ALLOC_SIZE(VAR) /* nothing to do */
@@ -80,7 +72,7 @@ extern void *__exec_alloc(size_t size, int func) attribute_hidden;
# ifdef L___exec_alloc
-void attribute_hidden *__exec_alloc(size_t size, int func)
+void *__exec_alloc(size_t size, int func)
{
static void *common_cache, *execvp_cache;
static size_t common_size, execvp_size;
@@ -147,7 +139,7 @@ libc_hidden_def(execl)
/**********************************************************************/
#ifdef L_execv
-int execv(__const char *path, char *__const argv[])
+int execv(const char *path, char *const argv[])
{
return execve(path, argv, __environ);
}
@@ -231,16 +223,18 @@ libc_hidden_def(execlp)
#endif
/**********************************************************************/
-#ifdef L_execvp
+#if defined (L_execvp) || defined(L_execvpe)
-/* Experimentally off - libc_hidden_proto(strchrnul) */
/* Use a default path that matches glibc behavior, since SUSv3 says
* this is implementation-defined. The default is current working dir,
* /bin, and then /usr/bin. */
static const char default_path[] = ":/bin:/usr/bin";
-
+#if defined (L_execvp)
int execvp(const char *path, char *const argv[])
+#elif defined (L_execvpe)
+int execvpe(const char *path, char *const argv[], char *const envp[])
+#endif
{
char *buf = NULL;
char *p;
@@ -258,7 +252,11 @@ int execvp(const char *path, char *const argv[])
}
if (strchr(path, '/')) {
+#if defined (L_execvp)
execve(path, argv, __environ);
+#elif defined (L_execvpe)
+ execve(path, argv, envp);
+#endif
if (errno == ENOEXEC) {
char **nargv;
EXEC_ALLOC_SIZE(size2) /* Do NOT add a semicolon! */
@@ -267,11 +265,19 @@ int execvp(const char *path, char *const argv[])
/* Need the dimension - 1. We omit counting the trailing
* NULL but we actually omit the first entry. */
for (n=0 ; argv[n] ; n++) {}
+#if defined (L_execvp)
nargv = (char **) EXEC_ALLOC((n+2) * sizeof(char *), size2, EXEC_FUNC_EXECVP);
+#elif defined (L_execvpe)
+ nargv = (char **) EXEC_ALLOC((n+2) * sizeof(char *), size2, EXEC_FUNC_EXECVPE);
+#endif
nargv[0] = argv[0];
nargv[1] = (char *)path;
memcpy(nargv+2, argv+1, n*sizeof(char *));
- execve("/bin/sh", nargv, __environ);
+#if defined (L_execvp)
+ execve(_PATH_BSHELL, nargv, __environ);
+#elif defined (L_execvpe)
+ execve(_PATH_BSHELL, nargv, envp);
+#endif
EXEC_FREE(nargv, size2);
}
} else {
@@ -290,8 +296,11 @@ int execvp(const char *path, char *const argv[])
return -1;
}
len = (FILENAME_MAX - 1) - plen;
-
+#if defined (L_execvp)
buf = EXEC_ALLOC(FILENAME_MAX, size, EXEC_FUNC_EXECVP);
+#elif defined (L_execvpe)
+ buf = EXEC_ALLOC(FILENAME_MAX, size, EXEC_FUNC_EXECVPE);
+#endif
{
int seen_small = 0;
s0 = buf + len;
@@ -313,8 +322,11 @@ int execvp(const char *path, char *const argv[])
s[plen-1] = '/';
}
+#if defined (L_execvp)
execve(s, argv, __environ);
-
+#elif defined (L_execvpe)
+ execve(s, argv, envp);
+#endif
seen_small = 1;
if (errno == ENOEXEC) {
@@ -338,7 +350,11 @@ int execvp(const char *path, char *const argv[])
return -1;
}
+#if defined (L_execvp)
libc_hidden_def(execvp)
-
+#elif defined (L_execvpe)
+libc_hidden_def(execvpe)
#endif
+
+#endif /* #if defined (L_execvp) || defined(L_execvpe) */
/**********************************************************************/
diff --git a/libc/unistd/execvpe.c b/libc/unistd/execvpe.c
new file mode 100644
index 000000000..c3c1e43fe
--- /dev/null
+++ b/libc/unistd/execvpe.c
@@ -0,0 +1,7 @@
+/* Copyright (C) 2011-2013 Hennning Heinold <heinold@inf.fu-berlin.de>
+ *
+ * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
+ */
+
+#define L_execvpe
+#include "exec.c"
diff --git a/libc/unistd/fpathconf.c b/libc/unistd/fpathconf.c
index 7b0457c75..fe4bcea67 100644
--- a/libc/unistd/fpathconf.c
+++ b/libc/unistd/fpathconf.c
@@ -13,9 +13,8 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#include <errno.h>
#include <unistd.h>
@@ -24,11 +23,7 @@
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/statfs.h>
-//#include <sys/statvfs.h>
-//#include "linux_fsinfo.h"
-
-libc_hidden_proto(fstat)
#ifndef __USE_FILE_OFFSET64
extern int fstatfs (int __fildes, struct statfs *__buf)
@@ -43,7 +38,6 @@ extern int fstatfs (int __fildes, struct statfs *__buf)
#endif
extern __typeof(fstatfs) __libc_fstatfs;
-libc_hidden_proto(__libc_fstatfs)
/* The Linux kernel headers mention this as a kind of generic value. */
#define LINUX_LINK_MAX 127
diff --git a/libc/unistd/getlogin.c b/libc/unistd/getlogin.c
index 1998a7fc8..b855e50ac 100644
--- a/libc/unistd/getlogin.c
+++ b/libc/unistd/getlogin.c
@@ -10,9 +10,6 @@
#include <unistd.h>
#include <stdio.h>
-/* Experimentally off - libc_hidden_proto(strcpy) */
-/* Experimentally off - libc_hidden_proto(strncpy) */
-libc_hidden_proto(getenv)
/* uClibc makes it policy to not mess with the utmp file whenever
* possible, since I consider utmp a complete waste of time. Since
@@ -20,7 +17,6 @@ libc_hidden_proto(getenv)
* the user specify whatever they want via the LOGNAME environment
* variable, or we return NULL if getenv() fails to find anything */
-libc_hidden_proto(getlogin)
char * getlogin(void)
{
return (getenv("LOGNAME"));
diff --git a/libc/unistd/getopt-susv3.c b/libc/unistd/getopt-susv3.c
index c22dd9ffb..49f9626bc 100644
--- a/libc/unistd/getopt-susv3.c
+++ b/libc/unistd/getopt-susv3.c
@@ -22,16 +22,7 @@
#include <string.h>
#include <stdio.h>
#include <getopt.h>
-
-libc_hidden_proto(fprintf)
-/* Experimentally off - libc_hidden_proto(strchr) */
-
-#ifdef __UCLIBC_MJN3_ONLY__
-#warning TODO: Enable gettext awareness.
-#endif /* __UCLIBC_MJN3_ONLY__ */
-
-#undef _
-#define _(X) X
+#include <libintl.h>
#ifdef __BCC__
static const char missing[] = "option requires an argument";
@@ -46,7 +37,6 @@ int optind = 1;
int optopt = 0;
char *optarg = NULL;
-libc_hidden_proto(getopt)
int getopt(int argc, char * const argv[], const char *optstring)
{
static const char *o; /* multi opt position */
diff --git a/libc/unistd/getopt.c b/libc/unistd/getopt.c
index ac005e4f8..db5e12c59 100644
--- a/libc/unistd/getopt.c
+++ b/libc/unistd/getopt.c
@@ -17,9 +17,8 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
/*
* Modified for uClibc by Manuel Novoa III on 1/5/01.
@@ -36,9 +35,6 @@
# include <config.h>
#endif
-#define __FORCE_GLIBC
-#include <features.h>
-
#include <stdio.h>
/* Comment out all this code if we are using the GNU C Library, and are not
@@ -62,7 +58,7 @@
/* This needs to come after some library #include
to get __GNU_LIBRARY__ defined. */
-#ifdef __GNU_LIBRARY__
+#if defined __GNU_LIBRARY__ || defined __UCLIBC__
/* Don't include stdlib.h for non-GNU C libraries because some of them
contain conflicting prototypes for getopt. */
# include <stdlib.h>
@@ -75,22 +71,12 @@
# include <unixlib.h>
#endif
-#if !defined __UCLIBC__ && !defined __UCLIBC_HAS_GETTEXT_AWARENESS__
#ifdef _LIBC
# include <libintl.h>
#else
# include "gettext.h"
# define _(msgid) gettext (msgid)
#endif
-#else
-#ifdef __UCLIBC_MJN3_ONLY__
-#warning TODO: Enable gettext awareness.
-#endif /* __UCLIBC_MJN3_ONLY__ */
-
-#undef _
-#define _(X) X
-
-#endif
/* Treat '-W foo' the same as the long option '--foo',
* disabled for the moment since it costs about 2k... */
@@ -119,14 +105,8 @@
they can distinguish the relative order of options and other arguments. */
#include <getopt.h>
-#include "getopt_int.h"
+#include <bits/getopt_int.h>
-/* Experimentally off - libc_hidden_proto(strchr) */
-/* Experimentally off - libc_hidden_proto(strcmp) */
-/* Experimentally off - libc_hidden_proto(strlen) */
-/* Experimentally off - libc_hidden_proto(strncmp) */
-libc_hidden_proto(getenv)
-libc_hidden_proto(fprintf)
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
@@ -167,7 +147,7 @@ int optopt = '?';
static struct _getopt_data getopt_data;
-#ifndef __GNU_LIBRARY__
+#if !defined __GNU_LIBRARY__ && !defined __UCLIBC__
/* Avoid depending on library functions or files
whose names are inconsistent. */
@@ -241,7 +221,7 @@ exchange (char **argv, struct _getopt_data *d)
d->__nonoption_flags_len = d->__nonoption_flags_max_len = 0;
else
{
- memset (__mempcpy (new_str, __getopt_nonoption_flags,
+ memset (mempcpy (new_str, __getopt_nonoption_flags,
d->__nonoption_flags_max_len),
'\0', top + 1 - d->__nonoption_flags_max_len);
d->__nonoption_flags_max_len = top + 1;
@@ -347,7 +327,7 @@ _getopt_initialize (attribute_unused int argc, attribute_unused char *const *arg
if (__getopt_nonoption_flags == NULL)
d->__nonoption_flags_max_len = -1;
else
- memset (__mempcpy (__getopt_nonoption_flags, orig_str, len),
+ memset (mempcpy (__getopt_nonoption_flags, orig_str, len),
'\0', d->__nonoption_flags_max_len - len);
}
}
@@ -1180,7 +1160,9 @@ getopt (int argc, char *const *argv, const char *optstring)
(int *) 0,
0);
}
+libc_hidden_def(getopt)
+#if defined __UCLIBC_HAS_GETOPT_LONG__
int
getopt_long (int argc, char *const *argv, const char *options,
const struct option *long_options, int *opt_index)
@@ -1188,6 +1170,15 @@ getopt_long (int argc, char *const *argv, const char *options,
return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
}
+int
+_getopt_long_r (int argc, char *const *argv, const char *options,
+ const struct option *long_options, int *opt_index,
+ struct _getopt_data *d)
+{
+ return _getopt_internal_r (argc, argv, options, long_options, opt_index,
+ 0, d);
+}
+
/* Like 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
@@ -1199,5 +1190,14 @@ getopt_long_only (int argc, char *const *argv, const char *options,
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
}
+#endif /* __UCLIBC_HAS_GETOPT_LONG__ */
+
+int
+_getopt_long_only_r (int argc, char *const *argv, const char *options,
+ const struct option *long_options, int *opt_index,
+ struct _getopt_data *d)
+{
+ return _getopt_internal_r (argc, argv, options, long_options, opt_index, 1, d);
+}
#endif /* Not ELIDE_CODE. */
diff --git a/libc/unistd/getopt_int.h b/libc/unistd/getopt_int.h
index a871785d1..a70fa8b92 100644
--- a/libc/unistd/getopt_int.h
+++ b/libc/unistd/getopt_int.h
@@ -14,9 +14,8 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#ifndef _GETOPT_INT_H
#define _GETOPT_INT_H 1
diff --git a/libc/unistd/getopt_long-simple.c b/libc/unistd/getopt_long-simple.c
index 2dae341a3..47612dfe6 100644
--- a/libc/unistd/getopt_long-simple.c
+++ b/libc/unistd/getopt_long-simple.c
@@ -8,7 +8,6 @@
#include <getopt.h>
#include <stdio.h>
-libc_hidden_proto(getopt)
static int __getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly)
{
diff --git a/libc/unistd/getpass.c b/libc/unistd/getpass.c
index d1100b308..c46d3d442 100644
--- a/libc/unistd/getpass.c
+++ b/libc/unistd/getpass.c
@@ -12,30 +12,17 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#include <stdio.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
+#include <malloc.h>
#if defined __USE_BSD || (defined __USE_XOPEN && !defined __USE_XOPEN2K)
-/* Experimentally off - libc_hidden_proto(strlen) */
-libc_hidden_proto(tcsetattr)
-libc_hidden_proto(tcgetattr)
-libc_hidden_proto(setvbuf)
-libc_hidden_proto(fopen)
-libc_hidden_proto(fclose)
-libc_hidden_proto(fileno)
-libc_hidden_proto(fflush)
-libc_hidden_proto(fgets)
-libc_hidden_proto(fputs)
-libc_hidden_proto(fputc)
-libc_hidden_proto(putc)
-libc_hidden_proto(__fputc_unlocked)
/* It is desirable to use this bit on systems that have it.
The only bit of terminal state we want to twiddle is echoing, which is
@@ -52,23 +39,31 @@ char * getpass (const char *prompt)
FILE *in, *out;
struct termios s, t;
int tty_changed;
- static char buf[PWD_BUFFER_SIZE];
+ static char *buf = NULL;
int nread;
+ if (buf == NULL)
+ buf = (char *)__uc_malloc(PWD_BUFFER_SIZE);
+
/* Try to write to and read from the terminal if we can.
If we can't open the terminal, use stderr and stdin. */
- in = fopen ("/dev/tty", "r+");
+ out = in = fopen ("/dev/tty", "r+");
if (in == NULL)
{
in = stdin;
out = stderr;
}
else
- out = in;
+ {
+ /* Disable buffering for read/write FILE to prevent problems with
+ * fseek and buffering for read/write auto-transitioning. */
+ setvbuf(in, NULL, _IONBF, 0);
+ }
/* Turn echoing off if it is on now. */
+ tty_changed = 0;
if (tcgetattr (fileno (in), &t) == 0)
{
/* Save the old one. */
@@ -76,41 +71,28 @@ char * getpass (const char *prompt)
/* Tricky, tricky. */
t.c_lflag &= ~(ECHO|ISIG);
tty_changed = (tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &t) == 0);
- if (in != stdin) {
- /* Disable buffering for read/write FILE to prevent problems with
- * fseek and buffering for read/write auto-transitioning. */
- setvbuf(in, NULL, _IONBF, 0);
- }
}
- else
- tty_changed = 0;
/* Write the prompt. */
fputs(prompt, out);
fflush(out);
/* Read the password. */
- fgets (buf, PWD_BUFFER_SIZE-1, in);
- if (buf != NULL)
+ if (!fgets (buf, PWD_BUFFER_SIZE, in))
+ buf[0] = '\0';
+ nread = strlen(buf);
+ if (nread > 0 && buf[nread - 1] == '\n')
+ /* Remove the newline. */
+ buf[nread - 1] = '\0';
+
+ if (tty_changed)
{
- nread = strlen(buf);
- if (nread < 0)
- buf[0] = '\0';
- else if (buf[nread - 1] == '\n')
- {
- /* Remove the newline. */
- buf[nread - 1] = '\0';
- if (tty_changed)
- /* Write the newline that was not echoed. */
- putc('\n', out);
- }
+ /* Write the newline that was not echoed. */
+ putc('\n', out);
+ /* Restore the original setting. */
+ (void) tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &s);
}
- /* Restore the original setting. */
- if (tty_changed) {
- (void) tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &s);
- }
-
if (in != stdin)
/* We opened the terminal; now close it. */
fclose (in);
diff --git a/libc/unistd/getsubopt-susv3.c b/libc/unistd/getsubopt-susv3.c
index 10c97ca9a..9ff33ef11 100644
--- a/libc/unistd/getsubopt-susv3.c
+++ b/libc/unistd/getsubopt-susv3.c
@@ -7,9 +7,6 @@
#include <stdlib.h>
#include <string.h>
-/* Experimentally off - libc_hidden_proto(strchr) */
-/* Experimentally off - libc_hidden_proto(strlen) */
-/* Experimentally off - libc_hidden_proto(strncmp) */
int getsubopt(char **opt, char *const *keys, char **val)
{
diff --git a/libc/unistd/getsubopt.c b/libc/unistd/getsubopt.c
index 301410232..6e4659523 100644
--- a/libc/unistd/getsubopt.c
+++ b/libc/unistd/getsubopt.c
@@ -14,16 +14,12 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
#include <stdlib.h>
#include <string.h>
-/* Experimentally off - libc_hidden_proto(memchr) */
-/* Experimentally off - libc_hidden_proto(strncmp) */
-/* Experimentally off - libc_hidden_proto(strchrnul) */
/* Parse comma separated suboption from *OPTIONP and match against
strings in TOKENS. If found return index and set *VALUEP to
diff --git a/libc/unistd/pathconf.c b/libc/unistd/pathconf.c
index 7f7efbb7f..de78a83e9 100644
--- a/libc/unistd/pathconf.c
+++ b/libc/unistd/pathconf.c
@@ -13,9 +13,8 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
/* pathconf -- adjusted for busybox */
@@ -29,11 +28,8 @@
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/statfs.h>
-//#include <sys/statvfs.h>
extern __typeof(statfs) __libc_statfs;
-libc_hidden_proto(__libc_statfs)
-libc_hidden_proto(stat)
/* The Linux kernel headers mention this as a kind of generic value. */
diff --git a/libc/unistd/sleep.c b/libc/unistd/sleep.c
index 435d105c5..9d50ee163 100644
--- a/libc/unistd/sleep.c
+++ b/libc/unistd/sleep.c
@@ -15,27 +15,62 @@
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ see <http://www.gnu.org/licenses/>. */
#include <errno.h>
#include <time.h>
#include <signal.h>
#include <unistd.h>
-libc_hidden_proto(sleep)
-
-libc_hidden_proto(sigaction)
-libc_hidden_proto(sigprocmask)
/* version perusing nanosleep */
#if defined __UCLIBC_HAS_REALTIME__
-//libc_hidden_proto(__sigaddset)
-//libc_hidden_proto(__sigemptyset)
-//libc_hidden_proto(__sigismember)
-/*libc_hidden_proto(nanosleep) need the reloc for cancellation*/
-#if 0
+/* I am unable to reproduce alleged "Linux quirk".
+ * I used the following test program:
+#include <unistd.h>
+#include <time.h>
+#include <signal.h>
+static void dummy(int sig) {}
+int main() {
+ struct timespec t = { 2, 0 };
+ if (fork() == 0) {
+ sleep(1);
+ return 0;
+ }
+ signal(SIGCHLD, SIG_DFL); //
+ signal(SIGCHLD, dummy); // Pick one
+ signal(SIGCHLD, SIG_IGN); //
+ nanosleep(&t, &t);
+ return 0;
+}
+ * Testing on 2.4.20 and on 2.6.35-rc4:
+ * With SIG_DFL, nanosleep is not interrupted by SIGCHLD. Ok.
+ * With dummy handler, nanosleep is interrupted by SIGCHLD. Ok.
+ * With SIG_IGN, nanosleep is NOT interrupted by SIGCHLD.
+ * It looks like sleep's workaround for SIG_IGN is no longer needed?
+ * The only emails I can find are from 1998 (!):
+ * ----------
+ * Subject: Re: sleep ignore sigchld
+ * From: Linus Torvalds <torvalds@transmeta.com>
+ * Date: Mon, 16 Nov 1998 11:02:15 -0800 (PST)
+ *
+ * On Mon, 16 Nov 1998, H. J. Lu wrote:
+ * > That is a kernel bug. SIGCHLD is a special one. Usually it cannot
+ * > be ignored. [snip...]
+ *
+ * No can do.
+ *
+ * "nanosleep()" is implemented in a bad way that makes it impossible to
+ * restart it cleanly. It was done that way because glibc wanted it that way,
+ * not because it's a good idea. [snip...]
+ * ----------
+ * I assume that in the passed twelve+ years, nanosleep got fixed,
+ * but the hack in sleep to work around broken nanosleep was never removed.
+ */
+
+# if 0
+
/* This is a quick and dirty, but not 100% compliant with
* the stupid SysV SIGCHLD vs. SIG_IGN behaviour. It is
* fine unless you are messing with SIGCHLD... */
@@ -48,7 +83,7 @@ unsigned int sleep (unsigned int sec)
return res;
}
-#else
+# else
/* We are going to use the `nanosleep' syscall of the kernel. But the
kernel does not implement the sstupid SysV SIGCHLD vs. SIG_IGN
@@ -56,69 +91,55 @@ unsigned int sleep (unsigned int sec)
unsigned int sleep (unsigned int seconds)
{
struct timespec ts = { .tv_sec = (long int) seconds, .tv_nsec = 0 };
- sigset_t set, oset;
+ sigset_t set;
+ struct sigaction oact;
unsigned int result;
/* This is not necessary but some buggy programs depend on this. */
- if (seconds == 0)
+ if (seconds == 0) {
+# ifdef CANCELLATION_P
+ int cancelhandling;
+ CANCELLATION_P (THREAD_SELF);
+# endif
return 0;
+ }
/* Linux will wake up the system call, nanosleep, when SIGCHLD
arrives even if SIGCHLD is ignored. We have to deal with it
- in libc. We block SIGCHLD first. */
- if (__sigemptyset (&set) < 0
- || __sigaddset (&set, SIGCHLD) < 0
- || sigprocmask (SIG_BLOCK, &set, &oset))
- return -1;
-
- /* If SIGCHLD is already blocked, we don't have to do anything. */
- if (!__sigismember (&oset, SIGCHLD))
- {
- int saved_errno;
- struct sigaction oact;
-
- if (__sigemptyset (&set) < 0 || __sigaddset (&set, SIGCHLD) < 0)
- return -1;
-
- /* We get the signal handler for SIGCHLD. */
- if (sigaction (SIGCHLD, (struct sigaction *) NULL, &oact) < 0)
- {
- saved_errno = errno;
- /* Restore the original signal mask. */
- (void) sigprocmask (SIG_SETMASK, &oset, (sigset_t *) NULL);
- __set_errno (saved_errno);
- return -1;
- }
-
- if (oact.sa_handler == SIG_IGN)
- {
- /* We should leave SIGCHLD blocked. */
- result = nanosleep (&ts, &ts);
-
- saved_errno = errno;
- /* Restore the original signal mask. */
- (void) sigprocmask (SIG_SETMASK, &oset, (sigset_t *) NULL);
- __set_errno (saved_errno);
- }
- else
- {
- /* We should unblock SIGCHLD. Restore the original signal mask. */
- (void) sigprocmask (SIG_SETMASK, &oset, (sigset_t *) NULL);
- result = nanosleep (&ts, &ts);
- }
+ in libc. */
+
+ __sigemptyset (&set);
+ __sigaddset (&set, SIGCHLD);
+
+ /* Is SIGCHLD set to SIG_IGN? */
+ sigaction (SIGCHLD, NULL, &oact); /* never fails */
+ if (oact.sa_handler == SIG_IGN) {
+ /* Yes. Block SIGCHLD, save old mask. */
+ sigprocmask (SIG_BLOCK, &set, &set); /* never fails */
}
- else
- result = nanosleep (&ts, &ts);
- if (result != 0)
- /* Round remaining time. */
+ /* Run nanosleep, with SIGCHLD blocked if SIGCHLD is SIG_IGNed. */
+ result = nanosleep (&ts, &ts);
+ if (result != 0) {
+ /* Got EINTR. Return remaining time. */
result = (unsigned int) ts.tv_sec + (ts.tv_nsec >= 500000000L);
+ }
+
+ if (!__sigismember (&set, SIGCHLD)) {
+ /* We did block SIGCHLD, and old mask had no SIGCHLD bit.
+ IOW: we need to unblock SIGCHLD now. Do it. */
+ /* this sigprocmask call never fails, thus never updates errno,
+ and therefore we don't need to save/restore it. */
+ sigprocmask (SIG_SETMASK, &set, NULL); /* never fails */
+ }
return result;
}
-#endif
+
+# endif
+
#else /* __UCLIBC_HAS_REALTIME__ */
-libc_hidden_proto(sigaction)
+
/* no nanosleep, use signals and alarm() */
static void sleep_alarm_handler(int attribute_unused sig)
{
@@ -136,29 +157,27 @@ unsigned int sleep (unsigned int seconds)
return 0;
/* block SIGALRM */
- if (__sigemptyset (&set) < 0
- || __sigaddset (&set, SIGALRM) < 0
- || sigprocmask (SIG_BLOCK, &set, &oset))
- return seconds;
+ __sigemptyset (&set);
+ __sigaddset (&set, SIGALRM);
+ sigprocmask (SIG_BLOCK, &set, &oset); /* can't fail */
act.sa_handler = sleep_alarm_handler;
act.sa_flags = 0;
act.sa_mask = oset;
- if (sigaction(SIGALRM, &act, &oact) < 0)
- return seconds;
+ sigaction(SIGALRM, &act, &oact); /* never fails */
before = time(NULL);
remaining = alarm(seconds);
if (remaining && remaining > seconds) {
/* restore user's alarm */
- (void) sigaction(SIGALRM, &oact, (struct sigaction *) NULL);
+ sigaction(SIGALRM, &oact, NULL);
alarm(remaining); /* restore old alarm */
sigsuspend(&oset);
after = time(NULL);
} else {
sigsuspend (&oset);
after = time(NULL);
- (void) sigaction (SIGALRM, &oact, NULL);
+ sigaction (SIGALRM, &oact, NULL);
}
result = after - before;
alarm(remaining > result ? remaining - result : 0);
@@ -168,5 +187,7 @@ unsigned int sleep (unsigned int seconds)
return result > seconds ? 0 : seconds - result;
}
+
#endif /* __UCLIBC_HAS_REALTIME__ */
+
libc_hidden_def(sleep)
diff --git a/libc/unistd/sysconf.c b/libc/unistd/sysconf.c
index 549c13ca6..503b39585 100644
--- a/libc/unistd/sysconf.c
+++ b/libc/unistd/sysconf.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 1991, 93, 95, 96, 97, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1991,1993,1995-1997,2000
+ Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -13,11 +14,11 @@
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ see <http://www.gnu.org/licenses/>. */
#define _XOPEN_SOURCE 500
#include <features.h>
+#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <grp.h>
@@ -30,14 +31,87 @@
#include <sys/syscall.h>
#include <sys/sysinfo.h>
#include <sys/types.h>
+#include <sys/param.h>
#ifdef __UCLIBC_HAS_REGEX__
#include <regex.h>
#endif
+#ifdef __UCLIBC_HAS_THREADS_NATIVE__
+#include <sysdep.h>
+#endif
+#include <sys/resource.h>
+#include <string.h>
+#include <dirent.h>
+#include "internal/parse_config.h"
+
+static int nprocessors_onln(void)
+{
+ char **l = NULL;
+ parser_t *p = config_open("/proc/stat");
+ int ret = 0;
+
+ if (p) {
+ while (config_read(p, &l, 2, 1, " ", 0))
+ if (l[0][0] == 'c'
+ && l[0][1] == 'p'
+ && l[0][2] == 'u'
+ && isdigit(l[0][3]))
+ ++ret;
+ } else if ((p = config_open("/proc/cpuinfo"))) {
+#if defined __sparc__
+ while (config_read(p, &l, 2, 2, "\0:", PARSE_NORMAL))
+ if (strncmp("ncpus active", l[0], 12) == 0) {
+ ret = atoi(l[1]);
+ break;
+ }
+#else
+ while (config_read(p, &l, 2, 2, "\0:\t", PARSE_NORMAL))
+ if (strcmp("processor", l[0]) == 0)
+ ++ret;
+#endif
+ }
+ config_close(p);
+ return ret != 0 ? ret : 1;
+}
-libc_hidden_proto(sysconf)
+#if defined __UCLIBC__ && !defined __UCLIBC_HAS_LFS__
+# define readdir64 readdir
+# define dirent64 dirent
+#endif
+static int nprocessors_conf(void)
+{
+ int ret = 0;
+ DIR *dir = opendir("/sys/devices/system/cpu");
+
+ if (dir) {
+ struct dirent64 *dp;
+
+ while ((dp = readdir64(dir))) {
+ if (dp->d_type == DT_DIR
+ && dp->d_name[0] == 'c'
+ && dp->d_name[1] == 'p'
+ && dp->d_name[2] == 'u'
+ && isdigit(dp->d_name[3]))
+ ++ret;
+ }
+ closedir(dir);
+ } else
+ {
+#if defined __sparc__
+ char **l = NULL;
+ parser_t *p = config_open("/proc/stat");
+ while (config_read(p, &l, 2, 2, "\0:", PARSE_NORMAL))
+ if (strncmp("ncpus probed", l[0], 13) == 0) {
+ ret = atoi(l[1]);
+ break;
+ }
+ config_close(p);
+#else
+ ret = nprocessors_onln();
+#endif
+ }
+ return ret != 0 ? ret : 1;
+}
-libc_hidden_proto(getpagesize)
-libc_hidden_proto(getdtablesize)
#ifndef __UCLIBC_CLK_TCK_CONST
#error __UCLIBC_CLK_TCK_CONST not defined!
@@ -73,9 +147,15 @@ libc_hidden_proto(getdtablesize)
#define RETURN_FUNCTION(f) return f;
#endif /* _UCLIBC_GENERATE_SYSCONF_ARCH */
+/* Legacy value of ARG_MAX. The macro is now not defined since the
+ actual value varies based on the stack size. */
+#define legacy_ARG_MAX 131072
+
/* Get the value of the system variable NAME. */
long int sysconf(int name)
{
+ struct rlimit rlimit;
+
switch (name)
{
default:
@@ -83,10 +163,13 @@ long int sysconf(int name)
return -1;
case _SC_ARG_MAX:
-#ifdef ARG_MAX
+ /* Use getrlimit to get the stack limit. */
+ if (getrlimit (RLIMIT_STACK, &rlimit) == 0)
+ return MAX (legacy_ARG_MAX, rlimit.rlim_cur / 4);
+#if defined ARG_MAX
return ARG_MAX;
#else
- RETURN_NEG_1;
+ return legacy_ARG_MAX;
#endif
case _SC_CHILD_MAX:
@@ -658,20 +741,10 @@ long int sysconf(int name)
#endif
case _SC_NPROCESSORS_CONF:
-#if 0
- RETURN_FUNCTION(get_nprocs_conf());
-#else
- /* this is a hack. for now always claim we have exactly one cpu */
- return 1;
-#endif
+ RETURN_FUNCTION(nprocessors_conf());
case _SC_NPROCESSORS_ONLN:
-#if 0
- RETURN_FUNCTION(get_nprocs());
-#else
- /* this is a hack. for now always claim we have exactly one cpu */
- return 1;
-#endif
+ RETURN_FUNCTION(nprocessors_onln());
case _SC_PHYS_PAGES:
#if 0
@@ -866,6 +939,30 @@ long int sysconf(int name)
#else
RETURN_NEG_1;
#endif
+ case _SC_V7_ILP32_OFF32:
+#ifdef _POSIX_V7_ILP32_OFF32
+ return _POSIX_V7_ILP32_OFF32;
+#else
+ RETURN_NEG_1;
+#endif
+ case _SC_V7_ILP32_OFFBIG:
+#ifdef _POSIX_V7_ILP32_OFFBIG
+ return _POSIX_V7_ILP32_OFFBIG;
+#else
+ RETURN_NEG_1;
+#endif
+ case _SC_V7_LP64_OFF64:
+#ifdef _POSIX_V7_LP64_OFF64
+ return _POSIX_V7_LP64_OFF64;
+#else
+ RETURN_NEG_1;
+#endif
+ case _SC_V7_LPBIG_OFFBIG:
+#ifdef _POSIX_V7_LPBIG_OFFBIG
+ return _POSIX_V7_LPBIG_OFFBIG;
+#else
+ RETURN_NEG_1;
+#endif
case _SC_XOPEN_LEGACY:
return _XOPEN_LEGACY;
@@ -885,12 +982,19 @@ long int sysconf(int name)
case _SC_MONOTONIC_CLOCK:
#if defined __UCLIBC_HAS_REALTIME__ && defined __NR_clock_getres
- /* Check using the clock_getres system call. */
if (clock_getres(CLOCK_MONOTONIC, NULL) >= 0)
return _POSIX_VERSION;
#endif
+ RETURN_NEG_1;
+#ifdef __UCLIBC_HAS_THREADS_NATIVE__
+ case _SC_THREAD_CPUTIME:
+# if _POSIX_THREAD_CPUTIME > 0
+ return _POSIX_THREAD_CPUTIME;
+# else
RETURN_NEG_1;
+# endif
+#endif
}
}
libc_hidden_def(sysconf)
diff --git a/libc/unistd/ualarm.c b/libc/unistd/ualarm.c
index 07bea2a50..82eb972b2 100644
--- a/libc/unistd/ualarm.c
+++ b/libc/unistd/ualarm.c
@@ -9,7 +9,6 @@
#include <sys/types.h>
#include <unistd.h>
-libc_hidden_proto(setitimer)
useconds_t ualarm(useconds_t value, useconds_t interval)
{
diff --git a/libc/unistd/usershell.c b/libc/unistd/usershell.c
index 1bf143daf..261c1c10c 100644
--- a/libc/unistd/usershell.c
+++ b/libc/unistd/usershell.c
@@ -1,146 +1,78 @@
-/*
- * Copyright (c) 1985, 1993
- * The Regents of the University of California. All rights reserved.
+/* setusershell(), getusershell(), endusershell() for uClibc.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
+ * Copyright (C) 2010 Bernhard Reutner-Fischer <uclibc@uclibc.org>
*
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * This version has been hevily modified for use with uClibc
- * November 2002, Erik Andersen <andersen@codepoet.org>
+ * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in
+ * this tarball.
+ */
+/* My manpage reads:
+ * The getusershell() function returns the next line from the file
+ * /etc/shells, opening the file if necessary. The line should contain
+ * the pathname of a valid user shell. If /etc/shells does not exist
+ * or is unreadable, getusershell() behaves as if /bin/sh and /bin/csh
+ * were listed in the file.
+ * The getusershell() function returns a NULL pointer on end-of-file.
*/
-
-#include <sys/param.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <stdio.h>
-#include <stdio_ext.h>
-#include <ctype.h>
-#include <stdlib.h>
#include <unistd.h>
+#include <stdlib.h>
#include <paths.h>
+#include <string.h>
+#include "internal/parse_config.h"
#if defined __USE_BSD || (defined __USE_XOPEN && !defined __USE_UNIX98)
-libc_hidden_proto(fstat)
-libc_hidden_proto(fopen)
-libc_hidden_proto(fclose)
-libc_hidden_proto(__fsetlocking)
-libc_hidden_proto(fileno)
-libc_hidden_proto(fgets_unlocked)
-#ifdef __UCLIBC_HAS_XLOCALE__
-libc_hidden_proto(__ctype_b_loc)
-#elif defined __UCLIBC_HAS_CTYPE_TABLES__
-libc_hidden_proto(__ctype_b)
-#endif
-
-/*
- * Local shells should NOT be added here. They should be added in
- * /etc/shells.
- */
-
-static const char * const validsh[] = { _PATH_BSHELL, _PATH_CSHELL, NULL };
-static char **curshell, **shells, *strings;
-static char **initshells __P((void));
-
-/*
- * Get a list of shells from _PATH_SHELLS, if it exists.
- */
-char * getusershell(void)
-{
- char *ret;
-
- if (curshell == NULL)
- curshell = initshells();
- ret = *curshell;
- if (ret != NULL)
- curshell++;
- return (ret);
-}
-
-static void __free_initshell_memory(void)
-{
- free(shells);
- shells = NULL;
- free(strings);
- strings = NULL;
-}
+static const char * const defaultsh[] = { _PATH_BSHELL, _PATH_CSHELL, NULL};
+static char *shellb, **shells;
+static parser_t *shellp;
void endusershell(void)
{
- __free_initshell_memory();
- curshell = NULL;
+ if (shellp) {
+ shells = (char**) shellb;
+ while (shells && *shells) {
+ char*xxx = *shells++;
+ free(xxx);
+ }
+ config_close(shellp);
+ shellp = NULL;
+ }
+ free(shellb);
+ shellb = NULL;
+ shells = NULL;
}
+libc_hidden_def(endusershell)
void setusershell(void)
{
- curshell = initshells();
-}
+ endusershell();
+ shellp = config_open(_PATH_SHELLS);
+ if (shellp == NULL)
+ shells = (char **)defaultsh;
+ else {
+ char **shell = NULL;
+ int pos = 0;
-static char ** initshells(void)
-{
- register char **sp, *cp;
- register FILE *fp;
- struct stat statb;
- int flen;
-
- __free_initshell_memory();
+ while (config_read(shellp, &shell, 1, 1, "# \t", PARSE_NORMAL))
+ {
+ shellb = realloc(shellb, (pos + 2) * sizeof(char*));
+ shells = (char**) shellb + pos++;
+ *shells++ = strdup(*shell);
+ *shells = NULL;
- if ((fp = fopen(_PATH_SHELLS, "r")) == NULL)
- return (char **) validsh;
- if (fstat(fileno(fp), &statb) == -1) {
- goto cleanup;
- }
- if ((strings = malloc((unsigned)statb.st_size + 1)) == NULL) {
- goto cleanup;
- }
- if ((shells = calloc((unsigned)statb.st_size / 3, sizeof (char *))) == NULL) {
- goto cleanup;
- }
- /* No threads using this stream. */
-#ifdef __UCLIBC_HAS_THREADS__
- __fsetlocking (fp, FSETLOCKING_BYCALLER);
-#endif
- sp = shells;
- cp = strings;
- flen = statb.st_size;
- while (fgets_unlocked(cp, flen - (cp - strings), fp) != NULL) {
- while (*cp != '#' && *cp != '/' && *cp != '\0')
- cp++;
- if (*cp == '#' || *cp == '\0')
- continue;
- *sp++ = cp;
- while (!isspace(*cp) && *cp != '#' && *cp != '\0')
- cp++;
- *cp++ = '\0';
- }
- *sp = NULL;
- fclose(fp);
- return (shells);
+ }
+ shells = (char **)shellb;
+ }
+}
+libc_hidden_def(setusershell)
-cleanup:
- __free_initshell_memory();
- fclose(fp);
- return (char **) validsh;
+char *getusershell(void)
+{
+ char *sh;
+ if (shells == NULL)
+ setusershell();
+ sh = *shells;
+ if (sh)
+ shells++;
+ return sh;
}
#endif
diff --git a/libc/unistd/usleep.c b/libc/unistd/usleep.c
index 8a27f900a..8d01703ec 100644
--- a/libc/unistd/usleep.c
+++ b/libc/unistd/usleep.c
@@ -11,24 +11,22 @@
#if defined __USE_BSD || defined __USE_POSIX98
#if defined __UCLIBC_HAS_REALTIME__
-/*libc_hidden_proto(nanosleep) need the reloc for cancellation*/
int usleep (__useconds_t usec)
{
- const struct timespec ts = {
- .tv_sec = (long int) (usec / 1000000),
- .tv_nsec = (long int) (usec % 1000000) * 1000ul
- };
- return(nanosleep(&ts, NULL));
+ const struct timespec ts = {
+ .tv_sec = (long int) (usec / 1000000),
+ .tv_nsec = (long int) (usec % 1000000) * 1000ul
+ };
+ return nanosleep(&ts, NULL);
}
#else /* __UCLIBC_HAS_REALTIME__ */
-libc_hidden_proto(select)
int usleep (__useconds_t usec)
{
struct timeval tv;
- tv.tv_sec = 0;
- tv.tv_usec = usec;
+ tv.tv_sec = (long int) (usec / 1000000);
+ tv.tv_usec = (long int) (usec % 1000000);
return select(0, NULL, NULL, NULL, &tv);
}
#endif /* __UCLIBC_HAS_REALTIME__ */