1 /* general.c -- Stuff that is used by all files. */
3 /* Copyright (C) 1987-1999 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 it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
12 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License along
18 with Bash; see the file COPYING. If not, write to the Free Software
19 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
23 #include "bashtypes.h"
25 # include <sys/param.h>
27 #include "posixstat.h"
29 #if defined (HAVE_UNISTD_H)
40 #include <tilde/tilde.h>
49 # define to_upper(c) (islower(c) ? toupper(c) : (c))
50 # define to_lower(c) (isupper(c) ? tolower(c) : (c))
53 extern int interrupt_immediately
;
54 extern int interactive_comments
;
56 /* A standard error message to use when getcwd() returns NULL. */
57 char *bash_getcwd_errstr
= "getcwd: cannot access parent directories";
59 /* Do whatever is necessary to initialize `Posix mode'. */
64 interactive_comments
= on
!= 0;
67 /* **************************************************************** */
69 /* Functions to convert to and from and display non-standard types */
71 /* **************************************************************** */
73 #if defined (RLIMTYPE)
75 string_to_rlimtype (s
)
83 while (s
&& *s
&& whitespace (*s
))
85 if (*s
== '-' || *s
== '+')
90 for ( ; s
&& *s
&& digit (*s
); s
++)
91 ret
= (ret
* 10) + digit_value (*s
);
92 return (neg
? -ret
: ret
);
96 print_rlimtype (n
, addnl
)
100 char s
[sizeof (RLIMTYPE
) * 3 + 1];
105 printf ("0%s", addnl
? "\n" : "");
115 len
= sizeof (RLIMTYPE
) * 3 + 1;
117 for ( ; n
!= 0; n
/= 10)
118 s
[--len
] = n
% 10 + '0';
119 printf ("%s%s", s
+ len
, addnl
? "\n" : "");
121 #endif /* RLIMTYPE */
123 /* **************************************************************** */
125 /* Input Validation Functions */
127 /* **************************************************************** */
129 /* Return non-zero if all of the characters in STRING are digits. */
136 if (!digit (*string
))
144 /* Return non-zero if the characters pointed to by STRING constitute a
145 valid number. Stuff the converted number into RESULT if RESULT is
146 a non-null pointer to a long. */
148 legal_number (string
, result
)
158 value
= strtol (string
, &ep
, 10);
160 /* If *string is not '\0' but *ep is '\0' on return, the entire string
162 if (string
&& *string
&& *ep
== '\0')
166 /* The SunOS4 implementation of strtol() will happily ignore
167 overflow conditions, so this cannot do overflow correctly
175 /* Return 1 if this token is a legal shell `identifier'; that is, it consists
176 solely of letters, digits, and underscores, and does not begin with a
179 legal_identifier (name
)
184 if (!name
|| !*name
|| (legal_variable_starter (*name
) == 0))
187 for (s
= name
+ 1; *s
; s
++)
189 if (legal_variable_char (*s
) == 0)
195 /* Make sure that WORD is a valid shell identifier, i.e.
196 does not contain a dollar sign, nor is quoted in any way. Nor
197 does it consist of all digits. If CHECK_WORD is non-zero,
198 the word is checked to ensure that it consists of only letters,
199 digits, and underscores. */
201 check_identifier (word
, check_word
)
205 if ((word
->flags
& (W_HASDOLLAR
|W_QUOTED
)) || all_digits (word
->word
))
207 internal_error ("`%s': not a valid identifier", word
->word
);
210 else if (check_word
&& legal_identifier (word
->word
) == 0)
212 internal_error ("`%s': not a valid identifier", word
->word
);
219 /* **************************************************************** */
221 /* Functions to manage files and file descriptors */
223 /* **************************************************************** */
225 /* A function to unset no-delay mode on a file descriptor. Used in shell.c
226 to unset it on the fd passed as stdin. Should be called on stdin if
227 readline gets an EAGAIN or EWOULDBLOCK when trying to read input. */
229 #if !defined (O_NDELAY)
230 # if defined (FNDELAY)
231 # define O_NDELAY FNDELAY
233 #endif /* O_NDELAY */
235 /* Make sure no-delay mode is not set on file descriptor FD. */
237 unset_nodelay_mode (fd
)
242 if ((flags
= fcntl (fd
, F_GETFL
, 0)) < 0)
247 /* This is defined to O_NDELAY in filecntl.h if O_NONBLOCK is not present
248 and O_NDELAY is defined. */
250 bflags
|= O_NONBLOCK
;
260 return (fcntl (fd
, F_SETFL
, flags
));
266 /* There is a bug in the NeXT 2.1 rlogind that causes opens
267 of /dev/tty to fail. */
269 #if defined (__BEOS__)
270 /* On BeOS, opening in non-blocking mode exposes a bug in BeOS, so turn it
271 into a no-op. This should probably go away in the future. */
273 # define O_NONBLOCK 0
274 #endif /* __BEOS__ */
282 tty_fd
= open ("/dev/tty", O_RDWR
|O_NONBLOCK
);
286 tty
= (char *)ttyname (fileno (stdin
));
289 tty_fd
= open (tty
, O_RDWR
|O_NONBLOCK
);
294 /* Return 1 if PATH1 and PATH2 are the same file. This is kind of
295 expensive. If non-NULL STP1 and STP2 point to stat structures
296 corresponding to PATH1 and PATH2, respectively. */
298 same_file (path1
, path2
, stp1
, stp2
)
300 struct stat
*stp1
, *stp2
;
302 struct stat st1
, st2
;
306 if (stat (path1
, &st1
) != 0)
313 if (stat (path2
, &st2
) != 0)
318 return ((stp1
->st_dev
== stp2
->st_dev
) && (stp1
->st_ino
== stp2
->st_ino
));
321 /* Move FD to a number close to the maximum number of file descriptors
322 allowed in the shell process, to avoid the user stepping on it with
323 redirection and causing us extra work. If CHECK_NEW is non-zero,
324 we check whether or not the file descriptors are in use before
325 duplicating FD onto them. MAXFD says where to start checking the
326 file descriptors. If it's less than 20, we get the maximum value
327 available from getdtablesize(2). */
329 move_to_high_fd (fd
, check_new
, maxfd
)
330 int fd
, check_new
, maxfd
;
332 int script_fd
, nfds
, ignore
;
336 nfds
= getdtablesize ();
345 for (nfds
--; check_new
&& nfds
> 3; nfds
--)
346 if (fcntl (nfds
, F_GETFD
, &ignore
) == -1)
349 if (nfds
&& fd
!= nfds
&& (script_fd
= dup2 (fd
, nfds
)) != -1)
351 if (check_new
== 0 || fd
!= fileno (stderr
)) /* don't close stderr */
359 /* Return non-zero if the characters from SAMPLE are not all valid
360 characters to be found in the first line of a shell script. We
361 check up to the first newline, or SAMPLE_LEN, whichever comes first.
362 All of the characters must be printable or whitespace. */
364 #if !defined (isspace)
365 #define isspace(c) ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\f')
368 #if !defined (isprint)
369 #define isprint(c) (isletter(c) || digit(c) || ispunct(c))
373 check_binary_file (sample
, sample_len
)
374 unsigned char *sample
;
379 for (i
= 0; i
< sample_len
; i
++)
381 if (sample
[i
] == '\n')
384 if (isspace (sample
[i
]) == 0 && isprint (sample
[i
]) == 0)
391 /* **************************************************************** */
393 /* Functions to manipulate pathnames */
395 /* **************************************************************** */
397 /* Return 1 if PATH corresponds to a directory. */
412 l
= stat (s
, &sb
) == 0 && S_ISDIR (sb
.st_mode
);
417 /* Canonicalize PATH, and return a new path. The new path differs from PATH
419 Multple `/'s are collapsed to a single `/'.
420 Leading `./'s and trailing `/.'s are removed.
421 Trailing `/'s are removed.
422 Non-leading `../'s and trailing `..'s are handled by removing
423 portions of the path. */
425 canonicalize_pathname (path
)
428 register int i
, start
;
432 /* The result cannot be larger than the input PATH. */
433 result
= savestring (path
);
435 stub_char
= (*path
== '/') ? '/' : '.';
437 /* Walk along RESULT looking for things to compact. */
444 while (result
[i
] && result
[i
] != '/')
449 /* If we didn't find any slashes, then there is nothing left to do. */
453 /* Handle multiple `/'s in a row. */
454 while (result
[i
] == '/')
458 if ((start
+ 1) != i
)
460 /* Leave a leading `//' alone, as POSIX requires. */
461 if ((start
+ 1) != i
&& (start
!= 0 || i
!= 2))
464 strcpy (result
+ start
+ 1, result
+ i
);
466 /* Make sure that what we have so far corresponds to a directory.
467 If it does not, just punt. */
472 result
[start
] = '\0';
473 if (canon_stat (result
) == 0)
476 return ((char *)NULL
);
482 /* Handle backslash-quoted `/'. */
483 if (start
> 0 && result
[start
- 1] == '\\')
487 /* Check for trailing `/'. */
488 if (start
&& !result
[i
])
495 /* Check for `../', `./' or trailing `.' by itself. */
496 if (result
[i
] == '.')
498 /* Handle trailing `.' by itself. */
503 if (result
[i
+ 1] == '/')
505 strcpy (result
+ i
, result
+ i
+ 1);
506 i
= (start
< 0) ? 0 : start
;
510 /* Handle `../' or trailing `..' by itself. */
511 if (result
[i
+ 1] == '.' &&
512 (result
[i
+ 2] == '/' || !result
[i
+ 2]))
514 /* Make sure that the last component corresponds to a directory
515 before blindly chopping it off. */
519 if (canon_stat (result
) == 0)
522 return ((char *)NULL
);
526 while (--start
> -1 && result
[start
] != '/');
527 strcpy (result
+ start
+ 1, result
+ i
+ 2);
528 #if 0 /* Unnecessary */
529 if (*result
&& canon_stat (result
) == 0)
532 return ((char *)NULL
);
535 i
= (start
< 0) ? 0 : start
;
547 /* If the result starts with `//', but the original path does not, we
548 can turn the // into /. */
549 if ((result
[0] == '/' && result
[1] == '/' && result
[2] != '/') &&
550 (path
[0] != '/' || path
[1] != '/' || path
[2] == '/'))
553 if (result
[2] == '\0') /* short-circuit for bare `//' */
557 r2
= savestring (result
+ 1);
566 /* Turn STRING (a pathname) into an absolute pathname, assuming that
567 DOT_PATH contains the symbolic location of `.'. This always
568 returns a new string, even if STRING was an absolute pathname to
571 make_absolute (string
, dot_path
)
572 char *string
, *dot_path
;
576 if (dot_path
== 0 || *string
== '/')
577 result
= savestring (string
);
579 result
= sh_makepath (dot_path
, string
, 0);
584 /* Return 1 if STRING contains an absolute pathname, else 0. */
586 absolute_pathname (string
)
589 if (!string
|| !*string
)
595 if (*string
++ == '.')
597 if (!*string
|| *string
== '/' ||
598 (*string
== '.' && (string
[1] == '\0' || string
[1] == '/')))
604 /* Return 1 if STRING is an absolute program name; it is absolute if it
605 contains any slashes. This is used to decide whether or not to look
608 absolute_program (string
)
611 return ((char *)strchr (string
, '/') != (char *)NULL
);
614 /* Return the `basename' of the pathname in STRING (the stuff after the
615 last '/'). If STRING is not a full pathname, simply return it. */
617 base_pathname (string
)
622 if (!absolute_pathname (string
))
625 p
= (char *)strrchr (string
, '/');
626 return (p
? ++p
: string
);
629 /* Return the full pathname of FILE. Easy. Filenames that begin
630 with a '/' are returned as themselves. Other filenames have
631 the current working directory prepended. A new string is
632 returned in either case. */
639 file
= (*file
== '~') ? bash_tilde_expand (file
) : savestring (file
);
641 if ((*file
== '/') && absolute_pathname (file
))
644 ret
= sh_makepath ((char *)NULL
, file
, (MP_DOCWD
|MP_RMDOT
));
650 /* A slightly related function. Get the prettiest name of this
651 directory possible. */
652 static char tdir
[PATH_MAX
];
654 /* Return a pretty pathname. If the first part of the pathname is
655 the same as $HOME, then replace that with `~'. */
657 polite_directory_format (name
)
663 home
= get_string_value ("HOME");
664 l
= home
? strlen (home
) : 0;
665 if (l
> 1 && strncmp (home
, name
, l
) == 0 && (!name
[l
] || name
[l
] == '/'))
667 strncpy (tdir
+ 1, name
+ l
, sizeof(tdir
) - 2);
669 tdir
[sizeof(tdir
) - 1] = '\0';
676 /* Given a string containing units of information separated by colons,
677 return the next one pointed to by (P_INDEX), or NULL if there are no more.
678 Advance (P_INDEX) to the character after the colon. */
680 extract_colon_unit (string
, p_index
)
690 len
= strlen (string
);
692 return ((char *)NULL
);
696 /* Each call to this routine leaves the index pointing at a colon if
697 there is more to the path. If I is > 0, then increment past the
698 `:'. If I is 0, then the path has a leading colon. Trailing colons
699 are handled OK by the `else' part of the if statement; an empty
700 string is returned in that case. */
701 if (i
&& string
[i
] == ':')
704 for (start
= i
; string
[i
] && string
[i
] != ':'; i
++)
713 /* Return "" in the case of a trailing `:'. */
718 value
= substring (string
, start
, i
);
723 /* **************************************************************** */
725 /* Tilde Initialization and Expansion */
727 /* **************************************************************** */
729 #if defined (PUSHD_AND_POPD)
730 extern char *get_dirstack_from_string
__P((char *));
733 /* If tilde_expand hasn't been able to expand the text, perhaps it
734 is a special shell expansion. This function is installed as the
735 tilde_expansion_preexpansion_hook. It knows how to expand ~- and ~+.
736 If PUSHD_AND_POPD is defined, ~[+-]N expands to directories from the
739 bash_special_tilde_expansions (text
)
744 result
= (char *)NULL
;
746 if (text
[0] == '+' && text
[1] == '\0')
747 result
= get_string_value ("PWD");
748 else if (text
[0] == '-' && text
[1] == '\0')
749 result
= get_string_value ("OLDPWD");
750 #if defined (PUSHD_AND_POPD)
751 else if (isdigit (*text
) || ((*text
== '+' || *text
== '-') && isdigit (text
[1])))
752 result
= get_dirstack_from_string (text
);
755 return (result
? savestring (result
) : (char *)NULL
);
758 /* Initialize the tilde expander. In Bash, we handle `~-' and `~+', as
759 well as handling special tilde prefixes; `:~" and `=~' are indications
760 that we should do tilde expansion. */
764 static int times_called
= 0;
766 /* Tell the tilde expander that we want a crack first. */
767 tilde_expansion_preexpansion_hook
= (CPFunction
*)bash_special_tilde_expansions
;
769 /* Tell the tilde expander about special strings which start a tilde
770 expansion, and the special strings that end one. Only do this once.
771 tilde_initialize () is called from within bashline_reinitialize (). */
772 if (times_called
++ == 0)
774 tilde_additional_prefixes
= alloc_array (3);
775 tilde_additional_prefixes
[0] = "=~";
776 tilde_additional_prefixes
[1] = ":~";
777 tilde_additional_prefixes
[2] = (char *)NULL
;
779 tilde_additional_suffixes
= alloc_array (3);
780 tilde_additional_suffixes
[0] = ":";
781 tilde_additional_suffixes
[1] = "=~";
782 tilde_additional_suffixes
[2] = (char *)NULL
;
787 bash_tilde_expand (s
)
793 old_immed
= interrupt_immediately
;
794 interrupt_immediately
= 1;
795 ret
= tilde_expand (s
);
796 interrupt_immediately
= old_immed
;
800 /* **************************************************************** */
802 /* Functions to manipulate and search the group list */
804 /* **************************************************************** */
806 static int ngroups
, maxgroups
;
808 /* The set of groups that this user is a member of. */
809 static GETGROUPS_T
*group_array
= (GETGROUPS_T
*)NULL
;
811 #if !defined (NOGROUP)
812 # define NOGROUP (gid_t) -1
815 #if defined (HAVE_SYSCONF) && defined (_SC_NGROUPS_MAX)
816 # define getmaxgroups() sysconf(_SC_NGROUPS_MAX)
818 # if defined (NGROUPS_MAX)
819 # define getmaxgroups() NGROUPS_MAX
820 # else /* !NGROUPS_MAX */
821 # if defined (NGROUPS)
822 # define getmaxgroups() NGROUPS
823 # else /* !NGROUPS */
824 # define getmaxgroups() 64
825 # endif /* !NGROUPS */
826 # endif /* !NGROUPS_MAX */
827 #endif /* !HAVE_SYSCONF || !SC_NGROUPS_MAX */
830 initialize_group_array ()
835 maxgroups
= getmaxgroups ();
838 group_array
= (GETGROUPS_T
*)xrealloc (group_array
, maxgroups
* sizeof (GETGROUPS_T
));
840 #if defined (HAVE_GETGROUPS)
841 ngroups
= getgroups (maxgroups
, group_array
);
844 /* If getgroups returns nothing, or the OS does not support getgroups(),
845 make sure the groups array includes at least the current gid. */
848 group_array
[0] = current_user
.gid
;
852 /* If the primary group is not in the groups array, add it as group_array[0]
853 and shuffle everything else up 1, if there's room. */
854 for (i
= 0; i
< ngroups
; i
++)
855 if (current_user
.gid
== (gid_t
)group_array
[i
])
857 if (i
== ngroups
&& ngroups
< maxgroups
)
859 for (i
= ngroups
; i
> 0; i
--)
860 group_array
[i
] = group_array
[i
- 1];
861 group_array
[0] = current_user
.gid
;
865 /* If the primary group is not group_array[0], swap group_array[0] and
866 whatever the current group is. The vast majority of systems should
867 not need this; a notable exception is Linux. */
868 if (group_array
[0] != current_user
.gid
)
870 for (i
= 0; i
< ngroups
; i
++)
871 if (group_array
[i
] == current_user
.gid
)
875 group_array
[i
] = group_array
[0];
876 group_array
[0] = current_user
.gid
;
881 /* Return non-zero if GID is one that we have in our groups list. */
883 #if defined (__STDC__) || defined ( _MINIX)
884 group_member (gid_t gid
)
888 #endif /* !__STDC__ && !_MINIX */
890 #if defined (HAVE_GETGROUPS)
894 /* Short-circuit if possible, maybe saving a call to getgroups(). */
895 if (gid
== current_user
.gid
|| gid
== current_user
.egid
)
898 #if defined (HAVE_GETGROUPS)
900 initialize_group_array ();
902 /* In case of error, the user loses. */
906 /* Search through the list looking for GID. */
907 for (i
= 0; i
< ngroups
; i
++)
908 if (gid
== (gid_t
)group_array
[i
])
919 static char **group_vector
= (char **)NULL
;
931 initialize_group_array ();
937 return (char **)NULL
;
940 group_vector
= alloc_array (ngroups
);
941 for (i
= 0; i
< ngroups
; i
++)
943 nbuf
= itos ((int)group_array
[i
]);
944 group_vector
[i
] = nbuf
;
953 get_group_array (ngp
)
957 static int *group_iarray
= (int *)NULL
;
963 return (group_iarray
);
967 initialize_group_array ();
976 group_iarray
= (int *)xmalloc (ngroups
* sizeof (int));
977 for (i
= 0; i
< ngroups
; i
++)
978 group_iarray
[i
] = (int)group_array
[i
];