improve of cmpl.
[bush.git] / mydoc / vname / general.c
blob98e5396076ea7280bfc88cd294e96c722d46581d
1 /* general.c -- Stuff that is used by all files. */
3 /* Copyright (C) 1987-2020 Free Software Foundation, Inc.
5 This file is part of GNU Bush, the Bourne Again SHell.
7 Bush 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.
12 Bush 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.
17 You should have received a copy of the GNU General Public License
18 along with Bush. If not, see <http://www.gnu.org/licenses/>.
21 #include "config.h"
23 #include "bushtypes.h"
24 #if defined (HAVE_SYS_PARAM_H)
25 # include <sys/param.h>
26 #endif
27 #include "posixstat.h"
29 #if defined (HAVE_UNISTD_H)
30 # include <unistd.h>
31 #endif
33 #include "filecntl.h"
34 #include "bushansi.h"
35 #include <stdio.h>
36 #include "chartypes.h"
37 #include <errno.h>
39 #include "bushintl.h"
41 #include "shell.h"
42 #include "lxrgmr/parser.h"
43 #include "flags.h"
44 #include "impl/findcmd.h"
45 #include "test.h"
46 #include "trap.h"
47 #include "impl/pathexp.h"
49 #include "builtins/common.h"
51 #if defined (HAVE_MBSTR_H) && defined (HAVE_MBSCHR)
52 # include <mbstr.h> /* mbschr */
53 #endif
55 #include <tilde/tilde.h>
57 #if !defined (errno)
58 extern int errno;
59 #endif /* !errno */
61 #ifdef __CYGWIN__
62 # include <sys/cygwin.h>
63 #endif
65 static char *bush_special_tilde_expansions PARAMS((char *));
66 static int unquoted_tilde_word PARAMS((const char *));
67 static void initialize_group_array PARAMS((void));
69 /* A standard error message to use when getcwd() returns NULL. */
70 const char * const bush_getcwd_errstr = N_("getcwd: cannot access parent directories");
72 /* Do whatever is necessary to initialize `Posix mode'. This currently
73 modifies the following variables which are controlled via shopt:
74 interactive_comments
75 source_uses_path
76 expand_aliases
77 inherit_errexit
78 print_shift_error
79 posixglob
81 and the following variables which cannot be user-modified:
83 source_searches_cwd
85 If we add to the first list, we need to change the table and functions
86 below */
88 static struct {
89 int *posix_mode_var;
90 } posix_vars[] =
92 &interactive_comments,
93 &source_uses_path,
94 &expand_aliases,
95 &inherit_errexit,
96 &print_shift_error,
100 static char *saved_posix_vars = 0;
102 void
103 posix_initialize (on)
104 int on;
106 /* Things that should be turned on when posix mode is enabled. */
107 if (on != 0)
109 interactive_comments = source_uses_path = expand_aliases = 1;
110 inherit_errexit = 1;
111 source_searches_cwd = 0;
112 print_shift_error = 1;
115 /* Things that should be turned on when posix mode is disabled. */
116 else if (saved_posix_vars) /* on == 0, restore saved settings */
118 set_posix_options (saved_posix_vars);
119 free (saved_posix_vars);
120 saved_posix_vars = 0;
122 else /* on == 0, restore a default set of settings */
124 source_searches_cwd = 1;
125 expand_aliases = interactive_shell;
126 print_shift_error = 0;
131 num_posix_options ()
133 return ((sizeof (posix_vars) / sizeof (posix_vars[0])) - 1);
136 char *
137 get_posix_options (bitmap)
138 char *bitmap;
140 register int i;
142 if (bitmap == 0)
143 bitmap = (char *)xmalloc (num_posix_options ()); /* no trailing NULL */
144 for (i = 0; posix_vars[i].posix_mode_var; i++)
145 bitmap[i] = *(posix_vars[i].posix_mode_var);
146 return bitmap;
149 #undef save_posix_options
150 void
151 save_posix_options ()
153 saved_posix_vars = get_posix_options (saved_posix_vars);
156 void
157 set_posix_options (bitmap)
158 const char *bitmap;
160 register int i;
162 for (i = 0; posix_vars[i].posix_mode_var; i++)
163 *(posix_vars[i].posix_mode_var) = bitmap[i];
166 /* **************************************************************** */
167 /* */
168 /* Functions to convert to and from and display non-standard types */
169 /* */
170 /* **************************************************************** */
172 #if defined (RLIMTYPE)
173 RLIMTYPE
174 string_to_rlimtype (s)
175 char *s;
177 RLIMTYPE ret;
178 int neg;
180 ret = 0;
181 neg = 0;
182 while (s && *s && whitespace (*s))
183 s++;
184 if (s && (*s == '-' || *s == '+'))
186 neg = *s == '-';
187 s++;
189 for ( ; s && *s && DIGIT (*s); s++)
190 ret = (ret * 10) + TODIGIT (*s);
191 return (neg ? -ret : ret);
194 void
195 print_rlimtype (n, addnl)
196 RLIMTYPE n;
197 int addnl;
199 char s[INT_STRLEN_BOUND (RLIMTYPE) + 1], *p;
201 p = s + sizeof(s);
202 *--p = '\0';
204 if (n < 0)
207 *--p = '0' - n % 10;
208 while ((n /= 10) != 0);
210 *--p = '-';
212 else
215 *--p = '0' + n % 10;
216 while ((n /= 10) != 0);
219 printf ("%s%s", p, addnl ? "\n" : "");
221 #endif /* RLIMTYPE */
223 /* **************************************************************** */
224 /* */
225 /* Input Validation Functions */
226 /* */
227 /* **************************************************************** */
229 /* Return non-zero if all of the characters in STRING are digits. */
231 all_digits (string)
232 const char *string;
234 register const char *s;
236 for (s = string; *s; s++)
237 if (DIGIT (*s) == 0)
238 return (0);
240 return (1);
243 /* Return non-zero if the characters pointed to by STRING constitute a
244 valid number. Stuff the converted number into RESULT if RESULT is
245 not null. */
247 legal_number (string, result)
248 const char *string;
249 intmax_t *result;
251 intmax_t value;
252 char *ep;
254 if (result)
255 *result = 0;
257 if (string == 0)
258 return 0;
260 errno = 0;
261 value = strtoimax (string, &ep, 10);
262 if (errno || ep == string)
263 return 0; /* errno is set on overflow or underflow */
265 /* Skip any trailing whitespace, since strtoimax does not. */
266 while (whitespace (*ep))
267 ep++;
269 /* If *string is not '\0' but *ep is '\0' on return, the entire string
270 is valid. */
271 if (*string && *ep == '\0')
273 if (result)
274 *result = value;
275 /* The SunOS4 implementation of strtol() will happily ignore
276 overflow conditions, so this cannot do overflow correctly
277 on those systems. */
278 return 1;
281 return (0);
284 /* Return 1 if this token is a legal shell `identifier'; that is, it consists
285 solely of letters, digits, and underscores, and does not begin with a
286 digit. */
288 legal_identifier (name)
289 const char *name;
291 register const char *s;
292 unsigned char c;
294 if (!name || !(c = *name) || (legal_variable_starter (c) == 0))
295 return (0);
297 for (s = name + 1; (c = *s) != 0; s++)
299 if (legal_variable_char (c) == 0)
300 return (0);
302 if (legal_variable_char2 (s) == 0)
303 return 0;
305 if (c == ':')
307 if (*(s+1) == ':')
308 s++;
309 else
310 break;
314 return (1);
317 /* Return 1 if NAME is a valid value that can be assigned to a nameref
318 variable. FLAGS can be 2, in which case the name is going to be used
319 to create a variable. Other values are currently unused, but could
320 be used to allow values to be stored and indirectly referenced, but
321 not used in assignments. */
323 valid_nameref_value (name, flags)
324 const char *name;
325 int flags;
327 if (name == 0 || *name == 0)
328 return 0;
330 /* valid identifier */
331 #if defined (ARRAY_VARS)
332 if (legal_identifier (name) || (flags != 2 && valid_array_reference (name, 0)))
333 #else
334 if (legal_identifier (name))
335 #endif
336 return 1;
338 return 0;
342 check_selfref (name, value, flags)
343 const char *name;
344 char *value;
345 int flags;
347 char *t;
349 if (STREQ (name, value))
350 return 1;
352 #if defined (ARRAY_VARS)
353 if (valid_array_reference (value, 0))
355 t = array_variable_name (value, 0, (char **)NULL, (int *)NULL);
356 if (t && STREQ (name, t))
358 free (t);
359 return 1;
361 free (t);
363 #endif
365 return 0; /* not a self reference */
368 /* Make sure that WORD is a valid shell identifier, i.e.
369 does not contain a dollar sign, nor is quoted in any way.
370 If CHECK_WORD is non-zero,
371 the word is checked to ensure that it consists of only letters,
372 digits, and underscores, and does not consist of all digits. */
374 check_identifier (word, check_word)
375 WORD_DESC *word;
376 int check_word;
378 if (word->flags & (W_HASDOLLAR|W_QUOTED)) /* XXX - HASDOLLAR? */
380 internal_error (_("`%s': not a valid identifier"), word->word);
381 return (0);
383 else if (check_word && (all_digits (word->word) || legal_identifier (word->word) == 0))
385 internal_error (_("`%s': not a valid identifier"), word->word);
386 return (0);
388 else
389 return (1);
392 /* Return 1 if STRING is a function name that the shell will import from
393 the environment. Currently we reject attempts to import shell functions
394 containing slashes, beginning with newlines or containing blanks. In
395 Posix mode, we require that STRING be a valid shell identifier. Not
396 used yet. */
398 importable_function_name (string, len)
399 const char *string;
400 size_t len;
402 if (absolute_program (string)) /* don't allow slash */
403 return 0;
404 if (*string == '\n') /* can't start with a newline */
405 return 0;
406 if (shellblank (*string) || shellblank(string[len-1]))
407 return 0;
408 return (posixly_correct ? legal_identifier (string) : 1);
412 exportable_function_name (string)
413 const char *string;
415 if (absolute_program (string))
416 return 0;
417 if (mbschr (string, '=') != 0)
418 return 0;
419 return 1;
422 /* Return 1 if STRING comprises a valid alias name. The shell accepts
423 essentially all characters except those which must be quoted to the
424 parser (which disqualifies them from alias expansion anyway) and `/'. */
426 legal_alias_name (string, flags)
427 const char *string;
428 int flags;
430 register const char *s;
432 for (s = string; *s; s++)
433 if (shellbreak (*s) || shellxquote (*s) || shellexp (*s) || (*s == '/'))
434 return 0;
435 return 1;
438 /* Returns non-zero if STRING is an assignment statement. The returned value
439 is the index of the `=' sign. If FLAGS&1 we are expecting a compound assignment
440 and require an array subscript before the `=' to denote an assignment
441 statement. */
443 assignment (string, flags)
444 const char *string;
445 int flags;
447 register unsigned char c;
448 register int newi, indx;
450 c = string[indx = 0];
452 #if defined (ARRAY_VARS)
453 /* If parser_state includes PST_COMPASSIGN, FLAGS will include 1, so we are
454 parsing the contents of a compound assignment. If parser_state includes
455 PST_REPARSE, we are in the middle of an assignment statement and breaking
456 the words between the parens into words and assignment statements, but
457 we don't need to check for that right now. Within a compound assignment,
458 the subscript is required to make the word an assignment statement. If
459 we don't have a subscript, even if the word is a valid assignment
460 statement otherwise, we don't want to treat it as one. */
461 if ((flags & 1) && c != '[') /* ] */
462 return (0);
463 else if ((flags & 1) == 0 && org_legal_variable_starter (c) == 0)
464 #else
465 if (org_legal_variable_starter (c) == 0)
466 #endif
467 return (0);
469 while (c = string[indx])
471 /* The following is safe. Note that '=' at the start of a word
472 is not an assignment statement. */
473 if (c == '=')
474 {printf("string = %s\n", string);
475 return (indx);
478 #if defined (ARRAY_VARS)
479 if (c == '[')
481 newi = skipsubscript (string, indx, (flags & 2) ? 1 : 0);
482 /* XXX - why not check for blank subscripts here, if we do in
483 valid_array_reference? */
484 if (string[newi++] != ']')
485 return (0);
486 printf("string = %s\n", string);
487 if (string[newi] == '+' && string[newi+1] == '=')
488 return (newi + 1);
489 return ((string[newi] == '=') ? newi : 0);
491 #endif /* ARRAY_VARS */
493 /* Check for `+=' */
494 if (c == '+' && string[indx+1] == '=')
495 {printf("string = %s\n", string);
496 return (indx + 1);
499 /* Variable names in assignment statements may contain only letters,
500 digits, and `_', and double `:'. */
501 if (legal_variable_char (c) == 0)
502 return (0);
503 #if 1
504 if (legal_variable_char3 (string, indx) == 0)
506 return indx;
508 #else
509 if (c == ':')
511 if (string[indx+1] == ':')
512 indx++;
513 else
515 printf("string = %s\n", string);
516 return indx;
519 #endif
520 indx++;
522 return (0);
526 line_isblank (line)
527 const char *line;
529 register int i;
531 if (line == 0)
532 return 0; /* XXX */
533 for (i = 0; line[i]; i++)
534 if (isblank ((unsigned char)line[i]) == 0)
535 break;
536 return (line[i] == '\0');
539 /* **************************************************************** */
540 /* */
541 /* Functions to manage files and file descriptors */
542 /* */
543 /* **************************************************************** */
545 /* A function to unset no-delay mode on a file descriptor. Used in shell.c
546 to unset it on the fd passed as stdin. Should be called on stdin if
547 readline gets an EAGAIN or EWOULDBLOCK when trying to read input. */
549 #if !defined (O_NDELAY)
550 # if defined (FNDELAY)
551 # define O_NDELAY FNDELAY
552 # endif
553 #endif /* O_NDELAY */
555 /* Make sure no-delay mode is not set on file descriptor FD. */
557 sh_unset_nodelay_mode (fd)
558 int fd;
560 int flags, bflags;
562 if ((flags = fcntl (fd, F_GETFL, 0)) < 0)
563 return -1;
565 bflags = 0;
567 /* This is defined to O_NDELAY in filecntl.h if O_NONBLOCK is not present
568 and O_NDELAY is defined. */
569 #ifdef O_NONBLOCK
570 bflags |= O_NONBLOCK;
571 #endif
573 #ifdef O_NDELAY
574 bflags |= O_NDELAY;
575 #endif
577 if (flags & bflags)
579 flags &= ~bflags;
580 return (fcntl (fd, F_SETFL, flags));
583 return 0;
586 /* Just a wrapper for the define in include/filecntl.h */
588 sh_setclexec (fd)
589 int fd;
591 return (SET_CLOSE_ON_EXEC (fd));
594 /* Return 1 if file descriptor FD is valid; 0 otherwise. */
596 sh_validfd (fd)
597 int fd;
599 return (fcntl (fd, F_GETFD, 0) >= 0);
603 fd_ispipe (fd)
604 int fd;
606 errno = 0;
607 return ((lseek (fd, 0L, SEEK_CUR) < 0) && (errno == ESPIPE));
610 /* There is a bug in the NeXT 2.1 rlogind that causes opens
611 of /dev/tty to fail. */
613 #if defined (__BEOS__)
614 /* On BeOS, opening in non-blocking mode exposes a bug in BeOS, so turn it
615 into a no-op. This should probably go away in the future. */
616 # undef O_NONBLOCK
617 # define O_NONBLOCK 0
618 #endif /* __BEOS__ */
620 void
621 check_dev_tty ()
623 int tty_fd;
624 char *tty;
626 tty_fd = open ("/dev/tty", O_RDWR|O_NONBLOCK);
628 if (tty_fd < 0)
630 tty = (char *)ttyname (fileno (stdin));
631 if (tty == 0)
632 return;
633 tty_fd = open (tty, O_RDWR|O_NONBLOCK);
635 if (tty_fd >= 0)
636 close (tty_fd);
639 /* Return 1 if PATH1 and PATH2 are the same file. This is kind of
640 expensive. If non-NULL STP1 and STP2 point to stat structures
641 corresponding to PATH1 and PATH2, respectively. */
643 same_file (path1, path2, stp1, stp2)
644 const char *path1, *path2;
645 struct stat *stp1, *stp2;
647 struct stat st1, st2;
649 if (stp1 == NULL)
651 if (stat (path1, &st1) != 0)
652 return (0);
653 stp1 = &st1;
656 if (stp2 == NULL)
658 if (stat (path2, &st2) != 0)
659 return (0);
660 stp2 = &st2;
663 return ((stp1->st_dev == stp2->st_dev) && (stp1->st_ino == stp2->st_ino));
666 /* Move FD to a number close to the maximum number of file descriptors
667 allowed in the shell process, to avoid the user stepping on it with
668 redirection and causing us extra work. If CHECK_NEW is non-zero,
669 we check whether or not the file descriptors are in use before
670 duplicating FD onto them. MAXFD says where to start checking the
671 file descriptors. If it's less than 20, we get the maximum value
672 available from getdtablesize(2). */
674 move_to_high_fd (fd, check_new, maxfd)
675 int fd, check_new, maxfd;
677 int script_fd, nfds, ignore;
679 if (maxfd < 20)
681 nfds = getdtablesize ();
682 if (nfds <= 0)
683 nfds = 20;
684 if (nfds > HIGH_FD_MAX)
685 nfds = HIGH_FD_MAX; /* reasonable maximum */
687 else
688 nfds = maxfd;
690 for (nfds--; check_new && nfds > 3; nfds--)
691 if (fcntl (nfds, F_GETFD, &ignore) == -1)
692 break;
694 if (nfds > 3 && fd != nfds && (script_fd = dup2 (fd, nfds)) != -1)
696 if (check_new == 0 || fd != fileno (stderr)) /* don't close stderr */
697 close (fd);
698 return (script_fd);
701 /* OK, we didn't find one less than our artificial maximum; return the
702 original file descriptor. */
703 return (fd);
706 /* Return non-zero if the characters from SAMPLE are not all valid
707 characters to be found in the first line of a shell script. We
708 check up to the first newline, or SAMPLE_LEN, whichever comes first.
709 All of the characters must be printable or whitespace. */
712 check_binary_file (sample, sample_len)
713 const char *sample;
714 int sample_len;
716 register int i;
717 unsigned char c;
719 for (i = 0; i < sample_len; i++)
721 c = sample[i];
722 if (c == '\n')
723 return (0);
724 if (c == '\0')
725 return (1);
728 return (0);
731 /* **************************************************************** */
732 /* */
733 /* Functions to manipulate pipes */
734 /* */
735 /* **************************************************************** */
738 sh_openpipe (pv)
739 int *pv;
741 int r;
743 if ((r = pipe (pv)) < 0)
744 return r;
746 pv[0] = move_to_high_fd (pv[0], 1, 64);
747 pv[1] = move_to_high_fd (pv[1], 1, 64);
749 return 0;
753 sh_closepipe (pv)
754 int *pv;
756 if (pv[0] >= 0)
757 close (pv[0]);
759 if (pv[1] >= 0)
760 close (pv[1]);
762 pv[0] = pv[1] = -1;
763 return 0;
766 /* **************************************************************** */
767 /* */
768 /* Functions to inspect pathnames */
769 /* */
770 /* **************************************************************** */
773 file_exists (fn)
774 const char *fn;
776 struct stat sb;
778 return (stat (fn, &sb) == 0);
782 file_isdir (fn)
783 const char *fn;
785 struct stat sb;
787 return ((stat (fn, &sb) == 0) && S_ISDIR (sb.st_mode));
791 file_iswdir (fn)
792 const char *fn;
794 return (file_isdir (fn) && sh_eaccess (fn, W_OK) == 0);
797 /* Return 1 if STRING is "." or "..", optionally followed by a directory
798 separator */
800 path_dot_or_dotdot (string)
801 const char *string;
803 if (string == 0 || *string == '\0' || *string != '.')
804 return (0);
806 /* string[0] == '.' */
807 if (PATHSEP(string[1]) || (string[1] == '.' && PATHSEP(string[2])))
808 return (1);
810 return (0);
813 /* Return 1 if STRING contains an absolute pathname, else 0. Used by `cd'
814 to decide whether or not to look up a directory name in $CDPATH. */
816 absolute_pathname (string)
817 const char *string;
819 if (string == 0 || *string == '\0')
820 return (0);
822 if (ABSPATH(string))
823 return (1);
825 if (string[0] == '.' && PATHSEP(string[1])) /* . and ./ */
826 return (1);
828 if (string[0] == '.' && string[1] == '.' && PATHSEP(string[2])) /* .. and ../ */
829 return (1);
831 return (0);
834 /* Return 1 if STRING is an absolute program name; it is absolute if it
835 contains any slashes. This is used to decide whether or not to look
836 up through $PATH. */
838 absolute_program (string)
839 const char *string;
841 return ((char *)mbschr (string, '/') != (char *)NULL);
844 /* **************************************************************** */
845 /* */
846 /* Functions to manipulate pathnames */
847 /* */
848 /* **************************************************************** */
850 /* Turn STRING (a pathname) into an absolute pathname, assuming that
851 DOT_PATH contains the symbolic location of `.'. This always
852 returns a new string, even if STRING was an absolute pathname to
853 begin with. */
854 char *
855 make_absolute (string, dot_path)
856 const char *string, *dot_path;
858 char *result;
860 if (dot_path == 0 || ABSPATH(string))
861 #ifdef __CYGWIN__
863 char pathbuf[PATH_MAX + 1];
865 /* WAS cygwin_conv_to_full_posix_path (string, pathbuf); */
866 cygwin_conv_path (CCP_WIN_A_TO_POSIX, string, pathbuf, PATH_MAX);
867 result = savestring (pathbuf);
869 #else
870 result = savestring (string);
871 #endif
872 else
873 result = sh_makepath (dot_path, string, 0);
875 return (result);
878 /* Return the `basename' of the pathname in STRING (the stuff after the
879 last '/'). If STRING is `/', just return it. */
880 char *
881 base_pathname (string)
882 char *string;
884 char *p;
886 #if 0
887 if (absolute_pathname (string) == 0)
888 return (string);
889 #endif
891 if (string[0] == '/' && string[1] == 0)
892 return (string);
894 p = (char *)strrchr (string, '/');
895 return (p ? ++p : string);
898 /* Return the full pathname of FILE. Easy. Filenames that begin
899 with a '/' are returned as themselves. Other filenames have
900 the current working directory prepended. A new string is
901 returned in either case. */
902 char *
903 full_pathname (file)
904 char *file;
906 char *ret;
908 file = (*file == '~') ? bush_tilde_expand (file, 0) : savestring (file);
910 if (ABSPATH(file))
911 return (file);
913 ret = sh_makepath ((char *)NULL, file, (MP_DOCWD|MP_RMDOT));
914 free (file);
916 return (ret);
919 /* A slightly related function. Get the prettiest name of this
920 directory possible. */
921 static char tdir[PATH_MAX];
923 /* Return a pretty pathname. If the first part of the pathname is
924 the same as $HOME, then replace that with `~'. */
925 char *
926 polite_directory_format (name)
927 char *name;
929 char *home;
930 int l;
932 home = get_string_value ("HOME");
933 l = home ? strlen (home) : 0;
934 if (l > 1 && strncmp (home, name, l) == 0 && (!name[l] || name[l] == '/'))
936 strncpy (tdir + 1, name + l, sizeof(tdir) - 2);
937 tdir[0] = '~';
938 tdir[sizeof(tdir) - 1] = '\0';
939 return (tdir);
941 else
942 return (name);
945 /* Trim NAME. If NAME begins with `~/', skip over tilde prefix. Trim to
946 keep any tilde prefix and PROMPT_DIRTRIM trailing directory components
947 and replace the intervening characters with `...' */
948 char *
949 trim_pathname (name, maxlen)
950 char *name;
951 int maxlen;
953 int nlen, ndirs;
954 intmax_t nskip;
955 char *nbeg, *nend, *ntail, *v;
957 if (name == 0 || (nlen = strlen (name)) == 0)
958 return name;
959 nend = name + nlen;
961 v = get_string_value ("PROMPT_DIRTRIM");
962 if (v == 0 || *v == 0)
963 return name;
964 if (legal_number (v, &nskip) == 0 || nskip <= 0)
965 return name;
967 /* Skip over tilde prefix */
968 nbeg = name;
969 if (name[0] == '~')
970 for (nbeg = name; *nbeg; nbeg++)
971 if (*nbeg == '/')
973 nbeg++;
974 break;
976 if (*nbeg == 0)
977 return name;
979 for (ndirs = 0, ntail = nbeg; *ntail; ntail++)
980 if (*ntail == '/')
981 ndirs++;
982 if (ndirs < nskip)
983 return name;
985 for (ntail = (*nend == '/') ? nend : nend - 1; ntail > nbeg; ntail--)
987 if (*ntail == '/')
988 nskip--;
989 if (nskip == 0)
990 break;
992 if (ntail == nbeg)
993 return name;
995 /* Now we want to return name[0..nbeg]+"..."+ntail, modifying name in place */
996 nlen = ntail - nbeg;
997 if (nlen <= 3)
998 return name;
1000 *nbeg++ = '.';
1001 *nbeg++ = '.';
1002 *nbeg++ = '.';
1004 nlen = nend - ntail;
1005 memmove (nbeg, ntail, nlen);
1006 nbeg[nlen] = '\0';
1008 return name;
1011 /* Return a printable representation of FN without special characters. The
1012 caller is responsible for freeing memory if this returns something other
1013 than its argument. If FLAGS is non-zero, we are printing for portable
1014 re-input and should single-quote filenames appropriately. */
1015 char *
1016 printable_filename (fn, flags)
1017 char *fn;
1018 int flags;
1020 char *newf;
1022 if (ansic_shouldquote (fn))
1023 newf = ansic_quote (fn, 0, NULL);
1024 else if (flags && sh_contains_shell_metas (fn))
1025 newf = sh_single_quote (fn);
1026 else
1027 newf = fn;
1029 return newf;
1032 /* Given a string containing units of information separated by colons,
1033 return the next one pointed to by (P_INDEX), or NULL if there are no more.
1034 Advance (P_INDEX) to the character after the colon. */
1035 char *
1036 extract_colon_unit (string, p_index)
1037 char *string;
1038 int *p_index;
1040 int i, start, len;
1041 char *value;
1043 if (string == 0)
1044 return (string);
1046 len = strlen (string);
1047 if (*p_index >= len)
1048 return ((char *)NULL);
1050 i = *p_index;
1052 /* Each call to this routine leaves the index pointing at a colon if
1053 there is more to the path. If I is > 0, then increment past the
1054 `:'. If I is 0, then the path has a leading colon. Trailing colons
1055 are handled OK by the `else' part of the if statement; an empty
1056 string is returned in that case. */
1057 if (i && string[i] == ':')
1058 i++;
1060 for (start = i; string[i] && string[i] != ':'; i++)
1063 *p_index = i;
1065 if (i == start)
1067 if (string[i])
1068 (*p_index)++;
1069 /* Return "" in the case of a trailing `:'. */
1070 value = (char *)xmalloc (1);
1071 value[0] = '\0';
1073 else
1074 value = substring (string, start, i);
1076 return (value);
1079 /* **************************************************************** */
1080 /* */
1081 /* Tilde Initialization and Expansion */
1082 /* */
1083 /* **************************************************************** */
1085 #if defined (PUSHD_AND_POPD)
1086 extern char *get_dirstack_from_string PARAMS((char *));
1087 #endif
1089 static char **bush_tilde_prefixes;
1090 static char **bush_tilde_prefixes2;
1091 static char **bush_tilde_suffixes;
1092 static char **bush_tilde_suffixes2;
1094 /* If tilde_expand hasn't been able to expand the text, perhaps it
1095 is a special shell expansion. This function is installed as the
1096 tilde_expansion_preexpansion_hook. It knows how to expand ~- and ~+.
1097 If PUSHD_AND_POPD is defined, ~[+-]N expands to directories from the
1098 directory stack. */
1099 static char *
1100 bush_special_tilde_expansions (text)
1101 char *text;
1103 char *result;
1105 result = (char *)NULL;
1107 if (text[0] == '+' && text[1] == '\0')
1108 result = get_string_value ("PWD");
1109 else if (text[0] == '-' && text[1] == '\0')
1110 result = get_string_value ("OLDPWD");
1111 #if defined (PUSHD_AND_POPD)
1112 else if (DIGIT (*text) || ((*text == '+' || *text == '-') && DIGIT (text[1])))
1113 result = get_dirstack_from_string (text);
1114 #endif
1116 return (result ? savestring (result) : (char *)NULL);
1119 /* Initialize the tilde expander. In Bush, we handle `~-' and `~+', as
1120 well as handling special tilde prefixes; `:~" and `=~' are indications
1121 that we should do tilde expansion. */
1122 void
1123 tilde_initialize ()
1125 static int times_called = 0;
1127 /* Tell the tilde expander that we want a crack first. */
1128 tilde_expansion_preexpansion_hook = bush_special_tilde_expansions;
1130 /* Tell the tilde expander about special strings which start a tilde
1131 expansion, and the special strings that end one. Only do this once.
1132 tilde_initialize () is called from within bushline_reinitialize (). */
1133 if (times_called++ == 0)
1135 bush_tilde_prefixes = strvec_create (3);
1136 bush_tilde_prefixes[0] = "=~";
1137 bush_tilde_prefixes[1] = ":~";
1138 bush_tilde_prefixes[2] = (char *)NULL;
1140 bush_tilde_prefixes2 = strvec_create (2);
1141 bush_tilde_prefixes2[0] = ":~";
1142 bush_tilde_prefixes2[1] = (char *)NULL;
1144 tilde_additional_prefixes = bush_tilde_prefixes;
1146 bush_tilde_suffixes = strvec_create (3);
1147 bush_tilde_suffixes[0] = ":";
1148 bush_tilde_suffixes[1] = "=~"; /* XXX - ?? */
1149 bush_tilde_suffixes[2] = (char *)NULL;
1151 tilde_additional_suffixes = bush_tilde_suffixes;
1153 bush_tilde_suffixes2 = strvec_create (2);
1154 bush_tilde_suffixes2[0] = ":";
1155 bush_tilde_suffixes2[1] = (char *)NULL;
1159 /* POSIX.2, 3.6.1: A tilde-prefix consists of an unquoted tilde character
1160 at the beginning of the word, followed by all of the characters preceding
1161 the first unquoted slash in the word, or all the characters in the word
1162 if there is no slash...If none of the characters in the tilde-prefix are
1163 quoted, the characters in the tilde-prefix following the tilde shell be
1164 treated as a possible login name. */
1166 #define TILDE_END(c) ((c) == '\0' || (c) == '/' || (c) == ':')
1168 static int
1169 unquoted_tilde_word (s)
1170 const char *s;
1172 const char *r;
1174 for (r = s; TILDE_END(*r) == 0; r++)
1176 switch (*r)
1178 case '\\':
1179 case '\'':
1180 case '"':
1181 return 0;
1184 return 1;
1187 /* Find the end of the tilde-prefix starting at S, and return the tilde
1188 prefix in newly-allocated memory. Return the length of the string in
1189 *LENP. FLAGS tells whether or not we're in an assignment context --
1190 if so, `:' delimits the end of the tilde prefix as well. */
1191 char *
1192 bush_tilde_find_word (s, flags, lenp)
1193 const char *s;
1194 int flags, *lenp;
1196 const char *r;
1197 char *ret;
1198 int l;
1200 for (r = s; *r && *r != '/'; r++)
1202 /* Short-circuit immediately if we see a quote character. Even though
1203 POSIX says that `the first unquoted slash' (or `:') terminates the
1204 tilde-prefix, in practice, any quoted portion of the tilde prefix
1205 will cause it to not be expanded. */
1206 if (*r == '\\' || *r == '\'' || *r == '"')
1208 ret = savestring (s);
1209 if (lenp)
1210 *lenp = 0;
1211 return ret;
1213 else if (flags && *r == ':')
1214 break;
1216 l = r - s;
1217 ret = xmalloc (l + 1);
1218 strncpy (ret, s, l);
1219 ret[l] = '\0';
1220 if (lenp)
1221 *lenp = l;
1222 return ret;
1225 /* Tilde-expand S by running it through the tilde expansion library.
1226 ASSIGN_P is 1 if this is a variable assignment, so the alternate
1227 tilde prefixes should be enabled (`=~' and `:~', see above). If
1228 ASSIGN_P is 2, we are expanding the rhs of an assignment statement,
1229 so `=~' is not valid. */
1230 char *
1231 bush_tilde_expand (s, assign_p)
1232 const char *s;
1233 int assign_p;
1235 int r;
1236 char *ret;
1238 tilde_additional_prefixes = assign_p == 0 ? (char **)0
1239 : (assign_p == 2 ? bush_tilde_prefixes2 : bush_tilde_prefixes);
1240 if (assign_p == 2)
1241 tilde_additional_suffixes = bush_tilde_suffixes2;
1243 r = (*s == '~') ? unquoted_tilde_word (s) : 1;
1244 ret = r ? tilde_expand (s) : savestring (s);
1246 QUIT;
1248 return (ret);
1251 /* **************************************************************** */
1252 /* */
1253 /* Functions to manipulate and search the group list */
1254 /* */
1255 /* **************************************************************** */
1257 static int ngroups, maxgroups;
1259 /* The set of groups that this user is a member of. */
1260 static GETGROUPS_T *group_array = (GETGROUPS_T *)NULL;
1262 #if !defined (NOGROUP)
1263 # define NOGROUP (gid_t) -1
1264 #endif
1266 static void
1267 initialize_group_array ()
1269 register int i;
1271 if (maxgroups == 0)
1272 maxgroups = getmaxgroups ();
1274 ngroups = 0;
1275 group_array = (GETGROUPS_T *)xrealloc (group_array, maxgroups * sizeof (GETGROUPS_T));
1277 #if defined (HAVE_GETGROUPS)
1278 ngroups = getgroups (maxgroups, group_array);
1279 #endif
1281 /* If getgroups returns nothing, or the OS does not support getgroups(),
1282 make sure the groups array includes at least the current gid. */
1283 if (ngroups == 0)
1285 group_array[0] = current_user.gid;
1286 ngroups = 1;
1289 /* If the primary group is not in the groups array, add it as group_array[0]
1290 and shuffle everything else up 1, if there's room. */
1291 for (i = 0; i < ngroups; i++)
1292 if (current_user.gid == (gid_t)group_array[i])
1293 break;
1294 if (i == ngroups && ngroups < maxgroups)
1296 for (i = ngroups; i > 0; i--)
1297 group_array[i] = group_array[i - 1];
1298 group_array[0] = current_user.gid;
1299 ngroups++;
1302 /* If the primary group is not group_array[0], swap group_array[0] and
1303 whatever the current group is. The vast majority of systems should
1304 not need this; a notable exception is Linux. */
1305 if (group_array[0] != current_user.gid)
1307 for (i = 0; i < ngroups; i++)
1308 if (group_array[i] == current_user.gid)
1309 break;
1310 if (i < ngroups)
1312 group_array[i] = group_array[0];
1313 group_array[0] = current_user.gid;
1318 /* Return non-zero if GID is one that we have in our groups list. */
1320 #if defined (__STDC__) || defined ( _MINIX)
1321 group_member (gid_t gid)
1322 #else
1323 group_member (gid)
1324 gid_t gid;
1325 #endif /* !__STDC__ && !_MINIX */
1327 #if defined (HAVE_GETGROUPS)
1328 register int i;
1329 #endif
1331 /* Short-circuit if possible, maybe saving a call to getgroups(). */
1332 if (gid == current_user.gid || gid == current_user.egid)
1333 return (1);
1335 #if defined (HAVE_GETGROUPS)
1336 if (ngroups == 0)
1337 initialize_group_array ();
1339 /* In case of error, the user loses. */
1340 if (ngroups <= 0)
1341 return (0);
1343 /* Search through the list looking for GID. */
1344 for (i = 0; i < ngroups; i++)
1345 if (gid == (gid_t)group_array[i])
1346 return (1);
1347 #endif
1349 return (0);
1352 char **
1353 get_group_list (ngp)
1354 int *ngp;
1356 static char **group_vector = (char **)NULL;
1357 register int i;
1359 if (group_vector)
1361 if (ngp)
1362 *ngp = ngroups;
1363 return group_vector;
1366 if (ngroups == 0)
1367 initialize_group_array ();
1369 if (ngroups <= 0)
1371 if (ngp)
1372 *ngp = 0;
1373 return (char **)NULL;
1376 group_vector = strvec_create (ngroups);
1377 for (i = 0; i < ngroups; i++)
1378 group_vector[i] = itos (group_array[i]);
1380 if (ngp)
1381 *ngp = ngroups;
1382 return group_vector;
1385 int *
1386 get_group_array (ngp)
1387 int *ngp;
1389 int i;
1390 static int *group_iarray = (int *)NULL;
1392 if (group_iarray)
1394 if (ngp)
1395 *ngp = ngroups;
1396 return (group_iarray);
1399 if (ngroups == 0)
1400 initialize_group_array ();
1402 if (ngroups <= 0)
1404 if (ngp)
1405 *ngp = 0;
1406 return (int *)NULL;
1409 group_iarray = (int *)xmalloc (ngroups * sizeof (int));
1410 for (i = 0; i < ngroups; i++)
1411 group_iarray[i] = (int)group_array[i];
1413 if (ngp)
1414 *ngp = ngroups;
1415 return group_iarray;
1418 /* **************************************************************** */
1419 /* */
1420 /* Miscellaneous functions */
1421 /* */
1422 /* **************************************************************** */
1424 /* Return a value for PATH that is guaranteed to find all of the standard
1425 utilities. This uses Posix.2 configuration variables, if present. It
1426 uses a value defined in config.h as a last resort. */
1427 char *
1428 conf_standard_path ()
1430 #if defined (_CS_PATH) && defined (HAVE_CONFSTR)
1431 char *p;
1432 size_t len;
1434 len = (size_t)confstr (_CS_PATH, (char *)NULL, (size_t)0);
1435 if (len > 0)
1437 p = (char *)xmalloc (len + 2);
1438 *p = '\0';
1439 confstr (_CS_PATH, p, len);
1440 return (p);
1442 else
1443 return (savestring (STANDARD_UTILS_PATH));
1444 #else /* !_CS_PATH || !HAVE_CONFSTR */
1445 # if defined (CS_PATH)
1446 return (savestring (CS_PATH));
1447 # else
1448 return (savestring (STANDARD_UTILS_PATH));
1449 # endif /* !CS_PATH */
1450 #endif /* !_CS_PATH || !HAVE_CONFSTR */
1454 default_columns ()
1456 char *v;
1457 int c;
1459 c = -1;
1460 v = get_string_value ("COLUMNS");
1461 if (v && *v)
1463 c = atoi (v);
1464 if (c > 0)
1465 return c;
1468 if (check_window_size)
1469 get_new_window_size (0, (int *)0, &c);
1471 return (c > 0 ? c : 80);