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