diff options
Diffstat (limited to 'libc/unistd')
| -rw-r--r-- | libc/unistd/Makefile.in | 50 | ||||
| -rw-r--r-- | libc/unistd/confstr.c | 26 | ||||
| -rw-r--r-- | libc/unistd/daemon.c | 109 | ||||
| -rw-r--r-- | libc/unistd/exec.c | 58 | ||||
| -rw-r--r-- | libc/unistd/execvpe.c | 7 | ||||
| -rw-r--r-- | libc/unistd/fpathconf.c | 10 | ||||
| -rw-r--r-- | libc/unistd/getlogin.c | 4 | ||||
| -rw-r--r-- | libc/unistd/getopt-susv3.c | 12 | ||||
| -rw-r--r-- | libc/unistd/getopt.c | 54 | ||||
| -rw-r--r-- | libc/unistd/getopt_int.h | 5 | ||||
| -rw-r--r-- | libc/unistd/getopt_long-simple.c | 1 | ||||
| -rw-r--r-- | libc/unistd/getpass.c | 70 | ||||
| -rw-r--r-- | libc/unistd/getsubopt-susv3.c | 3 | ||||
| -rw-r--r-- | libc/unistd/getsubopt.c | 8 | ||||
| -rw-r--r-- | libc/unistd/pathconf.c | 8 | ||||
| -rw-r--r-- | libc/unistd/sleep.c | 159 | ||||
| -rw-r--r-- | libc/unistd/sysconf.c | 146 | ||||
| -rw-r--r-- | libc/unistd/ualarm.c | 1 | ||||
| -rw-r--r-- | libc/unistd/usershell.c | 184 | ||||
| -rw-r--r-- | libc/unistd/usleep.c | 16 |
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__ */ |
