1 /* copy_command.c -- copy a COMMAND structure.  This is needed
2    primarily for making function definitions, but I'm not sure
3    that anyone else will need it.  */
4 
5 /* Copyright (C) 1987-2020 Free Software Foundation, Inc.
6 
7    This file is part of GNU Bash, the Bourne Again SHell.
8 
9    Bash is free software: you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation, either version 3 of the License, or
12    (at your option) any later version.
13 
14    Bash is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with Bash.  If not, see <http://www.gnu.org/licenses/>.
21 */
22 
23 #include "config.h"
24 
25 #include "bashtypes.h"
26 
27 #if defined (HAVE_UNISTD_H)
28 #  include <unistd.h>
29 #endif
30 
31 #include <stdio.h>
32 
33 #include "shell.h"
34 
35 static PATTERN_LIST *copy_case_clause PARAMS((PATTERN_LIST *));
36 static PATTERN_LIST *copy_case_clauses PARAMS((PATTERN_LIST *));
37 static FOR_COM *copy_for_command PARAMS((FOR_COM *));
38 #if defined (ARITH_FOR_COMMAND)
39 static ARITH_FOR_COM *copy_arith_for_command PARAMS((ARITH_FOR_COM *));
40 #endif
41 static GROUP_COM *copy_group_command PARAMS((GROUP_COM *));
42 static SUBSHELL_COM *copy_subshell_command PARAMS((SUBSHELL_COM *));
43 static COPROC_COM *copy_coproc_command PARAMS((COPROC_COM *));
44 static CASE_COM *copy_case_command PARAMS((CASE_COM *));
45 static WHILE_COM *copy_while_command PARAMS((WHILE_COM *));
46 static IF_COM *copy_if_command PARAMS((IF_COM *));
47 #if defined (DPAREN_ARITHMETIC)
48 static ARITH_COM *copy_arith_command PARAMS((ARITH_COM *));
49 #endif
50 #if defined (COND_COMMAND)
51 static COND_COM *copy_cond_command PARAMS((COND_COM *));
52 #endif
53 static SIMPLE_COM *copy_simple_command PARAMS((SIMPLE_COM *));
54 
55 WORD_DESC *
copy_word(w)56 copy_word (w)
57      WORD_DESC *w;
58 {
59   WORD_DESC *new_word;
60 
61   new_word = make_bare_word (w->word);
62   new_word->flags = w->flags;
63   return (new_word);
64 }
65 
66 /* Copy the chain of words in LIST.  Return a pointer to
67    the new chain. */
68 WORD_LIST *
copy_word_list(list)69 copy_word_list (list)
70      WORD_LIST *list;
71 {
72   WORD_LIST *new_list, *tl;
73 
74   for (new_list = tl = (WORD_LIST *)NULL; list; list = list->next)
75     {
76       if (new_list == 0)
77 	new_list = tl = make_word_list (copy_word (list->word), new_list);
78       else
79 	{
80 	  tl->next = make_word_list (copy_word (list->word), (WORD_LIST *)NULL);
81 	  tl = tl->next;
82 	}
83     }
84 
85   return (new_list);
86 }
87 
88 static PATTERN_LIST *
copy_case_clause(clause)89 copy_case_clause (clause)
90      PATTERN_LIST *clause;
91 {
92   PATTERN_LIST *new_clause;
93 
94   new_clause = (PATTERN_LIST *)xmalloc (sizeof (PATTERN_LIST));
95   new_clause->patterns = copy_word_list (clause->patterns);
96   new_clause->action = copy_command (clause->action);
97   new_clause->flags = clause->flags;
98   return (new_clause);
99 }
100 
101 static PATTERN_LIST *
copy_case_clauses(clauses)102 copy_case_clauses (clauses)
103      PATTERN_LIST *clauses;
104 {
105   PATTERN_LIST *new_list, *new_clause;
106 
107   for (new_list = (PATTERN_LIST *)NULL; clauses; clauses = clauses->next)
108     {
109       new_clause = copy_case_clause (clauses);
110       new_clause->next = new_list;
111       new_list = new_clause;
112     }
113   return (REVERSE_LIST (new_list, PATTERN_LIST *));
114 }
115 
116 /* Copy a single redirect. */
117 REDIRECT *
copy_redirect(redirect)118 copy_redirect (redirect)
119      REDIRECT *redirect;
120 {
121   REDIRECT *new_redirect;
122 
123   new_redirect = (REDIRECT *)xmalloc (sizeof (REDIRECT));
124 #if 0
125   FASTCOPY ((char *)redirect, (char *)new_redirect, (sizeof (REDIRECT)));
126 #else
127   *new_redirect = *redirect;	/* let the compiler do the fast structure copy */
128 #endif
129 
130   if (redirect->rflags & REDIR_VARASSIGN)
131     new_redirect->redirector.filename = copy_word (redirect->redirector.filename);
132 
133   switch (redirect->instruction)
134     {
135     case r_reading_until:
136     case r_deblank_reading_until:
137       new_redirect->here_doc_eof = redirect->here_doc_eof ? savestring (redirect->here_doc_eof) : 0;
138       /*FALLTHROUGH*/
139     case r_reading_string:
140     case r_appending_to:
141     case r_output_direction:
142     case r_input_direction:
143     case r_inputa_direction:
144     case r_err_and_out:
145     case r_append_err_and_out:
146     case r_input_output:
147     case r_output_force:
148     case r_duplicating_input_word:
149     case r_duplicating_output_word:
150     case r_move_input_word:
151     case r_move_output_word:
152       new_redirect->redirectee.filename = copy_word (redirect->redirectee.filename);
153       break;
154     case r_duplicating_input:
155     case r_duplicating_output:
156     case r_move_input:
157     case r_move_output:
158     case r_close_this:
159       break;
160     }
161   return (new_redirect);
162 }
163 
164 REDIRECT *
copy_redirects(list)165 copy_redirects (list)
166      REDIRECT *list;
167 {
168   REDIRECT *new_list, *temp;
169 
170   for (new_list = (REDIRECT *)NULL; list; list = list->next)
171     {
172       temp = copy_redirect (list);
173       temp->next = new_list;
174       new_list = temp;
175     }
176   return (REVERSE_LIST (new_list, REDIRECT *));
177 }
178 
179 static FOR_COM *
copy_for_command(com)180 copy_for_command (com)
181      FOR_COM *com;
182 {
183   FOR_COM *new_for;
184 
185   new_for = (FOR_COM *)xmalloc (sizeof (FOR_COM));
186   new_for->flags = com->flags;
187   new_for->line = com->line;
188   new_for->name = copy_word (com->name);
189   new_for->map_list = copy_word_list (com->map_list);
190   new_for->action = copy_command (com->action);
191   return (new_for);
192 }
193 
194 #if defined (ARITH_FOR_COMMAND)
195 static ARITH_FOR_COM *
copy_arith_for_command(com)196 copy_arith_for_command (com)
197      ARITH_FOR_COM *com;
198 {
199   ARITH_FOR_COM *new_arith_for;
200 
201   new_arith_for = (ARITH_FOR_COM *)xmalloc (sizeof (ARITH_FOR_COM));
202   new_arith_for->flags = com->flags;
203   new_arith_for->line = com->line;
204   new_arith_for->init = copy_word_list (com->init);
205   new_arith_for->test = copy_word_list (com->test);
206   new_arith_for->step = copy_word_list (com->step);
207   new_arith_for->action = copy_command (com->action);
208   return (new_arith_for);
209 }
210 #endif /* ARITH_FOR_COMMAND */
211 
212 static GROUP_COM *
copy_group_command(com)213 copy_group_command (com)
214      GROUP_COM *com;
215 {
216   GROUP_COM *new_group;
217 
218   new_group = (GROUP_COM *)xmalloc (sizeof (GROUP_COM));
219   new_group->command = copy_command (com->command);
220   return (new_group);
221 }
222 
223 static SUBSHELL_COM *
copy_subshell_command(com)224 copy_subshell_command (com)
225      SUBSHELL_COM *com;
226 {
227   SUBSHELL_COM *new_subshell;
228 
229   new_subshell = (SUBSHELL_COM *)xmalloc (sizeof (SUBSHELL_COM));
230   new_subshell->command = copy_command (com->command);
231   new_subshell->flags = com->flags;
232   new_subshell->line = com->line;
233   return (new_subshell);
234 }
235 
236 static COPROC_COM *
copy_coproc_command(com)237 copy_coproc_command (com)
238      COPROC_COM *com;
239 {
240   COPROC_COM *new_coproc;
241 
242   new_coproc = (COPROC_COM *)xmalloc (sizeof (COPROC_COM));
243   new_coproc->name = savestring (com->name);
244   new_coproc->command = copy_command (com->command);
245   new_coproc->flags = com->flags;
246   return (new_coproc);
247 }
248 
249 static CASE_COM *
copy_case_command(com)250 copy_case_command (com)
251      CASE_COM *com;
252 {
253   CASE_COM *new_case;
254 
255   new_case = (CASE_COM *)xmalloc (sizeof (CASE_COM));
256   new_case->flags = com->flags;
257   new_case->line = com->line;
258   new_case->word = copy_word (com->word);
259   new_case->clauses = copy_case_clauses (com->clauses);
260   return (new_case);
261 }
262 
263 static WHILE_COM *
copy_while_command(com)264 copy_while_command (com)
265      WHILE_COM *com;
266 {
267   WHILE_COM *new_while;
268 
269   new_while = (WHILE_COM *)xmalloc (sizeof (WHILE_COM));
270   new_while->flags = com->flags;
271   new_while->test = copy_command (com->test);
272   new_while->action = copy_command (com->action);
273   return (new_while);
274 }
275 
276 static IF_COM *
copy_if_command(com)277 copy_if_command (com)
278      IF_COM *com;
279 {
280   IF_COM *new_if;
281 
282   new_if = (IF_COM *)xmalloc (sizeof (IF_COM));
283   new_if->flags = com->flags;
284   new_if->test = copy_command (com->test);
285   new_if->true_case = copy_command (com->true_case);
286   new_if->false_case = com->false_case ? copy_command (com->false_case) : com->false_case;
287   return (new_if);
288 }
289 
290 #if defined (DPAREN_ARITHMETIC)
291 static ARITH_COM *
copy_arith_command(com)292 copy_arith_command (com)
293      ARITH_COM *com;
294 {
295   ARITH_COM *new_arith;
296 
297   new_arith = (ARITH_COM *)xmalloc (sizeof (ARITH_COM));
298   new_arith->flags = com->flags;
299   new_arith->exp = copy_word_list (com->exp);
300   new_arith->line = com->line;
301 
302   return (new_arith);
303 }
304 #endif
305 
306 #if defined (COND_COMMAND)
307 static COND_COM *
copy_cond_command(com)308 copy_cond_command (com)
309      COND_COM *com;
310 {
311   COND_COM *new_cond;
312 
313   new_cond = (COND_COM *)xmalloc (sizeof (COND_COM));
314   new_cond->flags = com->flags;
315   new_cond->line = com->line;
316   new_cond->type = com->type;
317   new_cond->op = com->op ? copy_word (com->op) : com->op;
318   new_cond->left = com->left ? copy_cond_command (com->left) : (COND_COM *)NULL;
319   new_cond->right = com->right ? copy_cond_command (com->right) : (COND_COM *)NULL;
320 
321   return (new_cond);
322 }
323 #endif
324 
325 static SIMPLE_COM *
copy_simple_command(com)326 copy_simple_command (com)
327      SIMPLE_COM *com;
328 {
329   SIMPLE_COM *new_simple;
330 
331   new_simple = (SIMPLE_COM *)xmalloc (sizeof (SIMPLE_COM));
332   new_simple->flags = com->flags;
333   new_simple->words = copy_word_list (com->words);
334   new_simple->redirects = com->redirects ? copy_redirects (com->redirects) : (REDIRECT *)NULL;
335   new_simple->line = com->line;
336   return (new_simple);
337 }
338 
339 FUNCTION_DEF *
copy_function_def_contents(old,new_def)340 copy_function_def_contents (old, new_def)
341      FUNCTION_DEF *old, *new_def;
342 {
343   new_def->name = copy_word (old->name);
344   new_def->command = old->command ? copy_command (old->command) : old->command;
345   new_def->flags = old->flags;
346   new_def->line = old->line;
347   new_def->source_file = old->source_file ? savestring (old->source_file) : old->source_file;
348   return (new_def);
349 }
350 
351 FUNCTION_DEF *
copy_function_def(com)352 copy_function_def (com)
353      FUNCTION_DEF *com;
354 {
355   FUNCTION_DEF *new_def;
356 
357   new_def = (FUNCTION_DEF *)xmalloc (sizeof (FUNCTION_DEF));
358   new_def = copy_function_def_contents (com, new_def);
359   return (new_def);
360 }
361 
362 /* Copy the command structure in COMMAND.  Return a pointer to the
363    copy.  Don't you forget to dispose_command () on this pointer
364    later! */
365 COMMAND *
copy_command(command)366 copy_command (command)
367      COMMAND *command;
368 {
369   COMMAND *new_command;
370 
371   if (command == NULL)
372     return (command);
373 
374   new_command = (COMMAND *)xmalloc (sizeof (COMMAND));
375   FASTCOPY ((char *)command, (char *)new_command, sizeof (COMMAND));
376   new_command->flags = command->flags;
377   new_command->line = command->line;
378 
379   if (command->redirects)
380     new_command->redirects = copy_redirects (command->redirects);
381 
382   switch (command->type)
383     {
384       case cm_for:
385 	new_command->value.For = copy_for_command (command->value.For);
386 	break;
387 
388 #if defined (ARITH_FOR_COMMAND)
389       case cm_arith_for:
390 	new_command->value.ArithFor = copy_arith_for_command (command->value.ArithFor);
391 	break;
392 #endif
393 
394 #if defined (SELECT_COMMAND)
395       case cm_select:
396 	new_command->value.Select =
397 	  (SELECT_COM *)copy_for_command ((FOR_COM *)command->value.Select);
398 	break;
399 #endif
400 
401       case cm_group:
402 	new_command->value.Group = copy_group_command (command->value.Group);
403 	break;
404 
405       case cm_subshell:
406 	new_command->value.Subshell = copy_subshell_command (command->value.Subshell);
407 	break;
408 
409       case cm_coproc:
410 	new_command->value.Coproc = copy_coproc_command (command->value.Coproc);
411 	break;
412 
413       case cm_case:
414 	new_command->value.Case = copy_case_command (command->value.Case);
415 	break;
416 
417       case cm_until:
418       case cm_while:
419 	new_command->value.While = copy_while_command (command->value.While);
420 	break;
421 
422       case cm_if:
423 	new_command->value.If = copy_if_command (command->value.If);
424 	break;
425 
426 #if defined (DPAREN_ARITHMETIC)
427       case cm_arith:
428 	new_command->value.Arith = copy_arith_command (command->value.Arith);
429 	break;
430 #endif
431 
432 #if defined (COND_COMMAND)
433       case cm_cond:
434 	new_command->value.Cond = copy_cond_command (command->value.Cond);
435 	break;
436 #endif
437 
438       case cm_simple:
439 	new_command->value.Simple = copy_simple_command (command->value.Simple);
440 	break;
441 
442       case cm_connection:
443 	{
444 	  CONNECTION *new_connection;
445 
446 	  new_connection = (CONNECTION *)xmalloc (sizeof (CONNECTION));
447 	  new_connection->connector = command->value.Connection->connector;
448 	  new_connection->first = copy_command (command->value.Connection->first);
449 	  new_connection->second = copy_command (command->value.Connection->second);
450 	  new_command->value.Connection = new_connection;
451 	  break;
452 	}
453 
454       case cm_function_def:
455 	new_command->value.Function_def = copy_function_def (command->value.Function_def);
456 	break;
457     }
458   return (new_command);
459 }
460