mirror of
https://gitlab.redox-os.org/redox-os/redox.git
synced 2026-06-19 19:34:18 +08:00
1462 lines
37 KiB
Diff
1462 lines
37 KiB
Diff
diff -ruwN source/config-top.h source-new/config-top.h
|
|
--- source/config-top.h 2016-05-19 12:34:02.000000000 -0600
|
|
+++ source-new/config-top.h 2019-01-28 12:42:45.660815213 -0700
|
|
@@ -63,14 +63,14 @@
|
|
/* The default value of the PATH variable. */
|
|
#ifndef DEFAULT_PATH_VALUE
|
|
#define DEFAULT_PATH_VALUE \
|
|
- "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:."
|
|
+ "/usr/local/bin;/usr/local/sbin;/usr/bin;/usr/sbin;/bin;/sbin;."
|
|
#endif
|
|
|
|
/* The value for PATH when invoking `command -p'. This is only used when
|
|
the Posix.2 confstr () function, or CS_PATH define are not present. */
|
|
#ifndef STANDARD_UTILS_PATH
|
|
#define STANDARD_UTILS_PATH \
|
|
- "/bin:/usr/bin:/sbin:/usr/sbin:/etc:/usr/etc"
|
|
+ "/bin;/usr/bin;/sbin;/usr/sbin;/etc;/usr/etc"
|
|
#endif
|
|
|
|
/* Default primary and secondary prompt strings. */
|
|
diff -ruwN source/configure.ac source-new/configure.ac
|
|
--- source/configure.ac 2016-09-07 14:56:28.000000000 -0600
|
|
+++ source-new/configure.ac 2019-01-28 13:53:45.000616985 -0700
|
|
@@ -90,6 +90,7 @@
|
|
*-opennt*|*-interix*) opt_bash_malloc=no ;; # Interix, now owned by Microsoft
|
|
*-nsk*) opt_bash_malloc=no ;; # HP NonStop
|
|
*-haiku*) opt_bash_malloc=no ;; # Haiku OS
|
|
+*-redox*) opt_bash_malloc=no ;; # Redox OS
|
|
esac
|
|
|
|
# memory scrambling on free()
|
|
diff -ruwN source/execute_cmd.c source-new/execute_cmd.c
|
|
--- source/execute_cmd.c 2016-08-26 05:10:08.000000000 -0600
|
|
+++ source-new/execute_cmd.c 2019-01-28 12:42:52.680865726 -0700
|
|
@@ -1335,15 +1335,17 @@
|
|
nullcmd = (command == 0) || (command->type == cm_simple && command->value.Simple->words == 0 && command->value.Simple->redirects == 0);
|
|
if (posixly_correct && nullcmd)
|
|
{
|
|
-#if defined (HAVE_GETRUSAGE)
|
|
+#if defined (HAVE_GETRUSAGE) && defined (HAVE_GETTIMEOFDAY)
|
|
selfb.ru_utime.tv_sec = kidsb.ru_utime.tv_sec = selfb.ru_stime.tv_sec = kidsb.ru_stime.tv_sec = 0;
|
|
selfb.ru_utime.tv_usec = kidsb.ru_utime.tv_usec = selfb.ru_stime.tv_usec = kidsb.ru_stime.tv_usec = 0;
|
|
before.tv_sec = shell_start_time;
|
|
before.tv_usec = 0;
|
|
#else
|
|
+# if defined (HAVE_TIMES)
|
|
before.tms_utime = before.tms_stime = before.tms_cutime = before.tms_cstime = 0;
|
|
tbefore = shell_start_time;
|
|
#endif
|
|
+#endif
|
|
}
|
|
|
|
old_flags = command->flags;
|
|
diff -ruwN source/general.c source-new/general.c
|
|
--- source/general.c 2016-08-11 09:16:56.000000000 -0600
|
|
+++ source-new/general.c 2019-01-28 12:45:41.801895779 -0700
|
|
@@ -476,6 +476,7 @@
|
|
void
|
|
check_dev_tty ()
|
|
{
|
|
+#if !defined(__redox__)
|
|
int tty_fd;
|
|
char *tty;
|
|
|
|
@@ -490,6 +491,7 @@
|
|
}
|
|
if (tty_fd >= 0)
|
|
close (tty_fd);
|
|
+#endif
|
|
}
|
|
|
|
/* Return 1 if PATH1 and PATH2 are the same file. This is kind of
|
|
@@ -909,10 +911,10 @@
|
|
`:'. If I is 0, then the path has a leading colon. Trailing colons
|
|
are handled OK by the `else' part of the if statement; an empty
|
|
string is returned in that case. */
|
|
- if (i && string[i] == ':')
|
|
+ if (i && string[i] == ';')
|
|
i++;
|
|
|
|
- for (start = i; string[i] && string[i] != ':'; i++)
|
|
+ for (start = i; string[i] && string[i] != ';'; i++)
|
|
;
|
|
|
|
*p_index = i;
|
|
diff -ruwN source/general.c.orig source-new/general.c.orig
|
|
--- source/general.c.orig 1969-12-31 17:00:00.000000000 -0700
|
|
+++ source-new/general.c.orig 2019-01-28 12:42:40.972781097 -0700
|
|
@@ -0,0 +1,1325 @@
|
|
+/* general.c -- Stuff that is used by all files. */
|
|
+
|
|
+/* Copyright (C) 1987-2016 Free Software Foundation, Inc.
|
|
+
|
|
+ This file is part of GNU Bash, the Bourne Again SHell.
|
|
+
|
|
+ Bash is free software: you can redistribute it and/or modify
|
|
+ it under the terms of the GNU General Public License as published by
|
|
+ the Free Software Foundation, either version 3 of the License, or
|
|
+ (at your option) any later version.
|
|
+
|
|
+ Bash is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ GNU General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU General Public License
|
|
+ along with Bash. If not, see <http://www.gnu.org/licenses/>.
|
|
+*/
|
|
+
|
|
+#include "config.h"
|
|
+
|
|
+#include "bashtypes.h"
|
|
+#if defined (HAVE_SYS_PARAM_H)
|
|
+# include <sys/param.h>
|
|
+#endif
|
|
+#include "posixstat.h"
|
|
+
|
|
+#if defined (HAVE_UNISTD_H)
|
|
+# include <unistd.h>
|
|
+#endif
|
|
+
|
|
+#include "filecntl.h"
|
|
+#include "bashansi.h"
|
|
+#include <stdio.h>
|
|
+#include "chartypes.h"
|
|
+#include <errno.h>
|
|
+
|
|
+#include "bashintl.h"
|
|
+
|
|
+#include "shell.h"
|
|
+#include "test.h"
|
|
+#include "trap.h"
|
|
+
|
|
+#if defined (HAVE_MBSTR_H) && defined (HAVE_MBSCHR)
|
|
+# include <mbstr.h> /* mbschr */
|
|
+#endif
|
|
+
|
|
+#include <tilde/tilde.h>
|
|
+
|
|
+#if !defined (errno)
|
|
+extern int errno;
|
|
+#endif /* !errno */
|
|
+
|
|
+extern int expand_aliases;
|
|
+extern int interactive_comments;
|
|
+extern int check_hashed_filenames;
|
|
+extern int source_uses_path;
|
|
+extern int source_searches_cwd;
|
|
+extern int posixly_correct;
|
|
+extern int inherit_errexit;
|
|
+
|
|
+static char *bash_special_tilde_expansions __P((char *));
|
|
+static int unquoted_tilde_word __P((const char *));
|
|
+static void initialize_group_array __P((void));
|
|
+
|
|
+/* A standard error message to use when getcwd() returns NULL. */
|
|
+const char * const bash_getcwd_errstr = N_("getcwd: cannot access parent directories");
|
|
+
|
|
+/* Do whatever is necessary to initialize `Posix mode'. */
|
|
+void
|
|
+posix_initialize (on)
|
|
+ int on;
|
|
+{
|
|
+ /* Things that should be turned on when posix mode is enabled. */
|
|
+ if (on != 0)
|
|
+ {
|
|
+ interactive_comments = source_uses_path = expand_aliases = 1;
|
|
+ inherit_errexit = 1;
|
|
+ source_searches_cwd = 0;
|
|
+ }
|
|
+
|
|
+ /* Things that should be turned on when posix mode is disabled. */
|
|
+ if (on == 0)
|
|
+ {
|
|
+ source_searches_cwd = 1;
|
|
+ expand_aliases = interactive_shell;
|
|
+ }
|
|
+}
|
|
+
|
|
+/* **************************************************************** */
|
|
+/* */
|
|
+/* Functions to convert to and from and display non-standard types */
|
|
+/* */
|
|
+/* **************************************************************** */
|
|
+
|
|
+#if defined (RLIMTYPE)
|
|
+RLIMTYPE
|
|
+string_to_rlimtype (s)
|
|
+ char *s;
|
|
+{
|
|
+ RLIMTYPE ret;
|
|
+ int neg;
|
|
+
|
|
+ ret = 0;
|
|
+ neg = 0;
|
|
+ while (s && *s && whitespace (*s))
|
|
+ s++;
|
|
+ if (s && (*s == '-' || *s == '+'))
|
|
+ {
|
|
+ neg = *s == '-';
|
|
+ s++;
|
|
+ }
|
|
+ for ( ; s && *s && DIGIT (*s); s++)
|
|
+ ret = (ret * 10) + TODIGIT (*s);
|
|
+ return (neg ? -ret : ret);
|
|
+}
|
|
+
|
|
+void
|
|
+print_rlimtype (n, addnl)
|
|
+ RLIMTYPE n;
|
|
+ int addnl;
|
|
+{
|
|
+ char s[INT_STRLEN_BOUND (RLIMTYPE) + 1], *p;
|
|
+
|
|
+ p = s + sizeof(s);
|
|
+ *--p = '\0';
|
|
+
|
|
+ if (n < 0)
|
|
+ {
|
|
+ do
|
|
+ *--p = '0' - n % 10;
|
|
+ while ((n /= 10) != 0);
|
|
+
|
|
+ *--p = '-';
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ do
|
|
+ *--p = '0' + n % 10;
|
|
+ while ((n /= 10) != 0);
|
|
+ }
|
|
+
|
|
+ printf ("%s%s", p, addnl ? "\n" : "");
|
|
+}
|
|
+#endif /* RLIMTYPE */
|
|
+
|
|
+/* **************************************************************** */
|
|
+/* */
|
|
+/* Input Validation Functions */
|
|
+/* */
|
|
+/* **************************************************************** */
|
|
+
|
|
+/* Return non-zero if all of the characters in STRING are digits. */
|
|
+int
|
|
+all_digits (string)
|
|
+ const char *string;
|
|
+{
|
|
+ register const char *s;
|
|
+
|
|
+ for (s = string; *s; s++)
|
|
+ if (DIGIT (*s) == 0)
|
|
+ return (0);
|
|
+
|
|
+ return (1);
|
|
+}
|
|
+
|
|
+/* Return non-zero if the characters pointed to by STRING constitute a
|
|
+ valid number. Stuff the converted number into RESULT if RESULT is
|
|
+ not null. */
|
|
+int
|
|
+legal_number (string, result)
|
|
+ const char *string;
|
|
+ intmax_t *result;
|
|
+{
|
|
+ intmax_t value;
|
|
+ char *ep;
|
|
+
|
|
+ if (result)
|
|
+ *result = 0;
|
|
+
|
|
+ if (string == 0)
|
|
+ return 0;
|
|
+
|
|
+ errno = 0;
|
|
+ value = strtoimax (string, &ep, 10);
|
|
+ if (errno || ep == string)
|
|
+ return 0; /* errno is set on overflow or underflow */
|
|
+
|
|
+ /* Skip any trailing whitespace, since strtoimax does not. */
|
|
+ while (whitespace (*ep))
|
|
+ ep++;
|
|
+
|
|
+ /* If *string is not '\0' but *ep is '\0' on return, the entire string
|
|
+ is valid. */
|
|
+ if (*string && *ep == '\0')
|
|
+ {
|
|
+ if (result)
|
|
+ *result = value;
|
|
+ /* The SunOS4 implementation of strtol() will happily ignore
|
|
+ overflow conditions, so this cannot do overflow correctly
|
|
+ on those systems. */
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+/* Return 1 if this token is a legal shell `identifier'; that is, it consists
|
|
+ solely of letters, digits, and underscores, and does not begin with a
|
|
+ digit. */
|
|
+int
|
|
+legal_identifier (name)
|
|
+ const char *name;
|
|
+{
|
|
+ register const char *s;
|
|
+ unsigned char c;
|
|
+
|
|
+ if (!name || !(c = *name) || (legal_variable_starter (c) == 0))
|
|
+ return (0);
|
|
+
|
|
+ for (s = name + 1; (c = *s) != 0; s++)
|
|
+ {
|
|
+ if (legal_variable_char (c) == 0)
|
|
+ return (0);
|
|
+ }
|
|
+ return (1);
|
|
+}
|
|
+
|
|
+/* Return 1 if NAME is a valid value that can be assigned to a nameref
|
|
+ variable. FLAGS can be 2, in which case the name is going to be used
|
|
+ to create a variable. Other values are currently unused, but could
|
|
+ be used to allow values to be stored and indirectly referenced, but
|
|
+ not used in assignments. */
|
|
+int
|
|
+valid_nameref_value (name, flags)
|
|
+ const char *name;
|
|
+ int flags;
|
|
+{
|
|
+ if (name == 0 || *name == 0)
|
|
+ return 0;
|
|
+
|
|
+ /* valid identifier */
|
|
+#if defined (ARRAY_VARS)
|
|
+ if (legal_identifier (name) || (flags != 2 && valid_array_reference (name, 0)))
|
|
+#else
|
|
+ if (legal_identifier (name))
|
|
+#endif
|
|
+ return 1;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int
|
|
+check_selfref (name, value, flags)
|
|
+ const char *name;
|
|
+ char *value;
|
|
+ int flags;
|
|
+{
|
|
+ char *t;
|
|
+
|
|
+ if (STREQ (name, value))
|
|
+ return 1;
|
|
+
|
|
+#if defined (ARRAY_VARS)
|
|
+ if (valid_array_reference (value, 0))
|
|
+ {
|
|
+ t = array_variable_name (value, (char **)NULL, (int *)NULL);
|
|
+ if (t && STREQ (name, t))
|
|
+ {
|
|
+ free (t);
|
|
+ return 1;
|
|
+ }
|
|
+ free (t);
|
|
+ }
|
|
+#endif
|
|
+
|
|
+ return 0; /* not a self reference */
|
|
+}
|
|
+
|
|
+/* Make sure that WORD is a valid shell identifier, i.e.
|
|
+ does not contain a dollar sign, nor is quoted in any way. Nor
|
|
+ does it consist of all digits. If CHECK_WORD is non-zero,
|
|
+ the word is checked to ensure that it consists of only letters,
|
|
+ digits, and underscores. */
|
|
+int
|
|
+check_identifier (word, check_word)
|
|
+ WORD_DESC *word;
|
|
+ int check_word;
|
|
+{
|
|
+ if ((word->flags & (W_HASDOLLAR|W_QUOTED)) || all_digits (word->word))
|
|
+ {
|
|
+ internal_error (_("`%s': not a valid identifier"), word->word);
|
|
+ return (0);
|
|
+ }
|
|
+ else if (check_word && legal_identifier (word->word) == 0)
|
|
+ {
|
|
+ internal_error (_("`%s': not a valid identifier"), word->word);
|
|
+ return (0);
|
|
+ }
|
|
+ else
|
|
+ return (1);
|
|
+}
|
|
+
|
|
+/* Return 1 if STRING is a function name that the shell will import from
|
|
+ the environment. Currently we reject attempts to import shell functions
|
|
+ containing slashes, beginning with newlines or containing blanks. In
|
|
+ Posix mode, we require that STRING be a valid shell identifier. Not
|
|
+ used yet. */
|
|
+int
|
|
+importable_function_name (string, len)
|
|
+ const char *string;
|
|
+ size_t len;
|
|
+{
|
|
+ if (absolute_program (string)) /* don't allow slash */
|
|
+ return 0;
|
|
+ if (*string == '\n') /* can't start with a newline */
|
|
+ return 0;
|
|
+ if (shellblank (*string) || shellblank(string[len-1]))
|
|
+ return 0;
|
|
+ return (posixly_correct ? legal_identifier (string) : 1);
|
|
+}
|
|
+
|
|
+int
|
|
+exportable_function_name (string)
|
|
+ const char *string;
|
|
+{
|
|
+ if (absolute_program (string))
|
|
+ return 0;
|
|
+ if (mbschr (string, '=') != 0)
|
|
+ return 0;
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+/* Return 1 if STRING comprises a valid alias name. The shell accepts
|
|
+ essentially all characters except those which must be quoted to the
|
|
+ parser (which disqualifies them from alias expansion anyway) and `/'. */
|
|
+int
|
|
+legal_alias_name (string, flags)
|
|
+ const char *string;
|
|
+ int flags;
|
|
+{
|
|
+ register const char *s;
|
|
+
|
|
+ for (s = string; *s; s++)
|
|
+ if (shellbreak (*s) || shellxquote (*s) || shellexp (*s) || (*s == '/'))
|
|
+ return 0;
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+/* Returns non-zero if STRING is an assignment statement. The returned value
|
|
+ is the index of the `=' sign. */
|
|
+int
|
|
+assignment (string, flags)
|
|
+ const char *string;
|
|
+ int flags;
|
|
+{
|
|
+ register unsigned char c;
|
|
+ register int newi, indx;
|
|
+
|
|
+ c = string[indx = 0];
|
|
+
|
|
+#if defined (ARRAY_VARS)
|
|
+ if ((legal_variable_starter (c) == 0) && (flags == 0 || c != '[')) /* ] */
|
|
+#else
|
|
+ if (legal_variable_starter (c) == 0)
|
|
+#endif
|
|
+ return (0);
|
|
+
|
|
+ while (c = string[indx])
|
|
+ {
|
|
+ /* The following is safe. Note that '=' at the start of a word
|
|
+ is not an assignment statement. */
|
|
+ if (c == '=')
|
|
+ return (indx);
|
|
+
|
|
+#if defined (ARRAY_VARS)
|
|
+ if (c == '[')
|
|
+ {
|
|
+ newi = skipsubscript (string, indx, 0);
|
|
+ if (string[newi++] != ']')
|
|
+ return (0);
|
|
+ if (string[newi] == '+' && string[newi+1] == '=')
|
|
+ return (newi + 1);
|
|
+ return ((string[newi] == '=') ? newi : 0);
|
|
+ }
|
|
+#endif /* ARRAY_VARS */
|
|
+
|
|
+ /* Check for `+=' */
|
|
+ if (c == '+' && string[indx+1] == '=')
|
|
+ return (indx + 1);
|
|
+
|
|
+ /* Variable names in assignment statements may contain only letters,
|
|
+ digits, and `_'. */
|
|
+ if (legal_variable_char (c) == 0)
|
|
+ return (0);
|
|
+
|
|
+ indx++;
|
|
+ }
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+/* **************************************************************** */
|
|
+/* */
|
|
+/* Functions to manage files and file descriptors */
|
|
+/* */
|
|
+/* **************************************************************** */
|
|
+
|
|
+/* A function to unset no-delay mode on a file descriptor. Used in shell.c
|
|
+ to unset it on the fd passed as stdin. Should be called on stdin if
|
|
+ readline gets an EAGAIN or EWOULDBLOCK when trying to read input. */
|
|
+
|
|
+#if !defined (O_NDELAY)
|
|
+# if defined (FNDELAY)
|
|
+# define O_NDELAY FNDELAY
|
|
+# endif
|
|
+#endif /* O_NDELAY */
|
|
+
|
|
+/* Make sure no-delay mode is not set on file descriptor FD. */
|
|
+int
|
|
+sh_unset_nodelay_mode (fd)
|
|
+ int fd;
|
|
+{
|
|
+ int flags, bflags;
|
|
+
|
|
+ if ((flags = fcntl (fd, F_GETFL, 0)) < 0)
|
|
+ return -1;
|
|
+
|
|
+ bflags = 0;
|
|
+
|
|
+ /* This is defined to O_NDELAY in filecntl.h if O_NONBLOCK is not present
|
|
+ and O_NDELAY is defined. */
|
|
+#ifdef O_NONBLOCK
|
|
+ bflags |= O_NONBLOCK;
|
|
+#endif
|
|
+
|
|
+#ifdef O_NDELAY
|
|
+ bflags |= O_NDELAY;
|
|
+#endif
|
|
+
|
|
+ if (flags & bflags)
|
|
+ {
|
|
+ flags &= ~bflags;
|
|
+ return (fcntl (fd, F_SETFL, flags));
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/* Return 1 if file descriptor FD is valid; 0 otherwise. */
|
|
+int
|
|
+sh_validfd (fd)
|
|
+ int fd;
|
|
+{
|
|
+ return (fcntl (fd, F_GETFD, 0) >= 0);
|
|
+}
|
|
+
|
|
+int
|
|
+fd_ispipe (fd)
|
|
+ int fd;
|
|
+{
|
|
+ errno = 0;
|
|
+ return ((lseek (fd, 0L, SEEK_CUR) < 0) && (errno == ESPIPE));
|
|
+}
|
|
+
|
|
+/* There is a bug in the NeXT 2.1 rlogind that causes opens
|
|
+ of /dev/tty to fail. */
|
|
+
|
|
+#if defined (__BEOS__)
|
|
+/* On BeOS, opening in non-blocking mode exposes a bug in BeOS, so turn it
|
|
+ into a no-op. This should probably go away in the future. */
|
|
+# undef O_NONBLOCK
|
|
+# define O_NONBLOCK 0
|
|
+#endif /* __BEOS__ */
|
|
+
|
|
+void
|
|
+check_dev_tty ()
|
|
+{
|
|
+#if 0
|
|
+ int tty_fd;
|
|
+ char *tty;
|
|
+
|
|
+ tty_fd = open ("/dev/tty", O_RDWR|O_NONBLOCK);
|
|
+
|
|
+ if (tty_fd < 0)
|
|
+ {
|
|
+ tty = (char *)ttyname (fileno (stdin));
|
|
+ if (tty == 0)
|
|
+ return;
|
|
+ tty_fd = open (tty, O_RDWR|O_NONBLOCK);
|
|
+ }
|
|
+ if (tty_fd >= 0)
|
|
+ close (tty_fd);
|
|
+#endif
|
|
+}
|
|
+
|
|
+/* Return 1 if PATH1 and PATH2 are the same file. This is kind of
|
|
+ expensive. If non-NULL STP1 and STP2 point to stat structures
|
|
+ corresponding to PATH1 and PATH2, respectively. */
|
|
+int
|
|
+same_file (path1, path2, stp1, stp2)
|
|
+ const char *path1, *path2;
|
|
+ struct stat *stp1, *stp2;
|
|
+{
|
|
+ struct stat st1, st2;
|
|
+
|
|
+ if (stp1 == NULL)
|
|
+ {
|
|
+ if (stat (path1, &st1) != 0)
|
|
+ return (0);
|
|
+ stp1 = &st1;
|
|
+ }
|
|
+
|
|
+ if (stp2 == NULL)
|
|
+ {
|
|
+ if (stat (path2, &st2) != 0)
|
|
+ return (0);
|
|
+ stp2 = &st2;
|
|
+ }
|
|
+
|
|
+ return ((stp1->st_dev == stp2->st_dev) && (stp1->st_ino == stp2->st_ino));
|
|
+}
|
|
+
|
|
+/* Move FD to a number close to the maximum number of file descriptors
|
|
+ allowed in the shell process, to avoid the user stepping on it with
|
|
+ redirection and causing us extra work. If CHECK_NEW is non-zero,
|
|
+ we check whether or not the file descriptors are in use before
|
|
+ duplicating FD onto them. MAXFD says where to start checking the
|
|
+ file descriptors. If it's less than 20, we get the maximum value
|
|
+ available from getdtablesize(2). */
|
|
+int
|
|
+move_to_high_fd (fd, check_new, maxfd)
|
|
+ int fd, check_new, maxfd;
|
|
+{
|
|
+ int script_fd, nfds, ignore;
|
|
+
|
|
+ if (maxfd < 20)
|
|
+ {
|
|
+ nfds = getdtablesize ();
|
|
+ if (nfds <= 0)
|
|
+ nfds = 20;
|
|
+ if (nfds > HIGH_FD_MAX)
|
|
+ nfds = HIGH_FD_MAX; /* reasonable maximum */
|
|
+ }
|
|
+ else
|
|
+ nfds = maxfd;
|
|
+
|
|
+ for (nfds--; check_new && nfds > 3; nfds--)
|
|
+ if (fcntl (nfds, F_GETFD, &ignore) == -1)
|
|
+ break;
|
|
+
|
|
+ if (nfds > 3 && fd != nfds && (script_fd = dup2 (fd, nfds)) != -1)
|
|
+ {
|
|
+ if (check_new == 0 || fd != fileno (stderr)) /* don't close stderr */
|
|
+ close (fd);
|
|
+ return (script_fd);
|
|
+ }
|
|
+
|
|
+ /* OK, we didn't find one less than our artificial maximum; return the
|
|
+ original file descriptor. */
|
|
+ return (fd);
|
|
+}
|
|
+
|
|
+/* Return non-zero if the characters from SAMPLE are not all valid
|
|
+ characters to be found in the first line of a shell script. We
|
|
+ check up to the first newline, or SAMPLE_LEN, whichever comes first.
|
|
+ All of the characters must be printable or whitespace. */
|
|
+
|
|
+int
|
|
+check_binary_file (sample, sample_len)
|
|
+ const char *sample;
|
|
+ int sample_len;
|
|
+{
|
|
+ register int i;
|
|
+ unsigned char c;
|
|
+
|
|
+ for (i = 0; i < sample_len; i++)
|
|
+ {
|
|
+ c = sample[i];
|
|
+ if (c == '\n')
|
|
+ return (0);
|
|
+ if (c == '\0')
|
|
+ return (1);
|
|
+ }
|
|
+
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+/* **************************************************************** */
|
|
+/* */
|
|
+/* Functions to manipulate pipes */
|
|
+/* */
|
|
+/* **************************************************************** */
|
|
+
|
|
+int
|
|
+sh_openpipe (pv)
|
|
+ int *pv;
|
|
+{
|
|
+ int r;
|
|
+
|
|
+ if ((r = pipe (pv)) < 0)
|
|
+ return r;
|
|
+
|
|
+ pv[0] = move_to_high_fd (pv[0], 1, 64);
|
|
+ pv[1] = move_to_high_fd (pv[1], 1, 64);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int
|
|
+sh_closepipe (pv)
|
|
+ int *pv;
|
|
+{
|
|
+ if (pv[0] >= 0)
|
|
+ close (pv[0]);
|
|
+
|
|
+ if (pv[1] >= 0)
|
|
+ close (pv[1]);
|
|
+
|
|
+ pv[0] = pv[1] = -1;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/* **************************************************************** */
|
|
+/* */
|
|
+/* Functions to inspect pathnames */
|
|
+/* */
|
|
+/* **************************************************************** */
|
|
+
|
|
+int
|
|
+file_exists (fn)
|
|
+ const char *fn;
|
|
+{
|
|
+ struct stat sb;
|
|
+
|
|
+ return (stat (fn, &sb) == 0);
|
|
+}
|
|
+
|
|
+int
|
|
+file_isdir (fn)
|
|
+ const char *fn;
|
|
+{
|
|
+ struct stat sb;
|
|
+
|
|
+ return ((stat (fn, &sb) == 0) && S_ISDIR (sb.st_mode));
|
|
+}
|
|
+
|
|
+int
|
|
+file_iswdir (fn)
|
|
+ const char *fn;
|
|
+{
|
|
+ return (file_isdir (fn) && sh_eaccess (fn, W_OK) == 0);
|
|
+}
|
|
+
|
|
+/* Return 1 if STRING is "." or "..", optionally followed by a directory
|
|
+ separator */
|
|
+int
|
|
+path_dot_or_dotdot (string)
|
|
+ const char *string;
|
|
+{
|
|
+ if (string == 0 || *string == '\0' || *string != '.')
|
|
+ return (0);
|
|
+
|
|
+ /* string[0] == '.' */
|
|
+ if (PATHSEP(string[1]) || (string[1] == '.' && PATHSEP(string[2])))
|
|
+ return (1);
|
|
+
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+/* Return 1 if STRING contains an absolute pathname, else 0. Used by `cd'
|
|
+ to decide whether or not to look up a directory name in $CDPATH. */
|
|
+int
|
|
+absolute_pathname (string)
|
|
+ const char *string;
|
|
+{
|
|
+ if (string == 0 || *string == '\0')
|
|
+ return (0);
|
|
+
|
|
+ if (ABSPATH(string))
|
|
+ return (1);
|
|
+
|
|
+ if (string[0] == '.' && PATHSEP(string[1])) /* . and ./ */
|
|
+ return (1);
|
|
+
|
|
+ if (string[0] == '.' && string[1] == '.' && PATHSEP(string[2])) /* .. and ../ */
|
|
+ return (1);
|
|
+
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+/* Return 1 if STRING is an absolute program name; it is absolute if it
|
|
+ contains any slashes. This is used to decide whether or not to look
|
|
+ up through $PATH. */
|
|
+int
|
|
+absolute_program (string)
|
|
+ const char *string;
|
|
+{
|
|
+ return ((char *)mbschr (string, '/') != (char *)NULL);
|
|
+}
|
|
+
|
|
+/* **************************************************************** */
|
|
+/* */
|
|
+/* Functions to manipulate pathnames */
|
|
+/* */
|
|
+/* **************************************************************** */
|
|
+
|
|
+/* Turn STRING (a pathname) into an absolute pathname, assuming that
|
|
+ DOT_PATH contains the symbolic location of `.'. This always
|
|
+ returns a new string, even if STRING was an absolute pathname to
|
|
+ begin with. */
|
|
+char *
|
|
+make_absolute (string, dot_path)
|
|
+ const char *string, *dot_path;
|
|
+{
|
|
+ char *result;
|
|
+
|
|
+ if (dot_path == 0 || ABSPATH(string))
|
|
+#ifdef __CYGWIN__
|
|
+ {
|
|
+ char pathbuf[PATH_MAX + 1];
|
|
+
|
|
+ cygwin_conv_to_full_posix_path (string, pathbuf);
|
|
+ result = savestring (pathbuf);
|
|
+ }
|
|
+#else
|
|
+ result = savestring (string);
|
|
+#endif
|
|
+ else
|
|
+ result = sh_makepath (dot_path, string, 0);
|
|
+
|
|
+ return (result);
|
|
+}
|
|
+
|
|
+/* Return the `basename' of the pathname in STRING (the stuff after the
|
|
+ last '/'). If STRING is `/', just return it. */
|
|
+char *
|
|
+base_pathname (string)
|
|
+ char *string;
|
|
+{
|
|
+ char *p;
|
|
+
|
|
+#if 0
|
|
+ if (absolute_pathname (string) == 0)
|
|
+ return (string);
|
|
+#endif
|
|
+
|
|
+ if (string[0] == '/' && string[1] == 0)
|
|
+ return (string);
|
|
+
|
|
+ p = (char *)strrchr (string, '/');
|
|
+ return (p ? ++p : string);
|
|
+}
|
|
+
|
|
+/* Return the full pathname of FILE. Easy. Filenames that begin
|
|
+ with a '/' are returned as themselves. Other filenames have
|
|
+ the current working directory prepended. A new string is
|
|
+ returned in either case. */
|
|
+char *
|
|
+full_pathname (file)
|
|
+ char *file;
|
|
+{
|
|
+ char *ret;
|
|
+
|
|
+ file = (*file == '~') ? bash_tilde_expand (file, 0) : savestring (file);
|
|
+
|
|
+ if (ABSPATH(file))
|
|
+ return (file);
|
|
+
|
|
+ ret = sh_makepath ((char *)NULL, file, (MP_DOCWD|MP_RMDOT));
|
|
+ free (file);
|
|
+
|
|
+ return (ret);
|
|
+}
|
|
+
|
|
+/* A slightly related function. Get the prettiest name of this
|
|
+ directory possible. */
|
|
+static char tdir[PATH_MAX];
|
|
+
|
|
+/* Return a pretty pathname. If the first part of the pathname is
|
|
+ the same as $HOME, then replace that with `~'. */
|
|
+char *
|
|
+polite_directory_format (name)
|
|
+ char *name;
|
|
+{
|
|
+ char *home;
|
|
+ int l;
|
|
+
|
|
+ home = get_string_value ("HOME");
|
|
+ l = home ? strlen (home) : 0;
|
|
+ if (l > 1 && strncmp (home, name, l) == 0 && (!name[l] || name[l] == '/'))
|
|
+ {
|
|
+ strncpy (tdir + 1, name + l, sizeof(tdir) - 2);
|
|
+ tdir[0] = '~';
|
|
+ tdir[sizeof(tdir) - 1] = '\0';
|
|
+ return (tdir);
|
|
+ }
|
|
+ else
|
|
+ return (name);
|
|
+}
|
|
+
|
|
+/* Trim NAME. If NAME begins with `~/', skip over tilde prefix. Trim to
|
|
+ keep any tilde prefix and PROMPT_DIRTRIM trailing directory components
|
|
+ and replace the intervening characters with `...' */
|
|
+char *
|
|
+trim_pathname (name, maxlen)
|
|
+ char *name;
|
|
+ int maxlen;
|
|
+{
|
|
+ int nlen, ndirs;
|
|
+ intmax_t nskip;
|
|
+ char *nbeg, *nend, *ntail, *v;
|
|
+
|
|
+ if (name == 0 || (nlen = strlen (name)) == 0)
|
|
+ return name;
|
|
+ nend = name + nlen;
|
|
+
|
|
+ v = get_string_value ("PROMPT_DIRTRIM");
|
|
+ if (v == 0 || *v == 0)
|
|
+ return name;
|
|
+ if (legal_number (v, &nskip) == 0 || nskip <= 0)
|
|
+ return name;
|
|
+
|
|
+ /* Skip over tilde prefix */
|
|
+ nbeg = name;
|
|
+ if (name[0] == '~')
|
|
+ for (nbeg = name; *nbeg; nbeg++)
|
|
+ if (*nbeg == '/')
|
|
+ {
|
|
+ nbeg++;
|
|
+ break;
|
|
+ }
|
|
+ if (*nbeg == 0)
|
|
+ return name;
|
|
+
|
|
+ for (ndirs = 0, ntail = nbeg; *ntail; ntail++)
|
|
+ if (*ntail == '/')
|
|
+ ndirs++;
|
|
+ if (ndirs < nskip)
|
|
+ return name;
|
|
+
|
|
+ for (ntail = (*nend == '/') ? nend : nend - 1; ntail > nbeg; ntail--)
|
|
+ {
|
|
+ if (*ntail == '/')
|
|
+ nskip--;
|
|
+ if (nskip == 0)
|
|
+ break;
|
|
+ }
|
|
+ if (ntail == nbeg)
|
|
+ return name;
|
|
+
|
|
+ /* Now we want to return name[0..nbeg]+"..."+ntail, modifying name in place */
|
|
+ nlen = ntail - nbeg;
|
|
+ if (nlen <= 3)
|
|
+ return name;
|
|
+
|
|
+ *nbeg++ = '.';
|
|
+ *nbeg++ = '.';
|
|
+ *nbeg++ = '.';
|
|
+
|
|
+ nlen = nend - ntail;
|
|
+ memmove (nbeg, ntail, nlen);
|
|
+ nbeg[nlen] = '\0';
|
|
+
|
|
+ return name;
|
|
+}
|
|
+
|
|
+/* Return a printable representation of FN without special characters. The
|
|
+ caller is responsible for freeing memory if this returns something other
|
|
+ than its argument. If FLAGS is non-zero, we are printing for portable
|
|
+ re-input and should single-quote filenames appropriately. */
|
|
+char *
|
|
+printable_filename (fn, flags)
|
|
+ char *fn;
|
|
+ int flags;
|
|
+{
|
|
+ char *newf;
|
|
+
|
|
+ if (ansic_shouldquote (fn))
|
|
+ newf = ansic_quote (fn, 0, NULL);
|
|
+ else if (flags && sh_contains_shell_metas (fn))
|
|
+ newf = sh_single_quote (fn);
|
|
+ else
|
|
+ newf = fn;
|
|
+
|
|
+ return newf;
|
|
+}
|
|
+
|
|
+/* Given a string containing units of information separated by colons,
|
|
+ return the next one pointed to by (P_INDEX), or NULL if there are no more.
|
|
+ Advance (P_INDEX) to the character after the colon. */
|
|
+char *
|
|
+extract_colon_unit (string, p_index)
|
|
+ char *string;
|
|
+ int *p_index;
|
|
+{
|
|
+ int i, start, len;
|
|
+ char *value;
|
|
+
|
|
+ if (string == 0)
|
|
+ return (string);
|
|
+
|
|
+ len = strlen (string);
|
|
+ if (*p_index >= len)
|
|
+ return ((char *)NULL);
|
|
+
|
|
+ i = *p_index;
|
|
+
|
|
+ /* Each call to this routine leaves the index pointing at a colon if
|
|
+ there is more to the path. If I is > 0, then increment past the
|
|
+ `:'. If I is 0, then the path has a leading colon. Trailing colons
|
|
+ are handled OK by the `else' part of the if statement; an empty
|
|
+ string is returned in that case. */
|
|
+ if (i && string[i] == ':')
|
|
+ i++;
|
|
+
|
|
+ for (start = i; string[i] && string[i] != ':'; i++)
|
|
+ ;
|
|
+
|
|
+ *p_index = i;
|
|
+
|
|
+ if (i == start)
|
|
+ {
|
|
+ if (string[i])
|
|
+ (*p_index)++;
|
|
+ /* Return "" in the case of a trailing `:'. */
|
|
+ value = (char *)xmalloc (1);
|
|
+ value[0] = '\0';
|
|
+ }
|
|
+ else
|
|
+ value = substring (string, start, i);
|
|
+
|
|
+ return (value);
|
|
+}
|
|
+
|
|
+/* **************************************************************** */
|
|
+/* */
|
|
+/* Tilde Initialization and Expansion */
|
|
+/* */
|
|
+/* **************************************************************** */
|
|
+
|
|
+#if defined (PUSHD_AND_POPD)
|
|
+extern char *get_dirstack_from_string __P((char *));
|
|
+#endif
|
|
+
|
|
+static char **bash_tilde_prefixes;
|
|
+static char **bash_tilde_prefixes2;
|
|
+static char **bash_tilde_suffixes;
|
|
+static char **bash_tilde_suffixes2;
|
|
+
|
|
+/* If tilde_expand hasn't been able to expand the text, perhaps it
|
|
+ is a special shell expansion. This function is installed as the
|
|
+ tilde_expansion_preexpansion_hook. It knows how to expand ~- and ~+.
|
|
+ If PUSHD_AND_POPD is defined, ~[+-]N expands to directories from the
|
|
+ directory stack. */
|
|
+static char *
|
|
+bash_special_tilde_expansions (text)
|
|
+ char *text;
|
|
+{
|
|
+ char *result;
|
|
+
|
|
+ result = (char *)NULL;
|
|
+
|
|
+ if (text[0] == '+' && text[1] == '\0')
|
|
+ result = get_string_value ("PWD");
|
|
+ else if (text[0] == '-' && text[1] == '\0')
|
|
+ result = get_string_value ("OLDPWD");
|
|
+#if defined (PUSHD_AND_POPD)
|
|
+ else if (DIGIT (*text) || ((*text == '+' || *text == '-') && DIGIT (text[1])))
|
|
+ result = get_dirstack_from_string (text);
|
|
+#endif
|
|
+
|
|
+ return (result ? savestring (result) : (char *)NULL);
|
|
+}
|
|
+
|
|
+/* Initialize the tilde expander. In Bash, we handle `~-' and `~+', as
|
|
+ well as handling special tilde prefixes; `:~" and `=~' are indications
|
|
+ that we should do tilde expansion. */
|
|
+void
|
|
+tilde_initialize ()
|
|
+{
|
|
+ static int times_called = 0;
|
|
+
|
|
+ /* Tell the tilde expander that we want a crack first. */
|
|
+ tilde_expansion_preexpansion_hook = bash_special_tilde_expansions;
|
|
+
|
|
+ /* Tell the tilde expander about special strings which start a tilde
|
|
+ expansion, and the special strings that end one. Only do this once.
|
|
+ tilde_initialize () is called from within bashline_reinitialize (). */
|
|
+ if (times_called++ == 0)
|
|
+ {
|
|
+ bash_tilde_prefixes = strvec_create (3);
|
|
+ bash_tilde_prefixes[0] = "=~";
|
|
+ bash_tilde_prefixes[1] = ":~";
|
|
+ bash_tilde_prefixes[2] = (char *)NULL;
|
|
+
|
|
+ bash_tilde_prefixes2 = strvec_create (2);
|
|
+ bash_tilde_prefixes2[0] = ":~";
|
|
+ bash_tilde_prefixes2[1] = (char *)NULL;
|
|
+
|
|
+ tilde_additional_prefixes = bash_tilde_prefixes;
|
|
+
|
|
+ bash_tilde_suffixes = strvec_create (3);
|
|
+ bash_tilde_suffixes[0] = ":";
|
|
+ bash_tilde_suffixes[1] = "=~"; /* XXX - ?? */
|
|
+ bash_tilde_suffixes[2] = (char *)NULL;
|
|
+
|
|
+ tilde_additional_suffixes = bash_tilde_suffixes;
|
|
+
|
|
+ bash_tilde_suffixes2 = strvec_create (2);
|
|
+ bash_tilde_suffixes2[0] = ":";
|
|
+ bash_tilde_suffixes2[1] = (char *)NULL;
|
|
+ }
|
|
+}
|
|
+
|
|
+/* POSIX.2, 3.6.1: A tilde-prefix consists of an unquoted tilde character
|
|
+ at the beginning of the word, followed by all of the characters preceding
|
|
+ the first unquoted slash in the word, or all the characters in the word
|
|
+ if there is no slash...If none of the characters in the tilde-prefix are
|
|
+ quoted, the characters in the tilde-prefix following the tilde shell be
|
|
+ treated as a possible login name. */
|
|
+
|
|
+#define TILDE_END(c) ((c) == '\0' || (c) == '/' || (c) == ':')
|
|
+
|
|
+static int
|
|
+unquoted_tilde_word (s)
|
|
+ const char *s;
|
|
+{
|
|
+ const char *r;
|
|
+
|
|
+ for (r = s; TILDE_END(*r) == 0; r++)
|
|
+ {
|
|
+ switch (*r)
|
|
+ {
|
|
+ case '\\':
|
|
+ case '\'':
|
|
+ case '"':
|
|
+ return 0;
|
|
+ }
|
|
+ }
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+/* Find the end of the tilde-prefix starting at S, and return the tilde
|
|
+ prefix in newly-allocated memory. Return the length of the string in
|
|
+ *LENP. FLAGS tells whether or not we're in an assignment context --
|
|
+ if so, `:' delimits the end of the tilde prefix as well. */
|
|
+char *
|
|
+bash_tilde_find_word (s, flags, lenp)
|
|
+ const char *s;
|
|
+ int flags, *lenp;
|
|
+{
|
|
+ const char *r;
|
|
+ char *ret;
|
|
+ int l;
|
|
+
|
|
+ for (r = s; *r && *r != '/'; r++)
|
|
+ {
|
|
+ /* Short-circuit immediately if we see a quote character. Even though
|
|
+ POSIX says that `the first unquoted slash' (or `:') terminates the
|
|
+ tilde-prefix, in practice, any quoted portion of the tilde prefix
|
|
+ will cause it to not be expanded. */
|
|
+ if (*r == '\\' || *r == '\'' || *r == '"')
|
|
+ {
|
|
+ ret = savestring (s);
|
|
+ if (lenp)
|
|
+ *lenp = 0;
|
|
+ return ret;
|
|
+ }
|
|
+ else if (flags && *r == ':')
|
|
+ break;
|
|
+ }
|
|
+ l = r - s;
|
|
+ ret = xmalloc (l + 1);
|
|
+ strncpy (ret, s, l);
|
|
+ ret[l] = '\0';
|
|
+ if (lenp)
|
|
+ *lenp = l;
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/* Tilde-expand S by running it through the tilde expansion library.
|
|
+ ASSIGN_P is 1 if this is a variable assignment, so the alternate
|
|
+ tilde prefixes should be enabled (`=~' and `:~', see above). If
|
|
+ ASSIGN_P is 2, we are expanding the rhs of an assignment statement,
|
|
+ so `=~' is not valid. */
|
|
+char *
|
|
+bash_tilde_expand (s, assign_p)
|
|
+ const char *s;
|
|
+ int assign_p;
|
|
+{
|
|
+ int old_immed, old_term, r;
|
|
+ char *ret;
|
|
+
|
|
+#if 0
|
|
+ old_immed = interrupt_immediately;
|
|
+ old_term = terminate_immediately;
|
|
+ /* We want to be able to interrupt tilde expansion. Ordinarily, we can just
|
|
+ jump to top_level, but we don't want to run any trap commands in a signal
|
|
+ handler context. We might be able to get away with just checking for
|
|
+ things like SIGINT and SIGQUIT. */
|
|
+ if (any_signals_trapped () < 0)
|
|
+ interrupt_immediately = 1;
|
|
+ terminate_immediately = 1;
|
|
+#endif
|
|
+
|
|
+ tilde_additional_prefixes = assign_p == 0 ? (char **)0
|
|
+ : (assign_p == 2 ? bash_tilde_prefixes2 : bash_tilde_prefixes);
|
|
+ if (assign_p == 2)
|
|
+ tilde_additional_suffixes = bash_tilde_suffixes2;
|
|
+
|
|
+ r = (*s == '~') ? unquoted_tilde_word (s) : 1;
|
|
+ ret = r ? tilde_expand (s) : savestring (s);
|
|
+
|
|
+#if 0
|
|
+ interrupt_immediately = old_immed;
|
|
+ terminate_immediately = old_term;
|
|
+#endif
|
|
+
|
|
+ QUIT;
|
|
+
|
|
+ return (ret);
|
|
+}
|
|
+
|
|
+/* **************************************************************** */
|
|
+/* */
|
|
+/* Functions to manipulate and search the group list */
|
|
+/* */
|
|
+/* **************************************************************** */
|
|
+
|
|
+static int ngroups, maxgroups;
|
|
+
|
|
+/* The set of groups that this user is a member of. */
|
|
+static GETGROUPS_T *group_array = (GETGROUPS_T *)NULL;
|
|
+
|
|
+#if !defined (NOGROUP)
|
|
+# define NOGROUP (gid_t) -1
|
|
+#endif
|
|
+
|
|
+static void
|
|
+initialize_group_array ()
|
|
+{
|
|
+ register int i;
|
|
+
|
|
+ if (maxgroups == 0)
|
|
+ maxgroups = getmaxgroups ();
|
|
+
|
|
+ ngroups = 0;
|
|
+ group_array = (GETGROUPS_T *)xrealloc (group_array, maxgroups * sizeof (GETGROUPS_T));
|
|
+
|
|
+#if defined (HAVE_GETGROUPS)
|
|
+ ngroups = getgroups (maxgroups, group_array);
|
|
+#endif
|
|
+
|
|
+ /* If getgroups returns nothing, or the OS does not support getgroups(),
|
|
+ make sure the groups array includes at least the current gid. */
|
|
+ if (ngroups == 0)
|
|
+ {
|
|
+ group_array[0] = current_user.gid;
|
|
+ ngroups = 1;
|
|
+ }
|
|
+
|
|
+ /* If the primary group is not in the groups array, add it as group_array[0]
|
|
+ and shuffle everything else up 1, if there's room. */
|
|
+ for (i = 0; i < ngroups; i++)
|
|
+ if (current_user.gid == (gid_t)group_array[i])
|
|
+ break;
|
|
+ if (i == ngroups && ngroups < maxgroups)
|
|
+ {
|
|
+ for (i = ngroups; i > 0; i--)
|
|
+ group_array[i] = group_array[i - 1];
|
|
+ group_array[0] = current_user.gid;
|
|
+ ngroups++;
|
|
+ }
|
|
+
|
|
+ /* If the primary group is not group_array[0], swap group_array[0] and
|
|
+ whatever the current group is. The vast majority of systems should
|
|
+ not need this; a notable exception is Linux. */
|
|
+ if (group_array[0] != current_user.gid)
|
|
+ {
|
|
+ for (i = 0; i < ngroups; i++)
|
|
+ if (group_array[i] == current_user.gid)
|
|
+ break;
|
|
+ if (i < ngroups)
|
|
+ {
|
|
+ group_array[i] = group_array[0];
|
|
+ group_array[0] = current_user.gid;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+/* Return non-zero if GID is one that we have in our groups list. */
|
|
+int
|
|
+#if defined (__STDC__) || defined ( _MINIX)
|
|
+group_member (gid_t gid)
|
|
+#else
|
|
+group_member (gid)
|
|
+ gid_t gid;
|
|
+#endif /* !__STDC__ && !_MINIX */
|
|
+{
|
|
+#if defined (HAVE_GETGROUPS)
|
|
+ register int i;
|
|
+#endif
|
|
+
|
|
+ /* Short-circuit if possible, maybe saving a call to getgroups(). */
|
|
+ if (gid == current_user.gid || gid == current_user.egid)
|
|
+ return (1);
|
|
+
|
|
+#if defined (HAVE_GETGROUPS)
|
|
+ if (ngroups == 0)
|
|
+ initialize_group_array ();
|
|
+
|
|
+ /* In case of error, the user loses. */
|
|
+ if (ngroups <= 0)
|
|
+ return (0);
|
|
+
|
|
+ /* Search through the list looking for GID. */
|
|
+ for (i = 0; i < ngroups; i++)
|
|
+ if (gid == (gid_t)group_array[i])
|
|
+ return (1);
|
|
+#endif
|
|
+
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+char **
|
|
+get_group_list (ngp)
|
|
+ int *ngp;
|
|
+{
|
|
+ static char **group_vector = (char **)NULL;
|
|
+ register int i;
|
|
+
|
|
+ if (group_vector)
|
|
+ {
|
|
+ if (ngp)
|
|
+ *ngp = ngroups;
|
|
+ return group_vector;
|
|
+ }
|
|
+
|
|
+ if (ngroups == 0)
|
|
+ initialize_group_array ();
|
|
+
|
|
+ if (ngroups <= 0)
|
|
+ {
|
|
+ if (ngp)
|
|
+ *ngp = 0;
|
|
+ return (char **)NULL;
|
|
+ }
|
|
+
|
|
+ group_vector = strvec_create (ngroups);
|
|
+ for (i = 0; i < ngroups; i++)
|
|
+ group_vector[i] = itos (group_array[i]);
|
|
+
|
|
+ if (ngp)
|
|
+ *ngp = ngroups;
|
|
+ return group_vector;
|
|
+}
|
|
+
|
|
+int *
|
|
+get_group_array (ngp)
|
|
+ int *ngp;
|
|
+{
|
|
+ int i;
|
|
+ static int *group_iarray = (int *)NULL;
|
|
+
|
|
+ if (group_iarray)
|
|
+ {
|
|
+ if (ngp)
|
|
+ *ngp = ngroups;
|
|
+ return (group_iarray);
|
|
+ }
|
|
+
|
|
+ if (ngroups == 0)
|
|
+ initialize_group_array ();
|
|
+
|
|
+ if (ngroups <= 0)
|
|
+ {
|
|
+ if (ngp)
|
|
+ *ngp = 0;
|
|
+ return (int *)NULL;
|
|
+ }
|
|
+
|
|
+ group_iarray = (int *)xmalloc (ngroups * sizeof (int));
|
|
+ for (i = 0; i < ngroups; i++)
|
|
+ group_iarray[i] = (int)group_array[i];
|
|
+
|
|
+ if (ngp)
|
|
+ *ngp = ngroups;
|
|
+ return group_iarray;
|
|
+}
|
|
+
|
|
+/* **************************************************************** */
|
|
+/* */
|
|
+/* Miscellaneous functions */
|
|
+/* */
|
|
+/* **************************************************************** */
|
|
+
|
|
+/* Return a value for PATH that is guaranteed to find all of the standard
|
|
+ utilities. This uses Posix.2 configuration variables, if present. It
|
|
+ uses a value defined in config.h as a last resort. */
|
|
+char *
|
|
+conf_standard_path ()
|
|
+{
|
|
+#if defined (_CS_PATH) && defined (HAVE_CONFSTR)
|
|
+ char *p;
|
|
+ size_t len;
|
|
+
|
|
+ len = (size_t)confstr (_CS_PATH, (char *)NULL, (size_t)0);
|
|
+ if (len > 0)
|
|
+ {
|
|
+ p = (char *)xmalloc (len + 2);
|
|
+ *p = '\0';
|
|
+ confstr (_CS_PATH, p, len);
|
|
+ return (p);
|
|
+ }
|
|
+ else
|
|
+ return (savestring (STANDARD_UTILS_PATH));
|
|
+#else /* !_CS_PATH || !HAVE_CONFSTR */
|
|
+# if defined (CS_PATH)
|
|
+ return (savestring (CS_PATH));
|
|
+# else
|
|
+ return (savestring (STANDARD_UTILS_PATH));
|
|
+# endif /* !CS_PATH */
|
|
+#endif /* !_CS_PATH || !HAVE_CONFSTR */
|
|
+}
|
|
diff -ruwN source/include/posixwait.h source-new/include/posixwait.h
|
|
--- source/include/posixwait.h 2008-08-12 08:03:03.000000000 -0600
|
|
+++ source-new/include/posixwait.h 2019-01-28 12:42:40.972781097 -0700
|
|
@@ -34,7 +34,7 @@
|
|
|
|
/* How to get the status of a job. For Posix, this is just an
|
|
int, but for other systems we have to crack the union wait. */
|
|
-#if !defined (_POSIX_VERSION)
|
|
+#if 0
|
|
typedef union wait WAIT;
|
|
# define WSTATUS(t) (t.w_status)
|
|
#else /* _POSIX_VERSION */
|
|
@@ -50,7 +50,7 @@
|
|
|
|
/* More Posix P1003.1 definitions. In the POSIX versions, the parameter is
|
|
passed as an `int', in the non-POSIX version, as `union wait'. */
|
|
-#if defined (_POSIX_VERSION)
|
|
+#if 1
|
|
|
|
# if !defined (WSTOPSIG)
|
|
# define WSTOPSIG(s) ((s) >> 8)
|
|
diff -ruwN source/lib/sh/getcwd.c source-new/lib/sh/getcwd.c
|
|
--- source/lib/sh/getcwd.c 2012-03-10 08:48:50.000000000 -0700
|
|
+++ source-new/lib/sh/getcwd.c 2019-01-28 14:02:28.573259186 -0700
|
|
@@ -20,7 +20,7 @@
|
|
|
|
#include <config.h>
|
|
|
|
-#if !defined (HAVE_GETCWD)
|
|
+#if !defined (HAVE_GETCWD) && !defined(__redox__)
|
|
|
|
#if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX)
|
|
#pragma alloca
|
|
diff -ruwN source/sig.c source-new/sig.c
|
|
--- source/sig.c 2016-02-11 13:02:45.000000000 -0700
|
|
+++ source-new/sig.c 2019-01-28 13:48:08.303876705 -0700
|
|
@@ -680,7 +680,9 @@
|
|
}
|
|
|
|
/* Signal functions used by the rest of the code. */
|
|
-#if !defined (HAVE_POSIX_SIGNALS)
|
|
+#if defined(__redox__)
|
|
+// Redox already has sigprocmask
|
|
+#elif !defined (HAVE_POSIX_SIGNALS)
|
|
|
|
/* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
|
|
sigprocmask (operation, newset, oldset)
|