Jspice3
cshpar.c
Go to the documentation of this file.
1 /***************************************************************************
2 JSPICE3 adaptation of Spice3e2 - Copyright (c) Stephen R. Whiteley 1992
3 Copyright 1990 Regents of the University of California. All rights reserved.
4 Authors: 1987 Wayne A. Christopher
5  1992 Stephen R. Whiteley
6 ****************************************************************************/
7 
8 /*
9  * The main entry point for cshpar.
10  */
11 
12 #include "spice.h"
13 #include "cpdefs.h"
14 #define SHORT_SCEDIO
15 #include "scedio.h"
16 
17 #ifdef HAVE_SGTTY_H
18 #include <sgtty.h>
19 #else
20 #ifdef HAVE_TERMIO_H
21 #include <termio.h>
22 #else
23 #ifdef HAVE_TERMIOS_H
24 #include <termios.h>
25 #endif
26 #endif
27 #endif
28 
29 #ifdef HAVE_GETPWUID
30 #include <pwd.h>
31 #endif
32 #ifdef HAVE_SIGNAL
33 #include <signal.h>
34 #endif
35 #ifdef HAVE_SYS_WAIT_H
36 #include <sys/wait.h>
37 #endif
38 
39 
40 /* Things go as follows:
41  * (1) Read the line and do some initial quoting (by setting the 8th bit),
42  * and command ignoring. Also deal with command completion.
43  * (2) Do history substitutions. (!, ^)
44  * (3) Do alias substitution.
45  *
46  * In front.c these things get done:
47  * (4) Do variable substitution. ($varname)
48  * (5) Do backquote substitution. (``)
49  * (6) Do globbing. (*, ?, [], {}, ~)
50  * (7) Do io redirection.
51  */
52 
53 #ifdef __STDC__
54 static void pwlist(wordlist*,char*);
55 static bool fileexists(char*);
56 #else
57 static void pwlist();
58 static bool fileexists();
59 #endif
60 
61 bool cp_debug = false;
62 
63 char cp_gt = '>';
64 char cp_lt = '<';
65 char cp_amp = '&';
66 
67 FILE *cp_in;
68 FILE *cp_out;
69 FILE *cp_err;
70 
71 /* These are the fps that cp_ioreset resets the cp_* to. They are changed
72  * by the source routines.
73  */
74 
75 FILE *cp_curin = NULL;
76 FILE *cp_curout = NULL;
77 FILE *cp_curerr = NULL;
78 
79 char cp_chars[128];
80 
81 
82 void
84 
85 /* Initialize stuff. */
86 {
87  char *s, *singlec = "<>;&";
88 
90  bzero(cp_chars, 128);
91  for (s = singlec; *s; s++)
92  cp_chars[*s] = (CPC_BRR | CPC_BRL);
93  cp_vset("history", VT_NUM, (char *) &cp_maxhistlength);
94 
95  cp_curin = stdin;
96  cp_curout = stdout;
97  cp_curerr = stderr;
98 
99  cp_ioreset();
100 }
101 
102 
103 wordlist *
104 cp_parse(string)
105 
106 char *string;
107 {
108  wordlist *wlist;
109 
110  wlist = cp_lexer(string);
111 
112  if (!string)
113  cp_event++;
114 
115  if (!wlist || !wlist->wl_word)
116  return (wlist);
117 
118  pwlist(wlist, "Initial parse");
119 
120  cp_histsubst(&wlist);
121  if (!wlist || !wlist->wl_word)
122  return (wlist);
123 
124  pwlist(wlist, "After history substitution");
125 
126  if (cp_interactive && cp_didhsubst) {
127  wl_print(wlist, stdout);
128  (void) putc('\n', stdout);
129  }
130 
131  /* Add the word list to the history. */
132  if (!string && *wlist->wl_word)
133  cp_addhistent(cp_event - 1, wlist);
134 
135  cp_doalias(&wlist);
136  pwlist(wlist, "After alias substitution");
137 
138  return (wlist);
139 }
140 
141 
142 static void
143 pwlist(wlist, name)
144 
145 wordlist *wlist;
146 char *name;
147 {
148  wordlist *wl;
149 
150  if (!cp_debug)
151  return;
152  fprintf(cp_err, "%s : [ ", name);
153  for (wl = wlist; wl; wl = wl->wl_next)
154  fprintf(cp_err, "%s ", wl->wl_word);
155  fprintf(cp_err, "]\n");
156  return;
157 }
158 
159 
160 #ifdef notdef
161 
162 /* relocated to newgraf.c for graphics support */
163 
164 void
165 com_echo(wlist)
166 
167 wordlist *wlist;
168 {
169  bool nl = true;
170 
171  if (wlist && eq(wlist->wl_word, "-n")) {
172  wlist = wlist->wl_next;
173  nl = false;
174  }
175 
176  while (wlist) {
177  char *t = copy(wlist->wl_word);
178  cp_unquote(t);
179  fputs(t, cp_out);
180  tfree(t);
181  if (wlist->wl_next)
182  fputs(" ", cp_out);
183  wlist = wlist->wl_next;
184  }
185  if (nl)
186  fputs("\n", cp_out);
187 }
188 
189 #endif
190 
191 
192 /* This routine sets the cp_{in,out,err} pointers and takes the io
193  * directions out of the command line.
194  */
195 
196 void
198 
199 wordlist **list;
200 {
201  bool gotinput = false, gotoutput = false, goterror = false;
202  bool app = false, erralso = false;
203  wordlist *w, *wl, *bt, *nw;
204  char *s;
205  FILE *tmpfp;
206 
207  if (list == NULL)
208  return;
209  wl = *list;
210  w = wl->wl_next; /* Don't consider empty commands. */
211  while (w) {
212  if (*w->wl_word == cp_lt) {
213  bt = w;
214  if (gotinput) {
215  fprintf(cp_err,
216  "Error: ambiguous input redirect.\n");
217  goto error;
218  }
219  gotinput = true;
220  w = w->wl_next;
221  if (w == NULL) {
222  fprintf(cp_err,
223  "Error: missing name for input.\n");
224  goto error;
225  }
226  if (*w->wl_word == cp_lt) {
227  /* Do reasonable stuff here... */
228  }
229  else {
230  char *t = copy(w->wl_word);
231  cp_unquote(t);
232  tmpfp = fopen(t, "r");
233  tfree(t);
234  if (!tmpfp) {
235  perror(w->wl_word);
236  goto error;
237  }
238  else
239  cp_in = tmpfp;
240  }
241 #ifdef CPDEBUG
242  if (cp_debug)
243  fprintf(cp_err, "Input file is %s...\n",
244  w->wl_word);
245 #endif
246  bt->wl_prev->wl_next = w->wl_next;
247  if (w->wl_next)
248  w->wl_next->wl_prev = bt->wl_prev;
249  nw = w->wl_next;
250  w->wl_next = NULL;
251  w = nw;
252  wl_free(bt);
253  }
254  else if (*w->wl_word == cp_gt) {
255  bt = w;
256  if (gotoutput) {
257  fprintf(cp_err,
258  "Error: ambiguous output redirect.\n");
259  goto error;
260  }
261  gotoutput = true;
262  w = w->wl_next;
263  if (w == NULL) {
264  fprintf(cp_err,
265  "Error: missing name for output.\n");
266  goto error;
267  }
268  if (*w->wl_word == cp_gt) {
269  app = true;
270  w = w->wl_next;
271  if (w == NULL) {
272  fprintf(cp_err,
273  "Error: missing name for output.\n");
274  goto error;
275  }
276  }
277  if (*w->wl_word == cp_amp) {
278  erralso = true;
279  if (goterror) {
280  fprintf(cp_err,
281  "Error: ambiguous error redirect.\n");
282  goto error;
283  }
284  goterror = true;
285  w = w->wl_next;
286  if (w == NULL) {
287  fprintf(cp_err,
288  "Error: missing name for output.\n");
289  goto error;
290  }
291  }
292  s = copy(w->wl_word);
293  cp_unquote(s);
294  if (cp_noclobber && fileexists(s)) {
295  fprintf(stderr, "Error: %s: file exists\n", s);
296  tfree(s);
297  goto error;
298  }
299  if (app)
300  tmpfp = fopen(s, "a");
301  else
302  tmpfp = fopen(s, "w+");
303  tfree(s);
304  if (!tmpfp) {
305  perror(w->wl_word);
306  goto error;
307  }
308  else {
309  cp_out = tmpfp;
310  out_isatty = false;
311  }
312 #ifdef CPDEBUG
313  if (cp_debug)
314  fprintf(cp_err, "Output file is %s... %s\n",
315  w->wl_word, app ? "(append)" : "");
316 #endif
317  bt->wl_prev->wl_next = w->wl_next;
318  if (w->wl_next)
319  w->wl_next->wl_prev = bt->wl_prev;
320  w = w->wl_next;
321  if (w)
322  w->wl_prev->wl_next = NULL;
323  wl_free(bt);
324  if (erralso)
325  cp_err = cp_out;
326  }
327  else
328  w = w->wl_next;
329  }
330  *list = wl;
331  return;
332 
333 error:
334  wl_free(wl);
335  *list = NULL;
336  return;
337 }
338 
339 
340 /* Reset the cp_* FILE pointers to the standard ones. This is tricky, since
341  * if we are sourcing a command file, and io has been redirected from inside
342  * the file, we have to reset it back to what it was for the source, not for
343  * the top level. That way if you type "foo > bar" where foo is a script,
344  * and it has redirections of its own inside of it, none of the output from
345  * foo will get sent to stdout...
346  */
347 
348 void
350 {
351  // Careful not to double-close ">&" output.
352  FILE *fo = 0;
353  if (cp_in != cp_curin) {
354  if (cp_in && cp_in != stdin)
355  (void) fclose(cp_in);
356  cp_in = cp_curin;
357  }
358  if (cp_out != cp_curout) {
359  if (cp_out && cp_out != stdout) {
360  fo = cp_out;
361  (void) fclose(cp_out);
362  }
363  cp_out = cp_curout;
364  }
365  if (cp_err != cp_curerr) {
366  if (cp_err && cp_err != stderr && cp_err != stdout && cp_err != fo)
367  (void) fclose(cp_err);
368  cp_err = cp_curerr;
369  }
370 
371  /*** Minor bug here... */
372  out_isatty = true;
373  return;
374 }
375 
376 
377 static bool
379 
380 char *name;
381 {
382  if (access(name, 0) == 0)
383  return (true);
384  return (false);
385 }
386 
387 
388 /* Fork a shell. */
389 
390 void
392 
393 wordlist *wl;
394 {
395  char *com, *shell = NULL;
396  long pid, r;
397 #ifdef HAVE_SIGNAL
398  static RETSIGTYPE (*svint)( ), (*svquit)( ), (*svtstp)( );
399 #endif
400 
401  if (SCEDactive()) {
402  ShowPrompt("Can't do this from sced.");
403  return;
404  }
405 
406  shell = getenv("SHELL");
407  if (shell == NULL)
408  shell = "/bin/csh";
409  cp_ccon(false);
410 
411 #ifdef HAVE_FORK
412  pid = fork();
413  if (pid == 0) {
415  if (wl == NULL) {
416  (void) execl(shell, shell, 0);
417  _exit(99);
418  }
419  else {
420  com = wl_flatten(wl);
421  (void) execl("/bin/sh", "sh", "-c", com, 0);
422  }
423  }
424  else {
425  /* XXX Better have all these signals */
426  svint = signal(SIGINT, SIG_DFL);
427  svquit = signal(SIGQUIT, SIG_DFL);
428  svtstp = signal(SIGTSTP, SIG_DFL);
429  /* XXX Sig on proc group */
430  do {
431  r = wait(NULL);
432  } while ((r != pid) && pid != -1);
433  (void) signal(SIGINT, svint);
434  (void) signal(SIGQUIT, svquit);
435  (void) signal(SIGTSTP, svtstp);
436  }
437 #else
438  /* Easier to forget about changing the io descriptors. */
439  if (wl) {
440  com = wl_flatten(wl);
441  (void) system(com);
442  tfree(com);
443  }
444  else
445  (void) system(shell);
446 #endif
447  return;
448 }
449 
450 
451 /* Do this only right before an exec, since we lose the old std*'s. */
452 
453 void
455 {
456  if (cp_in != stdin)
457  (void) dup2(fileno(cp_in), fileno(stdin));
458  if (cp_out != stdout)
459  (void) dup2(fileno(cp_out), fileno(stdout));
460  if (cp_err != stderr)
461  (void) dup2(fileno(cp_err), fileno(stderr));
462  return;
463 }
464 
465 
466 /* ARGSUSED */
467 void
469 
470 wordlist *wl;
471 {
472  char *s;
473 
474  if (!cp_dounixcom) {
475  fprintf(cp_err, "Error: unixcom not set.\n");
476  return;
477  }
478  s = getenv("PATH");
479  if (s)
480  cp_rehash(s, !cp_nocc);
481  else
482  fprintf(cp_err, "Error: no PATH in environment.\n");
483  return;
484 }
485 
486 
487 #ifdef HAVE_CHDIR
488 void
489 com_chdir(wl)
490 
491 wordlist *wl;
492 {
493  char *s;
494  struct passwd *pw;
495  char localbuf[257];
496  int copied = 0;
497 
498  s = NULL;
499 
500  if (wl == NULL) {
501 
502  s = getenv("HOME");
503 
504 #ifdef HAVE_GETPWUID
505  if (!s) {
506  pw = getpwuid(getuid());
507  if (pw == NULL) {
508  fprintf(cp_err, "Can't get your password entry\n");
509  return;
510  }
511  s = pw->pw_dir;
512  }
513 #endif
514  if (!s) {
515  if (s = getcwd(localbuf, sizeof(localbuf))) {
516  out_printf("current directory: %s\n", s);
517  tfree(s);
518  }
519  else
520  fprintf(cp_err, "Can't get current working directory.\n");
521  return;
522  }
523  if (!s) {
524  out_printf("Specify directory.\n");
525  return;
526  }
527 
528  }
529  else {
530  s = copy(wl->wl_word);
531  cp_unquote(s);
532  copied = 1;
533  }
534 
535 #ifdef MSDOS
536  if (s && s[1] == ':') {
537  char buf[8];
538  sprintf(buf, "%c:", *s);
539  system(buf);
540  strcpy(s, s + 2);
541  }
542 #endif
543 
544  if (*s && chdir(s) == -1)
545  perror(s);
546 
547  if (copied)
548  tfree(s);
549 
550  if (cp_dounixcom)
552  return;
553 }
554 
555 #else
556 
557 void
559 
560 wordlist *wl;
561 {
562  fprintf(cp_err, "Error: 'chdir' not available.\n");
563  return;
564 }
565 
566 #endif
567 
568 
569 /* This is a truly evil thing */
570 
571 void
573 
574 wordlist *wl;
575 {
576  char *var, *s1, *s2;
577  int i;
578 
579  var = wl->wl_word;
580  s1 = copy(wl->wl_next->wl_word);
581  cp_unquote(s1);
582  s2 = copy(wl->wl_next->wl_next->wl_word);
583  cp_unquote(s2);
584 
585  i = strcmp(s1, s2);
586  tfree(s1);
587  tfree(s2);
588 
589  cp_vset(var, VT_NUM, (char *) &i);
590  return;
591 }
static char buf[MAXPROMPT]
Definition: arg.c:18
bool cp_dounixcom
Definition: front.c:123
void wl_print()
#define eq(a, b)
Definition: misc.h:29
void cp_fixdescriptors()
Definition: cshpar.c:454
static FILE * tmpfp
Definition: moretext.c:27
void cp_vset()
FILE * cp_err
Definition: cshpar.c:69
int cp_event
Definition: lexical.c:49
bool cp_debug
Definition: cshpar.c:61
void out_printf()
char * strcpy()
Definition: cddefs.h:119
bool cp_noclobber
Definition: variable.c:48
char cp_gt
Definition: cshpar.c:63
int system(char *str)
Definition: libfuncs.c:85
#define CPC_BRL
Definition: cpdefs.h:67
void cp_internal_init()
Definition: options.c:555
void com_echo()
void cp_addhistent()
void cp_redirect(wordlist **list)
Definition: cshpar.c:197
FILE * cp_curout
Definition: cshpar.c:76
Definition: cddefs.h:169
Definition: library.c:18
int bzero(char *ptr, int num)
Definition: string.c:357
char * getcwd(char *buf, int size)
Definition: libfuncs.c:124
void cp_unquote()
char * copy()
char * getenv(char *c)
Definition: libfuncs.c:106
FILE * cp_in
Definition: cshpar.c:67
void cp_ioreset()
Definition: cshpar.c:349
void wl_free()
char cp_amp
Definition: cshpar.c:65
struct wordlist * wl_prev
Definition: cpstd.h:24
bool cp_interactive
Definition: help.c:100
#define tfree(x)
Definition: cdmacs.h:22
#define NULL
Definition: spdefs.h:121
void com_rehash(wordlist *wl)
Definition: cshpar.c:468
void com_chdir(wordlist *wl)
Definition: cshpar.c:558
bool out_isatty
Definition: output.c:45
#define VT_NUM
Definition: cpstd.h:61
void cp_doalias()
int access(char *pth, int m)
Definition: libfuncs.c:75
FILE * cp_curerr
Definition: cshpar.c:77
void perror()
#define CPC_BRR
Definition: cpdefs.h:66
wordlist * cp_lexer()
char cp_lt
Definition: cshpar.c:64
wordlist * cp_parse(char *string)
Definition: cshpar.c:104
Definition: cpstd.h:21
void com_strcmp(wordlist *wl)
Definition: cshpar.c:572
bool cp_nocc
Definition: complete.c:75
Definition: dir.c:53
char cp_chars[128]
Definition: cshpar.c:79
Definition: cddefs.h:162
FILE * cp_curin
Definition: cshpar.c:75
void cp_rehash()
struct wordlist * wl_next
Definition: cpstd.h:23
int cp_maxhistlength
Definition: history.c:35
void cp_histsubst()
char * wl_word
Definition: cpstd.h:22
static bool fileexists()
void cp_init()
Definition: cshpar.c:83
enum Active SCEDactive()
Definition: scedstub.c:63
bool cp_didhsubst
Definition: history.c:38
char * wl_flatten()
Definition: cddefs.h:192
FILE * cp_out
Definition: cshpar.c:68
void ShowPrompt(char *str)
Definition: scedstub.c:71
void cp_ccon()
static void pwlist()
void com_shell(wordlist *wl)
Definition: cshpar.c:391