1 /* general.c -- Stuff that is used by all files. */
3 /* Copyright (C) 1987, 1988, 1989, 1990, 1991, 1992
4 Free Software Foundation, Inc.
6 This file is part of GNU Bash, the Bourne Again SHell.
8 Bash is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
13 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License along
19 with Bash; see the file COPYING. If not, write to the Free Software
20 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
24 #include "bashtypes.h"
26 # include <sys/param.h>
28 #include "posixstat.h"
30 #if defined (HAVE_UNISTD_H)
41 #include <tilde/tilde.h>
43 #if defined (TIME_WITH_SYS_TIME)
44 # include <sys/time.h>
47 # if defined (HAVE_SYS_TIME_H)
48 # include <sys/time.h>
54 #include <sys/times.h>
62 # define to_upper(c) (islower(c) ? toupper(c) : (c))
63 # define to_lower(c) (isupper(c) ? tolower(c) : (c))
66 extern int interrupt_immediately;
67 extern int interactive_comments;
69 /* A standard error message to use when getcwd() returns NULL. */
70 char *bash_getcwd_errstr = "getcwd: cannot access parent directories";
72 /* Do whatever is necessary to initialize `Posix mode'. */
77 interactive_comments = on != 0;
80 /* **************************************************************** */
82 /* Functions to convert to and from and display non-standard types */
84 /* **************************************************************** */
86 #if defined (RLIMTYPE)
88 string_to_rlimtype (s)
96 while (s && *s && whitespace (*s))
98 if (*s == '-' || *s == '+')
103 for ( ; s && *s && digit (*s); s++)
104 ret = (ret * 10) + digit_value (*s);
105 return (neg ? -ret : ret);
109 print_rlimtype (n, addnl)
113 char s[sizeof (RLIMTYPE) * 3 + 1];
118 printf ("0%s", addnl ? "\n" : "");
128 len = sizeof (RLIMTYPE) * 3 + 1;
130 for ( ; n != 0; n /= 10)
131 s[--len] = n % 10 + '0';
132 printf ("%s%s", s + len, addnl ? "\n" : "");
134 #endif /* RLIMTYPE */
136 #if defined (HAVE_TIMEVAL)
137 /* Convert a pointer to a struct timeval to seconds and thousandths of a
138 second, returning the values in *SP and *SFP, respectively. This does
139 rounding on the fractional part, not just truncation to three places. */
141 timeval_to_secs (tvp, sp, sfp)
150 *sfp = tvp->tv_usec % 1000000; /* pretty much a no-op */
152 *sfp = (*sfp * 1000) / 1000000;
157 /* Print the contents of a struct timeval * in a standard way to stdio
160 print_timeval (fp, tvp)
164 int minutes, seconds_fraction;
167 timeval_to_secs (tvp, &seconds, &seconds_fraction);
169 minutes = seconds / 60;
172 fprintf (fp, "%0dm%0ld.%03ds", minutes, seconds, seconds_fraction);
174 #endif /* HAVE_TIMEVAL */
176 #if defined (HAVE_TIMES)
178 clock_t_to_secs (t, sp, sfp)
183 static long clk_tck = 0;
186 clk_tck = get_clk_tck ();
189 *sfp = (*sfp * 1000) / clk_tck;
194 /* Print the time defined by a time_t (returned by the `times' and `time'
195 system calls) in a standard way to stdion stream FP. This is scaled in
196 terms of HZ, which is what is returned by the `times' call. */
198 print_time_in_hz (fp, t)
202 int minutes, seconds_fraction;
205 clock_t_to_secs (t, &seconds, &seconds_fraction);
207 minutes = seconds / 60;
210 fprintf (fp, "%0dm%0ld.%03ds", minutes, seconds, seconds_fraction);
212 #endif /* HAVE_TIMES */
214 /* **************************************************************** */
216 /* Input Validation Functions */
218 /* **************************************************************** */
220 /* Return non-zero if all of the characters in STRING are digits. */
227 if (!digit (*string))
235 /* Return non-zero if the characters pointed to by STRING constitute a
236 valid number. Stuff the converted number into RESULT if RESULT is
237 a non-null pointer to a long. */
239 legal_number (string, result)
249 value = strtol (string, &ep, 10);
251 /* If *string is not '\0' but *ep is '\0' on return, the entire string
253 if (string && *string && *ep == '\0')
257 /* The SunOS4 implementation of strtol() will happily ignore
258 overflow conditions, so this cannot do overflow correctly
266 /* Return 1 if this token is a legal shell `identifier'; that is, it consists
267 solely of letters, digits, and underscores, and does not begin with a
270 legal_identifier (name)
275 if (!name || !*name || (legal_variable_starter (*name) == 0))
278 for (s = name + 1; *s; s++)
280 if (legal_variable_char (*s) == 0)
286 /* Make sure that WORD is a valid shell identifier, i.e.
287 does not contain a dollar sign, nor is quoted in any way. Nor
288 does it consist of all digits. If CHECK_WORD is non-zero,
289 the word is checked to ensure that it consists of only letters,
290 digits, and underscores. */
292 check_identifier (word, check_word)
296 if ((word->flags & (W_HASDOLLAR|W_QUOTED)) || all_digits (word->word))
298 internal_error ("`%s': not a valid identifier", word->word);
301 else if (check_word && legal_identifier (word->word) == 0)
303 internal_error ("`%s': not a valid identifier", word->word);
310 /* **************************************************************** */
312 /* Functions to manage files and file descriptors */
314 /* **************************************************************** */
316 /* A function to unset no-delay mode on a file descriptor. Used in shell.c
317 to unset it on the fd passed as stdin. Should be called on stdin if
318 readline gets an EAGAIN or EWOULDBLOCK when trying to read input. */
320 #if !defined (O_NDELAY)
321 # if defined (FNDELAY)
322 # define O_NDELAY FNDELAY
324 #endif /* O_NDELAY */
326 /* Make sure no-delay mode is not set on file descriptor FD. */
328 unset_nodelay_mode (fd)
333 if ((flags = fcntl (fd, F_GETFL, 0)) < 0)
338 /* This is defined to O_NDELAY in filecntl.h if O_NONBLOCK is not present
339 and O_NDELAY is defined. */
340 if (flags & O_NONBLOCK)
342 flags &= ~O_NONBLOCK;
347 fcntl (fd, F_SETFL, flags);
350 /* There is a bug in the NeXT 2.1 rlogind that causes opens
351 of /dev/tty to fail. */
358 tty_fd = open ("/dev/tty", O_RDWR|O_NONBLOCK);
362 tty = (char *)ttyname (fileno (stdin));
365 tty_fd = open (tty, O_RDWR|O_NONBLOCK);
370 /* Return 1 if PATH1 and PATH2 are the same file. This is kind of
371 expensive. If non-NULL STP1 and STP2 point to stat structures
372 corresponding to PATH1 and PATH2, respectively. */
374 same_file (path1, path2, stp1, stp2)
376 struct stat *stp1, *stp2;
378 struct stat st1, st2;
382 if (stat (path1, &st1) != 0)
389 if (stat (path2, &st2) != 0)
394 return ((stp1->st_dev == stp2->st_dev) && (stp1->st_ino == stp2->st_ino));
397 /* Move FD to a number close to the maximum number of file descriptors
398 allowed in the shell process, to avoid the user stepping on it with
399 redirection and causing us extra work. If CHECK_NEW is non-zero,
400 we check whether or not the file descriptors are in use before
401 duplicating FD onto them. MAXFD says where to start checking the
402 file descriptors. If it's less than 20, we get the maximum value
403 available from getdtablesize(2). */
405 move_to_high_fd (fd, check_new, maxfd)
406 int fd, check_new, maxfd;
408 int script_fd, nfds, ignore;
412 nfds = getdtablesize ();
421 for (nfds--; check_new && nfds > 3; nfds--)
422 if (fcntl (nfds, F_GETFD, &ignore) == -1)
425 if (nfds && fd != nfds && (script_fd = dup2 (fd, nfds)) != -1)
427 if (check_new == 0 || fd != fileno (stderr)) /* don't close stderr */
435 /* Return non-zero if the characters from SAMPLE are not all valid
436 characters to be found in the first line of a shell script. We
437 check up to the first newline, or SAMPLE_LEN, whichever comes first.
438 All of the characters must be printable or whitespace. */
440 #if !defined (isspace)
441 #define isspace(c) ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\f')
444 #if !defined (isprint)
445 #define isprint(c) (isletter(c) || digit(c) || ispunct(c))
449 check_binary_file (sample, sample_len)
450 unsigned char *sample;
455 for (i = 0; i < sample_len; i++)
457 if (sample[i] == '\n')
460 if (isspace (sample[i]) == 0 && isprint (sample[i]) == 0)
467 /* **************************************************************** */
469 /* Functions to manipulate pathnames */
471 /* **************************************************************** */
473 /* Return 1 if PATH corresponds to a directory. */
488 l = stat (s, &sb) == 0 && S_ISDIR (sb.st_mode);
493 /* Canonicalize PATH, and return a new path. The new path differs from PATH
495 Multple `/'s are collapsed to a single `/'.
496 Leading `./'s and trailing `/.'s are removed.
497 Trailing `/'s are removed.
498 Non-leading `../'s and trailing `..'s are handled by removing
499 portions of the path. */
501 canonicalize_pathname (path)
504 register int i, start;
508 /* The result cannot be larger than the input PATH. */
509 result = savestring (path);
511 stub_char = (*path == '/') ? '/' : '.';
513 /* Walk along RESULT looking for things to compact. */
520 while (result[i] && result[i] != '/')
525 /* If we didn't find any slashes, then there is nothing left to do. */
529 /* Handle multiple `/'s in a row. */
530 while (result[i] == '/')
534 if ((start + 1) != i)
536 /* Leave a leading `//' alone, as POSIX requires. */
537 if ((start + 1) != i && (start != 0 || i != 2))
540 strcpy (result + start + 1, result + i);
542 /* Make sure that what we have so far corresponds to a directory.
543 If it does not, just punt. */
548 result[start] = '\0';
549 if (canon_stat (result) == 0)
552 return ((char *)NULL);
558 /* Handle backslash-quoted `/'. */
559 if (start > 0 && result[start - 1] == '\\')
563 /* Check for trailing `/'. */
564 if (start && !result[i])
571 /* Check for `../', `./' or trailing `.' by itself. */
572 if (result[i] == '.')
574 /* Handle trailing `.' by itself. */
579 if (result[i + 1] == '/')
581 strcpy (result + i, result + i + 1);
582 i = (start < 0) ? 0 : start;
586 /* Handle `../' or trailing `..' by itself. */
587 if (result[i + 1] == '.' &&
588 (result[i + 2] == '/' || !result[i + 2]))
590 /* Make sure that the last component corresponds to a directory
591 before blindly chopping it off. */
595 if (canon_stat (result) == 0)
598 return ((char *)NULL);
602 while (--start > -1 && result[start] != '/');
603 strcpy (result + start + 1, result + i + 2);
604 #if 0 /* Unnecessary */
605 if (*result && canon_stat (result) == 0)
608 return ((char *)NULL);
611 i = (start < 0) ? 0 : start;
624 /* Turn `//' into `/' -- XXX experimental */
625 if (result[0] == '/' && result[1] == '/' && result[2] == '\0')
632 /* Turn STRING (a pathname) into an absolute pathname, assuming that
633 DOT_PATH contains the symbolic location of `.'. This always
634 returns a new string, even if STRING was an absolute pathname to
637 make_absolute (string, dot_path)
638 char *string, *dot_path;
643 if (dot_path == 0 || *string == '/')
644 result = savestring (string);
649 result_len = strlen (dot_path);
650 result = xmalloc (2 + result_len + strlen (string));
651 strcpy (result, dot_path);
652 if (result[result_len - 1] != '/')
654 result[result_len++] = '/';
655 result[result_len] = '\0';
660 result = xmalloc (3 + strlen (string));
661 result[0] = '.'; result[1] = '/'; result[2] = '\0';
665 strcpy (result + result_len, string);
671 /* Return 1 if STRING contains an absolute pathname, else 0. */
673 absolute_pathname (string)
676 if (!string || !*string)
682 if (*string++ == '.')
684 if (!*string || *string == '/' ||
685 (*string == '.' && (string[1] == '\0' || string[1] == '/')))
691 /* Return 1 if STRING is an absolute program name; it is absolute if it
692 contains any slashes. This is used to decide whether or not to look
695 absolute_program (string)
698 return ((char *)strchr (string, '/') != (char *)NULL);
701 /* Return the `basename' of the pathname in STRING (the stuff after the
702 last '/'). If STRING is not a full pathname, simply return it. */
704 base_pathname (string)
709 if (!absolute_pathname (string))
712 p = (char *)strrchr (string, '/');
713 return (p ? ++p : string);
716 /* Return the full pathname of FILE. Easy. Filenames that begin
717 with a '/' are returned as themselves. Other filenames have
718 the current working directory prepended. A new string is
719 returned in either case. */
728 file = (*file == '~') ? bash_tilde_expand (file) : savestring (file);
730 if ((*file == '/') && absolute_pathname (file))
735 /* XXX - this should probably be just PATH_MAX or PATH_MAX + 1 */
736 current_dir = xmalloc (2 + PATH_MAX + strlen (file));
737 if (getcwd (current_dir, PATH_MAX) == 0)
739 sys_error (bash_getcwd_errstr);
742 return ((char *)NULL);
744 dlen = strlen (current_dir);
745 current_dir[dlen++] = '/';
747 /* Turn /foo/./bar into /foo/bar. */
748 if (file[0] == '.' && file[1] == '/')
751 strcpy (current_dir + dlen, file);
753 return (current_dir);
756 /* A slightly related function. Get the prettiest name of this
757 directory possible. */
758 static char tdir[PATH_MAX];
760 /* Return a pretty pathname. If the first part of the pathname is
761 the same as $HOME, then replace that with `~'. */
763 polite_directory_format (name)
769 home = get_string_value ("HOME");
770 l = home ? strlen (home) : 0;
771 if (l > 1 && strncmp (home, name, l) == 0 && (!name[l] || name[l] == '/'))
773 strncpy (tdir + 1, name + l, sizeof(tdir) - 2);
775 tdir[sizeof(tdir) - 1] = '\0';
782 /* Given a string containing units of information separated by colons,
783 return the next one pointed to by (P_INDEX), or NULL if there are no more.
784 Advance (P_INDEX) to the character after the colon. */
786 extract_colon_unit (string, p_index)
796 len = strlen (string);
798 return ((char *)NULL);
802 /* Each call to this routine leaves the index pointing at a colon if
803 there is more to the path. If I is > 0, then increment past the
804 `:'. If I is 0, then the path has a leading colon. Trailing colons
805 are handled OK by the `else' part of the if statement; an empty
806 string is returned in that case. */
807 if (i && string[i] == ':')
810 for (start = i; string[i] && string[i] != ':'; i++)
819 /* Return "" in the case of a trailing `:'. */
826 value = xmalloc (1 + len);
827 strncpy (value, string + start, len);
834 /* **************************************************************** */
836 /* Tilde Initialization and Expansion */
838 /* **************************************************************** */
840 #if defined (PUSHD_AND_POPD)
841 extern char *get_dirstack_from_string __P((char *));
844 /* If tilde_expand hasn't been able to expand the text, perhaps it
845 is a special shell expansion. This function is installed as the
846 tilde_expansion_preexpansion_hook. It knows how to expand ~- and ~+.
847 If PUSHD_AND_POPD is defined, ~[+-]N expands to directories from the
850 bash_special_tilde_expansions (text)
855 result = (char *)NULL;
857 if (text[0] == '+' && text[1] == '\0')
858 result = get_string_value ("PWD");
859 else if (text[0] == '-' && text[1] == '\0')
860 result = get_string_value ("OLDPWD");
861 #if defined (PUSHD_AND_POPD)
862 else if (isdigit (*text) || ((*text == '+' || *text == '-') && isdigit (text[1])))
863 result = get_dirstack_from_string (text);
866 return (result ? savestring (result) : (char *)NULL);
869 /* Initialize the tilde expander. In Bash, we handle `~-' and `~+', as
870 well as handling special tilde prefixes; `:~" and `=~' are indications
871 that we should do tilde expansion. */
875 static int times_called = 0;
877 /* Tell the tilde expander that we want a crack first. */
878 tilde_expansion_preexpansion_hook = (CPFunction *)bash_special_tilde_expansions;
880 /* Tell the tilde expander about special strings which start a tilde
881 expansion, and the special strings that end one. Only do this once.
882 tilde_initialize () is called from within bashline_reinitialize (). */
883 if (times_called++ == 0)
885 tilde_additional_prefixes = (char **)xmalloc (3 * sizeof (char *));
886 tilde_additional_prefixes[0] = "=~";
887 tilde_additional_prefixes[1] = ":~";
888 tilde_additional_prefixes[2] = (char *)NULL;
890 tilde_additional_suffixes = (char **)xmalloc (3 * sizeof (char *));
891 tilde_additional_suffixes[0] = ":";
892 tilde_additional_suffixes[1] = "=~";
893 tilde_additional_suffixes[2] = (char *)NULL;
898 bash_tilde_expand (s)
904 old_immed = interrupt_immediately;
905 interrupt_immediately = 1;
906 ret = tilde_expand (s);
907 interrupt_immediately = old_immed;
911 /* **************************************************************** */
913 /* Functions to manipulate and search the group list */
915 /* **************************************************************** */
917 static int ngroups, maxgroups;
919 /* The set of groups that this user is a member of. */
920 static GETGROUPS_T *group_array = (GETGROUPS_T *)NULL;
922 #if !defined (NOGROUP)
923 # define NOGROUP (gid_t) -1
926 #if defined (HAVE_SYSCONF) && defined (_SC_NGROUPS_MAX)
927 # define getmaxgroups() sysconf(_SC_NGROUPS_MAX)
929 # if defined (NGROUPS_MAX)
930 # define getmaxgroups() NGROUPS_MAX
931 # else /* !NGROUPS_MAX */
932 # if defined (NGROUPS)
933 # define getmaxgroups() NGROUPS
934 # else /* !NGROUPS */
935 # define getmaxgroups() 64
936 # endif /* !NGROUPS */
937 # endif /* !NGROUPS_MAX */
938 #endif /* !HAVE_SYSCONF || !SC_NGROUPS_MAX */
941 initialize_group_array ()
946 maxgroups = getmaxgroups ();
949 group_array = (GETGROUPS_T *)xrealloc (group_array, maxgroups * sizeof (GETGROUPS_T));
951 #if defined (HAVE_GETGROUPS)
952 ngroups = getgroups (maxgroups, group_array);
955 /* If getgroups returns nothing, or the OS does not support getgroups(),
956 make sure the groups array includes at least the current gid. */
959 group_array[0] = current_user.gid;
963 /* If the primary group is not in the groups array, add it as group_array[0]
964 and shuffle everything else up 1, if there's room. */
965 for (i = 0; i < ngroups; i++)
966 if (current_user.gid == (gid_t)group_array[i])
968 if (i == ngroups && ngroups < maxgroups)
970 for (i = ngroups; i > 0; i--)
971 group_array[i] = group_array[i - 1];
972 group_array[0] = current_user.gid;
976 /* If the primary group is not group_array[0], swap group_array[0] and
977 whatever the current group is. The vast majority of systems should
978 not need this; a notable exception is Linux. */
979 if (group_array[0] != current_user.gid)
981 for (i = 0; i < ngroups; i++)
982 if (group_array[i] == current_user.gid)
986 group_array[i] = group_array[0];
987 group_array[0] = current_user.gid;
992 /* Return non-zero if GID is one that we have in our groups list. */
994 #if defined (__STDC__) || defined ( _MINIX)
995 group_member (gid_t gid)
999 #endif /* !__STDC__ && !_MINIX */
1001 #if defined (HAVE_GETGROUPS)
1005 /* Short-circuit if possible, maybe saving a call to getgroups(). */
1006 if (gid == current_user.gid || gid == current_user.egid)
1009 #if defined (HAVE_GETGROUPS)
1011 initialize_group_array ();
1013 /* In case of error, the user loses. */
1017 /* Search through the list looking for GID. */
1018 for (i = 0; i < ngroups; i++)
1019 if (gid == (gid_t)group_array[i])
1027 get_group_list (ngp)
1030 static char **group_vector = (char **)NULL;
1038 return group_vector;
1042 initialize_group_array ();
1048 return (char **)NULL;
1051 group_vector = (char **)xmalloc (ngroups * sizeof (char *));
1052 for (i = 0; i < ngroups; i++)
1054 nbuf = itos ((int)group_array[i]);
1055 group_vector[i] = nbuf;
1059 return group_vector;