1 /* general.c -- Stuff that is used by all files. */
3 /* Copyright (C) 1987-2016 Free Software Foundation, Inc.
5 This file is part of GNU Bash, the Bourne Again SHell.
7 Bash 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 Bash 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 Bash. If not, see <http://www.gnu.org/licenses/>.
23 #include "bashtypes.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"
45 #if defined (HAVE_MBSTR_H) && defined (HAVE_MBSCHR)
46 # include <mbstr.h> /* mbschr */
49 #include <tilde/tilde.h>
55 extern int expand_aliases
;
56 extern int interactive_comments
;
57 extern int check_hashed_filenames
;
58 extern int source_uses_path
;
59 extern int source_searches_cwd
;
60 extern int posixly_correct
;
61 extern int inherit_errexit
;
63 static char *bash_special_tilde_expansions
__P((char *));
64 static int unquoted_tilde_word
__P((const char *));
65 static void initialize_group_array
__P((void));
67 /* A standard error message to use when getcwd() returns NULL. */
68 const char * const bash_getcwd_errstr
= N_("getcwd: cannot access parent directories");
70 /* Do whatever is necessary to initialize `Posix mode'. */
75 /* Things that should be turned on when posix mode is enabled. */
78 interactive_comments
= source_uses_path
= expand_aliases
= 1;
80 source_searches_cwd
= 0;
83 /* Things that should be turned on when posix mode is disabled. */
86 source_searches_cwd
= 1;
87 expand_aliases
= interactive_shell
;
91 /* **************************************************************** */
93 /* Functions to convert to and from and display non-standard types */
95 /* **************************************************************** */
97 #if defined (RLIMTYPE)
99 string_to_rlimtype (s
)
107 while (s
&& *s
&& whitespace (*s
))
109 if (s
&& (*s
== '-' || *s
== '+'))
114 for ( ; s
&& *s
&& DIGIT (*s
); s
++)
115 ret
= (ret
* 10) + TODIGIT (*s
);
116 return (neg
? -ret
: ret
);
120 print_rlimtype (n
, addnl
)
124 char s
[INT_STRLEN_BOUND (RLIMTYPE
) + 1], *p
;
133 while ((n
/= 10) != 0);
141 while ((n
/= 10) != 0);
144 printf ("%s%s", p
, addnl
? "\n" : "");
146 #endif /* RLIMTYPE */
148 /* **************************************************************** */
150 /* Input Validation Functions */
152 /* **************************************************************** */
154 /* Return non-zero if all of the characters in STRING are digits. */
159 register const char *s
;
161 for (s
= string
; *s
; s
++)
168 /* Return non-zero if the characters pointed to by STRING constitute a
169 valid number. Stuff the converted number into RESULT if RESULT is
172 legal_number (string
, result
)
186 value
= strtoimax (string
, &ep
, 10);
187 if (errno
|| ep
== string
)
188 return 0; /* errno is set on overflow or underflow */
190 /* Skip any trailing whitespace, since strtoimax does not. */
191 while (whitespace (*ep
))
194 /* If *string is not '\0' but *ep is '\0' on return, the entire string
196 if (*string
&& *ep
== '\0')
200 /* The SunOS4 implementation of strtol() will happily ignore
201 overflow conditions, so this cannot do overflow correctly
209 /* Return 1 if this token is a legal shell `identifier'; that is, it consists
210 solely of letters, digits, and underscores, and does not begin with a
213 legal_identifier (name
)
216 register const char *s
;
219 if (!name
|| !(c
= *name
) || (legal_variable_starter (c
) == 0))
222 for (s
= name
+ 1; (c
= *s
) != 0; s
++)
224 if (legal_variable_char (c
) == 0)
230 /* Return 1 if NAME is a valid value that can be assigned to a nameref
231 variable. FLAGS can be 2, in which case the name is going to be used
232 to create a variable. Other values are currently unused, but could
233 be used to allow values to be stored and indirectly referenced, but
234 not used in assignments. */
236 valid_nameref_value (name
, flags
)
240 if (name
== 0 || *name
== 0)
243 /* valid identifier */
244 #if defined (ARRAY_VARS)
245 if (legal_identifier (name
) || (flags
!= 2 && valid_array_reference (name
, 0)))
247 if (legal_identifier (name
))
255 check_selfref (name
, value
, flags
)
262 if (STREQ (name
, value
))
265 #if defined (ARRAY_VARS)
266 if (valid_array_reference (value
, 0))
268 t
= array_variable_name (value
, (char **)NULL
, (int *)NULL
);
269 if (t
&& STREQ (name
, t
))
278 return 0; /* not a self reference */
281 /* Make sure that WORD is a valid shell identifier, i.e.
282 does not contain a dollar sign, nor is quoted in any way. Nor
283 does it consist of all digits. If CHECK_WORD is non-zero,
284 the word is checked to ensure that it consists of only letters,
285 digits, and underscores. */
287 check_identifier (word
, check_word
)
291 if ((word
->flags
& (W_HASDOLLAR
|W_QUOTED
)) || all_digits (word
->word
))
293 internal_error (_("`%s': not a valid identifier"), word
->word
);
296 else if (check_word
&& legal_identifier (word
->word
) == 0)
298 internal_error (_("`%s': not a valid identifier"), word
->word
);
305 /* Return 1 if STRING is a function name that the shell will import from
306 the environment. Currently we reject attempts to import shell functions
307 containing slashes, beginning with newlines or containing blanks. In
308 Posix mode, we require that STRING be a valid shell identifier. Not
311 importable_function_name (string
, len
)
315 if (absolute_program (string
)) /* don't allow slash */
317 if (*string
== '\n') /* can't start with a newline */
319 if (shellblank (*string
) || shellblank(string
[len
-1]))
321 return (posixly_correct
? legal_identifier (string
) : 1);
325 exportable_function_name (string
)
328 if (absolute_program (string
))
330 if (mbschr (string
, '=') != 0)
335 /* Return 1 if STRING comprises a valid alias name. The shell accepts
336 essentially all characters except those which must be quoted to the
337 parser (which disqualifies them from alias expansion anyway) and `/'. */
339 legal_alias_name (string
, flags
)
343 register const char *s
;
345 for (s
= string
; *s
; s
++)
346 if (shellbreak (*s
) || shellxquote (*s
) || shellexp (*s
) || (*s
== '/'))
351 /* Returns non-zero if STRING is an assignment statement. The returned value
352 is the index of the `=' sign. */
354 assignment (string
, flags
)
358 register unsigned char c
;
359 register int newi
, indx
;
361 c
= string
[indx
= 0];
363 #if defined (ARRAY_VARS)
364 if ((legal_variable_starter (c
) == 0) && (flags
== 0 || c
!= '[')) /* ] */
366 if (legal_variable_starter (c
) == 0)
370 while (c
= string
[indx
])
372 /* The following is safe. Note that '=' at the start of a word
373 is not an assignment statement. */
377 #if defined (ARRAY_VARS)
380 newi
= skipsubscript (string
, indx
, 0);
381 if (string
[newi
++] != ']')
383 if (string
[newi
] == '+' && string
[newi
+1] == '=')
385 return ((string
[newi
] == '=') ? newi
: 0);
387 #endif /* ARRAY_VARS */
390 if (c
== '+' && string
[indx
+1] == '=')
393 /* Variable names in assignment statements may contain only letters,
395 if (legal_variable_char (c
) == 0)
403 /* **************************************************************** */
405 /* Functions to manage files and file descriptors */
407 /* **************************************************************** */
409 /* A function to unset no-delay mode on a file descriptor. Used in shell.c
410 to unset it on the fd passed as stdin. Should be called on stdin if
411 readline gets an EAGAIN or EWOULDBLOCK when trying to read input. */
413 #if !defined (O_NDELAY)
414 # if defined (FNDELAY)
415 # define O_NDELAY FNDELAY
417 #endif /* O_NDELAY */
419 /* Make sure no-delay mode is not set on file descriptor FD. */
421 sh_unset_nodelay_mode (fd
)
426 if ((flags
= fcntl (fd
, F_GETFL
, 0)) < 0)
431 /* This is defined to O_NDELAY in filecntl.h if O_NONBLOCK is not present
432 and O_NDELAY is defined. */
434 bflags
|= O_NONBLOCK
;
444 return (fcntl (fd
, F_SETFL
, flags
));
450 /* Return 1 if file descriptor FD is valid; 0 otherwise. */
455 return (fcntl (fd
, F_GETFD
, 0) >= 0);
463 return ((lseek (fd
, 0L, SEEK_CUR
) < 0) && (errno
== ESPIPE
));
466 /* There is a bug in the NeXT 2.1 rlogind that causes opens
467 of /dev/tty to fail. */
469 #if defined (__BEOS__)
470 /* On BeOS, opening in non-blocking mode exposes a bug in BeOS, so turn it
471 into a no-op. This should probably go away in the future. */
473 # define O_NONBLOCK 0
474 #endif /* __BEOS__ */
482 tty_fd
= open ("/dev/tty", O_RDWR
|O_NONBLOCK
);
486 tty
= (char *)ttyname (fileno (stdin
));
489 tty_fd
= open (tty
, O_RDWR
|O_NONBLOCK
);
495 /* Return 1 if PATH1 and PATH2 are the same file. This is kind of
496 expensive. If non-NULL STP1 and STP2 point to stat structures
497 corresponding to PATH1 and PATH2, respectively. */
499 same_file (path1
, path2
, stp1
, stp2
)
500 const char *path1
, *path2
;
501 struct stat
*stp1
, *stp2
;
503 struct stat st1
, st2
;
507 if (stat (path1
, &st1
) != 0)
514 if (stat (path2
, &st2
) != 0)
519 return ((stp1
->st_dev
== stp2
->st_dev
) && (stp1
->st_ino
== stp2
->st_ino
));
522 /* Move FD to a number close to the maximum number of file descriptors
523 allowed in the shell process, to avoid the user stepping on it with
524 redirection and causing us extra work. If CHECK_NEW is non-zero,
525 we check whether or not the file descriptors are in use before
526 duplicating FD onto them. MAXFD says where to start checking the
527 file descriptors. If it's less than 20, we get the maximum value
528 available from getdtablesize(2). */
530 move_to_high_fd (fd
, check_new
, maxfd
)
531 int fd
, check_new
, maxfd
;
533 int script_fd
, nfds
, ignore
;
537 nfds
= getdtablesize ();
540 if (nfds
> HIGH_FD_MAX
)
541 nfds
= HIGH_FD_MAX
; /* reasonable maximum */
546 for (nfds
--; check_new
&& nfds
> 3; nfds
--)
547 if (fcntl (nfds
, F_GETFD
, &ignore
) == -1)
550 if (nfds
> 3 && fd
!= nfds
&& (script_fd
= dup2 (fd
, nfds
)) != -1)
552 if (check_new
== 0 || fd
!= fileno (stderr
)) /* don't close stderr */
557 /* OK, we didn't find one less than our artificial maximum; return the
558 original file descriptor. */
562 /* Return non-zero if the characters from SAMPLE are not all valid
563 characters to be found in the first line of a shell script. We
564 check up to the first newline, or SAMPLE_LEN, whichever comes first.
565 All of the characters must be printable or whitespace. */
568 check_binary_file (sample
, sample_len
)
575 for (i
= 0; i
< sample_len
; i
++)
587 /* **************************************************************** */
589 /* Functions to manipulate pipes */
591 /* **************************************************************** */
599 if ((r
= pipe (pv
)) < 0)
602 pv
[0] = move_to_high_fd (pv
[0], 1, 64);
603 pv
[1] = move_to_high_fd (pv
[1], 1, 64);
622 /* **************************************************************** */
624 /* Functions to inspect pathnames */
626 /* **************************************************************** */
634 return (stat (fn
, &sb
) == 0);
643 return ((stat (fn
, &sb
) == 0) && S_ISDIR (sb
.st_mode
));
650 return (file_isdir (fn
) && sh_eaccess (fn
, W_OK
) == 0);
653 /* Return 1 if STRING is "." or "..", optionally followed by a directory
656 path_dot_or_dotdot (string
)
659 if (string
== 0 || *string
== '\0' || *string
!= '.')
662 /* string[0] == '.' */
663 if (PATHSEP(string
[1]) || (string
[1] == '.' && PATHSEP(string
[2])))
669 /* Return 1 if STRING contains an absolute pathname, else 0. Used by `cd'
670 to decide whether or not to look up a directory name in $CDPATH. */
672 absolute_pathname (string
)
675 if (string
== 0 || *string
== '\0')
681 if (string
[0] == '.' && PATHSEP(string
[1])) /* . and ./ */
684 if (string
[0] == '.' && string
[1] == '.' && PATHSEP(string
[2])) /* .. and ../ */
690 /* Return 1 if STRING is an absolute program name; it is absolute if it
691 contains any slashes. This is used to decide whether or not to look
694 absolute_program (string
)
697 return ((char *)mbschr (string
, '/') != (char *)NULL
);
700 /* **************************************************************** */
702 /* Functions to manipulate pathnames */
704 /* **************************************************************** */
706 /* Turn STRING (a pathname) into an absolute pathname, assuming that
707 DOT_PATH contains the symbolic location of `.'. This always
708 returns a new string, even if STRING was an absolute pathname to
711 make_absolute (string
, dot_path
)
712 const char *string
, *dot_path
;
716 if (dot_path
== 0 || ABSPATH(string
))
719 char pathbuf
[PATH_MAX
+ 1];
721 cygwin_conv_to_full_posix_path (string
, pathbuf
);
722 result
= savestring (pathbuf
);
725 result
= savestring (string
);
728 result
= sh_makepath (dot_path
, string
, 0);
733 /* Return the `basename' of the pathname in STRING (the stuff after the
734 last '/'). If STRING is `/', just return it. */
736 base_pathname (string
)
742 if (absolute_pathname (string
) == 0)
746 if (string
[0] == '/' && string
[1] == 0)
749 p
= (char *)strrchr (string
, '/');
750 return (p
? ++p
: string
);
753 /* Return the full pathname of FILE. Easy. Filenames that begin
754 with a '/' are returned as themselves. Other filenames have
755 the current working directory prepended. A new string is
756 returned in either case. */
763 file
= (*file
== '~') ? bash_tilde_expand (file
, 0) : savestring (file
);
768 ret
= sh_makepath ((char *)NULL
, file
, (MP_DOCWD
|MP_RMDOT
));
774 /* A slightly related function. Get the prettiest name of this
775 directory possible. */
776 static char tdir
[PATH_MAX
];
778 /* Return a pretty pathname. If the first part of the pathname is
779 the same as $HOME, then replace that with `~'. */
781 polite_directory_format (name
)
787 home
= get_string_value ("HOME");
788 l
= home
? strlen (home
) : 0;
789 if (l
> 1 && strncmp (home
, name
, l
) == 0 && (!name
[l
] || name
[l
] == '/'))
791 strncpy (tdir
+ 1, name
+ l
, sizeof(tdir
) - 2);
793 tdir
[sizeof(tdir
) - 1] = '\0';
800 /* Trim NAME. If NAME begins with `~/', skip over tilde prefix. Trim to
801 keep any tilde prefix and PROMPT_DIRTRIM trailing directory components
802 and replace the intervening characters with `...' */
804 trim_pathname (name
, maxlen
)
810 char *nbeg
, *nend
, *ntail
, *v
;
812 if (name
== 0 || (nlen
= strlen (name
)) == 0)
816 v
= get_string_value ("PROMPT_DIRTRIM");
817 if (v
== 0 || *v
== 0)
819 if (legal_number (v
, &nskip
) == 0 || nskip
<= 0)
822 /* Skip over tilde prefix */
825 for (nbeg
= name
; *nbeg
; nbeg
++)
834 for (ndirs
= 0, ntail
= nbeg
; *ntail
; ntail
++)
840 for (ntail
= (*nend
== '/') ? nend
: nend
- 1; ntail
> nbeg
; ntail
--)
850 /* Now we want to return name[0..nbeg]+"..."+ntail, modifying name in place */
860 memmove (nbeg
, ntail
, nlen
);
866 /* Return a printable representation of FN without special characters. The
867 caller is responsible for freeing memory if this returns something other
868 than its argument. If FLAGS is non-zero, we are printing for portable
869 re-input and should single-quote filenames appropriately. */
871 printable_filename (fn
, flags
)
877 if (ansic_shouldquote (fn
))
878 newf
= ansic_quote (fn
, 0, NULL
);
879 else if (flags
&& sh_contains_shell_metas (fn
))
880 newf
= sh_single_quote (fn
);
887 /* Given a string containing units of information separated by colons,
888 return the next one pointed to by (P_INDEX), or NULL if there are no more.
889 Advance (P_INDEX) to the character after the colon. */
891 extract_colon_unit (string
, p_index
)
901 len
= strlen (string
);
903 return ((char *)NULL
);
907 /* Each call to this routine leaves the index pointing at a colon if
908 there is more to the path. If I is > 0, then increment past the
909 `:'. If I is 0, then the path has a leading colon. Trailing colons
910 are handled OK by the `else' part of the if statement; an empty
911 string is returned in that case. */
912 if (i
&& string
[i
] == ':')
915 for (start
= i
; string
[i
] && string
[i
] != ':'; i
++)
924 /* Return "" in the case of a trailing `:'. */
925 value
= (char *)xmalloc (1);
929 value
= substring (string
, start
, i
);
934 /* **************************************************************** */
936 /* Tilde Initialization and Expansion */
938 /* **************************************************************** */
940 #if defined (PUSHD_AND_POPD)
941 extern char *get_dirstack_from_string
__P((char *));
944 static char **bash_tilde_prefixes
;
945 static char **bash_tilde_prefixes2
;
946 static char **bash_tilde_suffixes
;
947 static char **bash_tilde_suffixes2
;
949 /* If tilde_expand hasn't been able to expand the text, perhaps it
950 is a special shell expansion. This function is installed as the
951 tilde_expansion_preexpansion_hook. It knows how to expand ~- and ~+.
952 If PUSHD_AND_POPD is defined, ~[+-]N expands to directories from the
955 bash_special_tilde_expansions (text
)
960 result
= (char *)NULL
;
962 if (text
[0] == '+' && text
[1] == '\0')
963 result
= get_string_value ("PWD");
964 else if (text
[0] == '-' && text
[1] == '\0')
965 result
= get_string_value ("OLDPWD");
966 #if defined (PUSHD_AND_POPD)
967 else if (DIGIT (*text
) || ((*text
== '+' || *text
== '-') && DIGIT (text
[1])))
968 result
= get_dirstack_from_string (text
);
971 return (result
? savestring (result
) : (char *)NULL
);
974 /* Initialize the tilde expander. In Bash, we handle `~-' and `~+', as
975 well as handling special tilde prefixes; `:~" and `=~' are indications
976 that we should do tilde expansion. */
980 static int times_called
= 0;
982 /* Tell the tilde expander that we want a crack first. */
983 tilde_expansion_preexpansion_hook
= bash_special_tilde_expansions
;
985 /* Tell the tilde expander about special strings which start a tilde
986 expansion, and the special strings that end one. Only do this once.
987 tilde_initialize () is called from within bashline_reinitialize (). */
988 if (times_called
++ == 0)
990 bash_tilde_prefixes
= strvec_create (3);
991 bash_tilde_prefixes
[0] = "=~";
992 bash_tilde_prefixes
[1] = ":~";
993 bash_tilde_prefixes
[2] = (char *)NULL
;
995 bash_tilde_prefixes2
= strvec_create (2);
996 bash_tilde_prefixes2
[0] = ":~";
997 bash_tilde_prefixes2
[1] = (char *)NULL
;
999 tilde_additional_prefixes
= bash_tilde_prefixes
;
1001 bash_tilde_suffixes
= strvec_create (3);
1002 bash_tilde_suffixes
[0] = ":";
1003 bash_tilde_suffixes
[1] = "=~"; /* XXX - ?? */
1004 bash_tilde_suffixes
[2] = (char *)NULL
;
1006 tilde_additional_suffixes
= bash_tilde_suffixes
;
1008 bash_tilde_suffixes2
= strvec_create (2);
1009 bash_tilde_suffixes2
[0] = ":";
1010 bash_tilde_suffixes2
[1] = (char *)NULL
;
1014 /* POSIX.2, 3.6.1: A tilde-prefix consists of an unquoted tilde character
1015 at the beginning of the word, followed by all of the characters preceding
1016 the first unquoted slash in the word, or all the characters in the word
1017 if there is no slash...If none of the characters in the tilde-prefix are
1018 quoted, the characters in the tilde-prefix following the tilde shell be
1019 treated as a possible login name. */
1021 #define TILDE_END(c) ((c) == '\0' || (c) == '/' || (c) == ':')
1024 unquoted_tilde_word (s
)
1029 for (r
= s
; TILDE_END(*r
) == 0; r
++)
1042 /* Find the end of the tilde-prefix starting at S, and return the tilde
1043 prefix in newly-allocated memory. Return the length of the string in
1044 *LENP. FLAGS tells whether or not we're in an assignment context --
1045 if so, `:' delimits the end of the tilde prefix as well. */
1047 bash_tilde_find_word (s
, flags
, lenp
)
1055 for (r
= s
; *r
&& *r
!= '/'; r
++)
1057 /* Short-circuit immediately if we see a quote character. Even though
1058 POSIX says that `the first unquoted slash' (or `:') terminates the
1059 tilde-prefix, in practice, any quoted portion of the tilde prefix
1060 will cause it to not be expanded. */
1061 if (*r
== '\\' || *r
== '\'' || *r
== '"')
1063 ret
= savestring (s
);
1068 else if (flags
&& *r
== ':')
1072 ret
= xmalloc (l
+ 1);
1073 strncpy (ret
, s
, l
);
1080 /* Tilde-expand S by running it through the tilde expansion library.
1081 ASSIGN_P is 1 if this is a variable assignment, so the alternate
1082 tilde prefixes should be enabled (`=~' and `:~', see above). If
1083 ASSIGN_P is 2, we are expanding the rhs of an assignment statement,
1084 so `=~' is not valid. */
1086 bash_tilde_expand (s
, assign_p
)
1090 int old_immed
, old_term
, r
;
1094 old_immed
= interrupt_immediately
;
1095 old_term
= terminate_immediately
;
1096 /* We want to be able to interrupt tilde expansion. Ordinarily, we can just
1097 jump to top_level, but we don't want to run any trap commands in a signal
1098 handler context. We might be able to get away with just checking for
1099 things like SIGINT and SIGQUIT. */
1100 if (any_signals_trapped () < 0)
1101 interrupt_immediately
= 1;
1102 terminate_immediately
= 1;
1105 tilde_additional_prefixes
= assign_p
== 0 ? (char **)0
1106 : (assign_p
== 2 ? bash_tilde_prefixes2
: bash_tilde_prefixes
);
1108 tilde_additional_suffixes
= bash_tilde_suffixes2
;
1110 r
= (*s
== '~') ? unquoted_tilde_word (s
) : 1;
1111 ret
= r
? tilde_expand (s
) : savestring (s
);
1114 interrupt_immediately
= old_immed
;
1115 terminate_immediately
= old_term
;
1123 /* **************************************************************** */
1125 /* Functions to manipulate and search the group list */
1127 /* **************************************************************** */
1129 static int ngroups
, maxgroups
;
1131 /* The set of groups that this user is a member of. */
1132 static GETGROUPS_T
*group_array
= (GETGROUPS_T
*)NULL
;
1134 #if !defined (NOGROUP)
1135 # define NOGROUP (gid_t) -1
1139 initialize_group_array ()
1144 maxgroups
= getmaxgroups ();
1147 group_array
= (GETGROUPS_T
*)xrealloc (group_array
, maxgroups
* sizeof (GETGROUPS_T
));
1149 #if defined (HAVE_GETGROUPS)
1150 ngroups
= getgroups (maxgroups
, group_array
);
1153 /* If getgroups returns nothing, or the OS does not support getgroups(),
1154 make sure the groups array includes at least the current gid. */
1157 group_array
[0] = current_user
.gid
;
1161 /* If the primary group is not in the groups array, add it as group_array[0]
1162 and shuffle everything else up 1, if there's room. */
1163 for (i
= 0; i
< ngroups
; i
++)
1164 if (current_user
.gid
== (gid_t
)group_array
[i
])
1166 if (i
== ngroups
&& ngroups
< maxgroups
)
1168 for (i
= ngroups
; i
> 0; i
--)
1169 group_array
[i
] = group_array
[i
- 1];
1170 group_array
[0] = current_user
.gid
;
1174 /* If the primary group is not group_array[0], swap group_array[0] and
1175 whatever the current group is. The vast majority of systems should
1176 not need this; a notable exception is Linux. */
1177 if (group_array
[0] != current_user
.gid
)
1179 for (i
= 0; i
< ngroups
; i
++)
1180 if (group_array
[i
] == current_user
.gid
)
1184 group_array
[i
] = group_array
[0];
1185 group_array
[0] = current_user
.gid
;
1190 /* Return non-zero if GID is one that we have in our groups list. */
1192 #if defined (__STDC__) || defined ( _MINIX)
1193 group_member (gid_t gid
)
1197 #endif /* !__STDC__ && !_MINIX */
1199 #if defined (HAVE_GETGROUPS)
1203 /* Short-circuit if possible, maybe saving a call to getgroups(). */
1204 if (gid
== current_user
.gid
|| gid
== current_user
.egid
)
1207 #if defined (HAVE_GETGROUPS)
1209 initialize_group_array ();
1211 /* In case of error, the user loses. */
1215 /* Search through the list looking for GID. */
1216 for (i
= 0; i
< ngroups
; i
++)
1217 if (gid
== (gid_t
)group_array
[i
])
1225 get_group_list (ngp
)
1228 static char **group_vector
= (char **)NULL
;
1235 return group_vector
;
1239 initialize_group_array ();
1245 return (char **)NULL
;
1248 group_vector
= strvec_create (ngroups
);
1249 for (i
= 0; i
< ngroups
; i
++)
1250 group_vector
[i
] = itos (group_array
[i
]);
1254 return group_vector
;
1258 get_group_array (ngp
)
1262 static int *group_iarray
= (int *)NULL
;
1268 return (group_iarray
);
1272 initialize_group_array ();
1281 group_iarray
= (int *)xmalloc (ngroups
* sizeof (int));
1282 for (i
= 0; i
< ngroups
; i
++)
1283 group_iarray
[i
] = (int)group_array
[i
];
1287 return group_iarray
;
1290 /* **************************************************************** */
1292 /* Miscellaneous functions */
1294 /* **************************************************************** */
1296 /* Return a value for PATH that is guaranteed to find all of the standard
1297 utilities. This uses Posix.2 configuration variables, if present. It
1298 uses a value defined in config.h as a last resort. */
1300 conf_standard_path ()
1302 #if defined (_CS_PATH) && defined (HAVE_CONFSTR)
1306 len
= (size_t)confstr (_CS_PATH
, (char *)NULL
, (size_t)0);
1309 p
= (char *)xmalloc (len
+ 2);
1311 confstr (_CS_PATH
, p
, len
);
1315 return (savestring (STANDARD_UTILS_PATH
));
1316 #else /* !_CS_PATH || !HAVE_CONFSTR */
1317 # if defined (CS_PATH)
1318 return (savestring (CS_PATH
));
1320 return (savestring (STANDARD_UTILS_PATH
));
1321 # endif /* !CS_PATH */
1322 #endif /* !_CS_PATH || !HAVE_CONFSTR */