]> git.ipfire.org Git - thirdparty/bash.git/blame - general.c
Bash-5.1 patch 12: fix race condition with child processes and resetting trapped...
[thirdparty/bash.git] / general.c
CommitLineData
726f6388
JA
1/* general.c -- Stuff that is used by all files. */
2
8868edaf 3/* Copyright (C) 1987-2020 Free Software Foundation, Inc.
726f6388
JA
4
5 This file is part of GNU Bash, the Bourne Again SHell.
6
3185942a
JA
7 Bash is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
726f6388 11
3185942a
JA
12 Bash is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
726f6388 16
3185942a
JA
17 You should have received a copy of the GNU General Public License
18 along with Bash. If not, see <http://www.gnu.org/licenses/>.
19*/
726f6388 20
ccc6cda3
JA
21#include "config.h"
22
726f6388 23#include "bashtypes.h"
ac50fbac 24#if defined (HAVE_SYS_PARAM_H)
cce855bc
JA
25# include <sys/param.h>
26#endif
ccc6cda3
JA
27#include "posixstat.h"
28
29#if defined (HAVE_UNISTD_H)
30# include <unistd.h>
31#endif
32
726f6388
JA
33#include "filecntl.h"
34#include "bashansi.h"
ccc6cda3 35#include <stdio.h>
f73dda09 36#include "chartypes.h"
ccc6cda3
JA
37#include <errno.h>
38
b80f6443
JA
39#include "bashintl.h"
40
726f6388 41#include "shell.h"
d233b485
CR
42#include "parser.h"
43#include "flags.h"
44#include "findcmd.h"
95732b49 45#include "test.h"
ac50fbac 46#include "trap.h"
8868edaf 47#include "pathexp.h"
95732b49 48
d233b485
CR
49#include "builtins/common.h"
50
a0c0a00f
CR
51#if defined (HAVE_MBSTR_H) && defined (HAVE_MBSCHR)
52# include <mbstr.h> /* mbschr */
53#endif
54
726f6388
JA
55#include <tilde/tilde.h>
56
726f6388
JA
57#if !defined (errno)
58extern int errno;
59#endif /* !errno */
60
d233b485
CR
61#ifdef __CYGWIN__
62# include <sys/cygwin.h>
63#endif
cce855bc 64
8868edaf
CR
65static char *bash_special_tilde_expansions PARAMS((char *));
66static int unquoted_tilde_word PARAMS((const char *));
67static void initialize_group_array PARAMS((void));
7117c2d2 68
cce855bc 69/* A standard error message to use when getcwd() returns NULL. */
3185942a 70const char * const bash_getcwd_errstr = N_("getcwd: cannot access parent directories");
726f6388 71
d233b485
CR
72/* Do whatever is necessary to initialize `Posix mode'. This currently
73 modifies the following variables which are controlled via shopt:
74 interactive_comments
75 source_uses_path
76 expand_aliases
77 inherit_errexit
78 print_shift_error
8868edaf 79 posixglob
d233b485
CR
80
81 and the following variables which cannot be user-modified:
82
83 source_searches_cwd
84
85 If we add to the first list, we need to change the table and functions
86 below */
87
88static struct {
89 int *posix_mode_var;
90} posix_vars[] =
91{
92 &interactive_comments,
93 &source_uses_path,
94 &expand_aliases,
95 &inherit_errexit,
96 &print_shift_error,
97 0
98};
99
8868edaf
CR
100static char *saved_posix_vars = 0;
101
726f6388 102void
ccc6cda3
JA
103posix_initialize (on)
104 int on;
726f6388 105{
28ef6c31
JA
106 /* Things that should be turned on when posix mode is enabled. */
107 if (on != 0)
108 {
109 interactive_comments = source_uses_path = expand_aliases = 1;
a0c0a00f 110 inherit_errexit = 1;
3185942a 111 source_searches_cwd = 0;
d233b485 112 print_shift_error = 1;
28ef6c31
JA
113 }
114
115 /* Things that should be turned on when posix mode is disabled. */
8868edaf
CR
116 else if (saved_posix_vars) /* on == 0, restore saved settings */
117 {
118 set_posix_options (saved_posix_vars);
119 free (saved_posix_vars);
120 saved_posix_vars = 0;
121 }
122 else /* on == 0, restore a default set of settings */
28ef6c31
JA
123 {
124 source_searches_cwd = 1;
125 expand_aliases = interactive_shell;
d233b485 126 print_shift_error = 0;
28ef6c31 127 }
726f6388
JA
128}
129
d233b485
CR
130int
131num_posix_options ()
132{
133 return ((sizeof (posix_vars) / sizeof (posix_vars[0])) - 1);
134}
135
136char *
137get_posix_options (bitmap)
138 char *bitmap;
139{
140 register int i;
141
142 if (bitmap == 0)
143 bitmap = (char *)xmalloc (num_posix_options ()); /* no trailing NULL */
144 for (i = 0; posix_vars[i].posix_mode_var; i++)
145 bitmap[i] = *(posix_vars[i].posix_mode_var);
146 return bitmap;
147}
148
8868edaf
CR
149#undef save_posix_options
150void
151save_posix_options ()
152{
153 saved_posix_vars = get_posix_options (saved_posix_vars);
154}
155
d233b485
CR
156void
157set_posix_options (bitmap)
158 const char *bitmap;
159{
160 register int i;
161
162 for (i = 0; posix_vars[i].posix_mode_var; i++)
163 *(posix_vars[i].posix_mode_var) = bitmap[i];
164}
165
ccc6cda3
JA
166/* **************************************************************** */
167/* */
168/* Functions to convert to and from and display non-standard types */
169/* */
170/* **************************************************************** */
171
726f6388
JA
172#if defined (RLIMTYPE)
173RLIMTYPE
174string_to_rlimtype (s)
175 char *s;
176{
cce855bc
JA
177 RLIMTYPE ret;
178 int neg;
726f6388 179
cce855bc
JA
180 ret = 0;
181 neg = 0;
726f6388
JA
182 while (s && *s && whitespace (*s))
183 s++;
0001803f 184 if (s && (*s == '-' || *s == '+'))
726f6388
JA
185 {
186 neg = *s == '-';
187 s++;
188 }
f73dda09
JA
189 for ( ; s && *s && DIGIT (*s); s++)
190 ret = (ret * 10) + TODIGIT (*s);
726f6388
JA
191 return (neg ? -ret : ret);
192}
193
194void
195print_rlimtype (n, addnl)
196 RLIMTYPE n;
197 int addnl;
198{
f73dda09 199 char s[INT_STRLEN_BOUND (RLIMTYPE) + 1], *p;
726f6388 200
f73dda09
JA
201 p = s + sizeof(s);
202 *--p = '\0';
726f6388
JA
203
204 if (n < 0)
205 {
f73dda09
JA
206 do
207 *--p = '0' - n % 10;
208 while ((n /= 10) != 0);
209
210 *--p = '-';
211 }
212 else
213 {
214 do
215 *--p = '0' + n % 10;
216 while ((n /= 10) != 0);
726f6388
JA
217 }
218
f73dda09 219 printf ("%s%s", p, addnl ? "\n" : "");
726f6388
JA
220}
221#endif /* RLIMTYPE */
222
ccc6cda3
JA
223/* **************************************************************** */
224/* */
225/* Input Validation Functions */
226/* */
227/* **************************************************************** */
228
229/* Return non-zero if all of the characters in STRING are digits. */
230int
231all_digits (string)
a0c0a00f 232 const char *string;
ccc6cda3 233{
a0c0a00f 234 register const char *s;
28ef6c31
JA
235
236 for (s = string; *s; s++)
f73dda09 237 if (DIGIT (*s) == 0)
28ef6c31
JA
238 return (0);
239
ccc6cda3
JA
240 return (1);
241}
242
243/* Return non-zero if the characters pointed to by STRING constitute a
244 valid number. Stuff the converted number into RESULT if RESULT is
f73dda09 245 not null. */
ccc6cda3
JA
246int
247legal_number (string, result)
3185942a 248 const char *string;
7117c2d2 249 intmax_t *result;
ccc6cda3 250{
7117c2d2 251 intmax_t value;
cce855bc 252 char *ep;
ccc6cda3
JA
253
254 if (result)
255 *result = 0;
256
ac50fbac
CR
257 if (string == 0)
258 return 0;
259
f73dda09 260 errno = 0;
7117c2d2 261 value = strtoimax (string, &ep, 10);
3185942a 262 if (errno || ep == string)
f73dda09 263 return 0; /* errno is set on overflow or underflow */
ccc6cda3 264
7117c2d2 265 /* Skip any trailing whitespace, since strtoimax does not. */
28ef6c31
JA
266 while (whitespace (*ep))
267 ep++;
268
cce855bc
JA
269 /* If *string is not '\0' but *ep is '\0' on return, the entire string
270 is valid. */
ac50fbac 271 if (*string && *ep == '\0')
ccc6cda3
JA
272 {
273 if (result)
cce855bc
JA
274 *result = value;
275 /* The SunOS4 implementation of strtol() will happily ignore
276 overflow conditions, so this cannot do overflow correctly
277 on those systems. */
278 return 1;
ccc6cda3 279 }
cce855bc
JA
280
281 return (0);
ccc6cda3
JA
282}
283
726f6388
JA
284/* Return 1 if this token is a legal shell `identifier'; that is, it consists
285 solely of letters, digits, and underscores, and does not begin with a
286 digit. */
287int
288legal_identifier (name)
a0c0a00f 289 const char *name;
726f6388 290{
a0c0a00f 291 register const char *s;
f73dda09 292 unsigned char c;
726f6388 293
f73dda09 294 if (!name || !(c = *name) || (legal_variable_starter (c) == 0))
726f6388
JA
295 return (0);
296
f73dda09 297 for (s = name + 1; (c = *s) != 0; s++)
726f6388 298 {
f73dda09 299 if (legal_variable_char (c) == 0)
28ef6c31 300 return (0);
726f6388
JA
301 }
302 return (1);
303}
304
a0c0a00f
CR
305/* Return 1 if NAME is a valid value that can be assigned to a nameref
306 variable. FLAGS can be 2, in which case the name is going to be used
307 to create a variable. Other values are currently unused, but could
308 be used to allow values to be stored and indirectly referenced, but
309 not used in assignments. */
310int
311valid_nameref_value (name, flags)
312 const char *name;
313 int flags;
314{
315 if (name == 0 || *name == 0)
316 return 0;
317
318 /* valid identifier */
319#if defined (ARRAY_VARS)
320 if (legal_identifier (name) || (flags != 2 && valid_array_reference (name, 0)))
321#else
322 if (legal_identifier (name))
323#endif
324 return 1;
325
326 return 0;
327}
328
329int
330check_selfref (name, value, flags)
331 const char *name;
332 char *value;
333 int flags;
334{
335 char *t;
336
337 if (STREQ (name, value))
338 return 1;
339
340#if defined (ARRAY_VARS)
341 if (valid_array_reference (value, 0))
342 {
d233b485 343 t = array_variable_name (value, 0, (char **)NULL, (int *)NULL);
a0c0a00f
CR
344 if (t && STREQ (name, t))
345 {
346 free (t);
347 return 1;
348 }
349 free (t);
350 }
351#endif
352
353 return 0; /* not a self reference */
354}
355
726f6388 356/* Make sure that WORD is a valid shell identifier, i.e.
8868edaf
CR
357 does not contain a dollar sign, nor is quoted in any way.
358 If CHECK_WORD is non-zero,
726f6388 359 the word is checked to ensure that it consists of only letters,
8868edaf 360 digits, and underscores, and does not consist of all digits. */
ccc6cda3 361int
726f6388
JA
362check_identifier (word, check_word)
363 WORD_DESC *word;
364 int check_word;
365{
8868edaf 366 if (word->flags & (W_HASDOLLAR|W_QUOTED)) /* XXX - HASDOLLAR? */
726f6388 367 {
b80f6443 368 internal_error (_("`%s': not a valid identifier"), word->word);
726f6388
JA
369 return (0);
370 }
8868edaf 371 else if (check_word && (all_digits (word->word) || legal_identifier (word->word) == 0))
726f6388 372 {
b80f6443 373 internal_error (_("`%s': not a valid identifier"), word->word);
726f6388
JA
374 return (0);
375 }
376 else
377 return (1);
378}
379
a0c0a00f
CR
380/* Return 1 if STRING is a function name that the shell will import from
381 the environment. Currently we reject attempts to import shell functions
382 containing slashes, beginning with newlines or containing blanks. In
383 Posix mode, we require that STRING be a valid shell identifier. Not
384 used yet. */
385int
386importable_function_name (string, len)
387 const char *string;
388 size_t len;
389{
390 if (absolute_program (string)) /* don't allow slash */
391 return 0;
392 if (*string == '\n') /* can't start with a newline */
393 return 0;
394 if (shellblank (*string) || shellblank(string[len-1]))
395 return 0;
396 return (posixly_correct ? legal_identifier (string) : 1);
397}
398
399int
400exportable_function_name (string)
401 const char *string;
402{
403 if (absolute_program (string))
404 return 0;
405 if (mbschr (string, '=') != 0)
406 return 0;
407 return 1;
408}
409
b80f6443
JA
410/* Return 1 if STRING comprises a valid alias name. The shell accepts
411 essentially all characters except those which must be quoted to the
412 parser (which disqualifies them from alias expansion anyway) and `/'. */
413int
414legal_alias_name (string, flags)
a0c0a00f 415 const char *string;
b80f6443
JA
416 int flags;
417{
a0c0a00f 418 register const char *s;
b80f6443
JA
419
420 for (s = string; *s; s++)
421 if (shellbreak (*s) || shellxquote (*s) || shellexp (*s) || (*s == '/'))
422 return 0;
423 return 1;
424}
425
7117c2d2 426/* Returns non-zero if STRING is an assignment statement. The returned value
d233b485 427 is the index of the `=' sign. If FLAGS&1 we are expecting a compound assignment
8868edaf
CR
428 and require an array subscript before the `=' to denote an assignment
429 statement. */
7117c2d2 430int
b80f6443 431assignment (string, flags)
7117c2d2 432 const char *string;
b80f6443 433 int flags;
7117c2d2
JA
434{
435 register unsigned char c;
436 register int newi, indx;
437
438 c = string[indx = 0];
439
b80f6443 440#if defined (ARRAY_VARS)
8868edaf
CR
441 /* If parser_state includes PST_COMPASSIGN, FLAGS will include 1, so we are
442 parsing the contents of a compound assignment. If parser_state includes
443 PST_REPARSE, we are in the middle of an assignment statement and breaking
444 the words between the parens into words and assignment statements, but
445 we don't need to check for that right now. Within a compound assignment,
446 the subscript is required to make the word an assignment statement. If
447 we don't have a subscript, even if the word is a valid assignment
448 statement otherwise, we don't want to treat it as one. */
449 if ((flags & 1) && c != '[') /* ] */
450 return (0);
451 else if ((flags & 1) == 0 && legal_variable_starter (c) == 0)
b80f6443 452#else
7117c2d2 453 if (legal_variable_starter (c) == 0)
b80f6443 454#endif
7117c2d2
JA
455 return (0);
456
457 while (c = string[indx])
458 {
459 /* The following is safe. Note that '=' at the start of a word
460 is not an assignment statement. */
461 if (c == '=')
462 return (indx);
463
464#if defined (ARRAY_VARS)
465 if (c == '[')
466 {
d233b485
CR
467 newi = skipsubscript (string, indx, (flags & 2) ? 1 : 0);
468 /* XXX - why not check for blank subscripts here, if we do in
469 valid_array_reference? */
7117c2d2
JA
470 if (string[newi++] != ']')
471 return (0);
95732b49
JA
472 if (string[newi] == '+' && string[newi+1] == '=')
473 return (newi + 1);
7117c2d2
JA
474 return ((string[newi] == '=') ? newi : 0);
475 }
476#endif /* ARRAY_VARS */
477
95732b49
JA
478 /* Check for `+=' */
479 if (c == '+' && string[indx+1] == '=')
480 return (indx + 1);
481
7117c2d2
JA
482 /* Variable names in assignment statements may contain only letters,
483 digits, and `_'. */
484 if (legal_variable_char (c) == 0)
485 return (0);
486
487 indx++;
488 }
489 return (0);
490}
491
d233b485
CR
492int
493line_isblank (line)
494 const char *line;
495{
496 register int i;
497
498 if (line == 0)
499 return 0; /* XXX */
500 for (i = 0; line[i]; i++)
501 if (isblank ((unsigned char)line[i]) == 0)
502 break;
503 return (line[i] == '\0');
504}
505
ccc6cda3
JA
506/* **************************************************************** */
507/* */
508/* Functions to manage files and file descriptors */
509/* */
510/* **************************************************************** */
511
726f6388
JA
512/* A function to unset no-delay mode on a file descriptor. Used in shell.c
513 to unset it on the fd passed as stdin. Should be called on stdin if
514 readline gets an EAGAIN or EWOULDBLOCK when trying to read input. */
515
516#if !defined (O_NDELAY)
517# if defined (FNDELAY)
518# define O_NDELAY FNDELAY
519# endif
520#endif /* O_NDELAY */
521
522/* Make sure no-delay mode is not set on file descriptor FD. */
bb70624e 523int
28ef6c31 524sh_unset_nodelay_mode (fd)
726f6388
JA
525 int fd;
526{
bb70624e 527 int flags, bflags;
726f6388
JA
528
529 if ((flags = fcntl (fd, F_GETFL, 0)) < 0)
bb70624e 530 return -1;
726f6388 531
bb70624e 532 bflags = 0;
ccc6cda3
JA
533
534 /* This is defined to O_NDELAY in filecntl.h if O_NONBLOCK is not present
535 and O_NDELAY is defined. */
bb70624e
JA
536#ifdef O_NONBLOCK
537 bflags |= O_NONBLOCK;
538#endif
539
540#ifdef O_NDELAY
541 bflags |= O_NDELAY;
542#endif
543
544 if (flags & bflags)
726f6388 545 {
bb70624e
JA
546 flags &= ~bflags;
547 return (fcntl (fd, F_SETFL, flags));
726f6388 548 }
726f6388 549
bb70624e 550 return 0;
726f6388
JA
551}
552
d233b485
CR
553/* Just a wrapper for the define in include/filecntl.h */
554int
555sh_setclexec (fd)
556 int fd;
557{
558 return (SET_CLOSE_ON_EXEC (fd));
559}
560
7117c2d2
JA
561/* Return 1 if file descriptor FD is valid; 0 otherwise. */
562int
563sh_validfd (fd)
564 int fd;
565{
566 return (fcntl (fd, F_GETFD, 0) >= 0);
567}
568
495aee44
CR
569int
570fd_ispipe (fd)
571 int fd;
572{
573 errno = 0;
a0c0a00f 574 return ((lseek (fd, 0L, SEEK_CUR) < 0) && (errno == ESPIPE));
495aee44
CR
575}
576
b72432fd
JA
577/* There is a bug in the NeXT 2.1 rlogind that causes opens
578 of /dev/tty to fail. */
579
580#if defined (__BEOS__)
581/* On BeOS, opening in non-blocking mode exposes a bug in BeOS, so turn it
582 into a no-op. This should probably go away in the future. */
583# undef O_NONBLOCK
584# define O_NONBLOCK 0
585#endif /* __BEOS__ */
586
726f6388 587void
ccc6cda3 588check_dev_tty ()
726f6388 589{
ccc6cda3
JA
590 int tty_fd;
591 char *tty;
726f6388 592
d166f048 593 tty_fd = open ("/dev/tty", O_RDWR|O_NONBLOCK);
726f6388 594
ccc6cda3 595 if (tty_fd < 0)
726f6388 596 {
ccc6cda3
JA
597 tty = (char *)ttyname (fileno (stdin));
598 if (tty == 0)
599 return;
d166f048 600 tty_fd = open (tty, O_RDWR|O_NONBLOCK);
726f6388 601 }
ac50fbac
CR
602 if (tty_fd >= 0)
603 close (tty_fd);
726f6388
JA
604}
605
ccc6cda3
JA
606/* Return 1 if PATH1 and PATH2 are the same file. This is kind of
607 expensive. If non-NULL STP1 and STP2 point to stat structures
608 corresponding to PATH1 and PATH2, respectively. */
726f6388 609int
ccc6cda3 610same_file (path1, path2, stp1, stp2)
a0c0a00f 611 const char *path1, *path2;
ccc6cda3 612 struct stat *stp1, *stp2;
726f6388 613{
ccc6cda3 614 struct stat st1, st2;
726f6388 615
ccc6cda3 616 if (stp1 == NULL)
726f6388 617 {
ccc6cda3
JA
618 if (stat (path1, &st1) != 0)
619 return (0);
620 stp1 = &st1;
726f6388 621 }
726f6388 622
ccc6cda3
JA
623 if (stp2 == NULL)
624 {
625 if (stat (path2, &st2) != 0)
626 return (0);
627 stp2 = &st2;
628 }
726f6388 629
ccc6cda3 630 return ((stp1->st_dev == stp2->st_dev) && (stp1->st_ino == stp2->st_ino));
726f6388
JA
631}
632
ccc6cda3
JA
633/* Move FD to a number close to the maximum number of file descriptors
634 allowed in the shell process, to avoid the user stepping on it with
635 redirection and causing us extra work. If CHECK_NEW is non-zero,
636 we check whether or not the file descriptors are in use before
d166f048
JA
637 duplicating FD onto them. MAXFD says where to start checking the
638 file descriptors. If it's less than 20, we get the maximum value
639 available from getdtablesize(2). */
726f6388 640int
d166f048
JA
641move_to_high_fd (fd, check_new, maxfd)
642 int fd, check_new, maxfd;
726f6388 643{
ccc6cda3 644 int script_fd, nfds, ignore;
726f6388 645
d166f048
JA
646 if (maxfd < 20)
647 {
648 nfds = getdtablesize ();
649 if (nfds <= 0)
650 nfds = 20;
7117c2d2
JA
651 if (nfds > HIGH_FD_MAX)
652 nfds = HIGH_FD_MAX; /* reasonable maximum */
d166f048
JA
653 }
654 else
655 nfds = maxfd;
726f6388 656
ccc6cda3
JA
657 for (nfds--; check_new && nfds > 3; nfds--)
658 if (fcntl (nfds, F_GETFD, &ignore) == -1)
659 break;
726f6388 660
7117c2d2 661 if (nfds > 3 && fd != nfds && (script_fd = dup2 (fd, nfds)) != -1)
ccc6cda3
JA
662 {
663 if (check_new == 0 || fd != fileno (stderr)) /* don't close stderr */
664 close (fd);
665 return (script_fd);
666 }
726f6388 667
7117c2d2
JA
668 /* OK, we didn't find one less than our artificial maximum; return the
669 original file descriptor. */
ccc6cda3
JA
670 return (fd);
671}
672
673/* Return non-zero if the characters from SAMPLE are not all valid
674 characters to be found in the first line of a shell script. We
675 check up to the first newline, or SAMPLE_LEN, whichever comes first.
676 All of the characters must be printable or whitespace. */
726f6388 677
726f6388 678int
ccc6cda3 679check_binary_file (sample, sample_len)
a0c0a00f 680 const char *sample;
ccc6cda3 681 int sample_len;
726f6388 682{
ccc6cda3 683 register int i;
f73dda09 684 unsigned char c;
726f6388 685
ccc6cda3
JA
686 for (i = 0; i < sample_len; i++)
687 {
f73dda09
JA
688 c = sample[i];
689 if (c == '\n')
ccc6cda3 690 return (0);
0628567a 691 if (c == '\0')
ccc6cda3
JA
692 return (1);
693 }
726f6388 694
ccc6cda3 695 return (0);
726f6388
JA
696}
697
3185942a
JA
698/* **************************************************************** */
699/* */
700/* Functions to manipulate pipes */
701/* */
702/* **************************************************************** */
703
704int
705sh_openpipe (pv)
706 int *pv;
707{
708 int r;
709
710 if ((r = pipe (pv)) < 0)
711 return r;
712
713 pv[0] = move_to_high_fd (pv[0], 1, 64);
714 pv[1] = move_to_high_fd (pv[1], 1, 64);
715
716 return 0;
717}
718
719int
720sh_closepipe (pv)
721 int *pv;
722{
723 if (pv[0] >= 0)
724 close (pv[0]);
725
726 if (pv[1] >= 0)
727 close (pv[1]);
728
729 pv[0] = pv[1] = -1;
730 return 0;
731}
732
b80f6443
JA
733/* **************************************************************** */
734/* */
735/* Functions to inspect pathnames */
736/* */
737/* **************************************************************** */
738
3185942a
JA
739int
740file_exists (fn)
a0c0a00f 741 const char *fn;
3185942a
JA
742{
743 struct stat sb;
744
745 return (stat (fn, &sb) == 0);
746}
747
b80f6443
JA
748int
749file_isdir (fn)
a0c0a00f 750 const char *fn;
b80f6443
JA
751{
752 struct stat sb;
753
754 return ((stat (fn, &sb) == 0) && S_ISDIR (sb.st_mode));
755}
756
757int
758file_iswdir (fn)
a0c0a00f 759 const char *fn;
b80f6443 760{
0628567a 761 return (file_isdir (fn) && sh_eaccess (fn, W_OK) == 0);
b80f6443
JA
762}
763
495aee44
CR
764/* Return 1 if STRING is "." or "..", optionally followed by a directory
765 separator */
766int
ac50fbac 767path_dot_or_dotdot (string)
495aee44
CR
768 const char *string;
769{
770 if (string == 0 || *string == '\0' || *string != '.')
771 return (0);
772
773 /* string[0] == '.' */
774 if (PATHSEP(string[1]) || (string[1] == '.' && PATHSEP(string[2])))
775 return (1);
776
777 return (0);
778}
779
95732b49
JA
780/* Return 1 if STRING contains an absolute pathname, else 0. Used by `cd'
781 to decide whether or not to look up a directory name in $CDPATH. */
782int
783absolute_pathname (string)
784 const char *string;
785{
786 if (string == 0 || *string == '\0')
787 return (0);
788
789 if (ABSPATH(string))
790 return (1);
791
792 if (string[0] == '.' && PATHSEP(string[1])) /* . and ./ */
793 return (1);
794
795 if (string[0] == '.' && string[1] == '.' && PATHSEP(string[2])) /* .. and ../ */
796 return (1);
797
798 return (0);
799}
800
801/* Return 1 if STRING is an absolute program name; it is absolute if it
802 contains any slashes. This is used to decide whether or not to look
803 up through $PATH. */
804int
805absolute_program (string)
806 const char *string;
807{
0001803f 808 return ((char *)mbschr (string, '/') != (char *)NULL);
95732b49 809}
b80f6443 810
ccc6cda3
JA
811/* **************************************************************** */
812/* */
813/* Functions to manipulate pathnames */
814/* */
815/* **************************************************************** */
726f6388 816
726f6388
JA
817/* Turn STRING (a pathname) into an absolute pathname, assuming that
818 DOT_PATH contains the symbolic location of `.'. This always
819 returns a new string, even if STRING was an absolute pathname to
820 begin with. */
821char *
822make_absolute (string, dot_path)
a0c0a00f 823 const char *string, *dot_path;
726f6388
JA
824{
825 char *result;
ccc6cda3 826
28ef6c31 827 if (dot_path == 0 || ABSPATH(string))
b80f6443
JA
828#ifdef __CYGWIN__
829 {
830 char pathbuf[PATH_MAX + 1];
831
d233b485
CR
832 /* WAS cygwin_conv_to_full_posix_path (string, pathbuf); */
833 cygwin_conv_path (CCP_WIN_A_TO_POSIX, string, pathbuf, PATH_MAX);
b80f6443
JA
834 result = savestring (pathbuf);
835 }
836#else
726f6388 837 result = savestring (string);
b80f6443 838#endif
726f6388 839 else
bb70624e 840 result = sh_makepath (dot_path, string, 0);
726f6388
JA
841
842 return (result);
843}
844
726f6388 845/* Return the `basename' of the pathname in STRING (the stuff after the
95732b49 846 last '/'). If STRING is `/', just return it. */
726f6388
JA
847char *
848base_pathname (string)
849 char *string;
850{
851 char *p;
852
95732b49 853#if 0
28ef6c31 854 if (absolute_pathname (string) == 0)
726f6388 855 return (string);
95732b49
JA
856#endif
857
858 if (string[0] == '/' && string[1] == 0)
859 return (string);
726f6388
JA
860
861 p = (char *)strrchr (string, '/');
ccc6cda3 862 return (p ? ++p : string);
726f6388
JA
863}
864
865/* Return the full pathname of FILE. Easy. Filenames that begin
866 with a '/' are returned as themselves. Other filenames have
867 the current working directory prepended. A new string is
868 returned in either case. */
869char *
870full_pathname (file)
871 char *file;
872{
bb70624e 873 char *ret;
726f6388 874
7117c2d2 875 file = (*file == '~') ? bash_tilde_expand (file, 0) : savestring (file);
726f6388 876
28ef6c31 877 if (ABSPATH(file))
726f6388
JA
878 return (file);
879
bb70624e
JA
880 ret = sh_makepath ((char *)NULL, file, (MP_DOCWD|MP_RMDOT));
881 free (file);
726f6388 882
bb70624e 883 return (ret);
726f6388 884}
726f6388
JA
885
886/* A slightly related function. Get the prettiest name of this
887 directory possible. */
ccc6cda3 888static char tdir[PATH_MAX];
726f6388
JA
889
890/* Return a pretty pathname. If the first part of the pathname is
891 the same as $HOME, then replace that with `~'. */
892char *
893polite_directory_format (name)
894 char *name;
895{
ccc6cda3
JA
896 char *home;
897 int l;
726f6388 898
ccc6cda3
JA
899 home = get_string_value ("HOME");
900 l = home ? strlen (home) : 0;
726f6388
JA
901 if (l > 1 && strncmp (home, name, l) == 0 && (!name[l] || name[l] == '/'))
902 {
e8ce775d 903 strncpy (tdir + 1, name + l, sizeof(tdir) - 2);
726f6388 904 tdir[0] = '~';
e8ce775d 905 tdir[sizeof(tdir) - 1] = '\0';
726f6388
JA
906 return (tdir);
907 }
908 else
909 return (name);
910}
911
3185942a
JA
912/* Trim NAME. If NAME begins with `~/', skip over tilde prefix. Trim to
913 keep any tilde prefix and PROMPT_DIRTRIM trailing directory components
914 and replace the intervening characters with `...' */
915char *
916trim_pathname (name, maxlen)
917 char *name;
918 int maxlen;
919{
920 int nlen, ndirs;
921 intmax_t nskip;
922 char *nbeg, *nend, *ntail, *v;
923
924 if (name == 0 || (nlen = strlen (name)) == 0)
925 return name;
926 nend = name + nlen;
927
928 v = get_string_value ("PROMPT_DIRTRIM");
929 if (v == 0 || *v == 0)
930 return name;
931 if (legal_number (v, &nskip) == 0 || nskip <= 0)
932 return name;
933
934 /* Skip over tilde prefix */
935 nbeg = name;
936 if (name[0] == '~')
937 for (nbeg = name; *nbeg; nbeg++)
938 if (*nbeg == '/')
939 {
940 nbeg++;
941 break;
942 }
943 if (*nbeg == 0)
944 return name;
945
946 for (ndirs = 0, ntail = nbeg; *ntail; ntail++)
947 if (*ntail == '/')
948 ndirs++;
0001803f 949 if (ndirs < nskip)
3185942a
JA
950 return name;
951
952 for (ntail = (*nend == '/') ? nend : nend - 1; ntail > nbeg; ntail--)
953 {
954 if (*ntail == '/')
955 nskip--;
956 if (nskip == 0)
957 break;
958 }
959 if (ntail == nbeg)
960 return name;
961
962 /* Now we want to return name[0..nbeg]+"..."+ntail, modifying name in place */
963 nlen = ntail - nbeg;
964 if (nlen <= 3)
965 return name;
966
967 *nbeg++ = '.';
968 *nbeg++ = '.';
969 *nbeg++ = '.';
970
971 nlen = nend - ntail;
ac50fbac 972 memmove (nbeg, ntail, nlen);
3185942a
JA
973 nbeg[nlen] = '\0';
974
975 return name;
976}
977
a0c0a00f
CR
978/* Return a printable representation of FN without special characters. The
979 caller is responsible for freeing memory if this returns something other
980 than its argument. If FLAGS is non-zero, we are printing for portable
981 re-input and should single-quote filenames appropriately. */
982char *
983printable_filename (fn, flags)
984 char *fn;
985 int flags;
986{
987 char *newf;
988
989 if (ansic_shouldquote (fn))
990 newf = ansic_quote (fn, 0, NULL);
991 else if (flags && sh_contains_shell_metas (fn))
992 newf = sh_single_quote (fn);
993 else
994 newf = fn;
995
996 return newf;
997}
998
ccc6cda3
JA
999/* Given a string containing units of information separated by colons,
1000 return the next one pointed to by (P_INDEX), or NULL if there are no more.
1001 Advance (P_INDEX) to the character after the colon. */
1002char *
1003extract_colon_unit (string, p_index)
1004 char *string;
1005 int *p_index;
726f6388 1006{
ccc6cda3
JA
1007 int i, start, len;
1008 char *value;
726f6388 1009
ccc6cda3
JA
1010 if (string == 0)
1011 return (string);
726f6388 1012
ccc6cda3
JA
1013 len = strlen (string);
1014 if (*p_index >= len)
1015 return ((char *)NULL);
726f6388 1016
ccc6cda3 1017 i = *p_index;
726f6388 1018
ccc6cda3
JA
1019 /* Each call to this routine leaves the index pointing at a colon if
1020 there is more to the path. If I is > 0, then increment past the
1021 `:'. If I is 0, then the path has a leading colon. Trailing colons
1022 are handled OK by the `else' part of the if statement; an empty
1023 string is returned in that case. */
1024 if (i && string[i] == ':')
1025 i++;
1026
1027 for (start = i; string[i] && string[i] != ':'; i++)
1028 ;
1029
1030 *p_index = i;
1031
1032 if (i == start)
1033 {
1034 if (string[i])
1035 (*p_index)++;
1036 /* Return "" in the case of a trailing `:'. */
f73dda09 1037 value = (char *)xmalloc (1);
ccc6cda3
JA
1038 value[0] = '\0';
1039 }
1040 else
bb70624e 1041 value = substring (string, start, i);
ccc6cda3
JA
1042
1043 return (value);
726f6388 1044}
726f6388
JA
1045
1046/* **************************************************************** */
1047/* */
1048/* Tilde Initialization and Expansion */
1049/* */
1050/* **************************************************************** */
1051
cce855bc 1052#if defined (PUSHD_AND_POPD)
8868edaf 1053extern char *get_dirstack_from_string PARAMS((char *));
cce855bc
JA
1054#endif
1055
f73dda09 1056static char **bash_tilde_prefixes;
95732b49 1057static char **bash_tilde_prefixes2;
f73dda09 1058static char **bash_tilde_suffixes;
95732b49 1059static char **bash_tilde_suffixes2;
f73dda09 1060
726f6388
JA
1061/* If tilde_expand hasn't been able to expand the text, perhaps it
1062 is a special shell expansion. This function is installed as the
cce855bc
JA
1063 tilde_expansion_preexpansion_hook. It knows how to expand ~- and ~+.
1064 If PUSHD_AND_POPD is defined, ~[+-]N expands to directories from the
1065 directory stack. */
726f6388 1066static char *
d166f048 1067bash_special_tilde_expansions (text)
726f6388
JA
1068 char *text;
1069{
ccc6cda3 1070 char *result;
726f6388 1071
ccc6cda3 1072 result = (char *)NULL;
cce855bc
JA
1073
1074 if (text[0] == '+' && text[1] == '\0')
1075 result = get_string_value ("PWD");
1076 else if (text[0] == '-' && text[1] == '\0')
1077 result = get_string_value ("OLDPWD");
1078#if defined (PUSHD_AND_POPD)
f73dda09 1079 else if (DIGIT (*text) || ((*text == '+' || *text == '-') && DIGIT (text[1])))
cce855bc
JA
1080 result = get_dirstack_from_string (text);
1081#endif
726f6388 1082
ccc6cda3 1083 return (result ? savestring (result) : (char *)NULL);
726f6388
JA
1084}
1085
1086/* Initialize the tilde expander. In Bash, we handle `~-' and `~+', as
1087 well as handling special tilde prefixes; `:~" and `=~' are indications
1088 that we should do tilde expansion. */
1089void
1090tilde_initialize ()
1091{
1092 static int times_called = 0;
1093
d166f048 1094 /* Tell the tilde expander that we want a crack first. */
f73dda09 1095 tilde_expansion_preexpansion_hook = bash_special_tilde_expansions;
726f6388
JA
1096
1097 /* Tell the tilde expander about special strings which start a tilde
1098 expansion, and the special strings that end one. Only do this once.
1099 tilde_initialize () is called from within bashline_reinitialize (). */
cce855bc 1100 if (times_called++ == 0)
726f6388 1101 {
7117c2d2 1102 bash_tilde_prefixes = strvec_create (3);
f73dda09
JA
1103 bash_tilde_prefixes[0] = "=~";
1104 bash_tilde_prefixes[1] = ":~";
1105 bash_tilde_prefixes[2] = (char *)NULL;
1106
95732b49
JA
1107 bash_tilde_prefixes2 = strvec_create (2);
1108 bash_tilde_prefixes2[0] = ":~";
1109 bash_tilde_prefixes2[1] = (char *)NULL;
1110
f73dda09
JA
1111 tilde_additional_prefixes = bash_tilde_prefixes;
1112
7117c2d2 1113 bash_tilde_suffixes = strvec_create (3);
f73dda09
JA
1114 bash_tilde_suffixes[0] = ":";
1115 bash_tilde_suffixes[1] = "=~"; /* XXX - ?? */
1116 bash_tilde_suffixes[2] = (char *)NULL;
1117
1118 tilde_additional_suffixes = bash_tilde_suffixes;
95732b49
JA
1119
1120 bash_tilde_suffixes2 = strvec_create (2);
1121 bash_tilde_suffixes2[0] = ":";
1122 bash_tilde_suffixes2[1] = (char *)NULL;
726f6388 1123 }
726f6388
JA
1124}
1125
f73dda09
JA
1126/* POSIX.2, 3.6.1: A tilde-prefix consists of an unquoted tilde character
1127 at the beginning of the word, followed by all of the characters preceding
1128 the first unquoted slash in the word, or all the characters in the word
1129 if there is no slash...If none of the characters in the tilde-prefix are
1130 quoted, the characters in the tilde-prefix following the tilde shell be
1131 treated as a possible login name. */
1132
1133#define TILDE_END(c) ((c) == '\0' || (c) == '/' || (c) == ':')
1134
1135static int
1136unquoted_tilde_word (s)
1137 const char *s;
1138{
1139 const char *r;
1140
1141 for (r = s; TILDE_END(*r) == 0; r++)
1142 {
1143 switch (*r)
1144 {
1145 case '\\':
1146 case '\'':
1147 case '"':
1148 return 0;
1149 }
1150 }
1151 return 1;
1152}
1153
95732b49
JA
1154/* Find the end of the tilde-prefix starting at S, and return the tilde
1155 prefix in newly-allocated memory. Return the length of the string in
1156 *LENP. FLAGS tells whether or not we're in an assignment context --
1157 if so, `:' delimits the end of the tilde prefix as well. */
1158char *
1159bash_tilde_find_word (s, flags, lenp)
1160 const char *s;
1161 int flags, *lenp;
1162{
1163 const char *r;
1164 char *ret;
1165 int l;
1166
1167 for (r = s; *r && *r != '/'; r++)
1168 {
1169 /* Short-circuit immediately if we see a quote character. Even though
1170 POSIX says that `the first unquoted slash' (or `:') terminates the
1171 tilde-prefix, in practice, any quoted portion of the tilde prefix
1172 will cause it to not be expanded. */
1173 if (*r == '\\' || *r == '\'' || *r == '"')
1174 {
1175 ret = savestring (s);
1176 if (lenp)
1177 *lenp = 0;
1178 return ret;
1179 }
1180 else if (flags && *r == ':')
1181 break;
1182 }
1183 l = r - s;
1184 ret = xmalloc (l + 1);
1185 strncpy (ret, s, l);
1186 ret[l] = '\0';
1187 if (lenp)
1188 *lenp = l;
1189 return ret;
1190}
1191
7117c2d2
JA
1192/* Tilde-expand S by running it through the tilde expansion library.
1193 ASSIGN_P is 1 if this is a variable assignment, so the alternate
95732b49
JA
1194 tilde prefixes should be enabled (`=~' and `:~', see above). If
1195 ASSIGN_P is 2, we are expanding the rhs of an assignment statement,
1196 so `=~' is not valid. */
ccc6cda3 1197char *
7117c2d2 1198bash_tilde_expand (s, assign_p)
f73dda09 1199 const char *s;
7117c2d2 1200 int assign_p;
726f6388 1201{
8868edaf 1202 int r;
ccc6cda3 1203 char *ret;
726f6388 1204
95732b49
JA
1205 tilde_additional_prefixes = assign_p == 0 ? (char **)0
1206 : (assign_p == 2 ? bash_tilde_prefixes2 : bash_tilde_prefixes);
1207 if (assign_p == 2)
1208 tilde_additional_suffixes = bash_tilde_suffixes2;
1209
f73dda09
JA
1210 r = (*s == '~') ? unquoted_tilde_word (s) : 1;
1211 ret = r ? tilde_expand (s) : savestring (s);
ac50fbac 1212
ac50fbac
CR
1213 QUIT;
1214
ccc6cda3 1215 return (ret);
726f6388 1216}
d166f048
JA
1217
1218/* **************************************************************** */
1219/* */
1220/* Functions to manipulate and search the group list */
1221/* */
1222/* **************************************************************** */
1223
1224static int ngroups, maxgroups;
1225
1226/* The set of groups that this user is a member of. */
1227static GETGROUPS_T *group_array = (GETGROUPS_T *)NULL;
1228
1229#if !defined (NOGROUP)
1230# define NOGROUP (gid_t) -1
1231#endif
1232
d166f048
JA
1233static void
1234initialize_group_array ()
1235{
1236 register int i;
1237
1238 if (maxgroups == 0)
1239 maxgroups = getmaxgroups ();
1240
1241 ngroups = 0;
1242 group_array = (GETGROUPS_T *)xrealloc (group_array, maxgroups * sizeof (GETGROUPS_T));
1243
1244#if defined (HAVE_GETGROUPS)
1245 ngroups = getgroups (maxgroups, group_array);
1246#endif
1247
1248 /* If getgroups returns nothing, or the OS does not support getgroups(),
1249 make sure the groups array includes at least the current gid. */
1250 if (ngroups == 0)
1251 {
1252 group_array[0] = current_user.gid;
1253 ngroups = 1;
1254 }
1255
1256 /* If the primary group is not in the groups array, add it as group_array[0]
1257 and shuffle everything else up 1, if there's room. */
1258 for (i = 0; i < ngroups; i++)
1259 if (current_user.gid == (gid_t)group_array[i])
1260 break;
1261 if (i == ngroups && ngroups < maxgroups)
1262 {
1263 for (i = ngroups; i > 0; i--)
28ef6c31 1264 group_array[i] = group_array[i - 1];
d166f048
JA
1265 group_array[0] = current_user.gid;
1266 ngroups++;
1267 }
cce855bc
JA
1268
1269 /* If the primary group is not group_array[0], swap group_array[0] and
1270 whatever the current group is. The vast majority of systems should
1271 not need this; a notable exception is Linux. */
1272 if (group_array[0] != current_user.gid)
1273 {
1274 for (i = 0; i < ngroups; i++)
28ef6c31
JA
1275 if (group_array[i] == current_user.gid)
1276 break;
cce855bc
JA
1277 if (i < ngroups)
1278 {
1279 group_array[i] = group_array[0];
1280 group_array[0] = current_user.gid;
1281 }
1282 }
d166f048
JA
1283}
1284
1285/* Return non-zero if GID is one that we have in our groups list. */
1286int
cce855bc
JA
1287#if defined (__STDC__) || defined ( _MINIX)
1288group_member (gid_t gid)
1289#else
d166f048
JA
1290group_member (gid)
1291 gid_t gid;
cce855bc 1292#endif /* !__STDC__ && !_MINIX */
d166f048
JA
1293{
1294#if defined (HAVE_GETGROUPS)
1295 register int i;
1296#endif
1297
1298 /* Short-circuit if possible, maybe saving a call to getgroups(). */
1299 if (gid == current_user.gid || gid == current_user.egid)
1300 return (1);
1301
1302#if defined (HAVE_GETGROUPS)
1303 if (ngroups == 0)
1304 initialize_group_array ();
1305
1306 /* In case of error, the user loses. */
1307 if (ngroups <= 0)
1308 return (0);
1309
1310 /* Search through the list looking for GID. */
1311 for (i = 0; i < ngroups; i++)
1312 if (gid == (gid_t)group_array[i])
1313 return (1);
1314#endif
1315
1316 return (0);
1317}
1318
1319char **
1320get_group_list (ngp)
1321 int *ngp;
1322{
1323 static char **group_vector = (char **)NULL;
1324 register int i;
d166f048
JA
1325
1326 if (group_vector)
1327 {
1328 if (ngp)
1329 *ngp = ngroups;
1330 return group_vector;
1331 }
1332
1333 if (ngroups == 0)
1334 initialize_group_array ();
1335
1336 if (ngroups <= 0)
1337 {
1338 if (ngp)
1339 *ngp = 0;
1340 return (char **)NULL;
1341 }
1342
7117c2d2 1343 group_vector = strvec_create (ngroups);
d166f048 1344 for (i = 0; i < ngroups; i++)
7117c2d2 1345 group_vector[i] = itos (group_array[i]);
b72432fd 1346
d166f048
JA
1347 if (ngp)
1348 *ngp = ngroups;
1349 return group_vector;
1350}
b72432fd
JA
1351
1352int *
1353get_group_array (ngp)
1354 int *ngp;
1355{
1356 int i;
1357 static int *group_iarray = (int *)NULL;
1358
1359 if (group_iarray)
1360 {
1361 if (ngp)
1362 *ngp = ngroups;
1363 return (group_iarray);
1364 }
1365
1366 if (ngroups == 0)
1367 initialize_group_array ();
1368
1369 if (ngroups <= 0)
1370 {
1371 if (ngp)
1372 *ngp = 0;
1373 return (int *)NULL;
1374 }
1375
1376 group_iarray = (int *)xmalloc (ngroups * sizeof (int));
1377 for (i = 0; i < ngroups; i++)
1378 group_iarray[i] = (int)group_array[i];
1379
1380 if (ngp)
1381 *ngp = ngroups;
1382 return group_iarray;
1383}
a0c0a00f
CR
1384
1385/* **************************************************************** */
1386/* */
1387/* Miscellaneous functions */
1388/* */
1389/* **************************************************************** */
1390
1391/* Return a value for PATH that is guaranteed to find all of the standard
1392 utilities. This uses Posix.2 configuration variables, if present. It
1393 uses a value defined in config.h as a last resort. */
1394char *
1395conf_standard_path ()
1396{
1397#if defined (_CS_PATH) && defined (HAVE_CONFSTR)
1398 char *p;
1399 size_t len;
1400
1401 len = (size_t)confstr (_CS_PATH, (char *)NULL, (size_t)0);
1402 if (len > 0)
1403 {
1404 p = (char *)xmalloc (len + 2);
1405 *p = '\0';
1406 confstr (_CS_PATH, p, len);
1407 return (p);
1408 }
1409 else
1410 return (savestring (STANDARD_UTILS_PATH));
1411#else /* !_CS_PATH || !HAVE_CONFSTR */
1412# if defined (CS_PATH)
1413 return (savestring (CS_PATH));
1414# else
1415 return (savestring (STANDARD_UTILS_PATH));
1416# endif /* !CS_PATH */
1417#endif /* !_CS_PATH || !HAVE_CONFSTR */
1418}
d233b485
CR
1419
1420int
1421default_columns ()
1422{
1423 char *v;
1424 int c;
1425
1426 c = -1;
1427 v = get_string_value ("COLUMNS");
1428 if (v && *v)
1429 {
1430 c = atoi (v);
1431 if (c > 0)
1432 return c;
1433 }
1434
1435 if (check_window_size)
1436 get_new_window_size (0, (int *)0, &c);
1437
1438 return (c > 0 ? c : 80);
1439}
1440
1441