source: vis_dev/vis-2.3/src/cmd/cmdCmd.c

Last change on this file was 14, checked in by cecile, 13 years ago

vis2.3

File size: 24.7 KB
Line 
1/**CFile***********************************************************************
2
3  FileName    [cmdCmd.c]
4
5  PackageName [cmd]
6
7  Synopsis    [Command table and command execution.]
8
9  Author      [Originated from SIS]
10
11  Copyright   [Copyright (c) 1994-1996 The Regents of the Univ. of California.
12  All rights reserved.
13
14  Permission is hereby granted, without written agreement and without license
15  or royalty fees, to use, copy, modify, and distribute this software and its
16  documentation for any purpose, provided that the above copyright notice and
17  the following two paragraphs appear in all copies of this software.
18
19  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
20  DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
21  OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
22  CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
24  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
25  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
26  FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN
27  "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE
28  MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.]
29
30******************************************************************************/
31
32#include "cmdInt.h"
33
34static char rcsid[] UNUSED = "$Id: cmdCmd.c,v 1.16 2005/04/16 04:23:02 fabio Exp $";
35
36/*---------------------------------------------------------------------------*/
37/* Stucture declarations                                                     */
38/*---------------------------------------------------------------------------*/
39
40/**Struct**********************************************************************
41
42  Synopsis    [required]
43
44  Description [optional]
45
46  SeeAlso     [optional]
47
48******************************************************************************/
49typedef struct CommandDescrStruct {
50  char *name;
51  PFI command_fp;
52  int changes_hmgr;
53} CommandDescr_t;
54
55
56/*---------------------------------------------------------------------------*/
57/* Variable declarations                                                     */
58/*---------------------------------------------------------------------------*/
59Hrc_Manager_t *cmdBackupHmgr;
60avl_tree *cmdCommandTable;
61
62static char visShellChar = '!';      /* can be reset using the "set shell_char" */
63
64static int autoexec;            /* indicates currently in autoexec */
65static jmp_buf env;
66
67
68/**AutomaticStart*************************************************************/
69
70/*---------------------------------------------------------------------------*/
71/* Static function prototypes                                                */
72/*---------------------------------------------------------------------------*/
73
74static int com_dispatch(Hrc_Manager_t ** hmgr, int argc, char ** argv);
75static int apply_alias(Hrc_Manager_t ** hmgr, int * argcp, char *** argvp, int * loop);
76static void variableInterpolation(int *argc, char ***argv);
77static char * variableInterpolationRecur(char *str);
78static char * split_line(char * command, int * argc, char *** argv);
79static int check_shell_escape(char * p, int * status);
80static void sigterm(int sig);
81
82/**AutomaticEnd***************************************************************/
83
84
85/*---------------------------------------------------------------------------*/
86/* Definition of exported functions                                          */
87/*---------------------------------------------------------------------------*/
88
89/**Function********************************************************************
90
91  Synopsis    [Adds a command to the command table.]
92
93  Description [Adds a command to the command table.  If name already defines
94  an existing command, its definition is replaced.  FuncFp is a function
95  pointer to code of the form: <p>
96
97                int <br>
98                CommandTest(hmgr, argc, argv)<br>
99                  Hrc_Manager_t **hmgr;<br>
100                  int argc;<br>
101                  char **argv;<br>
102                {<br>
103                    return 0;<br>
104                }<p>
105
106  Note the double de-reference on the hmgr which is passed to the command;
107  this allows the command to replace the current hmgr.  argv\[0\] will generally
108  be the command name, and argv\[1\] ... argv\[argc-1\] are the arguments for the
109  command.  util_getopt() can be used to parse the arguments, but
110  util_getopt_reset() must be used before calling util_getopt().  The command
111  function should return 0 for normal operation, 1 for any error.  The changes
112  flag is used to automatically save the hmgr before executing the command (in
113  order to support undo).]
114
115  SideEffects []
116
117******************************************************************************/
118void
119Cmd_CommandAdd(
120  char * name,
121  PFI  funcFp,
122  int  changes)
123{
124  char *key, *value;
125  CommandDescr_t *descr;
126  int status;
127
128  key = name;
129  if (avl_delete(cmdCommandTable, &key, &value)) {
130    /* delete existing definition for this command */
131    (void) fprintf
132      (vis_stderr, "** cmd warning: redefining '%s'\n", name);
133    CmdCommandFree(value);
134  }
135
136  descr = ALLOC(CommandDescr_t, 1);
137  descr->name = util_strsav(name);
138  descr->command_fp = funcFp;
139  descr->changes_hmgr = changes;
140  status = avl_insert(cmdCommandTable, descr->name, (char *) descr);
141  assert(!status);  /* error here in SIS version, TRS, 8/4/95 */
142}
143
144
145/**Function********************************************************************
146
147  Synopsis    [Executes a command line.]
148
149  Description [Executes a command line.  This is the top-level of the command
150  interpreter, and supports multiple commands (separated by ;), alias
151  substitution, etc.  For many simple operations, Cmd_CommandExecute() is the
152  easiest way to accomplish a given task. For example, to set a variable, use
153  the code: Cmd_CommandExecute(&hmgr, "set color blue").]
154
155  SideEffects []
156
157******************************************************************************/
158int
159Cmd_CommandExecute(
160  Hrc_Manager_t ** hmgr,
161  char * command)
162{
163  int status, argc;
164  int loop;
165  char *commandp, **argv;
166
167  (void) signal(SIGINT, SIG_IGN);
168  commandp = command;
169  do {
170    if (check_shell_escape(commandp, &status)) {
171      break;
172    }
173   
174    commandp = split_line(commandp, &argc, &argv);
175    loop = 0;
176    status = apply_alias(hmgr, &argc, &argv, &loop);
177    if (status == 0) {
178
179      variableInterpolation(&argc, &argv);
180
181      status = com_dispatch(hmgr, argc, argv);
182    }
183    CmdFreeArgv(argc, argv);
184  } while (status == 0 && *commandp != '\0');
185  return status;
186}
187
188
189
190/*---------------------------------------------------------------------------*/
191/* Definition of internal functions                                          */
192/*---------------------------------------------------------------------------*/
193
194
195/**Function********************************************************************
196
197  Synopsis    [required]
198
199  Description [optional]
200
201  SideEffects [required]
202
203  SeeAlso     [optional]
204
205******************************************************************************/
206void
207CmdCommandFree(
208  char * value)
209{
210  CommandDescr_t *command = (CommandDescr_t *) value;
211
212  FREE(command->name);          /* same as key */
213  FREE(command);
214}
215
216
217/*---------------------------------------------------------------------------*/
218/* Definition of static functions                                            */
219/*---------------------------------------------------------------------------*/
220
221/**Function********************************************************************
222
223  Synopsis    [required]
224
225  Description [optional]
226
227  SideEffects [required]
228
229  SeeAlso     [optional]
230
231******************************************************************************/
232static int
233com_dispatch(
234  Hrc_Manager_t ** hmgr,
235  int  argc,
236  char ** argv)
237{
238  int status;
239  char *value;
240  CommandDescr_t *descr;
241
242  if (argc == 0) {              /* empty command */
243    return 0;
244  }
245
246  if (! avl_lookup(cmdCommandTable, argv[0], &value)) {
247    (void) fprintf(vis_stderr, "** cmd error: unknown command '%s'\n", argv[0]);
248    return 1;
249  }
250
251  descr = (CommandDescr_t *) value;
252  if (setjmp(env)) {
253#if 0
254    /* FIX (Tom) need hmgr_dup and network_dup to use this functionality */
255    /* return from control-c -- restore the hmgr */
256    if (descr->changes_hmgr) {
257      *hmgr = cmdBackupHmgr;
258      cmdBackupHmgr = NIL(Hrc_Manager_t);
259    }
260#endif
261    return 1;
262  }
263
264 
265#if 0
266  /* FIX (Tom) need hmgr_dup and network_dup to use this functionality */
267  if (descr->changes_hmgr) {
268    if (cmdBackupHmgr != NIL(Hrc_Manager_t)) {
269      Hrc_ManagerFree(cmdBackupHmgr);
270    }
271    cmdBackupHmgr = hmgr_dup(*hmgr);
272  }
273#endif
274 
275  (void) signal(SIGINT, sigterm);
276  status = (*descr->command_fp)(hmgr, argc, argv);
277
278  /* automatic execution of arbitrary command after each command */
279  /* usually this is a passive command ... */
280  if (status == 0 && ! autoexec) {
281    if (avl_lookup(cmdFlagTable, "autoexec", &value)) {
282      autoexec = 1;
283      status = Cmd_CommandExecute(hmgr, value);
284      autoexec = 0;
285    }
286  }
287
288  (void) signal(SIGINT, SIG_IGN);
289  return status;
290}
291
292
293/**Function********************************************************************
294
295  Synopsis    [required]
296
297  Description [Applies alias.  If perform a history substitution in expanding
298  an alias, remove all the orginal trailing arguments.  For example:<p>
299
300    > alias t rl \!:1<br>
301    > t lion.blif  would otherwise expand to   rl lion.blif lion.blif <br>]
302
303  SideEffects [required]
304
305  SeeAlso     [optional]
306
307******************************************************************************/
308static int
309apply_alias(
310  Hrc_Manager_t ** hmgr,
311  int * argcp,
312  char *** argvp,
313  int * loop)
314{
315  int i, argc, stopit, added, offset, did_subst, subst, status, newc, j;
316  char *arg, **argv, **newv;
317  CmdAliasDescr_t *alias;
318
319  argc = *argcp;
320  argv = *argvp;
321  stopit = 0;
322  for(; *loop < 20; (*loop)++) {
323    if (argc == 0) {
324      return 0;
325    }
326    if (stopit != 0 || avl_lookup(cmdAliasTable, argv[0], &alias) == 0) {
327      return 0;
328    }
329    if (strcmp(argv[0], alias->argv[0]) == 0) {
330      stopit = 1;
331    }
332    FREE(argv[0]);
333    added = alias->argc - 1;
334
335    /* shift all the arguments to the right */
336    if (added != 0) {
337      argv = REALLOC(char *, argv, argc + added);
338      for (i = argc - 1; i >= 1; i--) {
339        argv[i + added] = argv[i];
340      }
341      for (i = 1; i <= added; i++) {
342        argv[i] = NIL(char);
343      }
344      argc += added;
345    }
346    subst = 0;
347    for (i = 0, offset = 0; i < alias->argc; i++, offset++) {
348      arg = CmdHistorySubstitution(alias->argv[i], &did_subst);
349      if (arg == NIL(char)) {
350        *argcp = argc;
351        *argvp = argv;
352        return(1);
353      }
354      if (did_subst != 0) {
355        subst = 1;
356      }
357      status = 0;
358      do {
359        arg = split_line(arg, &newc, &newv);
360        /*
361         * If there's a complete `;' terminated command in `arg',
362         * when split_line() returns arg[0] != '\0'.
363         */
364        if (arg[0] == '\0') {   /* just a bunch of words */
365          break;
366        }
367        status = apply_alias(hmgr, &newc, &newv, loop);
368        if (status == 0) {
369          status = com_dispatch(hmgr, newc, newv);
370        }
371        CmdFreeArgv(newc, newv);
372      } while (status == 0);
373      if (status != 0) {
374        *argcp = argc;
375        *argvp = argv;
376        return(1);
377      }
378      added = newc - 1;
379      if (added != 0) {
380        argv = REALLOC(char *, argv, argc + added);
381        for (j = argc - 1; j > offset; j--) {
382          argv[j + added] = argv[j];
383        }
384        argc += added;
385      }
386      for (j = 0; j <= added; j++) {
387        argv[j + offset] = newv[j];
388      }
389      FREE(newv);
390      offset += added;
391    }
392    if (subst == 1) {
393      for (i = offset; i < argc; i++) {
394        FREE(argv[i]);
395      }
396      argc = offset;
397    }
398    *argcp = argc;
399    *argvp = argv;
400  }
401
402  (void) fprintf(vis_stderr, "** cmd error: alias loop\n");
403  return 1;
404}
405
406
407/**Function********************************************************************
408
409  Synopsis    [Allows interpolation of variables]
410
411  Description [Allows interpolation of variables. Here it is implemented by
412  allowing variables to be referred to with the prefix of '$'. The variables
413  are set using the "set" command. So for example, the following can be done <p>
414
415  <code>
416  vis> set foo bar <br>
417  vis> echo $foo <br>
418  bar <br>
419  </code>
420 
421  The last line "bar" will the output produced by vis.
422
423  The following can also be done: <p>
424 
425  <code>
426  vis> set foo $foo:foobar <br>
427  vis> echo $foobar <br>
428  bar:foobar <br>
429  </code>
430  The last line will be the output produced by vis. <p>
431
432  These variables can
433  be used in recursive definitions. The following termination characters are
434  recognized for the variables \\n, \\0, ' ', \\t,  :,  ;,  #,  /.
435
436  Although the set command allows the usage of the some of the
437  above termination characters between quotes,
438  the variable interpolation procedure has the restriction
439  that the two characters ':' and '/' may not be used with quotes.
440  A variable with spaces in it may be used only if it is enclosed
441  within quotes. ]
442
443  SideEffects [required]
444
445  SeeAlso     [optional]
446
447******************************************************************************/
448
449static void
450variableInterpolation(int *ori_argc, char ***ori_argv)
451{
452  int i;          /* to iterate through the arguments */
453  char *newStr;   /* string returned by the expanded value */
454  char dollar;    /* character to store reference to the variable, now '$' */
455  int argc;
456  char **argv;
457  int index;
458  int null_string_flag;
459
460  argc = *ori_argc;
461  argv = *ori_argv;
462
463  dollar = '$';
464  null_string_flag = 0;
465
466  /* step through all argvs */
467  for (i = 0; i < argc; i++) {
468    if (strchr((char *)argv[i], (int)dollar) != NULL) {
469      /* expanded string returned by the procedure */
470      newStr = variableInterpolationRecur(argv[i]);
471      if(!strcmp(newStr, " ")) {
472        FREE(argv[i]);
473        /* replace old value with new */
474        argv[i] = 0;
475        null_string_flag = 1;
476      }
477      else {
478        FREE(argv[i]);
479        /* replace old value with new */
480        argv[i] = newStr;
481      }
482    }
483  } /* end of iterating through all arguments */
484
485  if(null_string_flag) {
486    *ori_argv = ALLOC(char *, argc);
487    index = 0;
488    for (i = 0; i < argc; i++) {
489      if(argv[i] == 0) {
490        (*ori_argc)--;
491        continue;
492      }
493      (*ori_argv)[index++] = argv[i];
494    }
495    FREE(argv);
496  }
497
498  return;
499}/* end of variable interpolation */
500
501
502/**Function********************************************************************
503
504  Synopsis    [Recursive procedure that expands the interpolation variables]
505
506  Description [Recursive procedure that expands the interpolation variables.
507  This procedure is designed to handle multiple occurrences of variables
508  in a string and recursive definitions. If the expanded variable has another
509  variable, then the procedure is called recursively. The existence of a
510  variable is identified by the $ sign in the string. But since this may be
511  an environment variable too, the variable is untouched if not found in
512  this table. A sophisticated check can be made to see if this variable
513  exists in the environment, but it is NOT done here. Therefore, detection
514  of bogus values cannot be done. The procedure steps through the string
515  to see if any variables are present. If a termination character (one of
516  :, /) is found after the '$', then the variable
517  is identified and looked up in the flag table. If the returned string again
518  has a dollar, then the procedure is called recursively. If not, the returned
519  value replaces the variable and the stepping through continues. If the
520  variable is not found, then it might be an environment variable.So the
521  procedure leaves the variable there. ]
522
523  SideEffects [required]
524
525  SeeAlso     [optional]
526
527******************************************************************************/
528
529static char *
530variableInterpolationRecur(char *str)
531{
532  int i;               /* iterators */
533  int findEndDollar;   /* flag to denote that a $ has been found. So
534                        * search till end of variable
535                        */
536  int endDollarIndex;  /* index in the current string of the end of the
537                        * variable
538                        */
539  int dollarIndex;     /* index in the current string of the dollar sign */ 
540  int singleQuote;     /* flag that symbolizes that a quote is started */ 
541  int doubleQuote;     /* flag that symbolizes that a quote is started */
542  char *value;         /* value of the variable that is returned by the table */
543  char *subStr;        /* string to store the variable */
544  int curStrIndex;     /* index to step through the current string */
545  int subLen;          /* length of the variable */
546  int index;           /* variable use to step through the various strings */
547  char *curStr;        /* current string which may change as substitutions
548                        * take place
549                        */
550  char *newCurStr;     /* new string pieced together with the expanded value */
551  char c;              /* current character in the string */
552
553  int freeNewValue;    /* new value of string returned by recursion needs
554                        * to be freed.
555                        */
556  char dollar;         /* character that stores the dollar sign */
557  int lastPos;         /* position of the last character of the variable
558                        * in the string.
559                        */
560  int envVar;           /* flag to say that the variable is not found in
561                         * the table, hence may be an environment variable
562                         */
563
564  dollar = '$';
565  curStrIndex = 0;
566  subLen = 0;
567  findEndDollar = 0;
568  singleQuote = 0;
569  doubleQuote = 0;
570  dollarIndex = -1;
571  endDollarIndex = -1;
572  /* make a local copy since the string may change */
573  curStr = ALLOC(char, strlen(str)+1);
574  curStr = strncpy(curStr, str, strlen(str)+1);
575  /* search through the end of string including te \0 character to detect
576   * end of variable, if required.
577   */
578  while (curStrIndex <= (int) strlen(curStr)) {
579    /* current character */
580    c = curStr[curStrIndex];
581    /* redundant here since split_line already strips out the quotes */
582    if ((c == '\"') || (c == '\'')) {
583      /* also termination charactrers for $ */
584      /* set flags for quote found */
585      singleQuote = !singleQuote;
586      doubleQuote = !doubleQuote;
587      /* also a variable termination */
588      if (findEndDollar) {
589        findEndDollar = 0;
590        endDollarIndex = curStrIndex;
591      }
592    }
593    /* detect a $ if not within quotes */
594    if ((c == '$') && (!singleQuote) && (!doubleQuote)) {
595      if (findEndDollar == 1) {
596        error_append("Cannot have nested $ signs, not found termination\n");
597        break;
598      }
599      /* note the beginning of the dollar position */
600      dollarIndex = curStrIndex;
601      /* start quest for end of dollar */
602      findEndDollar = 1;
603      endDollarIndex = -1;
604    }
605    /* termination characters are \0, :, / when not within quotes.
606     * Although, some of these may never be encountered
607     * since this is called after split_line and apply_alias
608     * Termination characters except '\0' are ignored within quotes
609     */
610    if ((findEndDollar) &&
611        ((c == '\0') ||
612         ((!singleQuote) && (!doubleQuote) &&
613          ((c == ':') || (c == '/'))))) {
614      /*     if (((c == '\n') || (c == '\t') || (isspace(c)) ||
615        (c == ':') || (c == ';') || (c == '\0') ||
616        (c == '#') || (c == '/')) && (findEndDollar)) { */
617        findEndDollar = 0;
618        endDollarIndex = curStrIndex;
619    } /* end of find termination characters */
620
621    /* found the interpolation variable and its end*/
622    if (!findEndDollar && (endDollarIndex != -1)) {
623      /* found an interpolation variable */
624      subLen = 0;
625      freeNewValue = 0;
626      envVar = 0;
627      subStr = NULL;
628      if (endDollarIndex > (dollarIndex +1)) {
629        /* if not empty string */
630        subStr = ALLOC(char, endDollarIndex - dollarIndex);
631        /* copy the variable into another string */
632        for ( i = 0; i <  endDollarIndex - dollarIndex - 1; i++) {
633          subStr[i] = curStr[dollarIndex+1+i];
634        }
635        subStr[i] = '\0';
636        /* quiet if of the form var$:iable or var$foo:iable and
637         * $foo not in flag table
638         */
639        if (avl_lookup(cmdFlagTable, subStr, (char **)&value) != 0) {
640          /* found the variable in the alias table */
641          if (strchr((char *)value, (int)dollar) != NULL) {
642            /* if more $s in the value */
643            value = variableInterpolationRecur(value);
644            subLen = strlen(value);
645            /* to be freed later since variableInterpolationRecur
646             * returns a new string to be freed later.
647             */
648            freeNewValue = 1;
649
650          }  else {
651          /* if no dollars in the value, substitute the return value
652           * in the string
653           */
654            subLen = strlen(value);
655          }
656        } else { 
657          /* if the variable is not found, it might be an
658           * environment variable and so keep it. This might be
659           * a hazard for bogus variables but that is upto the user.
660           */
661          value = subStr;
662          /* for environment variable keep the $ sign */
663          subLen = strlen(value) +1;
664          envVar = 1;
665        }
666
667      } /* end of interpolation variable not trivial */
668      /* prefix + strlen(substituted value) + suffix */
669      newCurStr = ALLOC(char, dollarIndex + 
670                              subLen +
671                              strlen(curStr) - endDollarIndex + 1);
672                       
673     
674     
675      /* copy prefix */
676      newCurStr = strncpy(newCurStr, curStr, dollarIndex);
677      i = dollarIndex;
678      if (subLen) {
679        /* copy substituted value */
680        if (envVar) {
681          /* if it is an environment variable, keep the $ sign */
682          newCurStr[i++] = '$';
683        }
684        index = 0;
685        while (value[index] != '\0') {
686          newCurStr[i++] = value[index++];
687        }
688        if (freeNewValue) {
689          FREE(value);
690        }
691      }
692      /* freed here cos value might be subStr in one case */
693      if (subStr != NULL) {
694        FREE(subStr);
695      }
696      /* copy suffix */
697      index = endDollarIndex;
698      /* figure out where to start the next search */
699      lastPos = i;
700      while (curStr[index] != '\0') {
701        newCurStr[i++] = curStr[index++];
702      }
703      newCurStr[i] = '\0';
704      FREE(curStr);
705      curStr = newCurStr;
706      /* reset counter for further search. Due to recursive calling of this
707       * function eventually, the value that is substituted will not have a $
708       */
709      curStrIndex = lastPos;
710      dollarIndex = -1;
711      endDollarIndex = -1;
712      /* end of found a variable */   
713    } else { /* if a variable is not found, keep going */
714      curStrIndex++;
715    }
716  } /* end of stepping through the string */
717  return(curStr);
718} /* end of variableInterpolationRecur */
719
720
721
722/**Function********************************************************************
723
724  Synopsis    [required]
725
726  Description [optional]
727
728  SideEffects [required]
729
730  SeeAlso     [optional]
731
732******************************************************************************/
733static char *
734split_line(
735  char * command,
736  int * argc,
737  char *** argv)
738{
739  register char *p, *start, c;
740  register int i, j;
741  register char *new_arg;
742  array_t *argv_array;
743  int single_quote, double_quote;
744
745  argv_array = array_alloc(char *, 5);
746
747  p = command;
748  for(;;) {
749    /* skip leading white space */
750    while (isspace((int)(*p))) {
751      p++;
752    }
753
754    /* skip until end of this token */
755    single_quote = double_quote = 0;
756    for(start = p; (c = *p) != '\0'; p++) {
757      if (c == ';' || c == '#' || isspace((int)c)) {
758        if (! single_quote && ! double_quote) {
759          break;
760        }
761      }
762      if (c == '\'') {
763        single_quote = ! single_quote;
764      }
765      if (c == '"') {
766        double_quote = ! double_quote;
767      }
768    }
769    if (single_quote || double_quote) {
770      (void) fprintf(vis_stderr, "** cmd warning: ignoring unbalanced quote ...\n");
771    }
772    if (start == p) break;
773
774    new_arg = ALLOC(char, p - start + 1);
775    j = 0;
776    for(i = 0; i < p - start; i++) {
777      c = start[i];
778      if ((c != '\'') && (c != '\"')) {
779        new_arg[j++] = isspace((int)c) ? ' ' : start[i];
780      }
781    }
782    new_arg[j] = '\0';
783    array_insert_last(char *, argv_array, new_arg);
784  }
785
786  *argc = array_n(argv_array);
787  *argv = array_data(char *, argv_array);
788  array_free(argv_array);
789  if (*p == ';') {
790    p++;
791  }
792  else if (*p == '#') {
793    for(; *p != 0; p++) ;               /* skip to end of line */
794  }
795  return p;
796}   
797
798
799/**Function********************************************************************
800
801  Synopsis    [required]
802
803  Description [optional]
804
805  SideEffects [required]
806
807  SeeAlso     [optional]
808
809******************************************************************************/
810static int
811check_shell_escape(
812  char * p,
813  int * status)
814{
815    char *value;
816    while (isspace((int)(*p))) {
817        p++;
818    }
819    if ((value = Cmd_FlagReadByName("shell_char")) != NIL(char)){
820        visShellChar = *value;
821    }
822    if (*p == visShellChar) {
823        *status = system(p+1);
824        return 1;
825    }
826    return 0;
827}
828
829/**Function********************************************************************
830
831  Synopsis    [Signal handler.]
832
833  SideEffects []
834
835  SeeAlso     [com_dispatch]
836
837******************************************************************************/
838static void
839sigterm(int sig)
840{
841    (void) signal(SIGINT, SIG_IGN);     /* ignore further ctl-c */
842    (void)fprintf(vis_stderr, "\n");
843    (void)fprintf(vis_stderr,
844                  "** cmd warning : data may be corrupted due to CTRL-c.\n");
845    (void)fprintf(vis_stderr,
846                  "                 It may cause abnormal termination.\n");
847    longjmp(env, 1);
848}
Note: See TracBrowser for help on using the repository browser.