Imported from ../bash-1.14.7.tar.gz.
[platform/upstream/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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
18
19 #include <stdio.h>
20 #include <sys/types.h>
21 #include "../posixstat.h"
22 #if defined (HAVE_VFPRINTF)
23 #include <varargs.h>
24 #endif /* VFPRINTF */
25
26 #if defined (HAVE_STRING_H)
27 #  include <string.h>
28 #else /* !HAVE_STRING_H */
29 #  include <strings.h>
30 #endif /* !HAVE_STRING_H */
31
32 #include "../shell.h"
33 #include "../unwind_prot.h"
34 #include "../maxpath.h"
35 #include "../jobs.h"
36 #include "../builtins.h"
37 #include "../input.h"
38 #include "../execute_cmd.h"
39 #include "hashcom.h"
40 #include "common.h"
41 #include <tilde/tilde.h>
42
43 #if defined (HISTORY)
44 #  include "../bashhist.h"
45 #endif
46
47 extern int no_symbolic_links, interactive, interactive_shell;
48 extern int indirection_level, startup_state;
49 extern int last_command_exit_value;
50 extern int hashing_disabled;
51 extern int variable_context;
52 extern char *this_command_name, *shell_name;
53 extern COMMAND *global_command;
54 extern HASH_TABLE *hashed_filenames;
55
56 /* Read a numeric arg for this_command_name, the name of the shell builtin
57    that wants it.  LIST is the word list that the arg is to come from. */
58 int
59 get_numeric_arg (list)
60      WORD_LIST *list;
61 {
62   int count = 1;
63
64   if (list)
65     {
66       register char *arg;
67       int sign = 1;
68
69       arg = list->word->word;
70       if (!arg)
71         goto bad_number;
72
73       /* Skip optional leading white space. */
74       while (whitespace (*arg))
75         arg++;
76
77       if (!*arg)
78         goto bad_number;
79
80       /* We allow leading `-' or `+'. */
81       if (*arg == '-' || *arg == '+')
82         {
83           if (!digit (arg[1]))
84             goto bad_number;
85
86           if (*arg == '-')
87             sign = -1;
88
89           arg++;
90         }
91
92       for (count = 0; digit (*arg); arg++)
93         count = (count * 10) + digit_value (*arg);
94
95       /* Skip trailing whitespace, if any. */
96       while (whitespace (*arg))
97         arg++;
98
99       if (!*arg)
100         count = count * sign;
101       else
102         {
103   bad_number:
104           builtin_error ("bad non-numeric arg `%s'", list->word->word);
105           throw_to_top_level ();
106         }
107       no_args (list->next);
108     }
109   return (count);
110 }
111
112 /* This is a lot like report_error (), but it is for shell builtins
113    instead of shell control structures, and it won't ever exit the
114    shell. */
115 #if defined (HAVE_VFPRINTF)
116 void
117 builtin_error (va_alist)
118      va_dcl
119 {
120   char *format;
121   va_list args;
122
123   if (this_command_name && *this_command_name)
124     fprintf (stderr, "%s: ", this_command_name);
125
126   va_start (args);
127   format = va_arg (args, char *);
128   vfprintf (stderr, format, args);
129   va_end (args);
130   fprintf (stderr, "\n");
131 }
132 #else /* !HAVE_VFPRINTF */
133 void
134 builtin_error (format, arg1, arg2, arg3, arg4, arg5)
135      char *format, *arg1, *arg2, *arg3, *arg4, *arg5;
136 {
137   if (this_command_name && *this_command_name)
138     fprintf (stderr, "%s: ", this_command_name);
139
140   fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
141   fprintf (stderr, "\n");
142   fflush (stderr);
143 }
144 #endif /* !HAVE_VFPRINTF */
145
146 /* Remember LIST in $0 ... $9, and REST_OF_ARGS.  If DESTRUCTIVE is
147    non-zero, then discard whatever the existing arguments are, else
148    only discard the ones that are to be replaced. */
149 void
150 remember_args (list, destructive)
151      WORD_LIST *list;
152      int destructive;
153 {
154   register int i;
155
156   for (i = 1; i < 10; i++)
157     {
158       if (destructive && dollar_vars[i])
159         {
160           free (dollar_vars[i]);
161           dollar_vars[i] = (char *)NULL;
162         }
163
164       if (list)
165         {
166           if (!destructive && dollar_vars[i])
167             free (dollar_vars[i]);
168
169           dollar_vars[i] = savestring (list->word->word);
170           list = list->next;
171         }
172     }
173
174   /* If arguments remain, assign them to REST_OF_ARGS.
175      Note that copy_word_list (NULL) returns NULL, and
176      that dispose_words (NULL) does nothing. */
177   if (destructive || list)
178     {
179       dispose_words (rest_of_args);
180       rest_of_args = copy_word_list (list);
181     }
182
183   if (destructive)
184     set_dollar_vars_changed ();
185 }
186
187 /* Return if LIST is NULL else barf and jump to top_level. */
188 void
189 no_args (list)
190      WORD_LIST *list;
191 {
192   if (list)
193     {
194       builtin_error ("extra arguments");
195       longjmp (top_level, DISCARD);
196     }
197 }
198
199 /* Return the octal number parsed from STRING, or -1 to indicate
200    that the string contained a bad number. */
201 int
202 read_octal (string)
203      char *string;
204 {
205   int result = 0;
206   int digits = 0;
207
208   while (*string && *string >= '0' && *string < '8')
209     {
210       digits++;
211       result = (result * 8) + *string++ - '0';
212     }
213
214   if (!digits || result > 0777 || *string)
215     result = -1;
216
217   return (result);
218 }
219
220 /* Temporary static. */
221 static char *dotted_filename = (char *)NULL;
222
223 /* Return the full pathname that FILENAME hashes to.  If FILENAME
224    is hashed, but data->check_dot is non-zero, check ./FILENAME
225    and return that if it is executable. */
226 char *
227 find_hashed_filename (filename)
228      char *filename;
229 {
230   register BUCKET_CONTENTS *item;
231
232   if (hashing_disabled)
233     return ((char *)NULL);
234
235   item = find_hash_item (filename, hashed_filenames);
236
237   if (item)
238     {
239       /* If this filename is hashed, but `.' comes before it in the path,
240          then see if `./filename' is an executable. */
241       if (pathdata(item)->check_dot)
242         {
243           if (dotted_filename)
244             free (dotted_filename);
245
246           dotted_filename = (char *)xmalloc (3 + strlen (filename));
247           strcpy (dotted_filename, "./");
248           strcat (dotted_filename, filename);
249
250           if (executable_file (dotted_filename))
251             return (dotted_filename);
252
253           /* Watch out.  If this file was hashed to "./filename", and
254              "./filename" is not executable, then return NULL. */
255
256           /* Since we already know "./filename" is not executable, what
257              we're really interested in is whether or not the `path'
258              portion of the hashed filename is equivalent to the current
259              directory, but only if it starts with a `.'.  (This catches
260              ./. and so on.)  same_file () is in execute_cmd.c; it tests
261              general Unix file equivalence -- same device and inode. */
262           {
263             char *path = pathdata (item)->path;
264
265             if (*path == '.')
266               {
267                 int same = 0;
268                 char *tail;
269
270                 tail = (char *) strrchr (path, '/');
271
272                 if (tail)
273                   {
274                     *tail = '\0';
275                     same = same_file
276                       (".", path, (struct stat *)NULL, (struct stat *)NULL);
277                     *tail = '/';
278                   }
279                 if (same)
280                   return ((char *)NULL);
281               }
282           }
283         }
284       return (pathdata (item)->path);
285     }
286   else
287     return ((char *)NULL);
288 }
289
290 /* Remove FILENAME from the table of hashed commands. */
291 void
292 remove_hashed_filename (filename)
293      char *filename;
294 {
295   register BUCKET_CONTENTS *item;
296
297   if (hashing_disabled)
298     return;
299
300   item = remove_hash_item (filename, hashed_filenames);
301   if (item)
302     {
303       if (item->data)
304         {
305           free (pathdata(item)->path);
306           free (item->data);
307         }
308       if (item->key)
309         free (item->key);
310       free (item);
311     }
312 }
313
314 /* **************************************************************** */
315 /*                                                                  */
316 /*                  Pushing and Popping a Context                   */
317 /*                                                                  */
318 /* **************************************************************** */
319
320 static WORD_LIST **dollar_arg_stack = (WORD_LIST **)NULL;
321 static int dollar_arg_stack_slots = 0;
322 static int dollar_arg_stack_index = 0;
323
324 void
325 push_context ()
326 {
327   push_dollar_vars ();
328   variable_context++;
329 }
330
331 void
332 pop_context ()
333 {
334   pop_dollar_vars ();
335   kill_all_local_variables ();
336   variable_context--;
337 }
338
339 /* Save the existing positional parameters on a stack. */
340 void
341 push_dollar_vars ()
342 {
343   if (dollar_arg_stack_index + 2 > dollar_arg_stack_slots)
344     {
345       dollar_arg_stack = (WORD_LIST **)
346         xrealloc (dollar_arg_stack, (dollar_arg_stack_slots += 10)
347                   * sizeof (WORD_LIST **));
348     }
349   dollar_arg_stack[dollar_arg_stack_index] = list_rest_of_args ();
350   dollar_arg_stack[++dollar_arg_stack_index] = (WORD_LIST *)NULL;
351 }
352
353 /* Restore the positional parameters from our stack. */
354 void
355 pop_dollar_vars ()
356 {
357   if (!dollar_arg_stack || !dollar_arg_stack_index)
358     return;
359
360   remember_args (dollar_arg_stack[--dollar_arg_stack_index], 1);
361   dispose_words (dollar_arg_stack[dollar_arg_stack_index]);
362   dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
363 }
364
365 void
366 dispose_saved_dollar_vars ()
367 {
368   if (!dollar_arg_stack || !dollar_arg_stack_index)
369     return;
370
371   dispose_words (dollar_arg_stack[dollar_arg_stack_index]);
372   dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
373 }
374
375 static int changed_dollar_vars = 0;
376
377 /* Have the dollar variables been reset to new values since we last
378    checked? */
379 dollar_vars_changed ()
380 {
381   return (changed_dollar_vars);
382 }
383
384 void
385 set_dollar_vars_unchanged ()
386 {
387   changed_dollar_vars = 0;
388 }
389
390 void
391 set_dollar_vars_changed ()
392 {
393   changed_dollar_vars  = 1;
394 }
395
396 /* Function called when one of the builtin commands detects a bad
397    option. */
398 void
399 bad_option (s)
400      char *s;
401 {
402   builtin_error ("unknown option: %s", s);
403 }
404
405 /* Return a consed string which is the current working directory.
406    FOR_WHOM is the name of the caller for error printing.  */
407 char *the_current_working_directory = (char *)NULL;
408
409 char *
410 get_working_directory (for_whom)
411      char *for_whom;
412 {
413   if (no_symbolic_links)
414     {
415       if (the_current_working_directory)
416         free (the_current_working_directory);
417
418       the_current_working_directory = (char *)NULL;
419     }
420
421   if (!the_current_working_directory)
422     {
423       char *directory;
424
425       the_current_working_directory = xmalloc (MAXPATHLEN);
426       directory = getwd (the_current_working_directory);
427       if (!directory)
428         {
429           if (for_whom && *for_whom)
430             fprintf (stderr, "%s: ", for_whom);
431           else
432             fprintf (stderr, "%s: ", get_name_for_error ());
433
434           fprintf (stderr, "could not get current directory: %s\n",
435                    the_current_working_directory);
436
437           free (the_current_working_directory);
438           the_current_working_directory = (char *)NULL;
439           return (char *)NULL;
440         }
441     }
442
443   return (savestring (the_current_working_directory));
444 }
445
446 /* Make NAME our internal idea of the current working directory. */
447 void
448 set_working_directory (name)
449      char *name;
450 {
451   if (the_current_working_directory)
452     free (the_current_working_directory);
453
454   the_current_working_directory = savestring (name);
455 }
456
457 #if defined (JOB_CONTROL)
458 /* Return the job spec found in LIST. */
459 get_job_spec (list)
460      WORD_LIST *list;
461 {
462   register char *word;
463   int job = NO_JOB;
464   int substring = 0;
465
466   if (!list)
467     return (current_job);
468
469   word = list->word->word;
470
471   if (!*word)
472     return (current_job);
473
474   if (*word == '%')
475     word++;
476
477   if (digit (*word) && (sscanf (word, "%d", &job) == 1))
478     return (job - 1);
479
480   switch (*word)
481     {
482     case 0:
483     case '%':
484     case '+':
485       return (current_job);
486
487     case '-':
488       return (previous_job);
489
490     case '?':                   /* Substring search requested. */
491       substring++;
492       word++;
493       goto find_string;
494
495     default:
496     find_string:
497       {
498         register int i, wl = strlen (word);
499         for (i = 0; i < job_slots; i++)
500           {
501             if (jobs[i])
502               {
503                 register PROCESS *p = jobs[i]->pipe;
504                 do
505                   {
506                     if ((substring && strindex (p->command, word)) ||
507                         (strncmp (p->command, word, wl) == 0))
508                       if (job != NO_JOB)
509                         {
510                           builtin_error ("ambigious job spec: %s", word);
511                           return (DUP_JOB);
512                         }
513                       else
514                         job = i;
515
516                     p = p->next;
517                   }
518                 while (p != jobs[i]->pipe);
519               }
520           }
521         return (job);
522       }
523     }
524 }
525 #endif /* JOB_CONTROL */
526
527 int parse_and_execute_level = 0;
528
529 /* How to force parse_and_execute () to clean up after itself. */
530 void
531 parse_and_execute_cleanup ()
532 {
533   run_unwind_frame ("parse_and_execute_top");
534 }
535
536 /* Parse and execute the commands in STRING.  Returns whatever
537    execute_command () returns.  This frees STRING.  INTERACT is
538    the new value for `interactive' while the commands are being
539    executed.  A value of -1 means don't change it. */
540 int
541 parse_and_execute (string, from_file, interact)
542      char *string;
543      char *from_file;
544      int interact;
545 {
546   int last_result = EXECUTION_SUCCESS;
547   int code = 0, jump_to_top_level = 0;
548   char *orig_string = string;
549
550   /* Unwind protect this invocation of parse_and_execute (). */
551   begin_unwind_frame ("parse_and_execute_top");
552   unwind_protect_int (parse_and_execute_level);
553   unwind_protect_jmp_buf (top_level);
554   unwind_protect_int (indirection_level);
555   if (interact != -1 && interactive != interact)
556     unwind_protect_int (interactive);
557
558 #if defined (HISTORY)
559   if (interactive_shell)
560     {
561       unwind_protect_int (remember_on_history);
562 #  if defined (BANG_HISTORY)
563       unwind_protect_int (history_expansion_inhibited);
564 #  endif /* BANG_HISTORY */
565     }
566 #endif /* HISTORY */
567
568   add_unwind_protect (pop_stream, (char *)NULL);
569   if (orig_string)
570     add_unwind_protect (xfree, orig_string);
571   end_unwind_frame ();
572
573   parse_and_execute_level++;
574   push_stream ();
575   indirection_level++;
576   if (interact != -1)
577     interactive = interact;
578
579 #if defined (HISTORY)
580   /* We don't remember text read by the shell this way on
581      the history list, and we don't use !$ in shell scripts. */
582   remember_on_history = 0;
583 #  if defined (BANG_HISTORY)
584   history_expansion_inhibited = 1;
585 #  endif /* BANG_HISTORY */
586 #endif /* HISTORY */
587
588   with_input_from_string (string, from_file);
589   {
590     COMMAND *command;
591
592     while (*(bash_input.location.string))
593       {
594         if (interrupt_state)
595           {
596             last_result = EXECUTION_FAILURE;
597             break;
598           }
599
600         /* Provide a location for functions which `longjmp (top_level)' to
601            jump to.  This prevents errors in substitution from restarting
602            the reader loop directly, for example. */
603         code = setjmp (top_level);
604
605         if (code)
606           {
607             jump_to_top_level = 0;
608             switch (code)
609               {
610               case FORCE_EOF:
611               case EXITPROG:
612                 run_unwind_frame ("pe_dispose");
613                 /* Remember to call longjmp (top_level) after the old
614                    value for it is restored. */
615                 jump_to_top_level = 1;
616                 goto out;
617
618               case DISCARD:
619                 dispose_command (command);
620                 run_unwind_frame ("pe_dispose");
621                 last_command_exit_value = 1;
622                 continue;
623
624               default:
625                 programming_error ("bad jump to top_level: %d", code);
626                 break;
627               }
628           }
629           
630         if (parse_command () == 0)
631           {
632             if ((command = global_command) != (COMMAND *)NULL)
633               {
634                 struct fd_bitmap *bitmap;
635
636                 bitmap = new_fd_bitmap (FD_BITMAP_SIZE);
637                 begin_unwind_frame ("pe_dispose");
638                 add_unwind_protect (dispose_fd_bitmap, bitmap);
639
640                 global_command = (COMMAND *)NULL;
641
642 #if defined (ONESHOT)
643                 if (startup_state == 2 && *bash_input.location.string == '\0' &&
644                     command->type == cm_simple && !command->redirects &&
645                     !command->value.Simple->redirects)
646                   {
647                     command->flags |= CMD_NO_FORK;
648                     command->value.Simple->flags |= CMD_NO_FORK;
649                   }
650 #endif /* ONESHOT */
651     
652                 last_result = execute_command_internal
653                     (command, 0, NO_PIPE, NO_PIPE, bitmap);
654
655                 dispose_command (command);
656                 run_unwind_frame ("pe_dispose");
657               }
658           }
659         else
660           {
661             last_result = EXECUTION_FAILURE;
662
663             /* Since we are shell compatible, syntax errors in a script
664                abort the execution of the script.  Right? */
665             break;
666           }
667       }
668   }
669
670  out:
671
672   run_unwind_frame ("parse_and_execute_top");
673
674   if (interrupt_state && parse_and_execute_level == 0)
675     {
676       /* An interrupt during non-interactive execution in an
677          interactive shell (e.g. via $PROMPT_COMMAND) should
678          not cause the shell to exit. */
679       interactive = interactive_shell;
680       throw_to_top_level ();
681     }
682
683   if (jump_to_top_level)
684     longjmp (top_level, code);
685
686   return (last_result);
687 }
688
689 /* Return the address of the builtin named NAME.
690    DISABLED_OKAY means find it even if the builtin is disabled. */
691 static Function *
692 builtin_address_internal (name, disabled_okay)
693      char *name;
694      int disabled_okay;
695 {
696   int hi, lo, mid, j;
697
698   hi = num_shell_builtins - 1;
699   lo = 0;
700
701   while (lo <= hi)
702     {
703       mid = (lo + hi) / 2;
704
705       j = shell_builtins[mid].name[0] - name[0];
706
707       if (j == 0)
708         j = strcmp (shell_builtins[mid].name, name);
709
710       if (j == 0)
711         {
712           /* It must have a function pointer.  It must be enabled, or we
713              must have explicitly allowed disabled functions to be found. */
714           if (shell_builtins[mid].function &&
715               ((shell_builtins[mid].flags & BUILTIN_ENABLED) || disabled_okay))
716             return (shell_builtins[mid].function);
717           else
718             return ((Function *)NULL);
719         }
720       if (j > 0)
721         hi = mid - 1;
722       else
723         lo = mid + 1;
724     }
725   return ((Function *)NULL);
726 }
727
728 /* Perform a binary search and return the address of the builtin function
729    whose name is NAME.  If the function couldn't be found, or the builtin
730    is disabled or has no function associated with it, return NULL. */
731 Function *
732 find_shell_builtin (name)
733         char *name;
734 {
735   return (builtin_address_internal (name, 0));
736 }
737
738 /* Return the address of builtin with NAME, irregardless of its state of
739    enableness. */
740 Function *
741 builtin_address (name)
742      char *name;
743 {
744   return (builtin_address_internal (name, 1));
745 }
746
747 static int
748 shell_builtin_compare (sbp1, sbp2)
749      struct builtin *sbp1, *sbp2;
750 {
751   int result;
752
753   if ((result = sbp1->name[0] - sbp2->name[0]) == 0)
754     result = strcmp (sbp1->name, sbp2->name);
755
756   return (result);
757 }
758
759 /* Sort the table of shell builtins so that the binary search will work
760    in find_shell_builtin. */
761 void
762 initialize_shell_builtins ()
763 {
764   qsort (shell_builtins, num_shell_builtins, sizeof (struct builtin),
765     shell_builtin_compare);
766 }
767
768 /* Return a new string which is the quoted version of STRING.  This is used
769    by alias and trap. */
770 char *
771 single_quote (string)
772      char *string;
773 {
774   register int i, j, c;
775   char *result;
776
777   result = (char *)xmalloc (3 + (3 * strlen (string)));
778
779   result[0] = '\'';
780
781   for (i = 0, j = 1; string && (c = string[i]); i++)
782     {
783       result[j++] = c;
784
785       if (c == '\'')
786         {
787           result[j++] = '\\';   /* insert escaped single quote */
788           result[j++] = '\'';
789           result[j++] = '\'';   /* start new quoted string */
790         }
791     }
792
793   result[j++] = '\'';
794   result[j] = '\0';
795
796   return (result);
797 }
798
799 char *
800 double_quote (string)
801      char *string;
802 {
803   register int i, j, c;
804   char *result;
805
806   result = (char *)xmalloc (3 + (3 * strlen (string)));
807
808   result[0] = '"';
809
810   for (i = 0, j = 1; string && (c = string[i]); i++)
811     {
812       switch (c)
813         {
814         case '"':
815         case '$':
816         case '`':
817         case '\\':
818           result[j++] = '\\';
819         default:
820           result[j++] = c;
821           break;
822         }
823     }
824
825   result[j++] = '"';
826   result[j] = '\0';
827
828   return (result);
829 }