📄 cshpar.c
字号:
/* RCS Info: $Revision: 1.1 $ on $Date: 91/04/02 12:04:11 $ * $Source: //pepper/atesse_spice/spice3/CP/RCS/cshpar.c,v $ * Copyright (c) 1985 Wayne A. Christopher, U. C. Berkeley CAD Group * * The main entry point for cshpar. */#include "prefix.h"#include "CPdefs.h"#ifdef UNIX#include <pwd.h>#endif#ifdef BSD#include <signal.h>#include <sys/wait.h>#endif#include "suffix.h"/* Things go as follows: * (1) Read the line and do some initial quoting (by setting the 8th bit), * and command ignoring. Also deal with command completion. * (2) Do history substitutions. (!, ^) * (3) Do alias substitution. * * Now, in front.c these things get done: * (4) Do variable substitution. ($varname) * (5) Do backquote substitution. (``) * (6) Do globbing. (*, ?, [], {}, ~) * (7) Do io redirection. */static bool fileexists();static void fixdescriptors();static void pwlist();bool cp_debug = false;char cp_gt = '>';char cp_lt = '<';char cp_amp = '&';FILE *cp_in;FILE *cp_out;FILE *cp_err;/* These are the fps that cp_ioreset resets the cp_* to. They are changed * by the source routines. */FILE *cp_curin = NULL;FILE *cp_curout = NULL;FILE *cp_curerr = NULL;wordlist *cp_parse(string) char *string;{ wordlist *wlist; wlist = cp_lexer(string); if (!string) cp_event++; if (!wlist || !wlist->wl_word) return (wlist); pwlist(wlist, "Initial parse"); wlist = cp_histsubst(wlist); if (!wlist || !wlist->wl_word) return (wlist); pwlist(wlist, "After history substitution"); if (cp_didhsubst) { wl_print(wlist, stdout); (void) putc('\n', stdout); } /* Add the word list to the history. */ if (*wlist->wl_word) cp_addhistent(cp_event - 1, wlist); wlist = cp_doalias(wlist); pwlist(wlist, "After alias substitution"); if (string && cp_lastone) { /* Don't put this one in... */ cp_lastone = cp_lastone->hi_prev; if (cp_lastone) cp_lastone->hi_next = NULL; } pwlist(wlist, "Returning "); return (wlist);}static voidpwlist(wlist, name) wordlist *wlist; char *name;{ wordlist *wl; if (!cp_debug) return; fprintf(cp_err, "%s : [ ", name); for (wl = wlist; wl; wl = wl->wl_next) fprintf(cp_err, "%s ", wl->wl_word); fprintf(cp_err, "]\n"); return;}/* This has to go somewhere... */voidcom_echo(wlist) wordlist *wlist;{ bool nl = true; if (wlist && eq(wlist->wl_word, "-n")) { wlist = wlist->wl_next; nl = false; } while (wlist) { fputs(cp_unquote(wlist->wl_word), cp_out); if (wlist->wl_next) fputs(" ", cp_out); wlist = wlist->wl_next; } if (nl) fputs("\n", cp_out);}/* This routine sets the cp_{in,out,err} pointers and takes the io * directions out of the command line. */wordlist *cp_redirect(wl) wordlist *wl;{ bool gotinput = false, gotoutput = false, goterror = false; bool app = false, erralso = false; wordlist *w, *bt, *nw; char *s; FILE *tmpfp; w = wl->wl_next; /* Don't consider empty commands. */ while (w) { if (*w->wl_word == cp_lt) { bt = w; if (gotinput) { fprintf(cp_err, "Error: ambiguous input redirect.\n"); goto error; } gotinput = true; w = w->wl_next; if (w == NULL) { fprintf(cp_err, "Error: missing name for input.\n"); return (NULL); } if (*w->wl_word == cp_lt) { /* Do reasonable stuff here... */ } else { tmpfp = fopen(cp_unquote(w->wl_word), "r"); if (!tmpfp) { perror(w->wl_word); goto error; } else cp_in = tmpfp; }#ifdef CPDEBUG if (cp_debug) fprintf(cp_err, "Input file is %s...\n", w->wl_word);#endif bt->wl_prev->wl_next = w->wl_next; if (w->wl_next) w->wl_next->wl_prev = bt->wl_prev; nw = w->wl_next; w->wl_next = NULL; w = nw; wl_free(bt); } else if (*w->wl_word == cp_gt) { bt = w; if (gotoutput) { fprintf(cp_err, "Error: ambiguous output redirect.\n"); goto error; } gotoutput = true; w = w->wl_next; if (w == NULL) { fprintf(cp_err, "Error: missing name for output.\n"); return (NULL); } if (*w->wl_word == cp_gt) { app = true; w = w->wl_next; if (w == NULL) { fprintf(cp_err, "Error: missing name for output.\n"); return (NULL); } } if (*w->wl_word == cp_amp) { erralso = true; if (goterror) { fprintf(cp_err, "Error: ambiguous error redirect.\n"); return (NULL); } goterror = true; w = w->wl_next; if (w == NULL) { fprintf(cp_err, "Error: missing name for output.\n"); return (NULL); } } s = cp_unquote(w->wl_word); if (cp_noclobber && fileexists(s)) { fprintf(stderr, "Error: %s: file exists\n", s); goto error; } if (app) tmpfp = fopen(s, "a"); else tmpfp = fopen(s, "w+"); if (!tmpfp) { perror(w->wl_word); goto error; } else { cp_out = tmpfp; out_isatty = false; }#ifdef CPDEBUG if (cp_debug) fprintf(cp_err, "Output file is %s... %s\n", w->wl_word, app ? "(append)" : "");#endif bt->wl_prev->wl_next = w->wl_next; if (w->wl_next) w->wl_next->wl_prev = bt->wl_prev; w = w->wl_next; if (w) w->wl_prev->wl_next = NULL; wl_free(bt); if (erralso) cp_err = cp_out; } else w = w->wl_next; } return (wl);error: wl_free(wl); return (NULL);}/* Reset the cp_* FILE pointers to the standard ones. This is tricky, since * if we are sourcing a command file, and io has been redirected from inside * the file, we have to reset it back to what it was for the source, not for * the top level. That way if you type "foo > bar" where foo is a script, * and it has redirections of its own inside of it, none of the output from * foo will get sent to stdout... */voidcp_ioreset(){ if (cp_in != cp_curin) { if (cp_in) (void) fclose(cp_in); cp_in = cp_curin; } if (cp_out != cp_curout) { if (cp_out) (void) fclose(cp_out); cp_out = cp_curout; } if (cp_err != cp_curerr) { if (cp_err) (void) fclose(cp_err); cp_err = cp_curerr; } /*** Minor bug here... */ out_isatty = true; return;}static boolfileexists(name) char *name;{#ifdef BSD if (access(name, 0) == 0) return (true);#endif return (false);}#ifdef UNIX/* Fork a shell. */voidcom_shell(wl) wordlist *wl;{ char *com, *shell = NULL; long pid, r;#ifdef BSD struct sigvec svint, svquit, svtstp; static struct sigvec svign = { NULL, 0, 0 } ;#endif#ifdef UNIX shell = getenv("SHELL"); if (shell == NULL) shell = "/bin/csh";#endif#ifdef BSD if (wl == NULL) { fprintf(cp_out, "Forking shell...\n"); cp_ccon(false); if ((pid = vfork()) == 0) { fixdescriptors(); (void) execl(shell, shell, 0); } else { (void) sigvec(SIGINT, &svign, &svint); (void) sigvec(SIGQUIT, &svign, &svquit); (void) sigvec(SIGTSTP, &svign, &svtstp); do { r = wait((union wait *) NULL); } while ((r != pid) && pid != -1); (void) sigvec(SIGINT, &svint, (struct sigvec *) NULL); (void) sigvec(SIGQUIT, &svquit, (struct sigvec *) NULL); (void) sigvec(SIGTSTP, &svtstp, (struct sigvec *) NULL); fprintf(cp_out, "\nWelcome back...\n"); } } else { com = wl_flatten(wl); if ((pid = vfork()) == 0) { fixdescriptors(); (void) execl("/bin/sh", "sh", "-c", com, 0); } else (void) sigvec(SIGINT, &svign, &svint); (void) sigvec(SIGQUIT, &svign, &svquit); (void) sigvec(SIGTSTP, &svign, &svtstp); do { r = wait((union wait *) NULL); } while ((r != pid) && pid != -1); (void) sigvec(SIGINT, &svint, (struct sigvec *) NULL); (void) sigvec(SIGQUIT, &svquit, (struct sigvec *) NULL); (void) sigvec(SIGTSTP, &svtstp, (struct sigvec *) NULL); }#else /* Easier to forget about changing the io descriptors. */ if (wl) { com = wl_flatten(wl); (void) system(com); } else (void) system(shell);#endif return;}#ifdef BSD/* Do this only right before an exec, since we lose the old std*'s. */static voidfixdescriptors(){ if (cp_in != stdin) (void) dup2(fileno(cp_in), fileno(stdin)); if (cp_out != stdout) (void) dup2(fileno(cp_out), fileno(stdout)); if (cp_err != stderr) (void) dup2(fileno(cp_err), fileno(stderr)); return;}#endifvoidcom_chdir(wl) wordlist *wl;{ char *s; struct passwd *pw; if (wl == NULL) { pw = getpwuid(getuid()); if (pw == NULL) { fprintf(cp_err, "Welcome to the twilight zone...\n"); return; } s = pw->pw_dir; } else s = cp_unquote(wl->wl_word); if (chdir(s) == -1) perror(s); return;}#else#ifdef VMSvoidcom_shell(wl) wordlist *wl;{ if (wl) { char *s = wl_flatten(wl); (void) system(wl); } else (void) system((char *) NULL); return;}#else/* ARGSUSED */voidcom_shell(wl) wordlist *wl;{ fprintf(cp_err, "Error: command only available with UNIX or VMS.\n"); return;}#endifvoidcom_chdir(wl) wordlist *wl;{ fprintf(cp_err, "Error: command only available with UNIX.\n"); return;}#endif/* ARGSUSED */voidcom_rehash(wl) wordlist *wl;{ char *s; if (!cp_dounixcom) { fprintf(cp_err, "Error: unixcom not set.\n"); return; } s = getenv("PATH"); if (s) cp_rehash(s, true); else fprintf(cp_err, "Error: no PATH in environment...\n"); return;}/* This is a truly evil thing... */voidcom_strcmp(wl) wordlist *wl;{ char *var, *s1, *s2; int i; var = wl->wl_word; s1 = cp_unquote(wl->wl_next->wl_word); s2 = cp_unquote(wl->wl_next->wl_next->wl_word); i = strcmp(s1, s2); cp_vset(var, VT_NUM, (char *) &i); return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -