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