Imported from ../bash-2.03.tar.gz.
[platform/upstream/bash.git] / general.c
1 /* general.c -- Stuff that is used by all files. */
2
3 /* Copyright (C) 1987, 1988, 1989, 1990, 1991, 1992
4    Free Software Foundation, Inc.
5
6    This file is part of GNU Bash, the Bourne Again SHell.
7
8    Bash is free software; you can redistribute it and/or modify it under
9    the terms of the GNU General Public License as published by the Free
10    Software Foundation; either version 2, or (at your option) any later
11    version.
12
13    Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14    WARRANTY; without even the implied warranty of MERCHANTABILITY or
15    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16    for more details.
17
18    You should have received a copy of the GNU General Public License along
19    with Bash; see the file COPYING.  If not, write to the Free Software
20    Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21
22 #include "config.h"
23
24 #include "bashtypes.h"
25 #ifndef _MINIX
26 #  include <sys/param.h>
27 #endif
28 #include "posixstat.h"
29
30 #if defined (HAVE_UNISTD_H)
31 #  include <unistd.h>
32 #endif
33
34 #include "filecntl.h"
35 #include "bashansi.h"
36 #include <stdio.h>
37 #include <ctype.h>
38 #include <errno.h>
39
40 #include "shell.h"
41 #include <tilde/tilde.h>
42
43 #if defined (TIME_WITH_SYS_TIME)
44 #  include <sys/time.h>
45 #  include <time.h>
46 #else
47 #  if defined (HAVE_SYS_TIME_H)
48 #    include <sys/time.h>
49 #  else
50 #    include <time.h>
51 #  endif
52 #endif
53
54 #include <sys/times.h>
55 #include "maxpath.h"
56
57 #if !defined (errno)
58 extern int errno;
59 #endif /* !errno */
60
61 #ifndef to_upper
62 #  define to_upper(c) (islower(c) ? toupper(c) : (c))
63 #  define to_lower(c) (isupper(c) ? tolower(c) : (c))
64 #endif
65
66 extern int interrupt_immediately;
67 extern int interactive_comments;
68
69 /* A standard error message to use when getcwd() returns NULL. */
70 char *bash_getcwd_errstr = "getcwd: cannot access parent directories";
71
72 /* Do whatever is necessary to initialize `Posix mode'. */
73 void
74 posix_initialize (on)
75      int on;
76 {
77   interactive_comments = on != 0;
78 }
79
80 /* **************************************************************** */
81 /*                                                                  */
82 /*  Functions to convert to and from and display non-standard types */
83 /*                                                                  */
84 /* **************************************************************** */
85
86 #if defined (RLIMTYPE)
87 RLIMTYPE
88 string_to_rlimtype (s)
89      char *s;
90 {
91   RLIMTYPE ret;
92   int neg;
93
94   ret = 0;
95   neg = 0;
96   while (s && *s && whitespace (*s))
97     s++;
98   if (*s == '-' || *s == '+')
99     {
100       neg = *s == '-';
101       s++;
102     }
103   for ( ; s && *s && digit (*s); s++)
104     ret = (ret * 10) + digit_value (*s);
105   return (neg ? -ret : ret);
106 }
107
108 void
109 print_rlimtype (n, addnl)
110      RLIMTYPE n;
111      int addnl;
112 {
113   char s[sizeof (RLIMTYPE) * 3 + 1];
114   int len;
115
116   if (n == 0)
117     {
118       printf ("0%s", addnl ? "\n" : "");
119       return;
120     }
121
122   if (n < 0)
123     {
124       putchar ('-');
125       n = -n;
126     }
127
128   len = sizeof (RLIMTYPE) * 3 + 1;
129   s[--len] = '\0';
130   for ( ; n != 0; n /= 10)
131     s[--len] = n % 10 + '0';
132   printf ("%s%s", s + len, addnl ? "\n" : "");
133 }
134 #endif /* RLIMTYPE */
135
136 #if defined (HAVE_TIMEVAL)
137 /* Convert a pointer to a struct timeval to seconds and thousandths of a
138    second, returning the values in *SP and *SFP, respectively.  This does
139    rounding on the fractional part, not just truncation to three places. */
140 void
141 timeval_to_secs (tvp, sp, sfp)
142      struct timeval *tvp;
143      long *sp;
144      int *sfp;
145 {
146   int rest;
147
148   *sp = tvp->tv_sec;
149
150   *sfp = tvp->tv_usec % 1000000;        /* pretty much a no-op */
151   rest = *sfp % 1000;
152   *sfp = (*sfp * 1000) / 1000000;
153   if (rest >= 500)
154     *sfp += 1;
155
156   /* Sanity check */
157   if (*sfp >= 1000)
158     {
159       *sp += 1;
160       *sfp -= 1000;
161     }
162 }
163   
164 /* Print the contents of a struct timeval * in a standard way to stdio
165    stream FP.  */
166 void
167 print_timeval (fp, tvp)
168      FILE *fp;
169      struct timeval *tvp;
170 {
171   int minutes, seconds_fraction;
172   long seconds;
173
174   timeval_to_secs (tvp, &seconds, &seconds_fraction);
175
176   minutes = seconds / 60;
177   seconds %= 60;
178
179   fprintf (fp, "%0dm%0ld.%03ds",  minutes, seconds, seconds_fraction);
180 }
181 #endif /* HAVE_TIMEVAL */
182
183 #if defined (HAVE_TIMES)
184 void
185 clock_t_to_secs (t, sp, sfp)
186      clock_t t;
187      long *sp;
188      int *sfp;
189 {
190   static long clk_tck = 0;
191
192   if (clk_tck == 0)
193     clk_tck = get_clk_tck ();
194
195   *sfp = t % clk_tck;
196   *sfp = (*sfp * 1000) / clk_tck;
197
198   *sp = t / clk_tck;
199
200   /* Sanity check */
201   if (*sfp >= 1000)
202     {
203       *sp += 1;
204       *sfp -= 1000;
205     }
206 }
207
208 /* Print the time defined by a time_t (returned by the `times' and `time'
209    system calls) in a standard way to stdion stream FP.  This is scaled in
210    terms of HZ, which is what is returned by the `times' call. */
211 void
212 print_time_in_hz (fp, t)
213      FILE *fp;
214      clock_t t;
215 {
216   int minutes, seconds_fraction;
217   long seconds;
218
219   clock_t_to_secs (t, &seconds, &seconds_fraction);
220
221   minutes = seconds / 60;
222   seconds %= 60;
223
224   fprintf (fp, "%0dm%0ld.%03ds",  minutes, seconds, seconds_fraction);
225 }
226 #endif /* HAVE_TIMES */
227
228 /* **************************************************************** */
229 /*                                                                  */
230 /*                     Input Validation Functions                   */
231 /*                                                                  */
232 /* **************************************************************** */
233
234 /* Return non-zero if all of the characters in STRING are digits. */
235 int
236 all_digits (string)
237      char *string;
238 {
239   while (*string)
240     {
241       if (!digit (*string))
242         return (0);
243       else
244         string++;
245     }
246   return (1);
247 }
248
249 /* Return non-zero if the characters pointed to by STRING constitute a
250    valid number.  Stuff the converted number into RESULT if RESULT is
251    a non-null pointer to a long. */
252 int
253 legal_number (string, result)
254      char *string;
255      long *result;
256 {
257   long value;
258   char *ep;
259
260   if (result)
261     *result = 0;
262
263   value = strtol (string, &ep, 10);
264
265   /* If *string is not '\0' but *ep is '\0' on return, the entire string
266      is valid. */
267   if (string && *string && *ep == '\0')
268     {
269       if (result)
270         *result = value;
271       /* The SunOS4 implementation of strtol() will happily ignore
272          overflow conditions, so this cannot do overflow correctly
273          on those systems. */
274       return 1;
275     }
276     
277   return (0);
278 }
279
280 /* Return 1 if this token is a legal shell `identifier'; that is, it consists
281    solely of letters, digits, and underscores, and does not begin with a
282    digit. */
283 int
284 legal_identifier (name)
285      char *name;
286 {
287   register char *s;
288
289   if (!name || !*name || (legal_variable_starter (*name) == 0))
290     return (0);
291
292   for (s = name + 1; *s; s++)
293     {
294       if (legal_variable_char (*s) == 0)
295         return (0);
296     }
297   return (1);
298 }
299
300 /* Make sure that WORD is a valid shell identifier, i.e.
301    does not contain a dollar sign, nor is quoted in any way.  Nor
302    does it consist of all digits.  If CHECK_WORD is non-zero,
303    the word is checked to ensure that it consists of only letters,
304    digits, and underscores. */
305 int
306 check_identifier (word, check_word)
307      WORD_DESC *word;
308      int check_word;
309 {
310   if ((word->flags & (W_HASDOLLAR|W_QUOTED)) || all_digits (word->word))
311     {
312       internal_error ("`%s': not a valid identifier", word->word);
313       return (0);
314     }
315   else if (check_word && legal_identifier (word->word) == 0)
316     {
317       internal_error ("`%s': not a valid identifier", word->word);
318       return (0);
319     }
320   else
321     return (1);
322 }
323
324 /* **************************************************************** */
325 /*                                                                  */
326 /*           Functions to manage files and file descriptors         */
327 /*                                                                  */
328 /* **************************************************************** */
329
330 /* A function to unset no-delay mode on a file descriptor.  Used in shell.c
331    to unset it on the fd passed as stdin.  Should be called on stdin if
332    readline gets an EAGAIN or EWOULDBLOCK when trying to read input. */
333
334 #if !defined (O_NDELAY)
335 #  if defined (FNDELAY)
336 #    define O_NDELAY FNDELAY
337 #  endif
338 #endif /* O_NDELAY */
339
340 /* Make sure no-delay mode is not set on file descriptor FD. */
341 void
342 unset_nodelay_mode (fd)
343      int fd;
344 {
345   int flags, set;
346
347   if ((flags = fcntl (fd, F_GETFL, 0)) < 0)
348     return;
349
350   set = 0;
351
352   /* This is defined to O_NDELAY in filecntl.h if O_NONBLOCK is not present
353      and O_NDELAY is defined. */
354   if (flags & O_NONBLOCK)
355     {
356       flags &= ~O_NONBLOCK;
357       set++;
358     }
359
360   if (set)
361     fcntl (fd, F_SETFL, flags);
362 }
363
364 /* There is a bug in the NeXT 2.1 rlogind that causes opens
365    of /dev/tty to fail. */
366
367 #if defined (__BEOS__)
368 /* On BeOS, opening in non-blocking mode exposes a bug in BeOS, so turn it
369    into a no-op.  This should probably go away in the future. */
370 #  undef O_NONBLOCK
371 #  define O_NONBLOCK 0
372 #endif /* __BEOS__ */
373
374 void
375 check_dev_tty ()
376 {
377   int tty_fd;
378   char *tty;
379
380   tty_fd = open ("/dev/tty", O_RDWR|O_NONBLOCK);
381
382   if (tty_fd < 0)
383     {
384       tty = (char *)ttyname (fileno (stdin));
385       if (tty == 0)
386         return;
387       tty_fd = open (tty, O_RDWR|O_NONBLOCK);
388     }
389   close (tty_fd);
390 }
391
392 /* Return 1 if PATH1 and PATH2 are the same file.  This is kind of
393    expensive.  If non-NULL STP1 and STP2 point to stat structures
394    corresponding to PATH1 and PATH2, respectively. */
395 int
396 same_file (path1, path2, stp1, stp2)
397      char *path1, *path2;
398      struct stat *stp1, *stp2;
399 {
400   struct stat st1, st2;
401
402   if (stp1 == NULL)
403     {
404       if (stat (path1, &st1) != 0)
405         return (0);
406       stp1 = &st1;
407     }
408
409   if (stp2 == NULL)
410     {
411       if (stat (path2, &st2) != 0)
412         return (0);
413       stp2 = &st2;
414     }
415
416   return ((stp1->st_dev == stp2->st_dev) && (stp1->st_ino == stp2->st_ino));
417 }
418
419 /* Move FD to a number close to the maximum number of file descriptors
420    allowed in the shell process, to avoid the user stepping on it with
421    redirection and causing us extra work.  If CHECK_NEW is non-zero,
422    we check whether or not the file descriptors are in use before
423    duplicating FD onto them.  MAXFD says where to start checking the
424    file descriptors.  If it's less than 20, we get the maximum value
425    available from getdtablesize(2). */
426 int
427 move_to_high_fd (fd, check_new, maxfd)
428      int fd, check_new, maxfd;
429 {
430   int script_fd, nfds, ignore;
431
432   if (maxfd < 20)
433     {
434       nfds = getdtablesize ();
435       if (nfds <= 0)
436         nfds = 20;
437       if (nfds > 256)
438         nfds = 256;
439     }
440   else
441     nfds = maxfd;
442
443   for (nfds--; check_new && nfds > 3; nfds--)
444     if (fcntl (nfds, F_GETFD, &ignore) == -1)
445       break;
446
447   if (nfds && fd != nfds && (script_fd = dup2 (fd, nfds)) != -1)
448     {
449       if (check_new == 0 || fd != fileno (stderr))      /* don't close stderr */
450         close (fd);
451       return (script_fd);
452     }
453
454   return (fd);
455 }
456  
457 /* Return non-zero if the characters from SAMPLE are not all valid
458    characters to be found in the first line of a shell script.  We
459    check up to the first newline, or SAMPLE_LEN, whichever comes first.
460    All of the characters must be printable or whitespace. */
461
462 #if !defined (isspace)
463 #define isspace(c) ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\f')
464 #endif
465
466 #if !defined (isprint)
467 #define isprint(c) (isletter(c) || digit(c) || ispunct(c))
468 #endif
469
470 int
471 check_binary_file (sample, sample_len)
472      unsigned char *sample;
473      int sample_len;
474 {
475   register int i;
476
477   for (i = 0; i < sample_len; i++)
478     {
479       if (sample[i] == '\n')
480         return (0);
481
482       if (isspace (sample[i]) == 0 && isprint (sample[i]) == 0)
483         return (1);
484     }
485
486   return (0);
487 }
488
489 /* **************************************************************** */
490 /*                                                                  */
491 /*                  Functions to manipulate pathnames               */
492 /*                                                                  */
493 /* **************************************************************** */
494
495 /* Return 1 if PATH corresponds to a directory. */
496 static int
497 canon_stat (path)
498      char *path;
499 {
500   int l;
501   char *s;
502   struct stat sb;
503
504   l = strlen (path);
505   s = xmalloc (l + 3);
506   strcpy (s, path);
507   s[l] = '/';
508   s[l+1] = '.';
509   s[l+2] = '\0';
510   l = stat (s, &sb) == 0 && S_ISDIR (sb.st_mode);
511   free (s);
512   return l;
513 }
514
515 /* Canonicalize PATH, and return a new path.  The new path differs from PATH
516    in that:
517         Multple `/'s are collapsed to a single `/'.
518         Leading `./'s and trailing `/.'s are removed.
519         Trailing `/'s are removed.
520         Non-leading `../'s and trailing `..'s are handled by removing
521         portions of the path. */
522 char *
523 canonicalize_pathname (path)
524      char *path;
525 {
526   register int i, start;
527   char stub_char;
528   char *result;
529
530   /* The result cannot be larger than the input PATH. */
531   result = savestring (path);
532
533   stub_char = (*path == '/') ? '/' : '.';
534
535   /* Walk along RESULT looking for things to compact. */
536   i = 0;
537   while (1)
538     {
539       if (!result[i])
540         break;
541
542       while (result[i] && result[i] != '/')
543         i++;
544
545       start = i++;
546
547       /* If we didn't find any slashes, then there is nothing left to do. */
548       if (!result[start])
549         break;
550
551       /* Handle multiple `/'s in a row. */
552       while (result[i] == '/')
553         i++;
554
555 #if 0
556       if ((start + 1) != i)
557 #else
558       /* Leave a leading `//' alone, as POSIX requires. */
559       if ((start + 1) != i && (start != 0 || i != 2))
560 #endif
561         {
562           strcpy (result + start + 1, result + i);
563           i = start + 1;
564           /* Make sure that what we have so far corresponds to a directory.
565              If it does not, just punt. */
566           if (*result)
567             {
568               char c;
569               c = result[start];
570               result[start] = '\0';
571               if (canon_stat (result) == 0)
572                 {
573                   free (result);
574                   return ((char *)NULL);
575                 }
576               result[start] = c;
577             }
578         }
579 #if 0
580       /* Handle backslash-quoted `/'. */
581       if (start > 0 && result[start - 1] == '\\')
582         continue;
583 #endif
584
585       /* Check for trailing `/'. */
586       if (start && !result[i])
587         {
588         zero_last:
589           result[--i] = '\0';
590           break;
591         }
592
593       /* Check for `../', `./' or trailing `.' by itself. */
594       if (result[i] == '.')
595         {
596           /* Handle trailing `.' by itself. */
597           if (!result[i + 1])
598             goto zero_last;
599
600           /* Handle `./'. */
601           if (result[i + 1] == '/')
602             {
603               strcpy (result + i, result + i + 1);
604               i = (start < 0) ? 0 : start;
605               continue;
606             }
607
608           /* Handle `../' or trailing `..' by itself. */
609           if (result[i + 1] == '.' &&
610               (result[i + 2] == '/' || !result[i + 2]))
611             {
612               /* Make sure that the last component corresponds to a directory
613                  before blindly chopping it off. */
614               if (i)
615                 {
616                   result[i] = '\0';
617                   if (canon_stat (result) == 0)
618                     {
619                       free (result);
620                       return ((char *)NULL);
621                     }
622                   result[i] = '.';
623                 }
624               while (--start > -1 && result[start] != '/');
625               strcpy (result + start + 1, result + i + 2);
626 #if 0   /* Unnecessary */
627               if (*result && canon_stat (result) == 0)
628                 {
629                   free (result);
630                   return ((char *)NULL);
631                 }
632 #endif
633               i = (start < 0) ? 0 : start;
634               continue;
635             }
636         }
637     }
638
639   if (!*result)
640     {
641       *result = stub_char;
642       result[1] = '\0';
643     }
644
645   /* If the result starts with `//', but the original path does not, we
646      can turn the // into /. */
647   if ((result[0] == '/' && result[1] == '/' && result[2] != '/') &&
648       (path[0] != '/' || path[1] != '/' || path[2] == '/'))
649     {
650       char *r2;
651       if (result[2] == '\0')    /* short-circuit for bare `//' */
652         result[1] = '\0';
653       else
654         {
655           r2 = savestring (result + 1);
656           free (result);
657           result = r2;
658         }
659     }
660
661   return (result);
662 }
663
664 /* Turn STRING (a pathname) into an absolute pathname, assuming that
665    DOT_PATH contains the symbolic location of `.'.  This always
666    returns a new string, even if STRING was an absolute pathname to
667    begin with. */
668 char *
669 make_absolute (string, dot_path)
670      char *string, *dot_path;
671 {
672   char *result;
673   int result_len;
674
675   if (dot_path == 0 || *string == '/')
676     result = savestring (string);
677   else
678     {
679       if (dot_path[0])
680         {
681           result_len = strlen (dot_path);
682           result = xmalloc (2 + result_len + strlen (string));
683           strcpy (result, dot_path);
684           if (result[result_len - 1] != '/')
685             {
686               result[result_len++] = '/';
687               result[result_len] = '\0';
688             }
689         }
690       else
691         {
692           result = xmalloc (3 + strlen (string));
693           result[0] = '.'; result[1] = '/'; result[2] = '\0';
694           result_len = 2;
695         }
696
697       strcpy (result + result_len, string);
698     }
699
700   return (result);
701 }
702
703 /* Return 1 if STRING contains an absolute pathname, else 0. */
704 int
705 absolute_pathname (string)
706      char *string;
707 {
708   if (!string || !*string)
709     return (0);
710
711   if (*string == '/')
712     return (1);
713
714   if (*string++ == '.')
715     {
716       if (!*string || *string == '/' ||
717            (*string == '.' && (string[1] == '\0' || string[1] == '/')))
718         return (1);
719     }
720   return (0);
721 }
722
723 /* Return 1 if STRING is an absolute program name; it is absolute if it
724    contains any slashes.  This is used to decide whether or not to look
725    up through $PATH. */
726 int
727 absolute_program (string)
728      char *string;
729 {
730   return ((char *)strchr (string, '/') != (char *)NULL);
731 }
732
733 /* Return the `basename' of the pathname in STRING (the stuff after the
734    last '/').  If STRING is not a full pathname, simply return it. */
735 char *
736 base_pathname (string)
737      char *string;
738 {
739   char *p;
740
741   if (!absolute_pathname (string))
742     return (string);
743
744   p = (char *)strrchr (string, '/');
745   return (p ? ++p : string);
746 }
747
748 /* Return the full pathname of FILE.  Easy.  Filenames that begin
749    with a '/' are returned as themselves.  Other filenames have
750    the current working directory prepended.  A new string is
751    returned in either case. */
752 char *
753 full_pathname (file)
754      char *file;
755 {
756   char *disposer;
757   char *current_dir;
758   int dlen;
759
760   file = (*file == '~') ? bash_tilde_expand (file) : savestring (file);
761
762   if ((*file == '/') && absolute_pathname (file))
763     return (file);
764
765   disposer = file;
766
767   /* XXX - this should probably be just PATH_MAX or PATH_MAX + 1 */
768   current_dir = xmalloc (2 + PATH_MAX + strlen (file));
769   if (getcwd (current_dir, PATH_MAX) == 0)
770     {
771       sys_error (bash_getcwd_errstr);
772       free (disposer);
773       free (current_dir);
774       return ((char *)NULL);
775     }
776   dlen = strlen (current_dir);
777   if (current_dir[0] == '/' && dlen > 1)
778     current_dir[dlen++] = '/';
779
780   /* Turn /foo/./bar into /foo/bar. */
781   if (file[0] == '.' && file[1] == '/')
782     file += 2;
783
784   strcpy (current_dir + dlen, file);
785   free (disposer);
786   return (current_dir);
787 }
788
789 /* A slightly related function.  Get the prettiest name of this
790    directory possible. */
791 static char tdir[PATH_MAX];
792
793 /* Return a pretty pathname.  If the first part of the pathname is
794    the same as $HOME, then replace that with `~'.  */
795 char *
796 polite_directory_format (name)
797      char *name;
798 {
799   char *home;
800   int l;
801
802   home = get_string_value ("HOME");
803   l = home ? strlen (home) : 0;
804   if (l > 1 && strncmp (home, name, l) == 0 && (!name[l] || name[l] == '/'))
805     {
806       strncpy (tdir + 1, name + l, sizeof(tdir) - 2);
807       tdir[0] = '~';
808       tdir[sizeof(tdir) - 1] = '\0';
809       return (tdir);
810     }
811   else
812     return (name);
813 }
814
815 /* Given a string containing units of information separated by colons,
816    return the next one pointed to by (P_INDEX), or NULL if there are no more.
817    Advance (P_INDEX) to the character after the colon. */
818 char *
819 extract_colon_unit (string, p_index)
820      char *string;
821      int *p_index;
822 {
823   int i, start, len;
824   char *value;
825
826   if (string == 0)
827     return (string);
828
829   len = strlen (string);
830   if (*p_index >= len)
831     return ((char *)NULL);
832
833   i = *p_index;
834
835   /* Each call to this routine leaves the index pointing at a colon if
836      there is more to the path.  If I is > 0, then increment past the
837      `:'.  If I is 0, then the path has a leading colon.  Trailing colons
838      are handled OK by the `else' part of the if statement; an empty
839      string is returned in that case. */
840   if (i && string[i] == ':')
841     i++;
842
843   for (start = i; string[i] && string[i] != ':'; i++)
844     ;
845
846   *p_index = i;
847
848   if (i == start)
849     {
850       if (string[i])
851         (*p_index)++;
852       /* Return "" in the case of a trailing `:'. */
853       value = xmalloc (1);
854       value[0] = '\0';
855     }
856   else
857     {
858       len = i - start;
859       value = xmalloc (1 + len);
860       strncpy (value, string + start, len);
861       value [len] = '\0';
862     }
863
864   return (value);
865 }
866
867 /* **************************************************************** */
868 /*                                                                  */
869 /*                  Tilde Initialization and Expansion              */
870 /*                                                                  */
871 /* **************************************************************** */
872
873 #if defined (PUSHD_AND_POPD)
874 extern char *get_dirstack_from_string __P((char *));
875 #endif
876
877 /* If tilde_expand hasn't been able to expand the text, perhaps it
878    is a special shell expansion.  This function is installed as the
879    tilde_expansion_preexpansion_hook.  It knows how to expand ~- and ~+.
880    If PUSHD_AND_POPD is defined, ~[+-]N expands to directories from the
881    directory stack. */
882 static char *
883 bash_special_tilde_expansions (text)
884      char *text;
885 {
886   char *result;
887
888   result = (char *)NULL;
889
890   if (text[0] == '+' && text[1] == '\0')
891     result = get_string_value ("PWD");
892   else if (text[0] == '-' && text[1] == '\0')
893     result = get_string_value ("OLDPWD");
894 #if defined (PUSHD_AND_POPD)
895   else if (isdigit (*text) || ((*text == '+' || *text == '-') && isdigit (text[1])))
896     result = get_dirstack_from_string (text);
897 #endif
898
899   return (result ? savestring (result) : (char *)NULL);
900 }
901
902 /* Initialize the tilde expander.  In Bash, we handle `~-' and `~+', as
903    well as handling special tilde prefixes; `:~" and `=~' are indications
904    that we should do tilde expansion. */
905 void
906 tilde_initialize ()
907 {
908   static int times_called = 0;
909
910   /* Tell the tilde expander that we want a crack first. */
911   tilde_expansion_preexpansion_hook = (CPFunction *)bash_special_tilde_expansions;
912
913   /* Tell the tilde expander about special strings which start a tilde
914      expansion, and the special strings that end one.  Only do this once.
915      tilde_initialize () is called from within bashline_reinitialize (). */
916   if (times_called++ == 0)
917     {
918       tilde_additional_prefixes = (char **)xmalloc (3 * sizeof (char *));
919       tilde_additional_prefixes[0] = "=~";
920       tilde_additional_prefixes[1] = ":~";
921       tilde_additional_prefixes[2] = (char *)NULL;
922
923       tilde_additional_suffixes = (char **)xmalloc (3 * sizeof (char *));
924       tilde_additional_suffixes[0] = ":";
925       tilde_additional_suffixes[1] = "=~";
926       tilde_additional_suffixes[2] = (char *)NULL;
927     }
928 }
929
930 char *
931 bash_tilde_expand (s)
932      char *s;
933 {
934   int old_immed;
935   char *ret;
936
937   old_immed = interrupt_immediately;
938   interrupt_immediately = 1;
939   ret = tilde_expand (s);
940   interrupt_immediately = old_immed;
941   return (ret);
942 }
943
944 /* **************************************************************** */
945 /*                                                                  */
946 /*        Functions to manipulate and search the group list         */
947 /*                                                                  */
948 /* **************************************************************** */
949
950 static int ngroups, maxgroups;
951
952 /* The set of groups that this user is a member of. */
953 static GETGROUPS_T *group_array = (GETGROUPS_T *)NULL;
954
955 #if !defined (NOGROUP)
956 #  define NOGROUP (gid_t) -1
957 #endif
958
959 #if defined (HAVE_SYSCONF) && defined (_SC_NGROUPS_MAX)
960 #  define getmaxgroups() sysconf(_SC_NGROUPS_MAX)
961 #else
962 #  if defined (NGROUPS_MAX)
963 #    define getmaxgroups() NGROUPS_MAX
964 #  else /* !NGROUPS_MAX */
965 #    if defined (NGROUPS)
966 #      define getmaxgroups() NGROUPS
967 #    else /* !NGROUPS */
968 #      define getmaxgroups() 64
969 #    endif /* !NGROUPS */
970 #  endif /* !NGROUPS_MAX */
971 #endif /* !HAVE_SYSCONF || !SC_NGROUPS_MAX */
972
973 static void
974 initialize_group_array ()
975 {
976   register int i;
977
978   if (maxgroups == 0)
979     maxgroups = getmaxgroups ();
980
981   ngroups = 0;
982   group_array = (GETGROUPS_T *)xrealloc (group_array, maxgroups * sizeof (GETGROUPS_T));
983
984 #if defined (HAVE_GETGROUPS)
985   ngroups = getgroups (maxgroups, group_array);
986 #endif
987
988   /* If getgroups returns nothing, or the OS does not support getgroups(),
989      make sure the groups array includes at least the current gid. */
990   if (ngroups == 0)
991     {
992       group_array[0] = current_user.gid;
993       ngroups = 1;
994     }
995
996   /* If the primary group is not in the groups array, add it as group_array[0]
997      and shuffle everything else up 1, if there's room. */
998   for (i = 0; i < ngroups; i++)
999     if (current_user.gid == (gid_t)group_array[i])
1000       break;
1001   if (i == ngroups && ngroups < maxgroups)
1002     {
1003       for (i = ngroups; i > 0; i--)
1004         group_array[i] = group_array[i - 1];
1005       group_array[0] = current_user.gid;
1006       ngroups++;
1007     }
1008
1009   /* If the primary group is not group_array[0], swap group_array[0] and
1010      whatever the current group is.  The vast majority of systems should
1011      not need this; a notable exception is Linux. */
1012   if (group_array[0] != current_user.gid)
1013     {
1014       for (i = 0; i < ngroups; i++)
1015         if (group_array[i] == current_user.gid)
1016           break;
1017       if (i < ngroups)
1018         {
1019           group_array[i] = group_array[0];
1020           group_array[0] = current_user.gid;
1021         }
1022     }
1023 }
1024
1025 /* Return non-zero if GID is one that we have in our groups list. */
1026 int
1027 #if defined (__STDC__) || defined ( _MINIX)
1028 group_member (gid_t gid)
1029 #else
1030 group_member (gid)
1031      gid_t gid;
1032 #endif /* !__STDC__ && !_MINIX */
1033 {
1034 #if defined (HAVE_GETGROUPS)
1035   register int i;
1036 #endif
1037
1038   /* Short-circuit if possible, maybe saving a call to getgroups(). */
1039   if (gid == current_user.gid || gid == current_user.egid)
1040     return (1);
1041
1042 #if defined (HAVE_GETGROUPS)
1043   if (ngroups == 0)
1044     initialize_group_array ();
1045
1046   /* In case of error, the user loses. */
1047   if (ngroups <= 0)
1048     return (0);
1049
1050   /* Search through the list looking for GID. */
1051   for (i = 0; i < ngroups; i++)
1052     if (gid == (gid_t)group_array[i])
1053       return (1);
1054 #endif
1055
1056   return (0);
1057 }
1058
1059 char **
1060 get_group_list (ngp)
1061      int *ngp;
1062 {
1063   static char **group_vector = (char **)NULL;
1064   register int i;
1065   char *nbuf;
1066
1067   if (group_vector)
1068     {
1069       if (ngp)
1070         *ngp = ngroups;
1071       return group_vector;
1072     }
1073
1074   if (ngroups == 0)
1075     initialize_group_array ();
1076
1077   if (ngroups <= 0)
1078     {
1079       if (ngp)
1080         *ngp = 0;
1081       return (char **)NULL;
1082     }
1083
1084   group_vector = (char **)xmalloc (ngroups * sizeof (char *));
1085   for (i = 0; i < ngroups; i++)
1086     {
1087       nbuf = itos ((int)group_array[i]);
1088       group_vector[i] = nbuf;
1089     }
1090
1091   if (ngp)
1092     *ngp = ngroups;
1093   return group_vector;
1094 }
1095
1096 int *
1097 get_group_array (ngp)
1098      int *ngp;
1099 {
1100   int i;
1101   static int *group_iarray = (int *)NULL;
1102
1103   if (group_iarray)
1104     {
1105       if (ngp)
1106         *ngp = ngroups;
1107       return (group_iarray);
1108     }
1109
1110   if (ngroups == 0)
1111     initialize_group_array ();    
1112
1113   if (ngroups <= 0)
1114     {
1115       if (ngp)
1116         *ngp = 0;
1117       return (int *)NULL;
1118     }
1119
1120   group_iarray = (int *)xmalloc (ngroups * sizeof (int));
1121   for (i = 0; i < ngroups; i++)
1122     group_iarray[i] = (int)group_array[i];
1123
1124   if (ngp)
1125     *ngp = ngroups;
1126   return group_iarray;
1127 }