]> git.ipfire.org Git - thirdparty/bash.git/blob - builtins/common.c
Imported from ../bash-2.05.tar.gz.
[thirdparty/bash.git] / builtins / common.c
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
7 Software Foundation; either version 2, or (at your option) any later
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
17 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
18
19 #include <config.h>
20
21 #if defined (HAVE_UNISTD_H)
22 # ifdef _MINIX
23 # include <sys/types.h>
24 # endif
25 # include <unistd.h>
26 #endif
27
28 #include <stdio.h>
29 #include "../bashtypes.h"
30 #include "posixstat.h"
31 #include <signal.h>
32
33 #include <errno.h>
34
35 #if defined (PREFER_STDARG)
36 # include <stdarg.h>
37 #else
38 # if defined (PREFER_VARARGS)
39 # include <varargs.h>
40 # endif
41 #endif
42
43 #include "../bashansi.h"
44
45 #include "../shell.h"
46 #include "maxpath.h"
47 #include "../flags.h"
48 #include "../jobs.h"
49 #include "../builtins.h"
50 #include "../input.h"
51 #include "../execute_cmd.h"
52 #include "../trap.h"
53 #include "bashgetopt.h"
54 #include "common.h"
55 #include "builtext.h"
56 #include <tilde/tilde.h>
57
58 #if defined (HISTORY)
59 # include "../bashhist.h"
60 #endif
61
62 #if !defined (errno)
63 extern int errno;
64 #endif /* !errno */
65
66 #ifdef __STDC__
67 typedef int QSFUNC (const void *, const void *);
68 #else
69 typedef int QSFUNC ();
70 #endif
71
72 extern int no_symbolic_links, interactive, interactive_shell;
73 extern int indirection_level, startup_state, subshell_environment;
74 extern int line_number;
75 extern int last_command_exit_value;
76 extern int running_trap;
77 extern int variable_context;
78 extern int posixly_correct;
79 extern char *this_command_name, *shell_name;
80 extern COMMAND *global_command;
81 extern char *bash_getcwd_errstr;
82
83 /* Used by some builtins and the mainline code. */
84 Function *last_shell_builtin = (Function *)NULL;
85 Function *this_shell_builtin = (Function *)NULL;
86
87 /* **************************************************************** */
88 /* */
89 /* Error reporting, usage, and option processing */
90 /* */
91 /* **************************************************************** */
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. */
96 #if defined (USE_VARARGS)
97 void
98 #if defined (PREFER_STDARG)
99 builtin_error (const char *format, ...)
100 #else
101 builtin_error (format, va_alist)
102 const char *format;
103 va_dcl
104 #endif
105 {
106 va_list args;
107 char *name;
108
109 name = get_name_for_error ();
110 fprintf (stderr, "%s: ", name);
111
112 if (this_command_name && *this_command_name)
113 fprintf (stderr, "%s: ", this_command_name);
114
115 #if defined (PREFER_STDARG)
116 va_start (args, format);
117 #else
118 va_start (args);
119 #endif
120
121 vfprintf (stderr, format, args);
122 va_end (args);
123 fprintf (stderr, "\n");
124 }
125 #else /* !USE_VARARGS */
126 void
127 builtin_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 }
137 #endif /* !USE_VARARGS */
138
139 /* Print a usage summary for the currently-executing builtin command. */
140 void
141 builtin_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. */
151 void
152 no_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. */
164 void
165 bad_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. */
173 int
174 no_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'. */
195 char **
196 make_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 }
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. */
210 void
211 remember_args (list, destructive)
212 WORD_LIST *list;
213 int destructive;
214 {
215 register int i;
216
217 for (i = 1; i < 10; i++)
218 {
219 if ((destructive || list) && dollar_vars[i])
220 {
221 free (dollar_vars[i]);
222 dollar_vars[i] = (char *)NULL;
223 }
224
225 if (list)
226 {
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
245 /* **************************************************************** */
246 /* */
247 /* Pushing and Popping variable contexts */
248 /* */
249 /* **************************************************************** */
250
251 static WORD_LIST **dollar_arg_stack = (WORD_LIST **)NULL;
252 static int dollar_arg_stack_slots;
253 static int dollar_arg_stack_index;
254
255 void
256 push_context ()
257 {
258 push_dollar_vars ();
259 variable_context++;
260 }
261
262 void
263 pop_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. */
271 void
272 push_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 }
280 dollar_arg_stack[dollar_arg_stack_index++] = list_rest_of_args ();
281 dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
282 }
283
284 /* Restore the positional parameters from our stack. */
285 void
286 pop_dollar_vars ()
287 {
288 if (!dollar_arg_stack || dollar_arg_stack_index == 0)
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
296 void
297 dispose_saved_dollar_vars ()
298 {
299 if (!dollar_arg_stack || dollar_arg_stack_index == 0)
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
306 static int changed_dollar_vars;
307
308 /* Have the dollar variables been reset to new values since we last
309 checked? */
310 int
311 dollar_vars_changed ()
312 {
313 return (changed_dollar_vars);
314 }
315
316 void
317 set_dollar_vars_unchanged ()
318 {
319 changed_dollar_vars = 0;
320 }
321
322 void
323 set_dollar_vars_changed ()
324 {
325 changed_dollar_vars = 1;
326 }
327
328 /* **************************************************************** */
329 /* */
330 /* Validating numeric input and arguments */
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
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. */
340 int
341 get_numeric_arg (list, fatal)
342 WORD_LIST *list;
343 int fatal;
344 {
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);
355 if (fatal)
356 throw_to_top_level ();
357 else
358 jump_to_top_level (DISCARD);
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. */
367 int
368 read_octal (string)
369 char *string;
370 {
371 int result, digits;
372
373 result = digits = 0;
374 while (*string && ISOCTAL (*string))
375 {
376 digits++;
377 result = (result * 8) + (*string++ - '0');
378 }
379
380 if (!digits || result > 0777 || *string)
381 result = -1;
382
383 return (result);
384 }
385
386 /* **************************************************************** */
387 /* */
388 /* Manipulating the current working directory */
389 /* */
390 /* **************************************************************** */
391
392 /* Return a consed string which is the current working directory.
393 FOR_WHOM is the name of the caller for error printing. */
394 char *the_current_working_directory = (char *)NULL;
395
396 char *
397 get_working_directory (for_whom)
398 char *for_whom;
399 {
400 char *directory;
401
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
410 if (the_current_working_directory == 0)
411 {
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)
416 {
417 fprintf (stderr, "%s: could not get current directory: %s: %s\n",
418 (for_whom && *for_whom) ? for_whom : get_name_for_error (),
419 bash_getcwd_errstr, strerror (errno));
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. */
431 void
432 set_working_directory (name)
433 char *name;
434 {
435 FREE (the_current_working_directory);
436 the_current_working_directory = savestring (name);
437 }
438
439 /* **************************************************************** */
440 /* */
441 /* Job control support functions */
442 /* */
443 /* **************************************************************** */
444
445 #if defined (JOB_CONTROL)
446 /* Return the job spec found in LIST. */
447 int
448 get_job_spec (list)
449 WORD_LIST *list;
450 {
451 register char *word;
452 int job, substring;
453
454 if (list == 0)
455 return (current_job);
456
457 word = list->word->word;
458
459 if (*word == '\0')
460 return (current_job);
461
462 if (*word == '%')
463 word++;
464
465 if (digit (*word) && all_digits (word))
466 {
467 job = atoi (word);
468 return (job >= job_slots ? NO_JOB : job - 1);
469 }
470
471 substring = 0;
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++;
485 /* FALLTHROUGH */
486
487 default:
488 {
489 register int i, wl;
490
491 job = NO_JOB;
492 wl = strlen (word);
493 for (i = 0; i < job_slots; i++)
494 {
495 if (jobs[i])
496 {
497 register PROCESS *p;
498 p = jobs[i]->pipe;
499 do
500 {
501 if ((substring && strindex (p->command, word)) ||
502 (STREQN (p->command, word, wl)))
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
522 int
523 display_signal_list (list, forcecols)
524 WORD_LIST *list;
525 int forcecols;
526 {
527 register int i, column;
528 char *name;
529 int result;
530 long signum;
531
532 result = EXECUTION_SUCCESS;
533 if (!list)
534 {
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;
540
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 }
556
557 if ((posixly_correct && !forcecols) || column != 0)
558 printf ("\n");
559 return result;
560 }
561
562 /* List individual signal names or numbers. */
563 while (list)
564 {
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 }
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
590 printf ("%s\n", name);
591 #endif
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;
606 }
607 return (result);
608 }
609
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.
620 DISABLED_OKAY means find it even if the builtin is disabled. */
621 struct builtin *
622 builtin_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
643 must have explicitly allowed disabled functions to be found,
644 and it must not have been deleted. */
645 if (shell_builtins[mid].function &&
646 ((shell_builtins[mid].flags & BUILTIN_DELETED) == 0) &&
647 ((shell_builtins[mid].flags & BUILTIN_ENABLED) || disabled_okay))
648 return (&shell_builtins[mid]);
649 else
650 return ((struct builtin *)NULL);
651 }
652 if (j > 0)
653 hi = mid - 1;
654 else
655 lo = mid + 1;
656 }
657 return ((struct builtin *)NULL);
658 }
659
660 /* Return the pointer to the function implementing builtin command NAME. */
661 Function *
662 find_shell_builtin (name)
663 char *name;
664 {
665 current_builtin = builtin_address_internal (name, 0);
666 return (current_builtin ? current_builtin->function : (Function *)NULL);
667 }
668
669 /* Return the address of builtin with NAME, whether it is enabled or not. */
670 Function *
671 builtin_address (name)
672 char *name;
673 {
674 current_builtin = builtin_address_internal (name, 1);
675 return (current_builtin ? current_builtin->function : (Function *)NULL);
676 }
677
678 /* Return the function implementing the builtin NAME, but only if it is a
679 POSIX.2 special builtin. */
680 Function *
681 find_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
690 static int
691 shell_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. */
704 void
705 initialize_shell_builtins ()
706 {
707 qsort (shell_builtins, num_shell_builtins, sizeof (struct builtin),
708 (QSFUNC *)shell_builtin_compare);
709 }