1 /* general.c -- Stuff that is used by all files. */
3 /* Copyright (C) 1987-2020 Free Software Foundation, Inc.
5 This file is part of GNU Bush, the Bourne Again SHell.
7 Bush is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 Bush is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Bush. If not, see <http://www.gnu.org/licenses/>.
23 #include "bushtypes.h"
24 #if defined (HAVE_SYS_PARAM_H)
25 # include <sys/param.h>
27 #include "posixstat.h"
29 #if defined (HAVE_UNISTD_H)
36 #include "chartypes.h"
42 #include "lxrgmr/parser.h"
44 #include "impl/findcmd.h"
47 #include "impl/pathexp.h"
49 #include "builtins/common.h"
51 #if defined (HAVE_MBSTR_H) && defined (HAVE_MBSCHR)
52 # include <mbstr.h> /* mbschr */
55 #include <tilde/tilde.h>
62 # include <sys/cygwin.h>
65 static char *bush_special_tilde_expansions
PARAMS((char *));
66 static int unquoted_tilde_word
PARAMS((const char *));
67 static void initialize_group_array
PARAMS((void));
69 /* A standard error message to use when getcwd() returns NULL. */
70 const char * const bush_getcwd_errstr
= N_("getcwd: cannot access parent directories");
72 /* Do whatever is necessary to initialize `Posix mode'. This currently
73 modifies the following variables which are controlled via shopt:
81 and the following variables which cannot be user-modified:
85 If we add to the first list, we need to change the table and functions
92 &interactive_comments
,
100 static char *saved_posix_vars
= 0;
103 posix_initialize (on
)
106 /* Things that should be turned on when posix mode is enabled. */
109 interactive_comments
= source_uses_path
= expand_aliases
= 1;
111 source_searches_cwd
= 0;
112 print_shift_error
= 1;
115 /* Things that should be turned on when posix mode is disabled. */
116 else if (saved_posix_vars
) /* on == 0, restore saved settings */
118 set_posix_options (saved_posix_vars
);
119 free (saved_posix_vars
);
120 saved_posix_vars
= 0;
122 else /* on == 0, restore a default set of settings */
124 source_searches_cwd
= 1;
125 expand_aliases
= interactive_shell
;
126 print_shift_error
= 0;
133 return ((sizeof (posix_vars
) / sizeof (posix_vars
[0])) - 1);
137 get_posix_options (bitmap
)
143 bitmap
= (char *)xmalloc (num_posix_options ()); /* no trailing NULL */
144 for (i
= 0; posix_vars
[i
].posix_mode_var
; i
++)
145 bitmap
[i
] = *(posix_vars
[i
].posix_mode_var
);
149 #undef save_posix_options
151 save_posix_options ()
153 saved_posix_vars
= get_posix_options (saved_posix_vars
);
157 set_posix_options (bitmap
)
162 for (i
= 0; posix_vars
[i
].posix_mode_var
; i
++)
163 *(posix_vars
[i
].posix_mode_var
) = bitmap
[i
];
166 /* **************************************************************** */
168 /* Functions to convert to and from and display non-standard types */
170 /* **************************************************************** */
172 #if defined (RLIMTYPE)
174 string_to_rlimtype (s
)
182 while (s
&& *s
&& whitespace (*s
))
184 if (s
&& (*s
== '-' || *s
== '+'))
189 for ( ; s
&& *s
&& DIGIT (*s
); s
++)
190 ret
= (ret
* 10) + TODIGIT (*s
);
191 return (neg
? -ret
: ret
);
195 print_rlimtype (n
, addnl
)
199 char s
[INT_STRLEN_BOUND (RLIMTYPE
) + 1], *p
;
208 while ((n
/= 10) != 0);
216 while ((n
/= 10) != 0);
219 printf ("%s%s", p
, addnl
? "\n" : "");
221 #endif /* RLIMTYPE */
223 /* **************************************************************** */
225 /* Input Validation Functions */
227 /* **************************************************************** */
229 /* Return non-zero if all of the characters in STRING are digits. */
234 register const char *s
;
236 for (s
= string
; *s
; s
++)
243 /* Return non-zero if the characters pointed to by STRING constitute a
244 valid number. Stuff the converted number into RESULT if RESULT is
247 legal_number (string
, result
)
261 value
= strtoimax (string
, &ep
, 10);
262 if (errno
|| ep
== string
)
263 return 0; /* errno is set on overflow or underflow */
265 /* Skip any trailing whitespace, since strtoimax does not. */
266 while (whitespace (*ep
))
269 /* If *string is not '\0' but *ep is '\0' on return, the entire string
271 if (*string
&& *ep
== '\0')
275 /* The SunOS4 implementation of strtol() will happily ignore
276 overflow conditions, so this cannot do overflow correctly
284 /* Return 1 if this token is a legal shell `identifier'; that is, it consists
285 solely of letters, digits, and underscores, and does not begin with a
288 legal_identifier (name
)
291 register const char *s
;
294 if (!name
|| !(c
= *name
) || (legal_variable_starter (c
) == 0))
297 for (s
= name
+ 1; (c
= *s
) != 0; s
++)
299 if (legal_variable_char (c
) == 0)
312 /* Return 1 if NAME is a valid value that can be assigned to a nameref
313 variable. FLAGS can be 2, in which case the name is going to be used
314 to create a variable. Other values are currently unused, but could
315 be used to allow values to be stored and indirectly referenced, but
316 not used in assignments. */
318 valid_nameref_value (name
, flags
)
322 if (name
== 0 || *name
== 0)
325 /* valid identifier */
326 #if defined (ARRAY_VARS)
327 if (legal_identifier (name
) || (flags
!= 2 && valid_array_reference (name
, 0)))
329 if (legal_identifier (name
))
337 check_selfref (name
, value
, flags
)
344 if (STREQ (name
, value
))
347 #if defined (ARRAY_VARS)
348 if (valid_array_reference (value
, 0))
350 t
= array_variable_name (value
, 0, (char **)NULL
, (int *)NULL
);
351 if (t
&& STREQ (name
, t
))
360 return 0; /* not a self reference */
363 /* Make sure that WORD is a valid shell identifier, i.e.
364 does not contain a dollar sign, nor is quoted in any way.
365 If CHECK_WORD is non-zero,
366 the word is checked to ensure that it consists of only letters,
367 digits, and underscores, and does not consist of all digits. */
369 check_identifier (word
, check_word
)
373 if (word
->flags
& (W_HASDOLLAR
|W_QUOTED
)) /* XXX - HASDOLLAR? */
375 internal_error (_("`%s': not a valid identifier"), word
->word
);
378 else if (check_word
&& (all_digits (word
->word
) || legal_identifier (word
->word
) == 0))
380 internal_error (_("`%s': not a valid identifier"), word
->word
);
387 /* Return 1 if STRING is a function name that the shell will import from
388 the environment. Currently we reject attempts to import shell functions
389 containing slashes, beginning with newlines or containing blanks. In
390 Posix mode, we require that STRING be a valid shell identifier. Not
393 importable_function_name (string
, len
)
397 if (absolute_program (string
)) /* don't allow slash */
399 if (*string
== '\n') /* can't start with a newline */
401 if (shellblank (*string
) || shellblank(string
[len
-1]))
403 return (posixly_correct
? legal_identifier (string
) : 1);
407 exportable_function_name (string
)
410 if (absolute_program (string
))
412 if (mbschr (string
, '=') != 0)
417 /* Return 1 if STRING comprises a valid alias name. The shell accepts
418 essentially all characters except those which must be quoted to the
419 parser (which disqualifies them from alias expansion anyway) and `/'. */
421 legal_alias_name (string
, flags
)
425 register const char *s
;
427 for (s
= string
; *s
; s
++)
428 if (shellbreak (*s
) || shellxquote (*s
) || shellexp (*s
) || (*s
== '/'))
433 /* Returns non-zero if STRING is an assignment statement. The returned value
434 is the index of the `=' sign. If FLAGS&1 we are expecting a compound assignment
435 and require an array subscript before the `=' to denote an assignment
438 assignment (string
, flags
)
442 register unsigned char c
;
443 register int newi
, indx
;
445 c
= string
[indx
= 0];
447 #if defined (ARRAY_VARS)
448 /* If parser_state includes PST_COMPASSIGN, FLAGS will include 1, so we are
449 parsing the contents of a compound assignment. If parser_state includes
450 PST_REPARSE, we are in the middle of an assignment statement and breaking
451 the words between the parens into words and assignment statements, but
452 we don't need to check for that right now. Within a compound assignment,
453 the subscript is required to make the word an assignment statement. If
454 we don't have a subscript, even if the word is a valid assignment
455 statement otherwise, we don't want to treat it as one. */
456 if ((flags
& 1) && c
!= '[') /* ] */
458 else if ((flags
& 1) == 0 && org_legal_variable_starter (c
) == 0)
460 if (org_legal_variable_starter (c
) == 0)
464 while (c
= string
[indx
])
466 /* The following is safe. Note that '=' at the start of a word
467 is not an assignment statement. */
469 {printf("string = %s\n", string
);
473 #if defined (ARRAY_VARS)
476 newi
= skipsubscript (string
, indx
, (flags
& 2) ? 1 : 0);
477 /* XXX - why not check for blank subscripts here, if we do in
478 valid_array_reference? */
479 if (string
[newi
++] != ']')
481 printf("string = %s\n", string
);
482 if (string
[newi
] == '+' && string
[newi
+1] == '=')
484 return ((string
[newi
] == '=') ? newi
: 0);
486 #endif /* ARRAY_VARS */
489 if (c
== '+' && string
[indx
+1] == '=')
490 {printf("string = %s\n", string
);
494 /* Variable names in assignment statements may contain only letters,
495 digits, and `_', and double `:'. */
496 if (legal_variable_char (c
) == 0)
501 if (string
[indx
+1] == ':')
505 printf("string = %s\n", string
);
523 for (i
= 0; line
[i
]; i
++)
524 if (isblank ((unsigned char)line
[i
]) == 0)
526 return (line
[i
] == '\0');
529 /* **************************************************************** */
531 /* Functions to manage files and file descriptors */
533 /* **************************************************************** */
535 /* A function to unset no-delay mode on a file descriptor. Used in shell.c
536 to unset it on the fd passed as stdin. Should be called on stdin if
537 readline gets an EAGAIN or EWOULDBLOCK when trying to read input. */
539 #if !defined (O_NDELAY)
540 # if defined (FNDELAY)
541 # define O_NDELAY FNDELAY
543 #endif /* O_NDELAY */
545 /* Make sure no-delay mode is not set on file descriptor FD. */
547 sh_unset_nodelay_mode (fd
)
552 if ((flags
= fcntl (fd
, F_GETFL
, 0)) < 0)
557 /* This is defined to O_NDELAY in filecntl.h if O_NONBLOCK is not present
558 and O_NDELAY is defined. */
560 bflags
|= O_NONBLOCK
;
570 return (fcntl (fd
, F_SETFL
, flags
));
576 /* Just a wrapper for the define in include/filecntl.h */
581 return (SET_CLOSE_ON_EXEC (fd
));
584 /* Return 1 if file descriptor FD is valid; 0 otherwise. */
589 return (fcntl (fd
, F_GETFD
, 0) >= 0);
597 return ((lseek (fd
, 0L, SEEK_CUR
) < 0) && (errno
== ESPIPE
));
600 /* There is a bug in the NeXT 2.1 rlogind that causes opens
601 of /dev/tty to fail. */
603 #if defined (__BEOS__)
604 /* On BeOS, opening in non-blocking mode exposes a bug in BeOS, so turn it
605 into a no-op. This should probably go away in the future. */
607 # define O_NONBLOCK 0
608 #endif /* __BEOS__ */
616 tty_fd
= open ("/dev/tty", O_RDWR
|O_NONBLOCK
);
620 tty
= (char *)ttyname (fileno (stdin
));
623 tty_fd
= open (tty
, O_RDWR
|O_NONBLOCK
);
629 /* Return 1 if PATH1 and PATH2 are the same file. This is kind of
630 expensive. If non-NULL STP1 and STP2 point to stat structures
631 corresponding to PATH1 and PATH2, respectively. */
633 same_file (path1
, path2
, stp1
, stp2
)
634 const char *path1
, *path2
;
635 struct stat
*stp1
, *stp2
;
637 struct stat st1
, st2
;
641 if (stat (path1
, &st1
) != 0)
648 if (stat (path2
, &st2
) != 0)
653 return ((stp1
->st_dev
== stp2
->st_dev
) && (stp1
->st_ino
== stp2
->st_ino
));
656 /* Move FD to a number close to the maximum number of file descriptors
657 allowed in the shell process, to avoid the user stepping on it with
658 redirection and causing us extra work. If CHECK_NEW is non-zero,
659 we check whether or not the file descriptors are in use before
660 duplicating FD onto them. MAXFD says where to start checking the
661 file descriptors. If it's less than 20, we get the maximum value
662 available from getdtablesize(2). */
664 move_to_high_fd (fd
, check_new
, maxfd
)
665 int fd
, check_new
, maxfd
;
667 int script_fd
, nfds
, ignore
;
671 nfds
= getdtablesize ();
674 if (nfds
> HIGH_FD_MAX
)
675 nfds
= HIGH_FD_MAX
; /* reasonable maximum */
680 for (nfds
--; check_new
&& nfds
> 3; nfds
--)
681 if (fcntl (nfds
, F_GETFD
, &ignore
) == -1)
684 if (nfds
> 3 && fd
!= nfds
&& (script_fd
= dup2 (fd
, nfds
)) != -1)
686 if (check_new
== 0 || fd
!= fileno (stderr
)) /* don't close stderr */
691 /* OK, we didn't find one less than our artificial maximum; return the
692 original file descriptor. */
696 /* Return non-zero if the characters from SAMPLE are not all valid
697 characters to be found in the first line of a shell script. We
698 check up to the first newline, or SAMPLE_LEN, whichever comes first.
699 All of the characters must be printable or whitespace. */
702 check_binary_file (sample
, sample_len
)
709 for (i
= 0; i
< sample_len
; i
++)
721 /* **************************************************************** */
723 /* Functions to manipulate pipes */
725 /* **************************************************************** */
733 if ((r
= pipe (pv
)) < 0)
736 pv
[0] = move_to_high_fd (pv
[0], 1, 64);
737 pv
[1] = move_to_high_fd (pv
[1], 1, 64);
756 /* **************************************************************** */
758 /* Functions to inspect pathnames */
760 /* **************************************************************** */
768 return (stat (fn
, &sb
) == 0);
777 return ((stat (fn
, &sb
) == 0) && S_ISDIR (sb
.st_mode
));
784 return (file_isdir (fn
) && sh_eaccess (fn
, W_OK
) == 0);
787 /* Return 1 if STRING is "." or "..", optionally followed by a directory
790 path_dot_or_dotdot (string
)
793 if (string
== 0 || *string
== '\0' || *string
!= '.')
796 /* string[0] == '.' */
797 if (PATHSEP(string
[1]) || (string
[1] == '.' && PATHSEP(string
[2])))
803 /* Return 1 if STRING contains an absolute pathname, else 0. Used by `cd'
804 to decide whether or not to look up a directory name in $CDPATH. */
806 absolute_pathname (string
)
809 if (string
== 0 || *string
== '\0')
815 if (string
[0] == '.' && PATHSEP(string
[1])) /* . and ./ */
818 if (string
[0] == '.' && string
[1] == '.' && PATHSEP(string
[2])) /* .. and ../ */
824 /* Return 1 if STRING is an absolute program name; it is absolute if it
825 contains any slashes. This is used to decide whether or not to look
828 absolute_program (string
)
831 return ((char *)mbschr (string
, '/') != (char *)NULL
);
834 /* **************************************************************** */
836 /* Functions to manipulate pathnames */
838 /* **************************************************************** */
840 /* Turn STRING (a pathname) into an absolute pathname, assuming that
841 DOT_PATH contains the symbolic location of `.'. This always
842 returns a new string, even if STRING was an absolute pathname to
845 make_absolute (string
, dot_path
)
846 const char *string
, *dot_path
;
850 if (dot_path
== 0 || ABSPATH(string
))
853 char pathbuf
[PATH_MAX
+ 1];
855 /* WAS cygwin_conv_to_full_posix_path (string, pathbuf); */
856 cygwin_conv_path (CCP_WIN_A_TO_POSIX
, string
, pathbuf
, PATH_MAX
);
857 result
= savestring (pathbuf
);
860 result
= savestring (string
);
863 result
= sh_makepath (dot_path
, string
, 0);
868 /* Return the `basename' of the pathname in STRING (the stuff after the
869 last '/'). If STRING is `/', just return it. */
871 base_pathname (string
)
877 if (absolute_pathname (string
) == 0)
881 if (string
[0] == '/' && string
[1] == 0)
884 p
= (char *)strrchr (string
, '/');
885 return (p
? ++p
: string
);
888 /* Return the full pathname of FILE. Easy. Filenames that begin
889 with a '/' are returned as themselves. Other filenames have
890 the current working directory prepended. A new string is
891 returned in either case. */
898 file
= (*file
== '~') ? bush_tilde_expand (file
, 0) : savestring (file
);
903 ret
= sh_makepath ((char *)NULL
, file
, (MP_DOCWD
|MP_RMDOT
));
909 /* A slightly related function. Get the prettiest name of this
910 directory possible. */
911 static char tdir
[PATH_MAX
];
913 /* Return a pretty pathname. If the first part of the pathname is
914 the same as $HOME, then replace that with `~'. */
916 polite_directory_format (name
)
922 home
= get_string_value ("HOME");
923 l
= home
? strlen (home
) : 0;
924 if (l
> 1 && strncmp (home
, name
, l
) == 0 && (!name
[l
] || name
[l
] == '/'))
926 strncpy (tdir
+ 1, name
+ l
, sizeof(tdir
) - 2);
928 tdir
[sizeof(tdir
) - 1] = '\0';
935 /* Trim NAME. If NAME begins with `~/', skip over tilde prefix. Trim to
936 keep any tilde prefix and PROMPT_DIRTRIM trailing directory components
937 and replace the intervening characters with `...' */
939 trim_pathname (name
, maxlen
)
945 char *nbeg
, *nend
, *ntail
, *v
;
947 if (name
== 0 || (nlen
= strlen (name
)) == 0)
951 v
= get_string_value ("PROMPT_DIRTRIM");
952 if (v
== 0 || *v
== 0)
954 if (legal_number (v
, &nskip
) == 0 || nskip
<= 0)
957 /* Skip over tilde prefix */
960 for (nbeg
= name
; *nbeg
; nbeg
++)
969 for (ndirs
= 0, ntail
= nbeg
; *ntail
; ntail
++)
975 for (ntail
= (*nend
== '/') ? nend
: nend
- 1; ntail
> nbeg
; ntail
--)
985 /* Now we want to return name[0..nbeg]+"..."+ntail, modifying name in place */
995 memmove (nbeg
, ntail
, nlen
);
1001 /* Return a printable representation of FN without special characters. The
1002 caller is responsible for freeing memory if this returns something other
1003 than its argument. If FLAGS is non-zero, we are printing for portable
1004 re-input and should single-quote filenames appropriately. */
1006 printable_filename (fn
, flags
)
1012 if (ansic_shouldquote (fn
))
1013 newf
= ansic_quote (fn
, 0, NULL
);
1014 else if (flags
&& sh_contains_shell_metas (fn
))
1015 newf
= sh_single_quote (fn
);
1022 /* Given a string containing units of information separated by colons,
1023 return the next one pointed to by (P_INDEX), or NULL if there are no more.
1024 Advance (P_INDEX) to the character after the colon. */
1026 extract_colon_unit (string
, p_index
)
1036 len
= strlen (string
);
1037 if (*p_index
>= len
)
1038 return ((char *)NULL
);
1042 /* Each call to this routine leaves the index pointing at a colon if
1043 there is more to the path. If I is > 0, then increment past the
1044 `:'. If I is 0, then the path has a leading colon. Trailing colons
1045 are handled OK by the `else' part of the if statement; an empty
1046 string is returned in that case. */
1047 if (i
&& string
[i
] == ':')
1050 for (start
= i
; string
[i
] && string
[i
] != ':'; i
++)
1059 /* Return "" in the case of a trailing `:'. */
1060 value
= (char *)xmalloc (1);
1064 value
= substring (string
, start
, i
);
1069 /* **************************************************************** */
1071 /* Tilde Initialization and Expansion */
1073 /* **************************************************************** */
1075 #if defined (PUSHD_AND_POPD)
1076 extern char *get_dirstack_from_string
PARAMS((char *));
1079 static char **bush_tilde_prefixes
;
1080 static char **bush_tilde_prefixes2
;
1081 static char **bush_tilde_suffixes
;
1082 static char **bush_tilde_suffixes2
;
1084 /* If tilde_expand hasn't been able to expand the text, perhaps it
1085 is a special shell expansion. This function is installed as the
1086 tilde_expansion_preexpansion_hook. It knows how to expand ~- and ~+.
1087 If PUSHD_AND_POPD is defined, ~[+-]N expands to directories from the
1090 bush_special_tilde_expansions (text
)
1095 result
= (char *)NULL
;
1097 if (text
[0] == '+' && text
[1] == '\0')
1098 result
= get_string_value ("PWD");
1099 else if (text
[0] == '-' && text
[1] == '\0')
1100 result
= get_string_value ("OLDPWD");
1101 #if defined (PUSHD_AND_POPD)
1102 else if (DIGIT (*text
) || ((*text
== '+' || *text
== '-') && DIGIT (text
[1])))
1103 result
= get_dirstack_from_string (text
);
1106 return (result
? savestring (result
) : (char *)NULL
);
1109 /* Initialize the tilde expander. In Bush, we handle `~-' and `~+', as
1110 well as handling special tilde prefixes; `:~" and `=~' are indications
1111 that we should do tilde expansion. */
1115 static int times_called
= 0;
1117 /* Tell the tilde expander that we want a crack first. */
1118 tilde_expansion_preexpansion_hook
= bush_special_tilde_expansions
;
1120 /* Tell the tilde expander about special strings which start a tilde
1121 expansion, and the special strings that end one. Only do this once.
1122 tilde_initialize () is called from within bushline_reinitialize (). */
1123 if (times_called
++ == 0)
1125 bush_tilde_prefixes
= strvec_create (3);
1126 bush_tilde_prefixes
[0] = "=~";
1127 bush_tilde_prefixes
[1] = ":~";
1128 bush_tilde_prefixes
[2] = (char *)NULL
;
1130 bush_tilde_prefixes2
= strvec_create (2);
1131 bush_tilde_prefixes2
[0] = ":~";
1132 bush_tilde_prefixes2
[1] = (char *)NULL
;
1134 tilde_additional_prefixes
= bush_tilde_prefixes
;
1136 bush_tilde_suffixes
= strvec_create (3);
1137 bush_tilde_suffixes
[0] = ":";
1138 bush_tilde_suffixes
[1] = "=~"; /* XXX - ?? */
1139 bush_tilde_suffixes
[2] = (char *)NULL
;
1141 tilde_additional_suffixes
= bush_tilde_suffixes
;
1143 bush_tilde_suffixes2
= strvec_create (2);
1144 bush_tilde_suffixes2
[0] = ":";
1145 bush_tilde_suffixes2
[1] = (char *)NULL
;
1149 /* POSIX.2, 3.6.1: A tilde-prefix consists of an unquoted tilde character
1150 at the beginning of the word, followed by all of the characters preceding
1151 the first unquoted slash in the word, or all the characters in the word
1152 if there is no slash...If none of the characters in the tilde-prefix are
1153 quoted, the characters in the tilde-prefix following the tilde shell be
1154 treated as a possible login name. */
1156 #define TILDE_END(c) ((c) == '\0' || (c) == '/' || (c) == ':')
1159 unquoted_tilde_word (s
)
1164 for (r
= s
; TILDE_END(*r
) == 0; r
++)
1177 /* Find the end of the tilde-prefix starting at S, and return the tilde
1178 prefix in newly-allocated memory. Return the length of the string in
1179 *LENP. FLAGS tells whether or not we're in an assignment context --
1180 if so, `:' delimits the end of the tilde prefix as well. */
1182 bush_tilde_find_word (s
, flags
, lenp
)
1190 for (r
= s
; *r
&& *r
!= '/'; r
++)
1192 /* Short-circuit immediately if we see a quote character. Even though
1193 POSIX says that `the first unquoted slash' (or `:') terminates the
1194 tilde-prefix, in practice, any quoted portion of the tilde prefix
1195 will cause it to not be expanded. */
1196 if (*r
== '\\' || *r
== '\'' || *r
== '"')
1198 ret
= savestring (s
);
1203 else if (flags
&& *r
== ':')
1207 ret
= xmalloc (l
+ 1);
1208 strncpy (ret
, s
, l
);
1215 /* Tilde-expand S by running it through the tilde expansion library.
1216 ASSIGN_P is 1 if this is a variable assignment, so the alternate
1217 tilde prefixes should be enabled (`=~' and `:~', see above). If
1218 ASSIGN_P is 2, we are expanding the rhs of an assignment statement,
1219 so `=~' is not valid. */
1221 bush_tilde_expand (s
, assign_p
)
1228 tilde_additional_prefixes
= assign_p
== 0 ? (char **)0
1229 : (assign_p
== 2 ? bush_tilde_prefixes2
: bush_tilde_prefixes
);
1231 tilde_additional_suffixes
= bush_tilde_suffixes2
;
1233 r
= (*s
== '~') ? unquoted_tilde_word (s
) : 1;
1234 ret
= r
? tilde_expand (s
) : savestring (s
);
1241 /* **************************************************************** */
1243 /* Functions to manipulate and search the group list */
1245 /* **************************************************************** */
1247 static int ngroups
, maxgroups
;
1249 /* The set of groups that this user is a member of. */
1250 static GETGROUPS_T
*group_array
= (GETGROUPS_T
*)NULL
;
1252 #if !defined (NOGROUP)
1253 # define NOGROUP (gid_t) -1
1257 initialize_group_array ()
1262 maxgroups
= getmaxgroups ();
1265 group_array
= (GETGROUPS_T
*)xrealloc (group_array
, maxgroups
* sizeof (GETGROUPS_T
));
1267 #if defined (HAVE_GETGROUPS)
1268 ngroups
= getgroups (maxgroups
, group_array
);
1271 /* If getgroups returns nothing, or the OS does not support getgroups(),
1272 make sure the groups array includes at least the current gid. */
1275 group_array
[0] = current_user
.gid
;
1279 /* If the primary group is not in the groups array, add it as group_array[0]
1280 and shuffle everything else up 1, if there's room. */
1281 for (i
= 0; i
< ngroups
; i
++)
1282 if (current_user
.gid
== (gid_t
)group_array
[i
])
1284 if (i
== ngroups
&& ngroups
< maxgroups
)
1286 for (i
= ngroups
; i
> 0; i
--)
1287 group_array
[i
] = group_array
[i
- 1];
1288 group_array
[0] = current_user
.gid
;
1292 /* If the primary group is not group_array[0], swap group_array[0] and
1293 whatever the current group is. The vast majority of systems should
1294 not need this; a notable exception is Linux. */
1295 if (group_array
[0] != current_user
.gid
)
1297 for (i
= 0; i
< ngroups
; i
++)
1298 if (group_array
[i
] == current_user
.gid
)
1302 group_array
[i
] = group_array
[0];
1303 group_array
[0] = current_user
.gid
;
1308 /* Return non-zero if GID is one that we have in our groups list. */
1310 #if defined (__STDC__) || defined ( _MINIX)
1311 group_member (gid_t gid
)
1315 #endif /* !__STDC__ && !_MINIX */
1317 #if defined (HAVE_GETGROUPS)
1321 /* Short-circuit if possible, maybe saving a call to getgroups(). */
1322 if (gid
== current_user
.gid
|| gid
== current_user
.egid
)
1325 #if defined (HAVE_GETGROUPS)
1327 initialize_group_array ();
1329 /* In case of error, the user loses. */
1333 /* Search through the list looking for GID. */
1334 for (i
= 0; i
< ngroups
; i
++)
1335 if (gid
== (gid_t
)group_array
[i
])
1343 get_group_list (ngp
)
1346 static char **group_vector
= (char **)NULL
;
1353 return group_vector
;
1357 initialize_group_array ();
1363 return (char **)NULL
;
1366 group_vector
= strvec_create (ngroups
);
1367 for (i
= 0; i
< ngroups
; i
++)
1368 group_vector
[i
] = itos (group_array
[i
]);
1372 return group_vector
;
1376 get_group_array (ngp
)
1380 static int *group_iarray
= (int *)NULL
;
1386 return (group_iarray
);
1390 initialize_group_array ();
1399 group_iarray
= (int *)xmalloc (ngroups
* sizeof (int));
1400 for (i
= 0; i
< ngroups
; i
++)
1401 group_iarray
[i
] = (int)group_array
[i
];
1405 return group_iarray
;
1408 /* **************************************************************** */
1410 /* Miscellaneous functions */
1412 /* **************************************************************** */
1414 /* Return a value for PATH that is guaranteed to find all of the standard
1415 utilities. This uses Posix.2 configuration variables, if present. It
1416 uses a value defined in config.h as a last resort. */
1418 conf_standard_path ()
1420 #if defined (_CS_PATH) && defined (HAVE_CONFSTR)
1424 len
= (size_t)confstr (_CS_PATH
, (char *)NULL
, (size_t)0);
1427 p
= (char *)xmalloc (len
+ 2);
1429 confstr (_CS_PATH
, p
, len
);
1433 return (savestring (STANDARD_UTILS_PATH
));
1434 #else /* !_CS_PATH || !HAVE_CONFSTR */
1435 # if defined (CS_PATH)
1436 return (savestring (CS_PATH
));
1438 return (savestring (STANDARD_UTILS_PATH
));
1439 # endif /* !CS_PATH */
1440 #endif /* !_CS_PATH || !HAVE_CONFSTR */
1450 v
= get_string_value ("COLUMNS");
1458 if (check_window_size
)
1459 get_new_window_size (0, (int *)0, &c
);
1461 return (c
> 0 ? c
: 80);