blob: 446e42f44923099afc94b281a5ecb1a27f581b47 [file] [log] [blame]
Jari Aalto726f6381996-08-26 18:22:31 +00001/* general.c -- Stuff that is used by all files. */
2
Jari Aalto7117c2d2002-07-17 14:10:11 +00003/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
Jari Aalto726f6381996-08-26 18:22:31 +00004
5 This file is part of GNU Bash, the Bourne Again SHell.
6
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
10 version.
11
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
15 for more details.
16
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
Jari Aaltobb706242000-03-17 21:46:59 +000019 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
Jari Aalto726f6381996-08-26 18:22:31 +000020
Jari Aaltoccc6cda1996-12-23 17:02:34 +000021#include "config.h"
22
23#include "bashtypes.h"
Jari Aaltocce855b1998-04-17 19:52:44 +000024#ifndef _MINIX
25# include <sys/param.h>
26#endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +000027#include "posixstat.h"
28
29#if defined (HAVE_UNISTD_H)
30# include <unistd.h>
31#endif
32
33#include "filecntl.h"
34#include "bashansi.h"
Jari Aalto726f6381996-08-26 18:22:31 +000035#include <stdio.h>
Jari Aaltof73dda02001-11-13 17:56:06 +000036#include "chartypes.h"
Jari Aalto726f6381996-08-26 18:22:31 +000037#include <errno.h>
Jari Aaltoccc6cda1996-12-23 17:02:34 +000038
Jari Aalto726f6381996-08-26 18:22:31 +000039#include "shell.h"
40#include <tilde/tilde.h>
41
Jari Aalto726f6381996-08-26 18:22:31 +000042#if !defined (errno)
43extern int errno;
44#endif /* !errno */
45
Jari Aaltof73dda02001-11-13 17:56:06 +000046extern int expand_aliases;
Jari Aaltoccc6cda1996-12-23 17:02:34 +000047extern int interrupt_immediately;
48extern int interactive_comments;
Jari Aalto28ef6c32001-04-06 19:14:31 +000049extern int check_hashed_filenames;
50extern int source_uses_path;
51extern int source_searches_cwd;
Jari Aaltocce855b1998-04-17 19:52:44 +000052
Jari Aalto7117c2d2002-07-17 14:10:11 +000053static char *bash_special_tilde_expansions __P((char *));
54static int unquoted_tilde_word __P((const char *));
55static void initialize_group_array __P((void));
56
Jari Aaltocce855b1998-04-17 19:52:44 +000057/* A standard error message to use when getcwd() returns NULL. */
58char *bash_getcwd_errstr = "getcwd: cannot access parent directories";
Jari Aalto726f6381996-08-26 18:22:31 +000059
Jari Aaltoccc6cda1996-12-23 17:02:34 +000060/* Do whatever is necessary to initialize `Posix mode'. */
Jari Aalto726f6381996-08-26 18:22:31 +000061void
Jari Aaltoccc6cda1996-12-23 17:02:34 +000062posix_initialize (on)
63 int on;
Jari Aalto726f6381996-08-26 18:22:31 +000064{
Jari Aalto28ef6c32001-04-06 19:14:31 +000065 /* Things that should be turned on when posix mode is enabled. */
66 if (on != 0)
67 {
68 interactive_comments = source_uses_path = expand_aliases = 1;
69 }
70
71 /* Things that should be turned on when posix mode is disabled. */
72 if (on == 0)
73 {
74 source_searches_cwd = 1;
75 expand_aliases = interactive_shell;
76 }
Jari Aalto726f6381996-08-26 18:22:31 +000077}
78
79/* **************************************************************** */
80/* */
Jari Aaltoccc6cda1996-12-23 17:02:34 +000081/* Functions to convert to and from and display non-standard types */
82/* */
83/* **************************************************************** */
84
Jari Aalto726f6381996-08-26 18:22:31 +000085#if defined (RLIMTYPE)
86RLIMTYPE
87string_to_rlimtype (s)
88 char *s;
89{
Jari Aaltocce855b1998-04-17 19:52:44 +000090 RLIMTYPE ret;
91 int neg;
Jari Aalto726f6381996-08-26 18:22:31 +000092
Jari Aaltocce855b1998-04-17 19:52:44 +000093 ret = 0;
94 neg = 0;
Jari Aalto726f6381996-08-26 18:22:31 +000095 while (s && *s && whitespace (*s))
96 s++;
97 if (*s == '-' || *s == '+')
98 {
99 neg = *s == '-';
100 s++;
101 }
Jari Aaltof73dda02001-11-13 17:56:06 +0000102 for ( ; s && *s && DIGIT (*s); s++)
103 ret = (ret * 10) + TODIGIT (*s);
Jari Aalto726f6381996-08-26 18:22:31 +0000104 return (neg ? -ret : ret);
105}
106
107void
108print_rlimtype (n, addnl)
109 RLIMTYPE n;
110 int addnl;
111{
Jari Aaltof73dda02001-11-13 17:56:06 +0000112 char s[INT_STRLEN_BOUND (RLIMTYPE) + 1], *p;
Jari Aalto726f6381996-08-26 18:22:31 +0000113
Jari Aaltof73dda02001-11-13 17:56:06 +0000114 p = s + sizeof(s);
115 *--p = '\0';
Jari Aalto726f6381996-08-26 18:22:31 +0000116
117 if (n < 0)
118 {
Jari Aaltof73dda02001-11-13 17:56:06 +0000119 do
120 *--p = '0' - n % 10;
121 while ((n /= 10) != 0);
122
123 *--p = '-';
124 }
125 else
126 {
127 do
128 *--p = '0' + n % 10;
129 while ((n /= 10) != 0);
Jari Aalto726f6381996-08-26 18:22:31 +0000130 }
131
Jari Aaltof73dda02001-11-13 17:56:06 +0000132 printf ("%s%s", p, addnl ? "\n" : "");
Jari Aalto726f6381996-08-26 18:22:31 +0000133}
134#endif /* RLIMTYPE */
135
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000136/* **************************************************************** */
137/* */
138/* Input Validation Functions */
139/* */
140/* **************************************************************** */
141
142/* Return non-zero if all of the characters in STRING are digits. */
143int
144all_digits (string)
145 char *string;
146{
Jari Aalto28ef6c32001-04-06 19:14:31 +0000147 register char *s;
148
149 for (s = string; *s; s++)
Jari Aaltof73dda02001-11-13 17:56:06 +0000150 if (DIGIT (*s) == 0)
Jari Aalto28ef6c32001-04-06 19:14:31 +0000151 return (0);
152
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000153 return (1);
154}
155
156/* Return non-zero if the characters pointed to by STRING constitute a
157 valid number. Stuff the converted number into RESULT if RESULT is
Jari Aaltof73dda02001-11-13 17:56:06 +0000158 not null. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000159int
160legal_number (string, result)
161 char *string;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000162 intmax_t *result;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000163{
Jari Aalto7117c2d2002-07-17 14:10:11 +0000164 intmax_t value;
Jari Aaltocce855b1998-04-17 19:52:44 +0000165 char *ep;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000166
167 if (result)
168 *result = 0;
169
Jari Aaltof73dda02001-11-13 17:56:06 +0000170 errno = 0;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000171 value = strtoimax (string, &ep, 10);
Jari Aaltof73dda02001-11-13 17:56:06 +0000172 if (errno)
173 return 0; /* errno is set on overflow or underflow */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000174
Jari Aalto7117c2d2002-07-17 14:10:11 +0000175 /* Skip any trailing whitespace, since strtoimax does not. */
Jari Aalto28ef6c32001-04-06 19:14:31 +0000176 while (whitespace (*ep))
177 ep++;
178
Jari Aaltocce855b1998-04-17 19:52:44 +0000179 /* If *string is not '\0' but *ep is '\0' on return, the entire string
180 is valid. */
181 if (string && *string && *ep == '\0')
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000182 {
183 if (result)
Jari Aaltocce855b1998-04-17 19:52:44 +0000184 *result = value;
185 /* The SunOS4 implementation of strtol() will happily ignore
186 overflow conditions, so this cannot do overflow correctly
187 on those systems. */
188 return 1;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000189 }
Jari Aaltocce855b1998-04-17 19:52:44 +0000190
191 return (0);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000192}
193
Jari Aalto726f6381996-08-26 18:22:31 +0000194/* Return 1 if this token is a legal shell `identifier'; that is, it consists
195 solely of letters, digits, and underscores, and does not begin with a
196 digit. */
197int
198legal_identifier (name)
199 char *name;
200{
201 register char *s;
Jari Aaltof73dda02001-11-13 17:56:06 +0000202 unsigned char c;
Jari Aalto726f6381996-08-26 18:22:31 +0000203
Jari Aaltof73dda02001-11-13 17:56:06 +0000204 if (!name || !(c = *name) || (legal_variable_starter (c) == 0))
Jari Aalto726f6381996-08-26 18:22:31 +0000205 return (0);
206
Jari Aaltof73dda02001-11-13 17:56:06 +0000207 for (s = name + 1; (c = *s) != 0; s++)
Jari Aalto726f6381996-08-26 18:22:31 +0000208 {
Jari Aaltof73dda02001-11-13 17:56:06 +0000209 if (legal_variable_char (c) == 0)
Jari Aalto28ef6c32001-04-06 19:14:31 +0000210 return (0);
Jari Aalto726f6381996-08-26 18:22:31 +0000211 }
212 return (1);
213}
214
215/* Make sure that WORD is a valid shell identifier, i.e.
216 does not contain a dollar sign, nor is quoted in any way. Nor
217 does it consist of all digits. If CHECK_WORD is non-zero,
218 the word is checked to ensure that it consists of only letters,
219 digits, and underscores. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000220int
Jari Aalto726f6381996-08-26 18:22:31 +0000221check_identifier (word, check_word)
222 WORD_DESC *word;
223 int check_word;
224{
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000225 if ((word->flags & (W_HASDOLLAR|W_QUOTED)) || all_digits (word->word))
Jari Aalto726f6381996-08-26 18:22:31 +0000226 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000227 internal_error ("`%s': not a valid identifier", word->word);
Jari Aalto726f6381996-08-26 18:22:31 +0000228 return (0);
229 }
230 else if (check_word && legal_identifier (word->word) == 0)
231 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000232 internal_error ("`%s': not a valid identifier", word->word);
Jari Aalto726f6381996-08-26 18:22:31 +0000233 return (0);
234 }
235 else
236 return (1);
237}
238
Jari Aalto7117c2d2002-07-17 14:10:11 +0000239/* Returns non-zero if STRING is an assignment statement. The returned value
240 is the index of the `=' sign. */
241int
242assignment (string)
243 const char *string;
244{
245 register unsigned char c;
246 register int newi, indx;
247
248 c = string[indx = 0];
249
250 if (legal_variable_starter (c) == 0)
251 return (0);
252
253 while (c = string[indx])
254 {
255 /* The following is safe. Note that '=' at the start of a word
256 is not an assignment statement. */
257 if (c == '=')
258 return (indx);
259
260#if defined (ARRAY_VARS)
261 if (c == '[')
262 {
263 newi = skipsubscript (string, indx);
264 if (string[newi++] != ']')
265 return (0);
266 return ((string[newi] == '=') ? newi : 0);
267 }
268#endif /* ARRAY_VARS */
269
270 /* Variable names in assignment statements may contain only letters,
271 digits, and `_'. */
272 if (legal_variable_char (c) == 0)
273 return (0);
274
275 indx++;
276 }
277 return (0);
278}
279
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000280/* **************************************************************** */
281/* */
282/* Functions to manage files and file descriptors */
283/* */
284/* **************************************************************** */
285
Jari Aalto726f6381996-08-26 18:22:31 +0000286/* A function to unset no-delay mode on a file descriptor. Used in shell.c
287 to unset it on the fd passed as stdin. Should be called on stdin if
288 readline gets an EAGAIN or EWOULDBLOCK when trying to read input. */
289
290#if !defined (O_NDELAY)
291# if defined (FNDELAY)
292# define O_NDELAY FNDELAY
293# endif
294#endif /* O_NDELAY */
295
296/* Make sure no-delay mode is not set on file descriptor FD. */
Jari Aaltobb706242000-03-17 21:46:59 +0000297int
Jari Aalto28ef6c32001-04-06 19:14:31 +0000298sh_unset_nodelay_mode (fd)
Jari Aalto726f6381996-08-26 18:22:31 +0000299 int fd;
300{
Jari Aaltobb706242000-03-17 21:46:59 +0000301 int flags, bflags;
Jari Aalto726f6381996-08-26 18:22:31 +0000302
303 if ((flags = fcntl (fd, F_GETFL, 0)) < 0)
Jari Aaltobb706242000-03-17 21:46:59 +0000304 return -1;
Jari Aalto726f6381996-08-26 18:22:31 +0000305
Jari Aaltobb706242000-03-17 21:46:59 +0000306 bflags = 0;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000307
308 /* This is defined to O_NDELAY in filecntl.h if O_NONBLOCK is not present
309 and O_NDELAY is defined. */
Jari Aaltobb706242000-03-17 21:46:59 +0000310#ifdef O_NONBLOCK
311 bflags |= O_NONBLOCK;
312#endif
313
314#ifdef O_NDELAY
315 bflags |= O_NDELAY;
316#endif
317
318 if (flags & bflags)
Jari Aalto726f6381996-08-26 18:22:31 +0000319 {
Jari Aaltobb706242000-03-17 21:46:59 +0000320 flags &= ~bflags;
321 return (fcntl (fd, F_SETFL, flags));
Jari Aalto726f6381996-08-26 18:22:31 +0000322 }
Jari Aalto726f6381996-08-26 18:22:31 +0000323
Jari Aaltobb706242000-03-17 21:46:59 +0000324 return 0;
Jari Aalto726f6381996-08-26 18:22:31 +0000325}
326
Jari Aalto7117c2d2002-07-17 14:10:11 +0000327/* Return 1 if file descriptor FD is valid; 0 otherwise. */
328int
329sh_validfd (fd)
330 int fd;
331{
332 return (fcntl (fd, F_GETFD, 0) >= 0);
333}
334
Jari Aaltob72432f1999-02-19 17:11:39 +0000335/* There is a bug in the NeXT 2.1 rlogind that causes opens
336 of /dev/tty to fail. */
337
338#if defined (__BEOS__)
339/* On BeOS, opening in non-blocking mode exposes a bug in BeOS, so turn it
340 into a no-op. This should probably go away in the future. */
341# undef O_NONBLOCK
342# define O_NONBLOCK 0
343#endif /* __BEOS__ */
344
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000345void
346check_dev_tty ()
347{
348 int tty_fd;
349 char *tty;
350
Jari Aaltod166f041997-06-05 14:59:13 +0000351 tty_fd = open ("/dev/tty", O_RDWR|O_NONBLOCK);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000352
353 if (tty_fd < 0)
354 {
355 tty = (char *)ttyname (fileno (stdin));
356 if (tty == 0)
357 return;
Jari Aaltod166f041997-06-05 14:59:13 +0000358 tty_fd = open (tty, O_RDWR|O_NONBLOCK);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000359 }
360 close (tty_fd);
361}
362
363/* Return 1 if PATH1 and PATH2 are the same file. This is kind of
364 expensive. If non-NULL STP1 and STP2 point to stat structures
365 corresponding to PATH1 and PATH2, respectively. */
366int
367same_file (path1, path2, stp1, stp2)
368 char *path1, *path2;
369 struct stat *stp1, *stp2;
370{
371 struct stat st1, st2;
372
373 if (stp1 == NULL)
374 {
375 if (stat (path1, &st1) != 0)
376 return (0);
377 stp1 = &st1;
378 }
379
380 if (stp2 == NULL)
381 {
382 if (stat (path2, &st2) != 0)
383 return (0);
384 stp2 = &st2;
385 }
386
387 return ((stp1->st_dev == stp2->st_dev) && (stp1->st_ino == stp2->st_ino));
388}
389
390/* Move FD to a number close to the maximum number of file descriptors
391 allowed in the shell process, to avoid the user stepping on it with
392 redirection and causing us extra work. If CHECK_NEW is non-zero,
393 we check whether or not the file descriptors are in use before
Jari Aaltod166f041997-06-05 14:59:13 +0000394 duplicating FD onto them. MAXFD says where to start checking the
395 file descriptors. If it's less than 20, we get the maximum value
396 available from getdtablesize(2). */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000397int
Jari Aaltod166f041997-06-05 14:59:13 +0000398move_to_high_fd (fd, check_new, maxfd)
399 int fd, check_new, maxfd;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000400{
401 int script_fd, nfds, ignore;
402
Jari Aaltod166f041997-06-05 14:59:13 +0000403 if (maxfd < 20)
404 {
405 nfds = getdtablesize ();
406 if (nfds <= 0)
407 nfds = 20;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000408 if (nfds > HIGH_FD_MAX)
409 nfds = HIGH_FD_MAX; /* reasonable maximum */
Jari Aaltod166f041997-06-05 14:59:13 +0000410 }
411 else
412 nfds = maxfd;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000413
414 for (nfds--; check_new && nfds > 3; nfds--)
415 if (fcntl (nfds, F_GETFD, &ignore) == -1)
416 break;
417
Jari Aalto7117c2d2002-07-17 14:10:11 +0000418 if (nfds > 3 && fd != nfds && (script_fd = dup2 (fd, nfds)) != -1)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000419 {
420 if (check_new == 0 || fd != fileno (stderr)) /* don't close stderr */
421 close (fd);
422 return (script_fd);
423 }
424
Jari Aalto7117c2d2002-07-17 14:10:11 +0000425 /* OK, we didn't find one less than our artificial maximum; return the
426 original file descriptor. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000427 return (fd);
428}
429
430/* Return non-zero if the characters from SAMPLE are not all valid
431 characters to be found in the first line of a shell script. We
432 check up to the first newline, or SAMPLE_LEN, whichever comes first.
433 All of the characters must be printable or whitespace. */
434
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000435int
436check_binary_file (sample, sample_len)
Jari Aaltof73dda02001-11-13 17:56:06 +0000437 char *sample;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000438 int sample_len;
439{
440 register int i;
Jari Aaltof73dda02001-11-13 17:56:06 +0000441 unsigned char c;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000442
443 for (i = 0; i < sample_len; i++)
444 {
Jari Aaltof73dda02001-11-13 17:56:06 +0000445 c = sample[i];
446 if (c == '\n')
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000447 return (0);
448
Jari Aaltof73dda02001-11-13 17:56:06 +0000449 if (ISSPACE (c) == 0 && ISPRINT (c) == 0)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000450 return (1);
451 }
452
453 return (0);
454}
Jari Aalto726f6381996-08-26 18:22:31 +0000455
456/* **************************************************************** */
457/* */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000458/* Functions to manipulate pathnames */
Jari Aalto726f6381996-08-26 18:22:31 +0000459/* */
460/* **************************************************************** */
461
Jari Aalto726f6381996-08-26 18:22:31 +0000462/* Turn STRING (a pathname) into an absolute pathname, assuming that
463 DOT_PATH contains the symbolic location of `.'. This always
464 returns a new string, even if STRING was an absolute pathname to
465 begin with. */
466char *
467make_absolute (string, dot_path)
468 char *string, *dot_path;
469{
470 char *result;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000471
Jari Aalto28ef6c32001-04-06 19:14:31 +0000472 if (dot_path == 0 || ABSPATH(string))
Jari Aalto726f6381996-08-26 18:22:31 +0000473 result = savestring (string);
474 else
Jari Aaltobb706242000-03-17 21:46:59 +0000475 result = sh_makepath (dot_path, string, 0);
Jari Aalto726f6381996-08-26 18:22:31 +0000476
477 return (result);
478}
479
Jari Aalto28ef6c32001-04-06 19:14:31 +0000480/* Return 1 if STRING contains an absolute pathname, else 0. Used by `cd'
481 to decide whether or not to look up a directory name in $CDPATH. */
Jari Aalto726f6381996-08-26 18:22:31 +0000482int
483absolute_pathname (string)
Jari Aaltof73dda02001-11-13 17:56:06 +0000484 const char *string;
Jari Aalto726f6381996-08-26 18:22:31 +0000485{
Jari Aalto28ef6c32001-04-06 19:14:31 +0000486 if (string == 0 || *string == '\0')
Jari Aalto726f6381996-08-26 18:22:31 +0000487 return (0);
488
Jari Aalto28ef6c32001-04-06 19:14:31 +0000489 if (ABSPATH(string))
Jari Aalto726f6381996-08-26 18:22:31 +0000490 return (1);
491
Jari Aalto28ef6c32001-04-06 19:14:31 +0000492 if (string[0] == '.' && PATHSEP(string[1])) /* . and ./ */
493 return (1);
494
495 if (string[0] == '.' && string[1] == '.' && PATHSEP(string[2])) /* .. and ../ */
496 return (1);
497
Jari Aalto726f6381996-08-26 18:22:31 +0000498 return (0);
499}
500
501/* Return 1 if STRING is an absolute program name; it is absolute if it
502 contains any slashes. This is used to decide whether or not to look
503 up through $PATH. */
504int
505absolute_program (string)
Jari Aaltof73dda02001-11-13 17:56:06 +0000506 const char *string;
Jari Aalto726f6381996-08-26 18:22:31 +0000507{
Jari Aalto7117c2d2002-07-17 14:10:11 +0000508 return ((char *)xstrchr (string, '/') != (char *)NULL);
Jari Aalto726f6381996-08-26 18:22:31 +0000509}
510
511/* Return the `basename' of the pathname in STRING (the stuff after the
512 last '/'). If STRING is not a full pathname, simply return it. */
513char *
514base_pathname (string)
515 char *string;
516{
517 char *p;
518
Jari Aalto28ef6c32001-04-06 19:14:31 +0000519 if (absolute_pathname (string) == 0)
Jari Aalto726f6381996-08-26 18:22:31 +0000520 return (string);
521
522 p = (char *)strrchr (string, '/');
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000523 return (p ? ++p : string);
Jari Aalto726f6381996-08-26 18:22:31 +0000524}
525
526/* Return the full pathname of FILE. Easy. Filenames that begin
527 with a '/' are returned as themselves. Other filenames have
528 the current working directory prepended. A new string is
529 returned in either case. */
530char *
531full_pathname (file)
532 char *file;
533{
Jari Aaltobb706242000-03-17 21:46:59 +0000534 char *ret;
Jari Aalto726f6381996-08-26 18:22:31 +0000535
Jari Aalto7117c2d2002-07-17 14:10:11 +0000536 file = (*file == '~') ? bash_tilde_expand (file, 0) : savestring (file);
Jari Aalto726f6381996-08-26 18:22:31 +0000537
Jari Aalto28ef6c32001-04-06 19:14:31 +0000538 if (ABSPATH(file))
Jari Aalto726f6381996-08-26 18:22:31 +0000539 return (file);
540
Jari Aaltobb706242000-03-17 21:46:59 +0000541 ret = sh_makepath ((char *)NULL, file, (MP_DOCWD|MP_RMDOT));
542 free (file);
Jari Aalto726f6381996-08-26 18:22:31 +0000543
Jari Aaltobb706242000-03-17 21:46:59 +0000544 return (ret);
Jari Aalto726f6381996-08-26 18:22:31 +0000545}
546
Jari Aalto726f6381996-08-26 18:22:31 +0000547/* A slightly related function. Get the prettiest name of this
548 directory possible. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000549static char tdir[PATH_MAX];
Jari Aalto726f6381996-08-26 18:22:31 +0000550
551/* Return a pretty pathname. If the first part of the pathname is
552 the same as $HOME, then replace that with `~'. */
553char *
554polite_directory_format (name)
555 char *name;
556{
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000557 char *home;
558 int l;
Jari Aalto726f6381996-08-26 18:22:31 +0000559
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000560 home = get_string_value ("HOME");
561 l = home ? strlen (home) : 0;
Jari Aalto726f6381996-08-26 18:22:31 +0000562 if (l > 1 && strncmp (home, name, l) == 0 && (!name[l] || name[l] == '/'))
563 {
Jari Aaltoe8ce7751997-09-22 20:22:27 +0000564 strncpy (tdir + 1, name + l, sizeof(tdir) - 2);
Jari Aalto726f6381996-08-26 18:22:31 +0000565 tdir[0] = '~';
Jari Aaltoe8ce7751997-09-22 20:22:27 +0000566 tdir[sizeof(tdir) - 1] = '\0';
Jari Aalto726f6381996-08-26 18:22:31 +0000567 return (tdir);
568 }
569 else
570 return (name);
571}
572
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000573/* Given a string containing units of information separated by colons,
574 return the next one pointed to by (P_INDEX), or NULL if there are no more.
575 Advance (P_INDEX) to the character after the colon. */
576char *
577extract_colon_unit (string, p_index)
578 char *string;
579 int *p_index;
Jari Aalto726f6381996-08-26 18:22:31 +0000580{
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000581 int i, start, len;
582 char *value;
583
584 if (string == 0)
585 return (string);
586
587 len = strlen (string);
588 if (*p_index >= len)
589 return ((char *)NULL);
590
591 i = *p_index;
592
593 /* Each call to this routine leaves the index pointing at a colon if
594 there is more to the path. If I is > 0, then increment past the
595 `:'. If I is 0, then the path has a leading colon. Trailing colons
596 are handled OK by the `else' part of the if statement; an empty
597 string is returned in that case. */
598 if (i && string[i] == ':')
599 i++;
600
601 for (start = i; string[i] && string[i] != ':'; i++)
602 ;
603
604 *p_index = i;
605
606 if (i == start)
Jari Aalto726f6381996-08-26 18:22:31 +0000607 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000608 if (string[i])
609 (*p_index)++;
610 /* Return "" in the case of a trailing `:'. */
Jari Aaltof73dda02001-11-13 17:56:06 +0000611 value = (char *)xmalloc (1);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000612 value[0] = '\0';
Jari Aalto726f6381996-08-26 18:22:31 +0000613 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000614 else
Jari Aaltobb706242000-03-17 21:46:59 +0000615 value = substring (string, start, i);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000616
617 return (value);
Jari Aalto726f6381996-08-26 18:22:31 +0000618}
619
Jari Aalto726f6381996-08-26 18:22:31 +0000620/* **************************************************************** */
621/* */
622/* Tilde Initialization and Expansion */
623/* */
624/* **************************************************************** */
625
Jari Aaltocce855b1998-04-17 19:52:44 +0000626#if defined (PUSHD_AND_POPD)
627extern char *get_dirstack_from_string __P((char *));
628#endif
629
Jari Aaltof73dda02001-11-13 17:56:06 +0000630static char **bash_tilde_prefixes;
631static char **bash_tilde_suffixes;
632
Jari Aalto726f6381996-08-26 18:22:31 +0000633/* If tilde_expand hasn't been able to expand the text, perhaps it
634 is a special shell expansion. This function is installed as the
Jari Aaltocce855b1998-04-17 19:52:44 +0000635 tilde_expansion_preexpansion_hook. It knows how to expand ~- and ~+.
636 If PUSHD_AND_POPD is defined, ~[+-]N expands to directories from the
637 directory stack. */
Jari Aalto726f6381996-08-26 18:22:31 +0000638static char *
Jari Aaltod166f041997-06-05 14:59:13 +0000639bash_special_tilde_expansions (text)
Jari Aalto726f6381996-08-26 18:22:31 +0000640 char *text;
641{
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000642 char *result;
Jari Aalto726f6381996-08-26 18:22:31 +0000643
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000644 result = (char *)NULL;
Jari Aaltocce855b1998-04-17 19:52:44 +0000645
646 if (text[0] == '+' && text[1] == '\0')
647 result = get_string_value ("PWD");
648 else if (text[0] == '-' && text[1] == '\0')
649 result = get_string_value ("OLDPWD");
650#if defined (PUSHD_AND_POPD)
Jari Aaltof73dda02001-11-13 17:56:06 +0000651 else if (DIGIT (*text) || ((*text == '+' || *text == '-') && DIGIT (text[1])))
Jari Aaltocce855b1998-04-17 19:52:44 +0000652 result = get_dirstack_from_string (text);
653#endif
Jari Aalto726f6381996-08-26 18:22:31 +0000654
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000655 return (result ? savestring (result) : (char *)NULL);
Jari Aalto726f6381996-08-26 18:22:31 +0000656}
657
658/* Initialize the tilde expander. In Bash, we handle `~-' and `~+', as
659 well as handling special tilde prefixes; `:~" and `=~' are indications
660 that we should do tilde expansion. */
661void
662tilde_initialize ()
663{
664 static int times_called = 0;
665
Jari Aaltod166f041997-06-05 14:59:13 +0000666 /* Tell the tilde expander that we want a crack first. */
Jari Aaltof73dda02001-11-13 17:56:06 +0000667 tilde_expansion_preexpansion_hook = bash_special_tilde_expansions;
Jari Aalto726f6381996-08-26 18:22:31 +0000668
669 /* Tell the tilde expander about special strings which start a tilde
670 expansion, and the special strings that end one. Only do this once.
671 tilde_initialize () is called from within bashline_reinitialize (). */
Jari Aaltocce855b1998-04-17 19:52:44 +0000672 if (times_called++ == 0)
Jari Aalto726f6381996-08-26 18:22:31 +0000673 {
Jari Aalto7117c2d2002-07-17 14:10:11 +0000674 bash_tilde_prefixes = strvec_create (3);
Jari Aaltof73dda02001-11-13 17:56:06 +0000675 bash_tilde_prefixes[0] = "=~";
676 bash_tilde_prefixes[1] = ":~";
677 bash_tilde_prefixes[2] = (char *)NULL;
Jari Aalto726f6381996-08-26 18:22:31 +0000678
Jari Aaltof73dda02001-11-13 17:56:06 +0000679 tilde_additional_prefixes = bash_tilde_prefixes;
680
Jari Aalto7117c2d2002-07-17 14:10:11 +0000681 bash_tilde_suffixes = strvec_create (3);
Jari Aaltof73dda02001-11-13 17:56:06 +0000682 bash_tilde_suffixes[0] = ":";
683 bash_tilde_suffixes[1] = "=~"; /* XXX - ?? */
684 bash_tilde_suffixes[2] = (char *)NULL;
685
686 tilde_additional_suffixes = bash_tilde_suffixes;
Jari Aalto726f6381996-08-26 18:22:31 +0000687 }
Jari Aalto726f6381996-08-26 18:22:31 +0000688}
689
Jari Aaltof73dda02001-11-13 17:56:06 +0000690/* POSIX.2, 3.6.1: A tilde-prefix consists of an unquoted tilde character
691 at the beginning of the word, followed by all of the characters preceding
692 the first unquoted slash in the word, or all the characters in the word
693 if there is no slash...If none of the characters in the tilde-prefix are
694 quoted, the characters in the tilde-prefix following the tilde shell be
695 treated as a possible login name. */
696
697#define TILDE_END(c) ((c) == '\0' || (c) == '/' || (c) == ':')
698
699static int
700unquoted_tilde_word (s)
701 const char *s;
702{
703 const char *r;
704
705 for (r = s; TILDE_END(*r) == 0; r++)
706 {
707 switch (*r)
708 {
709 case '\\':
710 case '\'':
711 case '"':
712 return 0;
713 }
714 }
715 return 1;
716}
717
Jari Aalto7117c2d2002-07-17 14:10:11 +0000718/* Tilde-expand S by running it through the tilde expansion library.
719 ASSIGN_P is 1 if this is a variable assignment, so the alternate
720 tilde prefixes should be enabled (`=~' and `:~', see above). */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000721char *
Jari Aalto7117c2d2002-07-17 14:10:11 +0000722bash_tilde_expand (s, assign_p)
Jari Aaltof73dda02001-11-13 17:56:06 +0000723 const char *s;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000724 int assign_p;
Jari Aalto726f6381996-08-26 18:22:31 +0000725{
Jari Aaltof73dda02001-11-13 17:56:06 +0000726 int old_immed, r;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000727 char *ret;
Jari Aalto726f6381996-08-26 18:22:31 +0000728
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000729 old_immed = interrupt_immediately;
730 interrupt_immediately = 1;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000731 tilde_additional_prefixes = assign_p ? bash_tilde_prefixes : (char **)0;
Jari Aaltof73dda02001-11-13 17:56:06 +0000732 r = (*s == '~') ? unquoted_tilde_word (s) : 1;
733 ret = r ? tilde_expand (s) : savestring (s);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000734 interrupt_immediately = old_immed;
735 return (ret);
Jari Aalto726f6381996-08-26 18:22:31 +0000736}
Jari Aaltod166f041997-06-05 14:59:13 +0000737
738/* **************************************************************** */
739/* */
740/* Functions to manipulate and search the group list */
741/* */
742/* **************************************************************** */
743
744static int ngroups, maxgroups;
745
746/* The set of groups that this user is a member of. */
747static GETGROUPS_T *group_array = (GETGROUPS_T *)NULL;
748
749#if !defined (NOGROUP)
750# define NOGROUP (gid_t) -1
751#endif
752
Jari Aaltod166f041997-06-05 14:59:13 +0000753static void
754initialize_group_array ()
755{
756 register int i;
757
758 if (maxgroups == 0)
759 maxgroups = getmaxgroups ();
760
761 ngroups = 0;
762 group_array = (GETGROUPS_T *)xrealloc (group_array, maxgroups * sizeof (GETGROUPS_T));
763
764#if defined (HAVE_GETGROUPS)
765 ngroups = getgroups (maxgroups, group_array);
766#endif
767
768 /* If getgroups returns nothing, or the OS does not support getgroups(),
769 make sure the groups array includes at least the current gid. */
770 if (ngroups == 0)
771 {
772 group_array[0] = current_user.gid;
773 ngroups = 1;
774 }
775
776 /* If the primary group is not in the groups array, add it as group_array[0]
777 and shuffle everything else up 1, if there's room. */
778 for (i = 0; i < ngroups; i++)
779 if (current_user.gid == (gid_t)group_array[i])
780 break;
781 if (i == ngroups && ngroups < maxgroups)
782 {
783 for (i = ngroups; i > 0; i--)
Jari Aalto28ef6c32001-04-06 19:14:31 +0000784 group_array[i] = group_array[i - 1];
Jari Aaltod166f041997-06-05 14:59:13 +0000785 group_array[0] = current_user.gid;
786 ngroups++;
787 }
Jari Aaltocce855b1998-04-17 19:52:44 +0000788
789 /* If the primary group is not group_array[0], swap group_array[0] and
790 whatever the current group is. The vast majority of systems should
791 not need this; a notable exception is Linux. */
792 if (group_array[0] != current_user.gid)
793 {
794 for (i = 0; i < ngroups; i++)
Jari Aalto28ef6c32001-04-06 19:14:31 +0000795 if (group_array[i] == current_user.gid)
796 break;
Jari Aaltocce855b1998-04-17 19:52:44 +0000797 if (i < ngroups)
798 {
799 group_array[i] = group_array[0];
800 group_array[0] = current_user.gid;
801 }
802 }
Jari Aaltod166f041997-06-05 14:59:13 +0000803}
804
805/* Return non-zero if GID is one that we have in our groups list. */
806int
Jari Aaltocce855b1998-04-17 19:52:44 +0000807#if defined (__STDC__) || defined ( _MINIX)
808group_member (gid_t gid)
809#else
Jari Aaltod166f041997-06-05 14:59:13 +0000810group_member (gid)
811 gid_t gid;
Jari Aaltocce855b1998-04-17 19:52:44 +0000812#endif /* !__STDC__ && !_MINIX */
Jari Aaltod166f041997-06-05 14:59:13 +0000813{
814#if defined (HAVE_GETGROUPS)
815 register int i;
816#endif
817
818 /* Short-circuit if possible, maybe saving a call to getgroups(). */
819 if (gid == current_user.gid || gid == current_user.egid)
820 return (1);
821
822#if defined (HAVE_GETGROUPS)
823 if (ngroups == 0)
824 initialize_group_array ();
825
826 /* In case of error, the user loses. */
827 if (ngroups <= 0)
828 return (0);
829
830 /* Search through the list looking for GID. */
831 for (i = 0; i < ngroups; i++)
832 if (gid == (gid_t)group_array[i])
833 return (1);
834#endif
835
836 return (0);
837}
838
839char **
840get_group_list (ngp)
841 int *ngp;
842{
843 static char **group_vector = (char **)NULL;
844 register int i;
Jari Aaltod166f041997-06-05 14:59:13 +0000845
846 if (group_vector)
847 {
848 if (ngp)
849 *ngp = ngroups;
850 return group_vector;
851 }
852
853 if (ngroups == 0)
854 initialize_group_array ();
855
856 if (ngroups <= 0)
857 {
858 if (ngp)
859 *ngp = 0;
860 return (char **)NULL;
861 }
862
Jari Aalto7117c2d2002-07-17 14:10:11 +0000863 group_vector = strvec_create (ngroups);
Jari Aaltod166f041997-06-05 14:59:13 +0000864 for (i = 0; i < ngroups; i++)
Jari Aalto7117c2d2002-07-17 14:10:11 +0000865 group_vector[i] = itos (group_array[i]);
Jari Aaltob72432f1999-02-19 17:11:39 +0000866
Jari Aaltod166f041997-06-05 14:59:13 +0000867 if (ngp)
868 *ngp = ngroups;
869 return group_vector;
870}
Jari Aaltob72432f1999-02-19 17:11:39 +0000871
872int *
873get_group_array (ngp)
874 int *ngp;
875{
876 int i;
877 static int *group_iarray = (int *)NULL;
878
879 if (group_iarray)
880 {
881 if (ngp)
882 *ngp = ngroups;
883 return (group_iarray);
884 }
885
886 if (ngroups == 0)
887 initialize_group_array ();
888
889 if (ngroups <= 0)
890 {
891 if (ngp)
892 *ngp = 0;
893 return (int *)NULL;
894 }
895
896 group_iarray = (int *)xmalloc (ngroups * sizeof (int));
897 for (i = 0; i < ngroups; i++)
898 group_iarray[i] = (int)group_array[i];
899
900 if (ngp)
901 *ngp = ngroups;
902 return group_iarray;
903}