]> git.ipfire.org Git - thirdparty/bash.git/blame - general.c
bash-5.2 distribution sources and documentation
[thirdparty/bash.git] / general.c
CommitLineData
726f6388
JA
1/* general.c -- Stuff that is used by all files. */
2
74091dd4 3/* Copyright (C) 1987-2021 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
74091dd4
CR
686 if (sample_len >= 4 && sample[0] == 0x7f && sample[1] == 'E' && sample[2] == 'L' && sample[3] == 'F')
687 return 1;
688
689 /* Generally we check the first line for NULs. If the first line looks like
690 a `#!' interpreter specifier, we just look for NULs anywhere in the
691 buffer. */
692 if (sample[0] == '#' && sample[1] == '!')
693 return (memchr (sample, '\0', sample_len) != NULL);
694
ccc6cda3
JA
695 for (i = 0; i < sample_len; i++)
696 {
f73dda09
JA
697 c = sample[i];
698 if (c == '\n')
ccc6cda3 699 return (0);
0628567a 700 if (c == '\0')
ccc6cda3
JA
701 return (1);
702 }
726f6388 703
ccc6cda3 704 return (0);
726f6388
JA
705}
706
3185942a
JA
707/* **************************************************************** */
708/* */
709/* Functions to manipulate pipes */
710/* */
711/* **************************************************************** */
712
713int
714sh_openpipe (pv)
715 int *pv;
716{
717 int r;
718
719 if ((r = pipe (pv)) < 0)
720 return r;
721
722 pv[0] = move_to_high_fd (pv[0], 1, 64);
723 pv[1] = move_to_high_fd (pv[1], 1, 64);
724
725 return 0;
726}
727
728int
729sh_closepipe (pv)
730 int *pv;
731{
732 if (pv[0] >= 0)
733 close (pv[0]);
734
735 if (pv[1] >= 0)
736 close (pv[1]);
737
738 pv[0] = pv[1] = -1;
739 return 0;
740}
741
b80f6443
JA
742/* **************************************************************** */
743/* */
744/* Functions to inspect pathnames */
745/* */
746/* **************************************************************** */
747
3185942a
JA
748int
749file_exists (fn)
a0c0a00f 750 const char *fn;
3185942a
JA
751{
752 struct stat sb;
753
754 return (stat (fn, &sb) == 0);
755}
756
b80f6443
JA
757int
758file_isdir (fn)
a0c0a00f 759 const char *fn;
b80f6443
JA
760{
761 struct stat sb;
762
763 return ((stat (fn, &sb) == 0) && S_ISDIR (sb.st_mode));
764}
765
766int
767file_iswdir (fn)
a0c0a00f 768 const char *fn;
b80f6443 769{
0628567a 770 return (file_isdir (fn) && sh_eaccess (fn, W_OK) == 0);
b80f6443
JA
771}
772
495aee44
CR
773/* Return 1 if STRING is "." or "..", optionally followed by a directory
774 separator */
775int
ac50fbac 776path_dot_or_dotdot (string)
495aee44
CR
777 const char *string;
778{
779 if (string == 0 || *string == '\0' || *string != '.')
780 return (0);
781
782 /* string[0] == '.' */
783 if (PATHSEP(string[1]) || (string[1] == '.' && PATHSEP(string[2])))
784 return (1);
785
786 return (0);
787}
788
95732b49
JA
789/* Return 1 if STRING contains an absolute pathname, else 0. Used by `cd'
790 to decide whether or not to look up a directory name in $CDPATH. */
791int
792absolute_pathname (string)
793 const char *string;
794{
795 if (string == 0 || *string == '\0')
796 return (0);
797
798 if (ABSPATH(string))
799 return (1);
800
801 if (string[0] == '.' && PATHSEP(string[1])) /* . and ./ */
802 return (1);
803
804 if (string[0] == '.' && string[1] == '.' && PATHSEP(string[2])) /* .. and ../ */
805 return (1);
806
807 return (0);
808}
809
810/* Return 1 if STRING is an absolute program name; it is absolute if it
811 contains any slashes. This is used to decide whether or not to look
812 up through $PATH. */
813int
814absolute_program (string)
815 const char *string;
816{
0001803f 817 return ((char *)mbschr (string, '/') != (char *)NULL);
95732b49 818}
b80f6443 819
ccc6cda3
JA
820/* **************************************************************** */
821/* */
822/* Functions to manipulate pathnames */
823/* */
824/* **************************************************************** */
726f6388 825
726f6388
JA
826/* Turn STRING (a pathname) into an absolute pathname, assuming that
827 DOT_PATH contains the symbolic location of `.'. This always
828 returns a new string, even if STRING was an absolute pathname to
829 begin with. */
830char *
831make_absolute (string, dot_path)
a0c0a00f 832 const char *string, *dot_path;
726f6388
JA
833{
834 char *result;
ccc6cda3 835
28ef6c31 836 if (dot_path == 0 || ABSPATH(string))
b80f6443
JA
837#ifdef __CYGWIN__
838 {
839 char pathbuf[PATH_MAX + 1];
840
d233b485
CR
841 /* WAS cygwin_conv_to_full_posix_path (string, pathbuf); */
842 cygwin_conv_path (CCP_WIN_A_TO_POSIX, string, pathbuf, PATH_MAX);
b80f6443
JA
843 result = savestring (pathbuf);
844 }
845#else
726f6388 846 result = savestring (string);
b80f6443 847#endif
726f6388 848 else
bb70624e 849 result = sh_makepath (dot_path, string, 0);
726f6388
JA
850
851 return (result);
852}
853
726f6388 854/* Return the `basename' of the pathname in STRING (the stuff after the
95732b49 855 last '/'). If STRING is `/', just return it. */
726f6388
JA
856char *
857base_pathname (string)
858 char *string;
859{
860 char *p;
861
95732b49 862#if 0
28ef6c31 863 if (absolute_pathname (string) == 0)
726f6388 864 return (string);
95732b49
JA
865#endif
866
867 if (string[0] == '/' && string[1] == 0)
868 return (string);
726f6388
JA
869
870 p = (char *)strrchr (string, '/');
ccc6cda3 871 return (p ? ++p : string);
726f6388
JA
872}
873
874/* Return the full pathname of FILE. Easy. Filenames that begin
875 with a '/' are returned as themselves. Other filenames have
876 the current working directory prepended. A new string is
877 returned in either case. */
878char *
879full_pathname (file)
880 char *file;
881{
bb70624e 882 char *ret;
726f6388 883
7117c2d2 884 file = (*file == '~') ? bash_tilde_expand (file, 0) : savestring (file);
726f6388 885
28ef6c31 886 if (ABSPATH(file))
726f6388
JA
887 return (file);
888
bb70624e
JA
889 ret = sh_makepath ((char *)NULL, file, (MP_DOCWD|MP_RMDOT));
890 free (file);
726f6388 891
bb70624e 892 return (ret);
726f6388 893}
726f6388
JA
894
895/* A slightly related function. Get the prettiest name of this
896 directory possible. */
ccc6cda3 897static char tdir[PATH_MAX];
726f6388
JA
898
899/* Return a pretty pathname. If the first part of the pathname is
900 the same as $HOME, then replace that with `~'. */
901char *
902polite_directory_format (name)
903 char *name;
904{
ccc6cda3
JA
905 char *home;
906 int l;
726f6388 907
ccc6cda3
JA
908 home = get_string_value ("HOME");
909 l = home ? strlen (home) : 0;
726f6388
JA
910 if (l > 1 && strncmp (home, name, l) == 0 && (!name[l] || name[l] == '/'))
911 {
e8ce775d 912 strncpy (tdir + 1, name + l, sizeof(tdir) - 2);
726f6388 913 tdir[0] = '~';
e8ce775d 914 tdir[sizeof(tdir) - 1] = '\0';
726f6388
JA
915 return (tdir);
916 }
917 else
918 return (name);
919}
920
3185942a
JA
921/* Trim NAME. If NAME begins with `~/', skip over tilde prefix. Trim to
922 keep any tilde prefix and PROMPT_DIRTRIM trailing directory components
923 and replace the intervening characters with `...' */
924char *
925trim_pathname (name, maxlen)
926 char *name;
927 int maxlen;
928{
929 int nlen, ndirs;
930 intmax_t nskip;
931 char *nbeg, *nend, *ntail, *v;
932
933 if (name == 0 || (nlen = strlen (name)) == 0)
934 return name;
935 nend = name + nlen;
936
937 v = get_string_value ("PROMPT_DIRTRIM");
938 if (v == 0 || *v == 0)
939 return name;
940 if (legal_number (v, &nskip) == 0 || nskip <= 0)
941 return name;
942
943 /* Skip over tilde prefix */
944 nbeg = name;
945 if (name[0] == '~')
946 for (nbeg = name; *nbeg; nbeg++)
947 if (*nbeg == '/')
948 {
949 nbeg++;
950 break;
951 }
952 if (*nbeg == 0)
953 return name;
954
955 for (ndirs = 0, ntail = nbeg; *ntail; ntail++)
956 if (*ntail == '/')
957 ndirs++;
0001803f 958 if (ndirs < nskip)
3185942a
JA
959 return name;
960
961 for (ntail = (*nend == '/') ? nend : nend - 1; ntail > nbeg; ntail--)
962 {
963 if (*ntail == '/')
964 nskip--;
965 if (nskip == 0)
966 break;
967 }
968 if (ntail == nbeg)
969 return name;
970
971 /* Now we want to return name[0..nbeg]+"..."+ntail, modifying name in place */
972 nlen = ntail - nbeg;
973 if (nlen <= 3)
974 return name;
975
976 *nbeg++ = '.';
977 *nbeg++ = '.';
978 *nbeg++ = '.';
979
980 nlen = nend - ntail;
ac50fbac 981 memmove (nbeg, ntail, nlen);
3185942a
JA
982 nbeg[nlen] = '\0';
983
984 return name;
985}
986
a0c0a00f
CR
987/* Return a printable representation of FN without special characters. The
988 caller is responsible for freeing memory if this returns something other
989 than its argument. If FLAGS is non-zero, we are printing for portable
990 re-input and should single-quote filenames appropriately. */
991char *
992printable_filename (fn, flags)
993 char *fn;
994 int flags;
995{
996 char *newf;
997
998 if (ansic_shouldquote (fn))
999 newf = ansic_quote (fn, 0, NULL);
1000 else if (flags && sh_contains_shell_metas (fn))
1001 newf = sh_single_quote (fn);
1002 else
1003 newf = fn;
1004
1005 return newf;
1006}
1007
ccc6cda3
JA
1008/* Given a string containing units of information separated by colons,
1009 return the next one pointed to by (P_INDEX), or NULL if there are no more.
1010 Advance (P_INDEX) to the character after the colon. */
1011char *
1012extract_colon_unit (string, p_index)
1013 char *string;
1014 int *p_index;
726f6388 1015{
ccc6cda3
JA
1016 int i, start, len;
1017 char *value;
726f6388 1018
ccc6cda3
JA
1019 if (string == 0)
1020 return (string);
726f6388 1021
ccc6cda3
JA
1022 len = strlen (string);
1023 if (*p_index >= len)
1024 return ((char *)NULL);
726f6388 1025
ccc6cda3 1026 i = *p_index;
726f6388 1027
ccc6cda3
JA
1028 /* Each call to this routine leaves the index pointing at a colon if
1029 there is more to the path. If I is > 0, then increment past the
1030 `:'. If I is 0, then the path has a leading colon. Trailing colons
1031 are handled OK by the `else' part of the if statement; an empty
1032 string is returned in that case. */
1033 if (i && string[i] == ':')
1034 i++;
1035
1036 for (start = i; string[i] && string[i] != ':'; i++)
1037 ;
1038
1039 *p_index = i;
1040
1041 if (i == start)
1042 {
1043 if (string[i])
1044 (*p_index)++;
1045 /* Return "" in the case of a trailing `:'. */
f73dda09 1046 value = (char *)xmalloc (1);
ccc6cda3
JA
1047 value[0] = '\0';
1048 }
1049 else
bb70624e 1050 value = substring (string, start, i);
ccc6cda3
JA
1051
1052 return (value);
726f6388 1053}
726f6388
JA
1054
1055/* **************************************************************** */
1056/* */
1057/* Tilde Initialization and Expansion */
1058/* */
1059/* **************************************************************** */
1060
cce855bc 1061#if defined (PUSHD_AND_POPD)
8868edaf 1062extern char *get_dirstack_from_string PARAMS((char *));
cce855bc
JA
1063#endif
1064
f73dda09 1065static char **bash_tilde_prefixes;
95732b49 1066static char **bash_tilde_prefixes2;
f73dda09 1067static char **bash_tilde_suffixes;
95732b49 1068static char **bash_tilde_suffixes2;
f73dda09 1069
726f6388
JA
1070/* If tilde_expand hasn't been able to expand the text, perhaps it
1071 is a special shell expansion. This function is installed as the
cce855bc
JA
1072 tilde_expansion_preexpansion_hook. It knows how to expand ~- and ~+.
1073 If PUSHD_AND_POPD is defined, ~[+-]N expands to directories from the
1074 directory stack. */
726f6388 1075static char *
d166f048 1076bash_special_tilde_expansions (text)
726f6388
JA
1077 char *text;
1078{
ccc6cda3 1079 char *result;
726f6388 1080
ccc6cda3 1081 result = (char *)NULL;
cce855bc
JA
1082
1083 if (text[0] == '+' && text[1] == '\0')
1084 result = get_string_value ("PWD");
1085 else if (text[0] == '-' && text[1] == '\0')
1086 result = get_string_value ("OLDPWD");
1087#if defined (PUSHD_AND_POPD)
f73dda09 1088 else if (DIGIT (*text) || ((*text == '+' || *text == '-') && DIGIT (text[1])))
cce855bc
JA
1089 result = get_dirstack_from_string (text);
1090#endif
726f6388 1091
ccc6cda3 1092 return (result ? savestring (result) : (char *)NULL);
726f6388
JA
1093}
1094
1095/* Initialize the tilde expander. In Bash, we handle `~-' and `~+', as
1096 well as handling special tilde prefixes; `:~" and `=~' are indications
1097 that we should do tilde expansion. */
1098void
1099tilde_initialize ()
1100{
1101 static int times_called = 0;
1102
d166f048 1103 /* Tell the tilde expander that we want a crack first. */
f73dda09 1104 tilde_expansion_preexpansion_hook = bash_special_tilde_expansions;
726f6388
JA
1105
1106 /* Tell the tilde expander about special strings which start a tilde
1107 expansion, and the special strings that end one. Only do this once.
1108 tilde_initialize () is called from within bashline_reinitialize (). */
cce855bc 1109 if (times_called++ == 0)
726f6388 1110 {
7117c2d2 1111 bash_tilde_prefixes = strvec_create (3);
f73dda09
JA
1112 bash_tilde_prefixes[0] = "=~";
1113 bash_tilde_prefixes[1] = ":~";
1114 bash_tilde_prefixes[2] = (char *)NULL;
1115
95732b49
JA
1116 bash_tilde_prefixes2 = strvec_create (2);
1117 bash_tilde_prefixes2[0] = ":~";
1118 bash_tilde_prefixes2[1] = (char *)NULL;
1119
f73dda09
JA
1120 tilde_additional_prefixes = bash_tilde_prefixes;
1121
7117c2d2 1122 bash_tilde_suffixes = strvec_create (3);
f73dda09
JA
1123 bash_tilde_suffixes[0] = ":";
1124 bash_tilde_suffixes[1] = "=~"; /* XXX - ?? */
1125 bash_tilde_suffixes[2] = (char *)NULL;
1126
1127 tilde_additional_suffixes = bash_tilde_suffixes;
95732b49
JA
1128
1129 bash_tilde_suffixes2 = strvec_create (2);
1130 bash_tilde_suffixes2[0] = ":";
1131 bash_tilde_suffixes2[1] = (char *)NULL;
726f6388 1132 }
726f6388
JA
1133}
1134
f73dda09
JA
1135/* POSIX.2, 3.6.1: A tilde-prefix consists of an unquoted tilde character
1136 at the beginning of the word, followed by all of the characters preceding
1137 the first unquoted slash in the word, or all the characters in the word
1138 if there is no slash...If none of the characters in the tilde-prefix are
1139 quoted, the characters in the tilde-prefix following the tilde shell be
1140 treated as a possible login name. */
1141
1142#define TILDE_END(c) ((c) == '\0' || (c) == '/' || (c) == ':')
1143
1144static int
1145unquoted_tilde_word (s)
1146 const char *s;
1147{
1148 const char *r;
1149
1150 for (r = s; TILDE_END(*r) == 0; r++)
1151 {
1152 switch (*r)
1153 {
1154 case '\\':
1155 case '\'':
1156 case '"':
1157 return 0;
1158 }
1159 }
1160 return 1;
1161}
1162
95732b49
JA
1163/* Find the end of the tilde-prefix starting at S, and return the tilde
1164 prefix in newly-allocated memory. Return the length of the string in
1165 *LENP. FLAGS tells whether or not we're in an assignment context --
1166 if so, `:' delimits the end of the tilde prefix as well. */
1167char *
1168bash_tilde_find_word (s, flags, lenp)
1169 const char *s;
1170 int flags, *lenp;
1171{
1172 const char *r;
1173 char *ret;
1174 int l;
1175
1176 for (r = s; *r && *r != '/'; r++)
1177 {
1178 /* Short-circuit immediately if we see a quote character. Even though
1179 POSIX says that `the first unquoted slash' (or `:') terminates the
1180 tilde-prefix, in practice, any quoted portion of the tilde prefix
1181 will cause it to not be expanded. */
1182 if (*r == '\\' || *r == '\'' || *r == '"')
1183 {
1184 ret = savestring (s);
1185 if (lenp)
1186 *lenp = 0;
1187 return ret;
1188 }
1189 else if (flags && *r == ':')
1190 break;
1191 }
1192 l = r - s;
1193 ret = xmalloc (l + 1);
1194 strncpy (ret, s, l);
1195 ret[l] = '\0';
1196 if (lenp)
1197 *lenp = l;
1198 return ret;
1199}
1200
7117c2d2
JA
1201/* Tilde-expand S by running it through the tilde expansion library.
1202 ASSIGN_P is 1 if this is a variable assignment, so the alternate
95732b49
JA
1203 tilde prefixes should be enabled (`=~' and `:~', see above). If
1204 ASSIGN_P is 2, we are expanding the rhs of an assignment statement,
1205 so `=~' is not valid. */
ccc6cda3 1206char *
7117c2d2 1207bash_tilde_expand (s, assign_p)
f73dda09 1208 const char *s;
7117c2d2 1209 int assign_p;
726f6388 1210{
8868edaf 1211 int r;
ccc6cda3 1212 char *ret;
726f6388 1213
95732b49
JA
1214 tilde_additional_prefixes = assign_p == 0 ? (char **)0
1215 : (assign_p == 2 ? bash_tilde_prefixes2 : bash_tilde_prefixes);
1216 if (assign_p == 2)
1217 tilde_additional_suffixes = bash_tilde_suffixes2;
1218
f73dda09
JA
1219 r = (*s == '~') ? unquoted_tilde_word (s) : 1;
1220 ret = r ? tilde_expand (s) : savestring (s);
ac50fbac 1221
ac50fbac
CR
1222 QUIT;
1223
ccc6cda3 1224 return (ret);
726f6388 1225}
d166f048
JA
1226
1227/* **************************************************************** */
1228/* */
1229/* Functions to manipulate and search the group list */
1230/* */
1231/* **************************************************************** */
1232
1233static int ngroups, maxgroups;
1234
1235/* The set of groups that this user is a member of. */
1236static GETGROUPS_T *group_array = (GETGROUPS_T *)NULL;
1237
1238#if !defined (NOGROUP)
1239# define NOGROUP (gid_t) -1
1240#endif
1241
d166f048
JA
1242static void
1243initialize_group_array ()
1244{
1245 register int i;
1246
1247 if (maxgroups == 0)
1248 maxgroups = getmaxgroups ();
1249
1250 ngroups = 0;
1251 group_array = (GETGROUPS_T *)xrealloc (group_array, maxgroups * sizeof (GETGROUPS_T));
1252
1253#if defined (HAVE_GETGROUPS)
1254 ngroups = getgroups (maxgroups, group_array);
1255#endif
1256
1257 /* If getgroups returns nothing, or the OS does not support getgroups(),
1258 make sure the groups array includes at least the current gid. */
1259 if (ngroups == 0)
1260 {
1261 group_array[0] = current_user.gid;
1262 ngroups = 1;
1263 }
1264
1265 /* If the primary group is not in the groups array, add it as group_array[0]
1266 and shuffle everything else up 1, if there's room. */
1267 for (i = 0; i < ngroups; i++)
1268 if (current_user.gid == (gid_t)group_array[i])
1269 break;
1270 if (i == ngroups && ngroups < maxgroups)
1271 {
1272 for (i = ngroups; i > 0; i--)
28ef6c31 1273 group_array[i] = group_array[i - 1];
d166f048
JA
1274 group_array[0] = current_user.gid;
1275 ngroups++;
1276 }
cce855bc
JA
1277
1278 /* If the primary group is not group_array[0], swap group_array[0] and
1279 whatever the current group is. The vast majority of systems should
1280 not need this; a notable exception is Linux. */
1281 if (group_array[0] != current_user.gid)
1282 {
1283 for (i = 0; i < ngroups; i++)
28ef6c31
JA
1284 if (group_array[i] == current_user.gid)
1285 break;
cce855bc
JA
1286 if (i < ngroups)
1287 {
1288 group_array[i] = group_array[0];
1289 group_array[0] = current_user.gid;
1290 }
1291 }
d166f048
JA
1292}
1293
1294/* Return non-zero if GID is one that we have in our groups list. */
1295int
cce855bc
JA
1296#if defined (__STDC__) || defined ( _MINIX)
1297group_member (gid_t gid)
1298#else
d166f048
JA
1299group_member (gid)
1300 gid_t gid;
cce855bc 1301#endif /* !__STDC__ && !_MINIX */
d166f048
JA
1302{
1303#if defined (HAVE_GETGROUPS)
1304 register int i;
1305#endif
1306
1307 /* Short-circuit if possible, maybe saving a call to getgroups(). */
1308 if (gid == current_user.gid || gid == current_user.egid)
1309 return (1);
1310
1311#if defined (HAVE_GETGROUPS)
1312 if (ngroups == 0)
1313 initialize_group_array ();
1314
1315 /* In case of error, the user loses. */
1316 if (ngroups <= 0)
1317 return (0);
1318
1319 /* Search through the list looking for GID. */
1320 for (i = 0; i < ngroups; i++)
1321 if (gid == (gid_t)group_array[i])
1322 return (1);
1323#endif
1324
1325 return (0);
1326}
1327
1328char **
1329get_group_list (ngp)
1330 int *ngp;
1331{
1332 static char **group_vector = (char **)NULL;
1333 register int i;
d166f048
JA
1334
1335 if (group_vector)
1336 {
1337 if (ngp)
1338 *ngp = ngroups;
1339 return group_vector;
1340 }
1341
1342 if (ngroups == 0)
1343 initialize_group_array ();
1344
1345 if (ngroups <= 0)
1346 {
1347 if (ngp)
1348 *ngp = 0;
1349 return (char **)NULL;
1350 }
1351
7117c2d2 1352 group_vector = strvec_create (ngroups);
d166f048 1353 for (i = 0; i < ngroups; i++)
7117c2d2 1354 group_vector[i] = itos (group_array[i]);
b72432fd 1355
d166f048
JA
1356 if (ngp)
1357 *ngp = ngroups;
1358 return group_vector;
1359}
b72432fd
JA
1360
1361int *
1362get_group_array (ngp)
1363 int *ngp;
1364{
1365 int i;
1366 static int *group_iarray = (int *)NULL;
1367
1368 if (group_iarray)
1369 {
1370 if (ngp)
1371 *ngp = ngroups;
1372 return (group_iarray);
1373 }
1374
1375 if (ngroups == 0)
1376 initialize_group_array ();
1377
1378 if (ngroups <= 0)
1379 {
1380 if (ngp)
1381 *ngp = 0;
1382 return (int *)NULL;
1383 }
1384
1385 group_iarray = (int *)xmalloc (ngroups * sizeof (int));
1386 for (i = 0; i < ngroups; i++)
1387 group_iarray[i] = (int)group_array[i];
1388
1389 if (ngp)
1390 *ngp = ngroups;
1391 return group_iarray;
1392}
a0c0a00f
CR
1393
1394/* **************************************************************** */
1395/* */
1396/* Miscellaneous functions */
1397/* */
1398/* **************************************************************** */
1399
1400/* Return a value for PATH that is guaranteed to find all of the standard
1401 utilities. This uses Posix.2 configuration variables, if present. It
1402 uses a value defined in config.h as a last resort. */
1403char *
1404conf_standard_path ()
1405{
1406#if defined (_CS_PATH) && defined (HAVE_CONFSTR)
1407 char *p;
1408 size_t len;
1409
1410 len = (size_t)confstr (_CS_PATH, (char *)NULL, (size_t)0);
1411 if (len > 0)
1412 {
1413 p = (char *)xmalloc (len + 2);
1414 *p = '\0';
1415 confstr (_CS_PATH, p, len);
1416 return (p);
1417 }
1418 else
1419 return (savestring (STANDARD_UTILS_PATH));
1420#else /* !_CS_PATH || !HAVE_CONFSTR */
1421# if defined (CS_PATH)
1422 return (savestring (CS_PATH));
1423# else
1424 return (savestring (STANDARD_UTILS_PATH));
1425# endif /* !CS_PATH */
1426#endif /* !_CS_PATH || !HAVE_CONFSTR */
1427}
d233b485
CR
1428
1429int
1430default_columns ()
1431{
1432 char *v;
1433 int c;
1434
1435 c = -1;
1436 v = get_string_value ("COLUMNS");
1437 if (v && *v)
1438 {
1439 c = atoi (v);
1440 if (c > 0)
1441 return c;
1442 }
1443
1444 if (check_window_size)
1445 get_new_window_size (0, (int *)0, &c);
1446
1447 return (c > 0 ? c : 80);
1448}
1449
1450