]> git.ipfire.org Git - thirdparty/bash.git/blame - builtins/common.c
Imported from ../bash-2.05.tar.gz.
[thirdparty/bash.git] / builtins / common.c
CommitLineData
726f6388
JA
1/* Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
2
3 This file is part of GNU Bash, the Bourne Again SHell.
4
5 Bash is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License as published by the Free
bb70624e 7 Software Foundation; either version 2, or (at your option) any later
726f6388
JA
8 version.
9
10 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
11 WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with Bash; see the file COPYING. If not, write to the Free Software
bb70624e 17 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
726f6388 18
ccc6cda3
JA
19#include <config.h>
20
21#if defined (HAVE_UNISTD_H)
cce855bc
JA
22# ifdef _MINIX
23# include <sys/types.h>
24# endif
ccc6cda3
JA
25# include <unistd.h>
26#endif
27
726f6388 28#include <stdio.h>
d166f048 29#include "../bashtypes.h"
bb70624e 30#include "posixstat.h"
ccc6cda3
JA
31#include <signal.h>
32
cce855bc
JA
33#include <errno.h>
34
ccc6cda3
JA
35#if defined (PREFER_STDARG)
36# include <stdarg.h>
37#else
38# if defined (PREFER_VARARGS)
39# include <varargs.h>
40# endif
41#endif
726f6388 42
ccc6cda3 43#include "../bashansi.h"
726f6388
JA
44
45#include "../shell.h"
bb70624e 46#include "maxpath.h"
ccc6cda3 47#include "../flags.h"
726f6388
JA
48#include "../jobs.h"
49#include "../builtins.h"
50#include "../input.h"
51#include "../execute_cmd.h"
ccc6cda3 52#include "../trap.h"
ccc6cda3 53#include "bashgetopt.h"
726f6388 54#include "common.h"
d166f048 55#include "builtext.h"
726f6388
JA
56#include <tilde/tilde.h>
57
58#if defined (HISTORY)
59# include "../bashhist.h"
60#endif
61
cce855bc
JA
62#if !defined (errno)
63extern int errno;
64#endif /* !errno */
65
bb70624e
JA
66#ifdef __STDC__
67typedef int QSFUNC (const void *, const void *);
68#else
69typedef int QSFUNC ();
70#endif
71
726f6388 72extern int no_symbolic_links, interactive, interactive_shell;
ccc6cda3
JA
73extern int indirection_level, startup_state, subshell_environment;
74extern int line_number;
726f6388 75extern int last_command_exit_value;
ccc6cda3 76extern int running_trap;
726f6388 77extern int variable_context;
ccc6cda3 78extern int posixly_correct;
726f6388
JA
79extern char *this_command_name, *shell_name;
80extern COMMAND *global_command;
ccc6cda3 81extern char *bash_getcwd_errstr;
726f6388 82
d166f048
JA
83/* Used by some builtins and the mainline code. */
84Function *last_shell_builtin = (Function *)NULL;
85Function *this_shell_builtin = (Function *)NULL;
86
ccc6cda3
JA
87/* **************************************************************** */
88/* */
89/* Error reporting, usage, and option processing */
90/* */
91/* **************************************************************** */
726f6388
JA
92
93/* This is a lot like report_error (), but it is for shell builtins
94 instead of shell control structures, and it won't ever exit the
95 shell. */
ccc6cda3 96#if defined (USE_VARARGS)
726f6388 97void
ccc6cda3
JA
98#if defined (PREFER_STDARG)
99builtin_error (const char *format, ...)
100#else
101builtin_error (format, va_alist)
102 const char *format;
726f6388 103 va_dcl
ccc6cda3 104#endif
726f6388 105{
726f6388 106 va_list args;
ccc6cda3
JA
107 char *name;
108
109 name = get_name_for_error ();
110 fprintf (stderr, "%s: ", name);
726f6388
JA
111
112 if (this_command_name && *this_command_name)
113 fprintf (stderr, "%s: ", this_command_name);
114
ccc6cda3
JA
115#if defined (PREFER_STDARG)
116 va_start (args, format);
117#else
726f6388 118 va_start (args);
ccc6cda3
JA
119#endif
120
726f6388
JA
121 vfprintf (stderr, format, args);
122 va_end (args);
123 fprintf (stderr, "\n");
124}
ccc6cda3 125#else /* !USE_VARARGS */
726f6388
JA
126void
127builtin_error (format, arg1, arg2, arg3, arg4, arg5)
128 char *format, *arg1, *arg2, *arg3, *arg4, *arg5;
129{
130 if (this_command_name && *this_command_name)
131 fprintf (stderr, "%s: ", this_command_name);
132
133 fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
134 fprintf (stderr, "\n");
135 fflush (stderr);
136}
ccc6cda3
JA
137#endif /* !USE_VARARGS */
138
139/* Print a usage summary for the currently-executing builtin command. */
140void
141builtin_usage ()
142{
143 if (this_command_name && *this_command_name)
144 fprintf (stderr, "%s: usage: ", this_command_name);
145 fprintf (stderr, "%s\n", current_builtin->short_doc);
146 fflush (stderr);
147}
148
149/* Return if LIST is NULL else barf and jump to top_level. Used by some
150 builtins that do not accept arguments. */
151void
152no_args (list)
153 WORD_LIST *list;
154{
155 if (list)
156 {
157 builtin_error ("too many arguments");
158 jump_to_top_level (DISCARD);
159 }
160}
161
162/* Function called when one of the builtin commands detects a bad
163 option. */
164void
165bad_option (s)
166 char *s;
167{
168 builtin_error ("unknown option: %s", s);
169}
170
171/* Check that no options were given to the currently-executing builtin,
172 and return 0 if there were options. */
173int
174no_options (list)
175 WORD_LIST *list;
176{
177 reset_internal_getopt ();
178 if (internal_getopt (list, "") != -1)
179 {
180 builtin_usage ();
181 return (1);
182 }
183 return (0);
184}
185
186/* **************************************************************** */
187/* */
188/* Shell positional parameter manipulation */
189/* */
190/* **************************************************************** */
191
192/* Convert a WORD_LIST into a C-style argv. Return the number of elements
193 in the list in *IP, if IP is non-null. A convenience function for
194 loadable builtins; also used by `test'. */
195char **
196make_builtin_argv (list, ip)
197 WORD_LIST *list;
198 int *ip;
199{
200 char **argv;
201
202 argv = word_list_to_argv (list, 0, 1, ip);
203 argv[0] = this_command_name;
204 return argv;
205}
726f6388
JA
206
207/* Remember LIST in $0 ... $9, and REST_OF_ARGS. If DESTRUCTIVE is
208 non-zero, then discard whatever the existing arguments are, else
209 only discard the ones that are to be replaced. */
210void
211remember_args (list, destructive)
212 WORD_LIST *list;
213 int destructive;
214{
215 register int i;
216
217 for (i = 1; i < 10; i++)
218 {
ccc6cda3 219 if ((destructive || list) && dollar_vars[i])
726f6388
JA
220 {
221 free (dollar_vars[i]);
222 dollar_vars[i] = (char *)NULL;
223 }
224
225 if (list)
226 {
726f6388
JA
227 dollar_vars[i] = savestring (list->word->word);
228 list = list->next;
229 }
230 }
231
232 /* If arguments remain, assign them to REST_OF_ARGS.
233 Note that copy_word_list (NULL) returns NULL, and
234 that dispose_words (NULL) does nothing. */
235 if (destructive || list)
236 {
237 dispose_words (rest_of_args);
238 rest_of_args = copy_word_list (list);
239 }
240
241 if (destructive)
242 set_dollar_vars_changed ();
243}
244
726f6388
JA
245/* **************************************************************** */
246/* */
ccc6cda3 247/* Pushing and Popping variable contexts */
726f6388
JA
248/* */
249/* **************************************************************** */
250
251static WORD_LIST **dollar_arg_stack = (WORD_LIST **)NULL;
ccc6cda3
JA
252static int dollar_arg_stack_slots;
253static int dollar_arg_stack_index;
726f6388
JA
254
255void
256push_context ()
257{
258 push_dollar_vars ();
259 variable_context++;
260}
261
262void
263pop_context ()
264{
265 pop_dollar_vars ();
266 kill_all_local_variables ();
267 variable_context--;
268}
269
270/* Save the existing positional parameters on a stack. */
271void
272push_dollar_vars ()
273{
274 if (dollar_arg_stack_index + 2 > dollar_arg_stack_slots)
275 {
276 dollar_arg_stack = (WORD_LIST **)
277 xrealloc (dollar_arg_stack, (dollar_arg_stack_slots += 10)
278 * sizeof (WORD_LIST **));
279 }
ccc6cda3
JA
280 dollar_arg_stack[dollar_arg_stack_index++] = list_rest_of_args ();
281 dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
726f6388
JA
282}
283
284/* Restore the positional parameters from our stack. */
285void
286pop_dollar_vars ()
287{
ccc6cda3 288 if (!dollar_arg_stack || dollar_arg_stack_index == 0)
726f6388
JA
289 return;
290
291 remember_args (dollar_arg_stack[--dollar_arg_stack_index], 1);
292 dispose_words (dollar_arg_stack[dollar_arg_stack_index]);
293 dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
294}
295
296void
297dispose_saved_dollar_vars ()
298{
ccc6cda3 299 if (!dollar_arg_stack || dollar_arg_stack_index == 0)
726f6388
JA
300 return;
301
302 dispose_words (dollar_arg_stack[dollar_arg_stack_index]);
303 dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
304}
305
ccc6cda3 306static int changed_dollar_vars;
726f6388
JA
307
308/* Have the dollar variables been reset to new values since we last
309 checked? */
ccc6cda3 310int
726f6388
JA
311dollar_vars_changed ()
312{
313 return (changed_dollar_vars);
314}
315
316void
317set_dollar_vars_unchanged ()
318{
319 changed_dollar_vars = 0;
320}
321
322void
323set_dollar_vars_changed ()
324{
ccc6cda3 325 changed_dollar_vars = 1;
726f6388
JA
326}
327
ccc6cda3
JA
328/* **************************************************************** */
329/* */
28ef6c31 330/* Validating numeric input and arguments */
ccc6cda3
JA
331/* */
332/* **************************************************************** */
333
334/* Read a numeric arg for this_command_name, the name of the shell builtin
335 that wants it. LIST is the word list that the arg is to come from.
336 Accept only the numeric argument; report an error if other arguments
d166f048
JA
337 follow. If FATAL is true, call throw_to_top_level, which exits the
338 shell; if not, call jump_to_top_level (DISCARD), which aborts the
339 current command. */
ccc6cda3 340int
d166f048 341get_numeric_arg (list, fatal)
ccc6cda3 342 WORD_LIST *list;
d166f048 343 int fatal;
726f6388 344{
ccc6cda3
JA
345 long count = 1;
346
347 if (list)
348 {
349 register char *arg;
350
351 arg = list->word->word;
352 if (!arg || (legal_number (arg, &count) == 0))
353 {
354 builtin_error ("bad non-numeric arg `%s'", list->word->word);
d166f048
JA
355 if (fatal)
356 throw_to_top_level ();
357 else
358 jump_to_top_level (DISCARD);
ccc6cda3
JA
359 }
360 no_args (list->next);
361 }
362 return (count);
363}
364
365/* Return the octal number parsed from STRING, or -1 to indicate
366 that the string contained a bad number. */
367int
368read_octal (string)
369 char *string;
370{
371 int result, digits;
372
373 result = digits = 0;
28ef6c31 374 while (*string && ISOCTAL (*string))
ccc6cda3
JA
375 {
376 digits++;
28ef6c31 377 result = (result * 8) + (*string++ - '0');
ccc6cda3
JA
378 }
379
380 if (!digits || result > 0777 || *string)
381 result = -1;
382
383 return (result);
384}
385
ccc6cda3
JA
386/* **************************************************************** */
387/* */
388/* Manipulating the current working directory */
389/* */
390/* **************************************************************** */
391
726f6388
JA
392/* Return a consed string which is the current working directory.
393 FOR_WHOM is the name of the caller for error printing. */
394char *the_current_working_directory = (char *)NULL;
395
396char *
397get_working_directory (for_whom)
398 char *for_whom;
399{
ccc6cda3
JA
400 char *directory;
401
726f6388
JA
402 if (no_symbolic_links)
403 {
404 if (the_current_working_directory)
405 free (the_current_working_directory);
406
407 the_current_working_directory = (char *)NULL;
408 }
409
ccc6cda3 410 if (the_current_working_directory == 0)
726f6388 411 {
ccc6cda3
JA
412 the_current_working_directory = xmalloc (PATH_MAX);
413 the_current_working_directory[0] = '\0';
414 directory = getcwd (the_current_working_directory, PATH_MAX);
415 if (directory == 0)
726f6388 416 {
cce855bc 417 fprintf (stderr, "%s: could not get current directory: %s: %s\n",
ccc6cda3 418 (for_whom && *for_whom) ? for_whom : get_name_for_error (),
28ef6c31 419 bash_getcwd_errstr, strerror (errno));
726f6388
JA
420
421 free (the_current_working_directory);
422 the_current_working_directory = (char *)NULL;
423 return (char *)NULL;
424 }
425 }
426
427 return (savestring (the_current_working_directory));
428}
429
430/* Make NAME our internal idea of the current working directory. */
431void
432set_working_directory (name)
433 char *name;
434{
ccc6cda3 435 FREE (the_current_working_directory);
726f6388
JA
436 the_current_working_directory = savestring (name);
437}
438
ccc6cda3
JA
439/* **************************************************************** */
440/* */
441/* Job control support functions */
442/* */
443/* **************************************************************** */
444
726f6388
JA
445#if defined (JOB_CONTROL)
446/* Return the job spec found in LIST. */
ccc6cda3 447int
726f6388
JA
448get_job_spec (list)
449 WORD_LIST *list;
450{
451 register char *word;
ccc6cda3 452 int job, substring;
726f6388 453
ccc6cda3 454 if (list == 0)
726f6388
JA
455 return (current_job);
456
457 word = list->word->word;
458
ccc6cda3 459 if (*word == '\0')
726f6388
JA
460 return (current_job);
461
462 if (*word == '%')
463 word++;
464
ccc6cda3
JA
465 if (digit (*word) && all_digits (word))
466 {
467 job = atoi (word);
bb70624e 468 return (job >= job_slots ? NO_JOB : job - 1);
ccc6cda3 469 }
726f6388 470
ccc6cda3 471 substring = 0;
726f6388
JA
472 switch (*word)
473 {
474 case 0:
475 case '%':
476 case '+':
477 return (current_job);
478
479 case '-':
480 return (previous_job);
481
482 case '?': /* Substring search requested. */
483 substring++;
484 word++;
ccc6cda3 485 /* FALLTHROUGH */
726f6388
JA
486
487 default:
726f6388 488 {
ccc6cda3
JA
489 register int i, wl;
490
491 job = NO_JOB;
492 wl = strlen (word);
726f6388
JA
493 for (i = 0; i < job_slots; i++)
494 {
495 if (jobs[i])
496 {
ccc6cda3
JA
497 register PROCESS *p;
498 p = jobs[i]->pipe;
726f6388
JA
499 do
500 {
501 if ((substring && strindex (p->command, word)) ||
ccc6cda3 502 (STREQN (p->command, word, wl)))
726f6388
JA
503 if (job != NO_JOB)
504 {
505 builtin_error ("ambigious job spec: %s", word);
506 return (DUP_JOB);
507 }
508 else
509 job = i;
510
511 p = p->next;
512 }
513 while (p != jobs[i]->pipe);
514 }
515 }
516 return (job);
517 }
518 }
519}
520#endif /* JOB_CONTROL */
521
726f6388 522int
ccc6cda3
JA
523display_signal_list (list, forcecols)
524 WORD_LIST *list;
525 int forcecols;
726f6388 526{
ccc6cda3
JA
527 register int i, column;
528 char *name;
529 int result;
530 long signum;
726f6388 531
ccc6cda3
JA
532 result = EXECUTION_SUCCESS;
533 if (!list)
726f6388 534 {
ccc6cda3
JA
535 for (i = 1, column = 0; i < NSIG; i++)
536 {
537 name = signal_name (i);
538 if (STREQN (name, "SIGJUNK", 7) || STREQN (name, "Unknown", 7))
539 continue;
726f6388 540
ccc6cda3
JA
541 if (posixly_correct && !forcecols)
542 printf ("%s%s", name, (i == NSIG - 1) ? "" : " ");
543 else
544 {
545 printf ("%2d) %s", i, name);
546
547 if (++column < 4)
548 printf ("\t");
549 else
550 {
551 printf ("\n");
552 column = 0;
553 }
554 }
555 }
726f6388 556
ccc6cda3
JA
557 if ((posixly_correct && !forcecols) || column != 0)
558 printf ("\n");
559 return result;
560 }
726f6388 561
ccc6cda3
JA
562 /* List individual signal names or numbers. */
563 while (list)
726f6388 564 {
ccc6cda3
JA
565 if (legal_number (list->word->word, &signum))
566 {
567 /* This is specified by Posix.2 so that exit statuses can be
568 mapped into signal numbers. */
569 if (signum > 128)
570 signum -= 128;
571 if (signum < 0 || signum >= NSIG)
572 {
573 builtin_error ("bad signal number: %s", list->word->word);
574 result = EXECUTION_FAILURE;
575 list = list->next;
576 continue;
577 }
578
579 name = signal_name (signum);
580 if (STREQN (name, "SIGJUNK", 7) || STREQN (name, "Unknown", 7))
581 {
582 list = list->next;
583 continue;
584 }
d166f048
JA
585#if defined (JOB_CONTROL)
586 /* POSIX.2 says that `kill -l signum' prints the signal name without
587 the `SIG' prefix. */
588 printf ("%s\n", (this_shell_builtin == kill_builtin) ? name + 3 : name);
589#else
ccc6cda3 590 printf ("%s\n", name);
d166f048 591#endif
ccc6cda3
JA
592 }
593 else
594 {
595 signum = decode_signal (list->word->word);
596 if (signum == NO_SIG)
597 {
598 builtin_error ("%s: not a signal specification", list->word->word);
599 result = EXECUTION_FAILURE;
600 list = list->next;
601 continue;
602 }
603 printf ("%ld\n", signum);
604 }
605 list = list->next;
726f6388 606 }
ccc6cda3 607 return (result);
726f6388
JA
608}
609
ccc6cda3
JA
610/* **************************************************************** */
611/* */
612/* Finding builtin commands and their functions */
613/* */
614/* **************************************************************** */
615
616/* Perform a binary search and return the address of the builtin function
617 whose name is NAME. If the function couldn't be found, or the builtin
618 is disabled or has no function associated with it, return NULL.
619 Return the address of the builtin.
726f6388 620 DISABLED_OKAY means find it even if the builtin is disabled. */
ccc6cda3 621struct builtin *
726f6388
JA
622builtin_address_internal (name, disabled_okay)
623 char *name;
624 int disabled_okay;
625{
626 int hi, lo, mid, j;
627
628 hi = num_shell_builtins - 1;
629 lo = 0;
630
631 while (lo <= hi)
632 {
633 mid = (lo + hi) / 2;
634
635 j = shell_builtins[mid].name[0] - name[0];
636
637 if (j == 0)
638 j = strcmp (shell_builtins[mid].name, name);
639
640 if (j == 0)
641 {
642 /* It must have a function pointer. It must be enabled, or we
ccc6cda3
JA
643 must have explicitly allowed disabled functions to be found,
644 and it must not have been deleted. */
726f6388 645 if (shell_builtins[mid].function &&
ccc6cda3 646 ((shell_builtins[mid].flags & BUILTIN_DELETED) == 0) &&
726f6388 647 ((shell_builtins[mid].flags & BUILTIN_ENABLED) || disabled_okay))
ccc6cda3 648 return (&shell_builtins[mid]);
726f6388 649 else
ccc6cda3 650 return ((struct builtin *)NULL);
726f6388
JA
651 }
652 if (j > 0)
653 hi = mid - 1;
654 else
655 lo = mid + 1;
656 }
ccc6cda3 657 return ((struct builtin *)NULL);
726f6388
JA
658}
659
ccc6cda3 660/* Return the pointer to the function implementing builtin command NAME. */
726f6388
JA
661Function *
662find_shell_builtin (name)
ccc6cda3 663 char *name;
726f6388 664{
ccc6cda3
JA
665 current_builtin = builtin_address_internal (name, 0);
666 return (current_builtin ? current_builtin->function : (Function *)NULL);
726f6388
JA
667}
668
ccc6cda3 669/* Return the address of builtin with NAME, whether it is enabled or not. */
726f6388
JA
670Function *
671builtin_address (name)
672 char *name;
673{
ccc6cda3
JA
674 current_builtin = builtin_address_internal (name, 1);
675 return (current_builtin ? current_builtin->function : (Function *)NULL);
726f6388
JA
676}
677
ccc6cda3
JA
678/* Return the function implementing the builtin NAME, but only if it is a
679 POSIX.2 special builtin. */
680Function *
681find_special_builtin (name)
682 char *name;
683{
684 current_builtin = builtin_address_internal (name, 0);
685 return ((current_builtin && (current_builtin->flags & SPECIAL_BUILTIN)) ?
686 current_builtin->function :
687 (Function *)NULL);
688}
689
726f6388
JA
690static int
691shell_builtin_compare (sbp1, sbp2)
692 struct builtin *sbp1, *sbp2;
693{
694 int result;
695
696 if ((result = sbp1->name[0] - sbp2->name[0]) == 0)
697 result = strcmp (sbp1->name, sbp2->name);
698
699 return (result);
700}
701
702/* Sort the table of shell builtins so that the binary search will work
703 in find_shell_builtin. */
704void
705initialize_shell_builtins ()
706{
707 qsort (shell_builtins, num_shell_builtins, sizeof (struct builtin),
bb70624e 708 (QSFUNC *)shell_builtin_compare);
726f6388 709}