improve of cmpl.
[bush.git] / mydoc / var-name / general.c
blobe85a0746e51cce3505c8617bd00ebf22641a6a50
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);
301 if (c == ':')
303 if (*(s+1) == ':')
304 s++;
305 else
306 break;
309 return (1);
312 /* Return 1 if NAME is a valid value that can be assigned to a nameref
313 variable. FLAGS can be 2, in which case the name is going to be used
314 to create a variable. Other values are currently unused, but could
315 be used to allow values to be stored and indirectly referenced, but
316 not used in assignments. */
318 valid_nameref_value (name, flags)
319 const char *name;
320 int flags;
322 if (name == 0 || *name == 0)
323 return 0;
325 /* valid identifier */
326 #if defined (ARRAY_VARS)
327 if (legal_identifier (name) || (flags != 2 && valid_array_reference (name, 0)))
328 #else
329 if (legal_identifier (name))
330 #endif
331 return 1;
333 return 0;
337 check_selfref (name, value, flags)
338 const char *name;
339 char *value;
340 int flags;
342 char *t;
344 if (STREQ (name, value))
345 return 1;
347 #if defined (ARRAY_VARS)
348 if (valid_array_reference (value, 0))
350 t = array_variable_name (value, 0, (char **)NULL, (int *)NULL);
351 if (t && STREQ (name, t))
353 free (t);
354 return 1;
356 free (t);
358 #endif
360 return 0; /* not a self reference */
363 /* Make sure that WORD is a valid shell identifier, i.e.
364 does not contain a dollar sign, nor is quoted in any way.
365 If CHECK_WORD is non-zero,
366 the word is checked to ensure that it consists of only letters,
367 digits, and underscores, and does not consist of all digits. */
369 check_identifier (word, check_word)
370 WORD_DESC *word;
371 int check_word;
373 if (word->flags & (W_HASDOLLAR|W_QUOTED)) /* XXX - HASDOLLAR? */
375 internal_error (_("`%s': not a valid identifier"), word->word);
376 return (0);
378 else if (check_word && (all_digits (word->word) || legal_identifier (word->word) == 0))
380 internal_error (_("`%s': not a valid identifier"), word->word);
381 return (0);
383 else
384 return (1);
387 /* Return 1 if STRING is a function name that the shell will import from
388 the environment. Currently we reject attempts to import shell functions
389 containing slashes, beginning with newlines or containing blanks. In
390 Posix mode, we require that STRING be a valid shell identifier. Not
391 used yet. */
393 importable_function_name (string, len)
394 const char *string;
395 size_t len;
397 if (absolute_program (string)) /* don't allow slash */
398 return 0;
399 if (*string == '\n') /* can't start with a newline */
400 return 0;
401 if (shellblank (*string) || shellblank(string[len-1]))
402 return 0;
403 return (posixly_correct ? legal_identifier (string) : 1);
407 exportable_function_name (string)
408 const char *string;
410 if (absolute_program (string))
411 return 0;
412 if (mbschr (string, '=') != 0)
413 return 0;
414 return 1;
417 /* Return 1 if STRING comprises a valid alias name. The shell accepts
418 essentially all characters except those which must be quoted to the
419 parser (which disqualifies them from alias expansion anyway) and `/'. */
421 legal_alias_name (string, flags)
422 const char *string;
423 int flags;
425 register const char *s;
427 for (s = string; *s; s++)
428 if (shellbreak (*s) || shellxquote (*s) || shellexp (*s) || (*s == '/'))
429 return 0;
430 return 1;
433 /* Returns non-zero if STRING is an assignment statement. The returned value
434 is the index of the `=' sign. If FLAGS&1 we are expecting a compound assignment
435 and require an array subscript before the `=' to denote an assignment
436 statement. */
438 assignment (string, flags)
439 const char *string;
440 int flags;
442 register unsigned char c;
443 register int newi, indx;
445 c = string[indx = 0];
447 #if defined (ARRAY_VARS)
448 /* If parser_state includes PST_COMPASSIGN, FLAGS will include 1, so we are
449 parsing the contents of a compound assignment. If parser_state includes
450 PST_REPARSE, we are in the middle of an assignment statement and breaking
451 the words between the parens into words and assignment statements, but
452 we don't need to check for that right now. Within a compound assignment,
453 the subscript is required to make the word an assignment statement. If
454 we don't have a subscript, even if the word is a valid assignment
455 statement otherwise, we don't want to treat it as one. */
456 if ((flags & 1) && c != '[') /* ] */
457 return (0);
458 else if ((flags & 1) == 0 && org_legal_variable_starter (c) == 0)
459 #else
460 if (org_legal_variable_starter (c) == 0)
461 #endif
462 return (0);
464 while (c = string[indx])
466 /* The following is safe. Note that '=' at the start of a word
467 is not an assignment statement. */
468 if (c == '=')
469 {printf("string = %s\n", string);
470 return (indx);
473 #if defined (ARRAY_VARS)
474 if (c == '[')
476 newi = skipsubscript (string, indx, (flags & 2) ? 1 : 0);
477 /* XXX - why not check for blank subscripts here, if we do in
478 valid_array_reference? */
479 if (string[newi++] != ']')
480 return (0);
481 printf("string = %s\n", string);
482 if (string[newi] == '+' && string[newi+1] == '=')
483 return (newi + 1);
484 return ((string[newi] == '=') ? newi : 0);
486 #endif /* ARRAY_VARS */
488 /* Check for `+=' */
489 if (c == '+' && string[indx+1] == '=')
490 {printf("string = %s\n", string);
491 return (indx + 1);
494 /* Variable names in assignment statements may contain only letters,
495 digits, and `_', and double `:'. */
496 if (legal_variable_char (c) == 0)
497 return (0);
499 if (c == ':')
501 if (string[indx+1] == ':')
502 indx++;
503 else
505 printf("string = %s\n", string);
506 return indx;
510 indx++;
512 return (0);
516 line_isblank (line)
517 const char *line;
519 register int i;
521 if (line == 0)
522 return 0; /* XXX */
523 for (i = 0; line[i]; i++)
524 if (isblank ((unsigned char)line[i]) == 0)
525 break;
526 return (line[i] == '\0');
529 /* **************************************************************** */
530 /* */
531 /* Functions to manage files and file descriptors */
532 /* */
533 /* **************************************************************** */
535 /* A function to unset no-delay mode on a file descriptor. Used in shell.c
536 to unset it on the fd passed as stdin. Should be called on stdin if
537 readline gets an EAGAIN or EWOULDBLOCK when trying to read input. */
539 #if !defined (O_NDELAY)
540 # if defined (FNDELAY)
541 # define O_NDELAY FNDELAY
542 # endif
543 #endif /* O_NDELAY */
545 /* Make sure no-delay mode is not set on file descriptor FD. */
547 sh_unset_nodelay_mode (fd)
548 int fd;
550 int flags, bflags;
552 if ((flags = fcntl (fd, F_GETFL, 0)) < 0)
553 return -1;
555 bflags = 0;
557 /* This is defined to O_NDELAY in filecntl.h if O_NONBLOCK is not present
558 and O_NDELAY is defined. */
559 #ifdef O_NONBLOCK
560 bflags |= O_NONBLOCK;
561 #endif
563 #ifdef O_NDELAY
564 bflags |= O_NDELAY;
565 #endif
567 if (flags & bflags)
569 flags &= ~bflags;
570 return (fcntl (fd, F_SETFL, flags));
573 return 0;
576 /* Just a wrapper for the define in include/filecntl.h */
578 sh_setclexec (fd)
579 int fd;
581 return (SET_CLOSE_ON_EXEC (fd));
584 /* Return 1 if file descriptor FD is valid; 0 otherwise. */
586 sh_validfd (fd)
587 int fd;
589 return (fcntl (fd, F_GETFD, 0) >= 0);
593 fd_ispipe (fd)
594 int fd;
596 errno = 0;
597 return ((lseek (fd, 0L, SEEK_CUR) < 0) && (errno == ESPIPE));
600 /* There is a bug in the NeXT 2.1 rlogind that causes opens
601 of /dev/tty to fail. */
603 #if defined (__BEOS__)
604 /* On BeOS, opening in non-blocking mode exposes a bug in BeOS, so turn it
605 into a no-op. This should probably go away in the future. */
606 # undef O_NONBLOCK
607 # define O_NONBLOCK 0
608 #endif /* __BEOS__ */
610 void
611 check_dev_tty ()
613 int tty_fd;
614 char *tty;
616 tty_fd = open ("/dev/tty", O_RDWR|O_NONBLOCK);
618 if (tty_fd < 0)
620 tty = (char *)ttyname (fileno (stdin));
621 if (tty == 0)
622 return;
623 tty_fd = open (tty, O_RDWR|O_NONBLOCK);
625 if (tty_fd >= 0)
626 close (tty_fd);
629 /* Return 1 if PATH1 and PATH2 are the same file. This is kind of
630 expensive. If non-NULL STP1 and STP2 point to stat structures
631 corresponding to PATH1 and PATH2, respectively. */
633 same_file (path1, path2, stp1, stp2)
634 const char *path1, *path2;
635 struct stat *stp1, *stp2;
637 struct stat st1, st2;
639 if (stp1 == NULL)
641 if (stat (path1, &st1) != 0)
642 return (0);
643 stp1 = &st1;
646 if (stp2 == NULL)
648 if (stat (path2, &st2) != 0)
649 return (0);
650 stp2 = &st2;
653 return ((stp1->st_dev == stp2->st_dev) && (stp1->st_ino == stp2->st_ino));
656 /* Move FD to a number close to the maximum number of file descriptors
657 allowed in the shell process, to avoid the user stepping on it with
658 redirection and causing us extra work. If CHECK_NEW is non-zero,
659 we check whether or not the file descriptors are in use before
660 duplicating FD onto them. MAXFD says where to start checking the
661 file descriptors. If it's less than 20, we get the maximum value
662 available from getdtablesize(2). */
664 move_to_high_fd (fd, check_new, maxfd)
665 int fd, check_new, maxfd;
667 int script_fd, nfds, ignore;
669 if (maxfd < 20)
671 nfds = getdtablesize ();
672 if (nfds <= 0)
673 nfds = 20;
674 if (nfds > HIGH_FD_MAX)
675 nfds = HIGH_FD_MAX; /* reasonable maximum */
677 else
678 nfds = maxfd;
680 for (nfds--; check_new && nfds > 3; nfds--)
681 if (fcntl (nfds, F_GETFD, &ignore) == -1)
682 break;
684 if (nfds > 3 && fd != nfds && (script_fd = dup2 (fd, nfds)) != -1)
686 if (check_new == 0 || fd != fileno (stderr)) /* don't close stderr */
687 close (fd);
688 return (script_fd);
691 /* OK, we didn't find one less than our artificial maximum; return the
692 original file descriptor. */
693 return (fd);
696 /* Return non-zero if the characters from SAMPLE are not all valid
697 characters to be found in the first line of a shell script. We
698 check up to the first newline, or SAMPLE_LEN, whichever comes first.
699 All of the characters must be printable or whitespace. */
702 check_binary_file (sample, sample_len)
703 const char *sample;
704 int sample_len;
706 register int i;
707 unsigned char c;
709 for (i = 0; i < sample_len; i++)
711 c = sample[i];
712 if (c == '\n')
713 return (0);
714 if (c == '\0')
715 return (1);
718 return (0);
721 /* **************************************************************** */
722 /* */
723 /* Functions to manipulate pipes */
724 /* */
725 /* **************************************************************** */
728 sh_openpipe (pv)
729 int *pv;
731 int r;
733 if ((r = pipe (pv)) < 0)
734 return r;
736 pv[0] = move_to_high_fd (pv[0], 1, 64);
737 pv[1] = move_to_high_fd (pv[1], 1, 64);
739 return 0;
743 sh_closepipe (pv)
744 int *pv;
746 if (pv[0] >= 0)
747 close (pv[0]);
749 if (pv[1] >= 0)
750 close (pv[1]);
752 pv[0] = pv[1] = -1;
753 return 0;
756 /* **************************************************************** */
757 /* */
758 /* Functions to inspect pathnames */
759 /* */
760 /* **************************************************************** */
763 file_exists (fn)
764 const char *fn;
766 struct stat sb;
768 return (stat (fn, &sb) == 0);
772 file_isdir (fn)
773 const char *fn;
775 struct stat sb;
777 return ((stat (fn, &sb) == 0) && S_ISDIR (sb.st_mode));
781 file_iswdir (fn)
782 const char *fn;
784 return (file_isdir (fn) && sh_eaccess (fn, W_OK) == 0);
787 /* Return 1 if STRING is "." or "..", optionally followed by a directory
788 separator */
790 path_dot_or_dotdot (string)
791 const char *string;
793 if (string == 0 || *string == '\0' || *string != '.')
794 return (0);
796 /* string[0] == '.' */
797 if (PATHSEP(string[1]) || (string[1] == '.' && PATHSEP(string[2])))
798 return (1);
800 return (0);
803 /* Return 1 if STRING contains an absolute pathname, else 0. Used by `cd'
804 to decide whether or not to look up a directory name in $CDPATH. */
806 absolute_pathname (string)
807 const char *string;
809 if (string == 0 || *string == '\0')
810 return (0);
812 if (ABSPATH(string))
813 return (1);
815 if (string[0] == '.' && PATHSEP(string[1])) /* . and ./ */
816 return (1);
818 if (string[0] == '.' && string[1] == '.' && PATHSEP(string[2])) /* .. and ../ */
819 return (1);
821 return (0);
824 /* Return 1 if STRING is an absolute program name; it is absolute if it
825 contains any slashes. This is used to decide whether or not to look
826 up through $PATH. */
828 absolute_program (string)
829 const char *string;
831 return ((char *)mbschr (string, '/') != (char *)NULL);
834 /* **************************************************************** */
835 /* */
836 /* Functions to manipulate pathnames */
837 /* */
838 /* **************************************************************** */
840 /* Turn STRING (a pathname) into an absolute pathname, assuming that
841 DOT_PATH contains the symbolic location of `.'. This always
842 returns a new string, even if STRING was an absolute pathname to
843 begin with. */
844 char *
845 make_absolute (string, dot_path)
846 const char *string, *dot_path;
848 char *result;
850 if (dot_path == 0 || ABSPATH(string))
851 #ifdef __CYGWIN__
853 char pathbuf[PATH_MAX + 1];
855 /* WAS cygwin_conv_to_full_posix_path (string, pathbuf); */
856 cygwin_conv_path (CCP_WIN_A_TO_POSIX, string, pathbuf, PATH_MAX);
857 result = savestring (pathbuf);
859 #else
860 result = savestring (string);
861 #endif
862 else
863 result = sh_makepath (dot_path, string, 0);
865 return (result);
868 /* Return the `basename' of the pathname in STRING (the stuff after the
869 last '/'). If STRING is `/', just return it. */
870 char *
871 base_pathname (string)
872 char *string;
874 char *p;
876 #if 0
877 if (absolute_pathname (string) == 0)
878 return (string);
879 #endif
881 if (string[0] == '/' && string[1] == 0)
882 return (string);
884 p = (char *)strrchr (string, '/');
885 return (p ? ++p : string);
888 /* Return the full pathname of FILE. Easy. Filenames that begin
889 with a '/' are returned as themselves. Other filenames have
890 the current working directory prepended. A new string is
891 returned in either case. */
892 char *
893 full_pathname (file)
894 char *file;
896 char *ret;
898 file = (*file == '~') ? bush_tilde_expand (file, 0) : savestring (file);
900 if (ABSPATH(file))
901 return (file);
903 ret = sh_makepath ((char *)NULL, file, (MP_DOCWD|MP_RMDOT));
904 free (file);
906 return (ret);
909 /* A slightly related function. Get the prettiest name of this
910 directory possible. */
911 static char tdir[PATH_MAX];
913 /* Return a pretty pathname. If the first part of the pathname is
914 the same as $HOME, then replace that with `~'. */
915 char *
916 polite_directory_format (name)
917 char *name;
919 char *home;
920 int l;
922 home = get_string_value ("HOME");
923 l = home ? strlen (home) : 0;
924 if (l > 1 && strncmp (home, name, l) == 0 && (!name[l] || name[l] == '/'))
926 strncpy (tdir + 1, name + l, sizeof(tdir) - 2);
927 tdir[0] = '~';
928 tdir[sizeof(tdir) - 1] = '\0';
929 return (tdir);
931 else
932 return (name);
935 /* Trim NAME. If NAME begins with `~/', skip over tilde prefix. Trim to
936 keep any tilde prefix and PROMPT_DIRTRIM trailing directory components
937 and replace the intervening characters with `...' */
938 char *
939 trim_pathname (name, maxlen)
940 char *name;
941 int maxlen;
943 int nlen, ndirs;
944 intmax_t nskip;
945 char *nbeg, *nend, *ntail, *v;
947 if (name == 0 || (nlen = strlen (name)) == 0)
948 return name;
949 nend = name + nlen;
951 v = get_string_value ("PROMPT_DIRTRIM");
952 if (v == 0 || *v == 0)
953 return name;
954 if (legal_number (v, &nskip) == 0 || nskip <= 0)
955 return name;
957 /* Skip over tilde prefix */
958 nbeg = name;
959 if (name[0] == '~')
960 for (nbeg = name; *nbeg; nbeg++)
961 if (*nbeg == '/')
963 nbeg++;
964 break;
966 if (*nbeg == 0)
967 return name;
969 for (ndirs = 0, ntail = nbeg; *ntail; ntail++)
970 if (*ntail == '/')
971 ndirs++;
972 if (ndirs < nskip)
973 return name;
975 for (ntail = (*nend == '/') ? nend : nend - 1; ntail > nbeg; ntail--)
977 if (*ntail == '/')
978 nskip--;
979 if (nskip == 0)
980 break;
982 if (ntail == nbeg)
983 return name;
985 /* Now we want to return name[0..nbeg]+"..."+ntail, modifying name in place */
986 nlen = ntail - nbeg;
987 if (nlen <= 3)
988 return name;
990 *nbeg++ = '.';
991 *nbeg++ = '.';
992 *nbeg++ = '.';
994 nlen = nend - ntail;
995 memmove (nbeg, ntail, nlen);
996 nbeg[nlen] = '\0';
998 return name;
1001 /* Return a printable representation of FN without special characters. The
1002 caller is responsible for freeing memory if this returns something other
1003 than its argument. If FLAGS is non-zero, we are printing for portable
1004 re-input and should single-quote filenames appropriately. */
1005 char *
1006 printable_filename (fn, flags)
1007 char *fn;
1008 int flags;
1010 char *newf;
1012 if (ansic_shouldquote (fn))
1013 newf = ansic_quote (fn, 0, NULL);
1014 else if (flags && sh_contains_shell_metas (fn))
1015 newf = sh_single_quote (fn);
1016 else
1017 newf = fn;
1019 return newf;
1022 /* Given a string containing units of information separated by colons,
1023 return the next one pointed to by (P_INDEX), or NULL if there are no more.
1024 Advance (P_INDEX) to the character after the colon. */
1025 char *
1026 extract_colon_unit (string, p_index)
1027 char *string;
1028 int *p_index;
1030 int i, start, len;
1031 char *value;
1033 if (string == 0)
1034 return (string);
1036 len = strlen (string);
1037 if (*p_index >= len)
1038 return ((char *)NULL);
1040 i = *p_index;
1042 /* Each call to this routine leaves the index pointing at a colon if
1043 there is more to the path. If I is > 0, then increment past the
1044 `:'. If I is 0, then the path has a leading colon. Trailing colons
1045 are handled OK by the `else' part of the if statement; an empty
1046 string is returned in that case. */
1047 if (i && string[i] == ':')
1048 i++;
1050 for (start = i; string[i] && string[i] != ':'; i++)
1053 *p_index = i;
1055 if (i == start)
1057 if (string[i])
1058 (*p_index)++;
1059 /* Return "" in the case of a trailing `:'. */
1060 value = (char *)xmalloc (1);
1061 value[0] = '\0';
1063 else
1064 value = substring (string, start, i);
1066 return (value);
1069 /* **************************************************************** */
1070 /* */
1071 /* Tilde Initialization and Expansion */
1072 /* */
1073 /* **************************************************************** */
1075 #if defined (PUSHD_AND_POPD)
1076 extern char *get_dirstack_from_string PARAMS((char *));
1077 #endif
1079 static char **bush_tilde_prefixes;
1080 static char **bush_tilde_prefixes2;
1081 static char **bush_tilde_suffixes;
1082 static char **bush_tilde_suffixes2;
1084 /* If tilde_expand hasn't been able to expand the text, perhaps it
1085 is a special shell expansion. This function is installed as the
1086 tilde_expansion_preexpansion_hook. It knows how to expand ~- and ~+.
1087 If PUSHD_AND_POPD is defined, ~[+-]N expands to directories from the
1088 directory stack. */
1089 static char *
1090 bush_special_tilde_expansions (text)
1091 char *text;
1093 char *result;
1095 result = (char *)NULL;
1097 if (text[0] == '+' && text[1] == '\0')
1098 result = get_string_value ("PWD");
1099 else if (text[0] == '-' && text[1] == '\0')
1100 result = get_string_value ("OLDPWD");
1101 #if defined (PUSHD_AND_POPD)
1102 else if (DIGIT (*text) || ((*text == '+' || *text == '-') && DIGIT (text[1])))
1103 result = get_dirstack_from_string (text);
1104 #endif
1106 return (result ? savestring (result) : (char *)NULL);
1109 /* Initialize the tilde expander. In Bush, we handle `~-' and `~+', as
1110 well as handling special tilde prefixes; `:~" and `=~' are indications
1111 that we should do tilde expansion. */
1112 void
1113 tilde_initialize ()
1115 static int times_called = 0;
1117 /* Tell the tilde expander that we want a crack first. */
1118 tilde_expansion_preexpansion_hook = bush_special_tilde_expansions;
1120 /* Tell the tilde expander about special strings which start a tilde
1121 expansion, and the special strings that end one. Only do this once.
1122 tilde_initialize () is called from within bushline_reinitialize (). */
1123 if (times_called++ == 0)
1125 bush_tilde_prefixes = strvec_create (3);
1126 bush_tilde_prefixes[0] = "=~";
1127 bush_tilde_prefixes[1] = ":~";
1128 bush_tilde_prefixes[2] = (char *)NULL;
1130 bush_tilde_prefixes2 = strvec_create (2);
1131 bush_tilde_prefixes2[0] = ":~";
1132 bush_tilde_prefixes2[1] = (char *)NULL;
1134 tilde_additional_prefixes = bush_tilde_prefixes;
1136 bush_tilde_suffixes = strvec_create (3);
1137 bush_tilde_suffixes[0] = ":";
1138 bush_tilde_suffixes[1] = "=~"; /* XXX - ?? */
1139 bush_tilde_suffixes[2] = (char *)NULL;
1141 tilde_additional_suffixes = bush_tilde_suffixes;
1143 bush_tilde_suffixes2 = strvec_create (2);
1144 bush_tilde_suffixes2[0] = ":";
1145 bush_tilde_suffixes2[1] = (char *)NULL;
1149 /* POSIX.2, 3.6.1: A tilde-prefix consists of an unquoted tilde character
1150 at the beginning of the word, followed by all of the characters preceding
1151 the first unquoted slash in the word, or all the characters in the word
1152 if there is no slash...If none of the characters in the tilde-prefix are
1153 quoted, the characters in the tilde-prefix following the tilde shell be
1154 treated as a possible login name. */
1156 #define TILDE_END(c) ((c) == '\0' || (c) == '/' || (c) == ':')
1158 static int
1159 unquoted_tilde_word (s)
1160 const char *s;
1162 const char *r;
1164 for (r = s; TILDE_END(*r) == 0; r++)
1166 switch (*r)
1168 case '\\':
1169 case '\'':
1170 case '"':
1171 return 0;
1174 return 1;
1177 /* Find the end of the tilde-prefix starting at S, and return the tilde
1178 prefix in newly-allocated memory. Return the length of the string in
1179 *LENP. FLAGS tells whether or not we're in an assignment context --
1180 if so, `:' delimits the end of the tilde prefix as well. */
1181 char *
1182 bush_tilde_find_word (s, flags, lenp)
1183 const char *s;
1184 int flags, *lenp;
1186 const char *r;
1187 char *ret;
1188 int l;
1190 for (r = s; *r && *r != '/'; r++)
1192 /* Short-circuit immediately if we see a quote character. Even though
1193 POSIX says that `the first unquoted slash' (or `:') terminates the
1194 tilde-prefix, in practice, any quoted portion of the tilde prefix
1195 will cause it to not be expanded. */
1196 if (*r == '\\' || *r == '\'' || *r == '"')
1198 ret = savestring (s);
1199 if (lenp)
1200 *lenp = 0;
1201 return ret;
1203 else if (flags && *r == ':')
1204 break;
1206 l = r - s;
1207 ret = xmalloc (l + 1);
1208 strncpy (ret, s, l);
1209 ret[l] = '\0';
1210 if (lenp)
1211 *lenp = l;
1212 return ret;
1215 /* Tilde-expand S by running it through the tilde expansion library.
1216 ASSIGN_P is 1 if this is a variable assignment, so the alternate
1217 tilde prefixes should be enabled (`=~' and `:~', see above). If
1218 ASSIGN_P is 2, we are expanding the rhs of an assignment statement,
1219 so `=~' is not valid. */
1220 char *
1221 bush_tilde_expand (s, assign_p)
1222 const char *s;
1223 int assign_p;
1225 int r;
1226 char *ret;
1228 tilde_additional_prefixes = assign_p == 0 ? (char **)0
1229 : (assign_p == 2 ? bush_tilde_prefixes2 : bush_tilde_prefixes);
1230 if (assign_p == 2)
1231 tilde_additional_suffixes = bush_tilde_suffixes2;
1233 r = (*s == '~') ? unquoted_tilde_word (s) : 1;
1234 ret = r ? tilde_expand (s) : savestring (s);
1236 QUIT;
1238 return (ret);
1241 /* **************************************************************** */
1242 /* */
1243 /* Functions to manipulate and search the group list */
1244 /* */
1245 /* **************************************************************** */
1247 static int ngroups, maxgroups;
1249 /* The set of groups that this user is a member of. */
1250 static GETGROUPS_T *group_array = (GETGROUPS_T *)NULL;
1252 #if !defined (NOGROUP)
1253 # define NOGROUP (gid_t) -1
1254 #endif
1256 static void
1257 initialize_group_array ()
1259 register int i;
1261 if (maxgroups == 0)
1262 maxgroups = getmaxgroups ();
1264 ngroups = 0;
1265 group_array = (GETGROUPS_T *)xrealloc (group_array, maxgroups * sizeof (GETGROUPS_T));
1267 #if defined (HAVE_GETGROUPS)
1268 ngroups = getgroups (maxgroups, group_array);
1269 #endif
1271 /* If getgroups returns nothing, or the OS does not support getgroups(),
1272 make sure the groups array includes at least the current gid. */
1273 if (ngroups == 0)
1275 group_array[0] = current_user.gid;
1276 ngroups = 1;
1279 /* If the primary group is not in the groups array, add it as group_array[0]
1280 and shuffle everything else up 1, if there's room. */
1281 for (i = 0; i < ngroups; i++)
1282 if (current_user.gid == (gid_t)group_array[i])
1283 break;
1284 if (i == ngroups && ngroups < maxgroups)
1286 for (i = ngroups; i > 0; i--)
1287 group_array[i] = group_array[i - 1];
1288 group_array[0] = current_user.gid;
1289 ngroups++;
1292 /* If the primary group is not group_array[0], swap group_array[0] and
1293 whatever the current group is. The vast majority of systems should
1294 not need this; a notable exception is Linux. */
1295 if (group_array[0] != current_user.gid)
1297 for (i = 0; i < ngroups; i++)
1298 if (group_array[i] == current_user.gid)
1299 break;
1300 if (i < ngroups)
1302 group_array[i] = group_array[0];
1303 group_array[0] = current_user.gid;
1308 /* Return non-zero if GID is one that we have in our groups list. */
1310 #if defined (__STDC__) || defined ( _MINIX)
1311 group_member (gid_t gid)
1312 #else
1313 group_member (gid)
1314 gid_t gid;
1315 #endif /* !__STDC__ && !_MINIX */
1317 #if defined (HAVE_GETGROUPS)
1318 register int i;
1319 #endif
1321 /* Short-circuit if possible, maybe saving a call to getgroups(). */
1322 if (gid == current_user.gid || gid == current_user.egid)
1323 return (1);
1325 #if defined (HAVE_GETGROUPS)
1326 if (ngroups == 0)
1327 initialize_group_array ();
1329 /* In case of error, the user loses. */
1330 if (ngroups <= 0)
1331 return (0);
1333 /* Search through the list looking for GID. */
1334 for (i = 0; i < ngroups; i++)
1335 if (gid == (gid_t)group_array[i])
1336 return (1);
1337 #endif
1339 return (0);
1342 char **
1343 get_group_list (ngp)
1344 int *ngp;
1346 static char **group_vector = (char **)NULL;
1347 register int i;
1349 if (group_vector)
1351 if (ngp)
1352 *ngp = ngroups;
1353 return group_vector;
1356 if (ngroups == 0)
1357 initialize_group_array ();
1359 if (ngroups <= 0)
1361 if (ngp)
1362 *ngp = 0;
1363 return (char **)NULL;
1366 group_vector = strvec_create (ngroups);
1367 for (i = 0; i < ngroups; i++)
1368 group_vector[i] = itos (group_array[i]);
1370 if (ngp)
1371 *ngp = ngroups;
1372 return group_vector;
1375 int *
1376 get_group_array (ngp)
1377 int *ngp;
1379 int i;
1380 static int *group_iarray = (int *)NULL;
1382 if (group_iarray)
1384 if (ngp)
1385 *ngp = ngroups;
1386 return (group_iarray);
1389 if (ngroups == 0)
1390 initialize_group_array ();
1392 if (ngroups <= 0)
1394 if (ngp)
1395 *ngp = 0;
1396 return (int *)NULL;
1399 group_iarray = (int *)xmalloc (ngroups * sizeof (int));
1400 for (i = 0; i < ngroups; i++)
1401 group_iarray[i] = (int)group_array[i];
1403 if (ngp)
1404 *ngp = ngroups;
1405 return group_iarray;
1408 /* **************************************************************** */
1409 /* */
1410 /* Miscellaneous functions */
1411 /* */
1412 /* **************************************************************** */
1414 /* Return a value for PATH that is guaranteed to find all of the standard
1415 utilities. This uses Posix.2 configuration variables, if present. It
1416 uses a value defined in config.h as a last resort. */
1417 char *
1418 conf_standard_path ()
1420 #if defined (_CS_PATH) && defined (HAVE_CONFSTR)
1421 char *p;
1422 size_t len;
1424 len = (size_t)confstr (_CS_PATH, (char *)NULL, (size_t)0);
1425 if (len > 0)
1427 p = (char *)xmalloc (len + 2);
1428 *p = '\0';
1429 confstr (_CS_PATH, p, len);
1430 return (p);
1432 else
1433 return (savestring (STANDARD_UTILS_PATH));
1434 #else /* !_CS_PATH || !HAVE_CONFSTR */
1435 # if defined (CS_PATH)
1436 return (savestring (CS_PATH));
1437 # else
1438 return (savestring (STANDARD_UTILS_PATH));
1439 # endif /* !CS_PATH */
1440 #endif /* !_CS_PATH || !HAVE_CONFSTR */
1444 default_columns ()
1446 char *v;
1447 int c;
1449 c = -1;
1450 v = get_string_value ("COLUMNS");
1451 if (v && *v)
1453 c = atoi (v);
1454 if (c > 0)
1455 return c;
1458 if (check_window_size)
1459 get_new_window_size (0, (int *)0, &c);
1461 return (c > 0 ? c : 80);