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;
164 /* Print the contents of a struct timeval * in a standard way to stdio
167 print_timeval (fp, tvp)
171 int minutes, seconds_fraction;
174 timeval_to_secs (tvp, &seconds, &seconds_fraction);
176 minutes = seconds / 60;
179 fprintf (fp, "%0dm%0ld.%03ds", minutes, seconds, seconds_fraction);
181 #endif /* HAVE_TIMEVAL */
183 #if defined (HAVE_TIMES)
185 clock_t_to_secs (t, sp, sfp)
190 static long clk_tck = 0;
193 clk_tck = get_clk_tck ();
196 *sfp = (*sfp * 1000) / clk_tck;
208 /* Print the time defined by a time_t (returned by the `times' and `time'
209 system calls) in a standard way to stdion stream FP. This is scaled in
210 terms of HZ, which is what is returned by the `times' call. */
212 print_time_in_hz (fp, t)
216 int minutes, seconds_fraction;
219 clock_t_to_secs (t, &seconds, &seconds_fraction);
221 minutes = seconds / 60;
224 fprintf (fp, "%0dm%0ld.%03ds", minutes, seconds, seconds_fraction);
226 #endif /* HAVE_TIMES */
228 /* **************************************************************** */
230 /* Input Validation Functions */
232 /* **************************************************************** */
234 /* Return non-zero if all of the characters in STRING are digits. */
241 if (!digit (*string))
249 /* Return non-zero if the characters pointed to by STRING constitute a
250 valid number. Stuff the converted number into RESULT if RESULT is
251 a non-null pointer to a long. */
253 legal_number (string, result)
263 value = strtol (string, &ep, 10);
265 /* If *string is not '\0' but *ep is '\0' on return, the entire string
267 if (string && *string && *ep == '\0')
271 /* The SunOS4 implementation of strtol() will happily ignore
272 overflow conditions, so this cannot do overflow correctly
280 /* Return 1 if this token is a legal shell `identifier'; that is, it consists
281 solely of letters, digits, and underscores, and does not begin with a
284 legal_identifier (name)
289 if (!name || !*name || (legal_variable_starter (*name) == 0))
292 for (s = name + 1; *s; s++)
294 if (legal_variable_char (*s) == 0)
300 /* Make sure that WORD is a valid shell identifier, i.e.
301 does not contain a dollar sign, nor is quoted in any way. Nor
302 does it consist of all digits. If CHECK_WORD is non-zero,
303 the word is checked to ensure that it consists of only letters,
304 digits, and underscores. */
306 check_identifier (word, check_word)
310 if ((word->flags & (W_HASDOLLAR|W_QUOTED)) || all_digits (word->word))
312 internal_error ("`%s': not a valid identifier", word->word);
315 else if (check_word && legal_identifier (word->word) == 0)
317 internal_error ("`%s': not a valid identifier", word->word);
324 /* **************************************************************** */
326 /* Functions to manage files and file descriptors */
328 /* **************************************************************** */
330 /* A function to unset no-delay mode on a file descriptor. Used in shell.c
331 to unset it on the fd passed as stdin. Should be called on stdin if
332 readline gets an EAGAIN or EWOULDBLOCK when trying to read input. */
334 #if !defined (O_NDELAY)
335 # if defined (FNDELAY)
336 # define O_NDELAY FNDELAY
338 #endif /* O_NDELAY */
340 /* Make sure no-delay mode is not set on file descriptor FD. */
342 unset_nodelay_mode (fd)
347 if ((flags = fcntl (fd, F_GETFL, 0)) < 0)
352 /* This is defined to O_NDELAY in filecntl.h if O_NONBLOCK is not present
353 and O_NDELAY is defined. */
354 if (flags & O_NONBLOCK)
356 flags &= ~O_NONBLOCK;
361 fcntl (fd, F_SETFL, flags);
364 /* There is a bug in the NeXT 2.1 rlogind that causes opens
365 of /dev/tty to fail. */
367 #if defined (__BEOS__)
368 /* On BeOS, opening in non-blocking mode exposes a bug in BeOS, so turn it
369 into a no-op. This should probably go away in the future. */
371 # define O_NONBLOCK 0
372 #endif /* __BEOS__ */
380 tty_fd = open ("/dev/tty", O_RDWR|O_NONBLOCK);
384 tty = (char *)ttyname (fileno (stdin));
387 tty_fd = open (tty, O_RDWR|O_NONBLOCK);
392 /* Return 1 if PATH1 and PATH2 are the same file. This is kind of
393 expensive. If non-NULL STP1 and STP2 point to stat structures
394 corresponding to PATH1 and PATH2, respectively. */
396 same_file (path1, path2, stp1, stp2)
398 struct stat *stp1, *stp2;
400 struct stat st1, st2;
404 if (stat (path1, &st1) != 0)
411 if (stat (path2, &st2) != 0)
416 return ((stp1->st_dev == stp2->st_dev) && (stp1->st_ino == stp2->st_ino));
419 /* Move FD to a number close to the maximum number of file descriptors
420 allowed in the shell process, to avoid the user stepping on it with
421 redirection and causing us extra work. If CHECK_NEW is non-zero,
422 we check whether or not the file descriptors are in use before
423 duplicating FD onto them. MAXFD says where to start checking the
424 file descriptors. If it's less than 20, we get the maximum value
425 available from getdtablesize(2). */
427 move_to_high_fd (fd, check_new, maxfd)
428 int fd, check_new, maxfd;
430 int script_fd, nfds, ignore;
434 nfds = getdtablesize ();
443 for (nfds--; check_new && nfds > 3; nfds--)
444 if (fcntl (nfds, F_GETFD, &ignore) == -1)
447 if (nfds && fd != nfds && (script_fd = dup2 (fd, nfds)) != -1)
449 if (check_new == 0 || fd != fileno (stderr)) /* don't close stderr */
457 /* Return non-zero if the characters from SAMPLE are not all valid
458 characters to be found in the first line of a shell script. We
459 check up to the first newline, or SAMPLE_LEN, whichever comes first.
460 All of the characters must be printable or whitespace. */
462 #if !defined (isspace)
463 #define isspace(c) ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\f')
466 #if !defined (isprint)
467 #define isprint(c) (isletter(c) || digit(c) || ispunct(c))
471 check_binary_file (sample, sample_len)
472 unsigned char *sample;
477 for (i = 0; i < sample_len; i++)
479 if (sample[i] == '\n')
482 if (isspace (sample[i]) == 0 && isprint (sample[i]) == 0)
489 /* **************************************************************** */
491 /* Functions to manipulate pathnames */
493 /* **************************************************************** */
495 /* Return 1 if PATH corresponds to a directory. */
510 l = stat (s, &sb) == 0 && S_ISDIR (sb.st_mode);
515 /* Canonicalize PATH, and return a new path. The new path differs from PATH
517 Multple `/'s are collapsed to a single `/'.
518 Leading `./'s and trailing `/.'s are removed.
519 Trailing `/'s are removed.
520 Non-leading `../'s and trailing `..'s are handled by removing
521 portions of the path. */
523 canonicalize_pathname (path)
526 register int i, start;
530 /* The result cannot be larger than the input PATH. */
531 result = savestring (path);
533 stub_char = (*path == '/') ? '/' : '.';
535 /* Walk along RESULT looking for things to compact. */
542 while (result[i] && result[i] != '/')
547 /* If we didn't find any slashes, then there is nothing left to do. */
551 /* Handle multiple `/'s in a row. */
552 while (result[i] == '/')
556 if ((start + 1) != i)
558 /* Leave a leading `//' alone, as POSIX requires. */
559 if ((start + 1) != i && (start != 0 || i != 2))
562 strcpy (result + start + 1, result + i);
564 /* Make sure that what we have so far corresponds to a directory.
565 If it does not, just punt. */
570 result[start] = '\0';
571 if (canon_stat (result) == 0)
574 return ((char *)NULL);
580 /* Handle backslash-quoted `/'. */
581 if (start > 0 && result[start - 1] == '\\')
585 /* Check for trailing `/'. */
586 if (start && !result[i])
593 /* Check for `../', `./' or trailing `.' by itself. */
594 if (result[i] == '.')
596 /* Handle trailing `.' by itself. */
601 if (result[i + 1] == '/')
603 strcpy (result + i, result + i + 1);
604 i = (start < 0) ? 0 : start;
608 /* Handle `../' or trailing `..' by itself. */
609 if (result[i + 1] == '.' &&
610 (result[i + 2] == '/' || !result[i + 2]))
612 /* Make sure that the last component corresponds to a directory
613 before blindly chopping it off. */
617 if (canon_stat (result) == 0)
620 return ((char *)NULL);
624 while (--start > -1 && result[start] != '/');
625 strcpy (result + start + 1, result + i + 2);
626 #if 0 /* Unnecessary */
627 if (*result && canon_stat (result) == 0)
630 return ((char *)NULL);
633 i = (start < 0) ? 0 : start;
645 /* If the result starts with `//', but the original path does not, we
646 can turn the // into /. */
647 if ((result[0] == '/' && result[1] == '/' && result[2] != '/') &&
648 (path[0] != '/' || path[1] != '/' || path[2] == '/'))
651 if (result[2] == '\0') /* short-circuit for bare `//' */
655 r2 = savestring (result + 1);
664 /* Turn STRING (a pathname) into an absolute pathname, assuming that
665 DOT_PATH contains the symbolic location of `.'. This always
666 returns a new string, even if STRING was an absolute pathname to
669 make_absolute (string, dot_path)
670 char *string, *dot_path;
675 if (dot_path == 0 || *string == '/')
676 result = savestring (string);
681 result_len = strlen (dot_path);
682 result = xmalloc (2 + result_len + strlen (string));
683 strcpy (result, dot_path);
684 if (result[result_len - 1] != '/')
686 result[result_len++] = '/';
687 result[result_len] = '\0';
692 result = xmalloc (3 + strlen (string));
693 result[0] = '.'; result[1] = '/'; result[2] = '\0';
697 strcpy (result + result_len, string);
703 /* Return 1 if STRING contains an absolute pathname, else 0. */
705 absolute_pathname (string)
708 if (!string || !*string)
714 if (*string++ == '.')
716 if (!*string || *string == '/' ||
717 (*string == '.' && (string[1] == '\0' || string[1] == '/')))
723 /* Return 1 if STRING is an absolute program name; it is absolute if it
724 contains any slashes. This is used to decide whether or not to look
727 absolute_program (string)
730 return ((char *)strchr (string, '/') != (char *)NULL);
733 /* Return the `basename' of the pathname in STRING (the stuff after the
734 last '/'). If STRING is not a full pathname, simply return it. */
736 base_pathname (string)
741 if (!absolute_pathname (string))
744 p = (char *)strrchr (string, '/');
745 return (p ? ++p : string);
748 /* Return the full pathname of FILE. Easy. Filenames that begin
749 with a '/' are returned as themselves. Other filenames have
750 the current working directory prepended. A new string is
751 returned in either case. */
760 file = (*file == '~') ? bash_tilde_expand (file) : savestring (file);
762 if ((*file == '/') && absolute_pathname (file))
767 /* XXX - this should probably be just PATH_MAX or PATH_MAX + 1 */
768 current_dir = xmalloc (2 + PATH_MAX + strlen (file));
769 if (getcwd (current_dir, PATH_MAX) == 0)
771 sys_error (bash_getcwd_errstr);
774 return ((char *)NULL);
776 dlen = strlen (current_dir);
777 if (current_dir[0] == '/' && dlen > 1)
778 current_dir[dlen++] = '/';
780 /* Turn /foo/./bar into /foo/bar. */
781 if (file[0] == '.' && file[1] == '/')
784 strcpy (current_dir + dlen, file);
786 return (current_dir);
789 /* A slightly related function. Get the prettiest name of this
790 directory possible. */
791 static char tdir[PATH_MAX];
793 /* Return a pretty pathname. If the first part of the pathname is
794 the same as $HOME, then replace that with `~'. */
796 polite_directory_format (name)
802 home = get_string_value ("HOME");
803 l = home ? strlen (home) : 0;
804 if (l > 1 && strncmp (home, name, l) == 0 && (!name[l] || name[l] == '/'))
806 strncpy (tdir + 1, name + l, sizeof(tdir) - 2);
808 tdir[sizeof(tdir) - 1] = '\0';
815 /* Given a string containing units of information separated by colons,
816 return the next one pointed to by (P_INDEX), or NULL if there are no more.
817 Advance (P_INDEX) to the character after the colon. */
819 extract_colon_unit (string, p_index)
829 len = strlen (string);
831 return ((char *)NULL);
835 /* Each call to this routine leaves the index pointing at a colon if
836 there is more to the path. If I is > 0, then increment past the
837 `:'. If I is 0, then the path has a leading colon. Trailing colons
838 are handled OK by the `else' part of the if statement; an empty
839 string is returned in that case. */
840 if (i && string[i] == ':')
843 for (start = i; string[i] && string[i] != ':'; i++)
852 /* Return "" in the case of a trailing `:'. */
859 value = xmalloc (1 + len);
860 strncpy (value, string + start, len);
867 /* **************************************************************** */
869 /* Tilde Initialization and Expansion */
871 /* **************************************************************** */
873 #if defined (PUSHD_AND_POPD)
874 extern char *get_dirstack_from_string __P((char *));
877 /* If tilde_expand hasn't been able to expand the text, perhaps it
878 is a special shell expansion. This function is installed as the
879 tilde_expansion_preexpansion_hook. It knows how to expand ~- and ~+.
880 If PUSHD_AND_POPD is defined, ~[+-]N expands to directories from the
883 bash_special_tilde_expansions (text)
888 result = (char *)NULL;
890 if (text[0] == '+' && text[1] == '\0')
891 result = get_string_value ("PWD");
892 else if (text[0] == '-' && text[1] == '\0')
893 result = get_string_value ("OLDPWD");
894 #if defined (PUSHD_AND_POPD)
895 else if (isdigit (*text) || ((*text == '+' || *text == '-') && isdigit (text[1])))
896 result = get_dirstack_from_string (text);
899 return (result ? savestring (result) : (char *)NULL);
902 /* Initialize the tilde expander. In Bash, we handle `~-' and `~+', as
903 well as handling special tilde prefixes; `:~" and `=~' are indications
904 that we should do tilde expansion. */
908 static int times_called = 0;
910 /* Tell the tilde expander that we want a crack first. */
911 tilde_expansion_preexpansion_hook = (CPFunction *)bash_special_tilde_expansions;
913 /* Tell the tilde expander about special strings which start a tilde
914 expansion, and the special strings that end one. Only do this once.
915 tilde_initialize () is called from within bashline_reinitialize (). */
916 if (times_called++ == 0)
918 tilde_additional_prefixes = (char **)xmalloc (3 * sizeof (char *));
919 tilde_additional_prefixes[0] = "=~";
920 tilde_additional_prefixes[1] = ":~";
921 tilde_additional_prefixes[2] = (char *)NULL;
923 tilde_additional_suffixes = (char **)xmalloc (3 * sizeof (char *));
924 tilde_additional_suffixes[0] = ":";
925 tilde_additional_suffixes[1] = "=~";
926 tilde_additional_suffixes[2] = (char *)NULL;
931 bash_tilde_expand (s)
937 old_immed = interrupt_immediately;
938 interrupt_immediately = 1;
939 ret = tilde_expand (s);
940 interrupt_immediately = old_immed;
944 /* **************************************************************** */
946 /* Functions to manipulate and search the group list */
948 /* **************************************************************** */
950 static int ngroups, maxgroups;
952 /* The set of groups that this user is a member of. */
953 static GETGROUPS_T *group_array = (GETGROUPS_T *)NULL;
955 #if !defined (NOGROUP)
956 # define NOGROUP (gid_t) -1
959 #if defined (HAVE_SYSCONF) && defined (_SC_NGROUPS_MAX)
960 # define getmaxgroups() sysconf(_SC_NGROUPS_MAX)
962 # if defined (NGROUPS_MAX)
963 # define getmaxgroups() NGROUPS_MAX
964 # else /* !NGROUPS_MAX */
965 # if defined (NGROUPS)
966 # define getmaxgroups() NGROUPS
967 # else /* !NGROUPS */
968 # define getmaxgroups() 64
969 # endif /* !NGROUPS */
970 # endif /* !NGROUPS_MAX */
971 #endif /* !HAVE_SYSCONF || !SC_NGROUPS_MAX */
974 initialize_group_array ()
979 maxgroups = getmaxgroups ();
982 group_array = (GETGROUPS_T *)xrealloc (group_array, maxgroups * sizeof (GETGROUPS_T));
984 #if defined (HAVE_GETGROUPS)
985 ngroups = getgroups (maxgroups, group_array);
988 /* If getgroups returns nothing, or the OS does not support getgroups(),
989 make sure the groups array includes at least the current gid. */
992 group_array[0] = current_user.gid;
996 /* If the primary group is not in the groups array, add it as group_array[0]
997 and shuffle everything else up 1, if there's room. */
998 for (i = 0; i < ngroups; i++)
999 if (current_user.gid == (gid_t)group_array[i])
1001 if (i == ngroups && ngroups < maxgroups)
1003 for (i = ngroups; i > 0; i--)
1004 group_array[i] = group_array[i - 1];
1005 group_array[0] = current_user.gid;
1009 /* If the primary group is not group_array[0], swap group_array[0] and
1010 whatever the current group is. The vast majority of systems should
1011 not need this; a notable exception is Linux. */
1012 if (group_array[0] != current_user.gid)
1014 for (i = 0; i < ngroups; i++)
1015 if (group_array[i] == current_user.gid)
1019 group_array[i] = group_array[0];
1020 group_array[0] = current_user.gid;
1025 /* Return non-zero if GID is one that we have in our groups list. */
1027 #if defined (__STDC__) || defined ( _MINIX)
1028 group_member (gid_t gid)
1032 #endif /* !__STDC__ && !_MINIX */
1034 #if defined (HAVE_GETGROUPS)
1038 /* Short-circuit if possible, maybe saving a call to getgroups(). */
1039 if (gid == current_user.gid || gid == current_user.egid)
1042 #if defined (HAVE_GETGROUPS)
1044 initialize_group_array ();
1046 /* In case of error, the user loses. */
1050 /* Search through the list looking for GID. */
1051 for (i = 0; i < ngroups; i++)
1052 if (gid == (gid_t)group_array[i])
1060 get_group_list (ngp)
1063 static char **group_vector = (char **)NULL;
1071 return group_vector;
1075 initialize_group_array ();
1081 return (char **)NULL;
1084 group_vector = (char **)xmalloc (ngroups * sizeof (char *));
1085 for (i = 0; i < ngroups; i++)
1087 nbuf = itos ((int)group_array[i]);
1088 group_vector[i] = nbuf;
1093 return group_vector;
1097 get_group_array (ngp)
1101 static int *group_iarray = (int *)NULL;
1107 return (group_iarray);
1111 initialize_group_array ();
1120 group_iarray = (int *)xmalloc (ngroups * sizeof (int));
1121 for (i = 0; i < ngroups; i++)
1122 group_iarray[i] = (int)group_array[i];
1126 return group_iarray;