diff options
Diffstat (limited to 'usr/src/cmd/fmli/sys/eval.c')
-rw-r--r-- | usr/src/cmd/fmli/sys/eval.c | 713 |
1 files changed, 0 insertions, 713 deletions
diff --git a/usr/src/cmd/fmli/sys/eval.c b/usr/src/cmd/fmli/sys/eval.c deleted file mode 100644 index 7d7bf7982b..0000000000 --- a/usr/src/cmd/fmli/sys/eval.c +++ /dev/null @@ -1,713 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ -/* All Rights Reserved */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef CACA -#define _DEBUG2 1 -int _Debug=4; -#endif - -#include <stdio.h> -#include <ctype.h> -#include "wish.h" -#include "eval.h" -#include "terror.h" -#include "message.h" -#include "moremacros.h" -#include "interrupt.h" - -#define MAXARGS 64 - -/* NOTE!!! the following flags compete for bits with - * the EV_**** flags in inc/eval.h Make sure - * there is no overlap. - */ -#define IN_DQ 1 -#define IN_SQ 2 -#define IN_BQ 4 -#define IN_SQUIG 8 -#define FROM_BQ 16 - -/* - * list of "special" characters, and flags in which they are not - * treated as special. NOTE that EV_SQUIG flag is opposite all - * others. set it in nflags if {} ARE to be treated as special. - */ -static char spchars[] = "\"'\\`$\n \t{}|&;<>2"; -/*static char spchars[] = "\"'\\`$\n \t{}|&;<>"; -abs */ -static int nflags[] = { - FROM_BQ | IN_SQ, /* double quote */ - FROM_BQ | IN_DQ, /* single quote */ - FROM_BQ, /* backslash */ - FROM_BQ | IN_SQ, /* back quote */ - FROM_BQ | IN_SQ, /* dollar sign */ - IN_SQUIG | IN_SQ | IN_DQ, /* new line */ - FROM_BQ | IN_SQ | IN_DQ | EV_GROUP, /* space */ - FROM_BQ | IN_SQ | IN_DQ | EV_GROUP, /* tab */ - FROM_BQ | IN_SQUIG | IN_SQ | IN_DQ | IN_BQ | EV_SQUIG, /* open squig */ - FROM_BQ | IN_SQ | IN_DQ | IN_BQ | EV_SQUIG, /* close squig */ - FROM_BQ | IN_SQ | IN_DQ | EV_GROUP, /* pipe symbol */ - FROM_BQ | IN_SQ | IN_DQ | EV_GROUP, /* ampersand */ - FROM_BQ | IN_SQ | IN_DQ | EV_GROUP, /* semicolon */ - FROM_BQ | IN_SQ | IN_DQ | EV_GROUP, /* less than */ - FROM_BQ | IN_SQ | IN_DQ | EV_GROUP /* greater than */ - ,FROM_BQ | IN_SQ | IN_DQ | EV_GROUP /* digit two */ -}; - -/* return code from most recently executed command */ -int EV_retcode; -int EV_backquotes; -int Lasttok; - -extern int in_an_if; /* (in an if statement) see evfuncs.c */ - -static int eval_dollar(); -static void eval_backquote(); - -char * -special_char(c, instr) -register int c; -IOSTRUCT *instr; -{ - char *strchr(); - int c2; - - if ((char)c == '2') - { - c2 = getac(instr); - if(c2 || instr->flags & EV_USE_FP) /* the other case: EV_USE_STRING */ - ungetac(c2, instr); /* and c2 = EndOfString. don't unget cause */ - /* it would unget c not c2. abs */ - if ((char)c2 != '>') - return(NULL); - } - return(strchr(spchars, c)); -} - - -int -eval(instr, outstr, flags) -IOSTRUCT *instr; -IOSTRUCT *outstr; -int flags; -{ - register int c; - register int tok; - bool done; - - flags ^= EV_SQUIG; /* flip flag so only have to set it - when special (one case) instead of - in all other cases. abs */ - if (!(flags & IN_BQ)) - EV_retcode = 0; - EV_backquotes = FALSE; - c = getac(instr); - /* skip leading white space */ - if (flags & (EV_TOKEN | EV_GROUP)) { - while (isspace(c)) - c = getac(instr); - if (c == '#') { - /* - * skip everything until end of line - */ - while ((c = getac(instr)) && c != '\n' && c != EOF) - ; - } - } - /* handler `` at beginning of line if in GROUP mode */ - if ((flags & EV_GROUP) && c == '`') { - eval_backquote(instr, outstr, flags); - io_flags(instr, io_flags(instr, 0) & ~FROM_BQ); - c = getac(instr); - } -#ifdef _DEBUG2 -/* - if ((flags & EV_TOKEN) && (instr->flags & EV_USE_STRING)) { - _debug2(stderr, "input is '%.*s'\n", instr->mu.str.count - instr->mu.str.pos, instr->mu.str.val + instr->mu.str.pos); - } -*/ -#endif - - Lasttok = tok = ET_EOF; - for (done = FALSE; c; c = getac(instr)) { - register char *p; - char *strchr(); - -/* while (!(p = strchr(spchars, c))) { -abs */ - while(!(p = special_char(c, instr))) { - Lasttok = ET_WORD; - putac(c, outstr); - if (!(c = getac(instr))) { - done = TRUE; - break; - } - } - if (done) - break; - /* single | and & are correct here */ - if ((instr->flags | flags) & nflags[tok = p - spchars]) - tok = !!c; - else { - tok += ET_DQUOTE; -#ifdef _DEBUG2 - _debug2(stderr, "eval: got special char 0x%x\n", tok); -#endif - } - switch (tok) { - case ET_EOF: - done = TRUE; - break; - case ET_WORD: - Lasttok = tok; - putac(c, outstr); - break; - case ET_DQUOTE: - flags ^= IN_DQ; - if (!(flags & EV_TOKEN)) - putac(c, outstr); - break; - case ET_SQUOTE: - flags ^= IN_SQ; - if (!(flags & EV_TOKEN)) - putac(c, outstr); - break; - case ET_BSLASH: - c = getac(instr); - /* - * if (not tokenizing or if we're in quotes and the - * next character is not special, leave backslash - * there - * else - * remove it (don't copy to output) - */ - if (!(flags & EV_TOKEN) || (flags & (IN_SQ | IN_DQ)) && (!(p = strchr(spchars, c)) || (instr->flags | flags) & nflags[p - spchars])) - putac('\\', outstr); - putac(c, outstr); - break; - case ET_BQUOTE: - if (flags & EV_TOKEN) { - if (flags & IN_BQ) { - if (Lasttok == ET_EOF) { - putac(c, outstr); - c = getac(instr); - Lasttok = tok; - } - done = TRUE; - } - else - eval_backquote(instr, outstr, flags); - } - else { - flags ^= IN_BQ; - putac(c, outstr); - } - EV_backquotes = TRUE; - break; - case ET_DOLLAR: - if (flags & EV_TOKEN) - eval_dollar(instr, outstr, flags); - else - putac(c, outstr); - break; - case ET_NEWLINE: - case ET_SPACE: - case ET_TAB: - Lasttok = ET_WORD; - if ((flags & EV_GROUP) && (flags & IN_BQ)) - putac(c, outstr); - else - done = TRUE; - break; - case ET_OSQUIG: - case ET_CSQUIG: - putac(c, outstr); - if (flags & EV_GROUP) - flags ^= IN_SQUIG; - else if (flags & EV_TOKEN) { - if (Lasttok == ET_EOF) { - c = getac(instr); - Lasttok = tok; - } - done = TRUE; - } - break; - case ET_PIPE: - case ET_AMPERSAND: - case ET_SEMI: - case ET_LTHAN: - case ET_GTHAN: - if (flags & IN_BQ) { - if (Lasttok == ET_EOF) { - register int oldc; - - putac(c, outstr); - oldc = c; - if ((c = getac(instr)) == oldc) { - putac(c, outstr); - c = getac(instr); - tok += DOUBLE; - } - Lasttok = tok; - } - done = TRUE; - } - else - putac(c, outstr); - break; - case ET_TWO: - if (flags & IN_BQ) { - if (Lasttok == ET_EOF) { - putac(c, outstr); - c = getac(instr); /* gets > known to follow 2 */ - putac(c, outstr); - if ((c = getac(instr)) == '>') { - putac(c, outstr); - c = getac(instr); - tok += DOUBLE; - } - Lasttok = tok; - } - done = TRUE; - } - else - putac(c, outstr); - break; - } - if (done) - break; - Lasttok = ET_WORD; - } - if (c) - ungetac(c, instr); -#ifdef _DEBUG2 - if (flags & EV_TOKEN) { - _debug2(stderr, "eval -> '%s'\n", io_ret_string(outstr)); - _debug2(stderr, "eval returning 0x%x\n", Lasttok); - } -#endif - - return Lasttok; -} - -/* - * NOTE: - * - * In pre-4.0 releases of FMLI, the contents of environment variables - * (after expansion) were put back into the input string for further - * evaluation (lets call it "double evaluation"). - * - * To remain backwards compatable, the global variable "Doublevars" - * will be set to TRUE if double evaluation should be performed on - * ALL environment variables. - * - * If Doublevars == FALSE, then only evaluate the "contents" of the - * variable if a "!" follows "$" (i.e., the "new" convention for double - * evaluation is "$!VARNAME"). - * - */ -/*ARGSUSED*/ -static int -eval_dollar(instr, outstr, flags) -IOSTRUCT *instr; -IOSTRUCT *outstr; -int flags; -{ - register char *p; - register int c; - register IOSTRUCT *iop; - char *expand(); - int evalagain; - extern bool Doublevars; - - iop = io_open(EV_USE_STRING, NULL); - putac('$', iop); - if (Doublevars == TRUE) - evalagain = TRUE; - else { - if ((c = getac(instr)) == '!') { - evalagain = TRUE; - } - else { - evalagain = FALSE; - ungetac(c, instr); - } - } - if ((c = getac(instr)) == '{') { - while (c != '}') { - putac(c, iop); - c = getac(instr); - } - putac(c, iop); - } - else { - while (isalpha(c) || isdigit(c) || c == '_') { - putac(c, iop); - c = getac(instr); - } - if (c) - ungetac(c, instr); - } - if (p = expand(io_ret_string(iop))) { - io_clear(iop); - if (evalagain) { - /* - * if the "contents" of the variable should - * be evaluated before passing it to outstr ... - */ - putastr(p, iop); - free(p); - p = (char *)NULL; - io_seek(iop, 0); - io_push(instr, iop); /* push it back in instr */ - } - else { - /* - * simply put the variable's contents into outstr - */ - putastr(p, outstr); - free(p); - p = (char *)NULL; - io_close(iop); - } - return SUCCESS; - } - return FAIL; -} - -static char * -eval_token(instr, flags) -IOSTRUCT *instr; -int flags; -{ - register char *p; - static IOSTRUCT *tmp; - - if (instr == NULL) { - io_close(tmp); - return NULL; - } - if (tmp == NULL) - tmp = io_open(EV_USE_STRING, NULL); - (void) eval(instr, tmp, flags); - p = io_string(tmp); - io_seek(tmp, 0); - return p; -} - -static void -eval_backquote(instr, outstr, flags) -IOSTRUCT *instr; -IOSTRUCT *outstr; -int flags; -{ - int argc; - char *argv[MAXARGS]; - bool doit; - int conditional = 0; - int if_elif = 0; - bool skip; - bool piped; - bool special; - IOSTRUCT *mystdin; - IOSTRUCT *mystdout; - IOSTRUCT *altstdout; - IOSTRUCT *altstderr; - -#ifdef _DEBUG2 - _debug2(stderr, "eval_backquote\n"); -#endif - mystdin = io_open(EV_USE_STRING, NULL); - mystdout = io_open(EV_USE_STRING, NULL); - altstdout = NULL; - altstderr = NULL; - doit = skip = piped = special = FALSE; - - for (argc = 0; ; ) { - conditional = 0; - argv[argc++] = eval_token(instr, EV_TOKEN | IN_BQ); - - if (argc == 1) { - /* - * determine whether we've found an - * if/then/else/elif statement - */ - if_elif = 0; - -#ifdef _DEBUG2 - _debug2(stderr, "argv[0]=\"%s\"\n\r", argv[0]); -#endif - - switch(argv[0][0]) { - case 'e': /* else, elif */ - if (!strcmp(argv[0], "else")) - conditional = 1; - else if (!strcmp(argv[0], "elif")) { - conditional = 1; - if_elif = 1; - } - break; - case 'i': /* if */ - if (argv[0][1] == 'f' && argv[0][2] == '\0') { - conditional = 1; - if_elif = 1; - } - break; - case 't': /* then */ - if (!strcmp(argv[0], "then")) - conditional = 1; - break; - } - - if (conditional) { - int a, nonwhite, start_look; - char *cp; - char ch; - - /* - * Force call to if/then/else/elif built-in - * (no arguments) ... Don't modify the input - * string here, just put a semi-colon in the - * "argv" array and set Lasttok (last token - * received) to ET_SEMI (semi-colon). - */ - argv[argc++] = strsave(";"); - Lasttok = ET_SEMI; - - - /* - * Though the implementation of if/then/else - * is done via built-ins ... don't allow - * semi-colons after if/then/else/elif !! - */ - start_look = instr->mu.str.pos; - cp = instr->mu.str.val + start_look; - nonwhite = 1; - for (a = 0; a < instr->mu.str.count - start_look + 1; a++) { - ch = *(cp + a); - - if (ch == '\n' ) - break; - else if (ch == ';') { - /* - * If all you've seen is - * white-space then produce - * an error message - */ - if (nonwhite) { - char errbuf[100]; - - sprintf(errbuf, "Syntax error - \";\" found after \"%s\"", argv[0]); - mess_temp(errbuf); - mess_lock(); - Lasttok = ET_EOF; - in_an_if = 0; - } - break; - } - else if (ch != '\t' && ch != ' ') { - /* - * not a space, tab, new-line - * or semi-colon ...... - */ - nonwhite = 0; - } - } - } - } - - switch (Lasttok) { - case ET_EOF: - case ET_BQUOTE: - special = doit = TRUE; - break; - case ET_PIPE: - { - register FILE *fp; - FILE *tempfile(); - - if (altstdout) { -#ifdef _DEBUG2 - _debug2(stderr, "PIPE and > in same eval command\n"); -#endif - io_close(altstdout); - altstdout = NULL; - } - if (fp = tempfile(NULL, "w+")) - altstdout = io_open(EV_USE_FP, fp); - special = doit = piped = TRUE; - } - break; - case ET_AMPERSAND: - break; - case ET_SEMI: - special = doit = TRUE; - break; - case ET_LTHAN: - { - register FILE *fp; - register char *p; - - special = TRUE; - p = eval_token(instr, EV_TOKEN | IN_BQ); - if (fp = fopen(p, "r")) { - io_close(mystdin); - mystdin = io_open(EV_USE_FP, fp); - } - else - warn(NOPEN, p); - free(p); - p = (char *)NULL; - } - break; - case ET_GTHAN: - case ET_GTHAN + DOUBLE: /* append symbol */ - { - register FILE *fp; - register char *p; - int savetok=Lasttok; - special = TRUE; - if (altstdout) { -#ifdef _DEBUG2 - _debug2(stderr, "2 >'s in eval command\n"); -#endif - io_close(altstdout); - } - p = eval_token(instr, EV_TOKEN | IN_BQ); - if (fp = fopen(p, (savetok & DOUBLE)?"a":"w")) - altstdout = io_open(EV_USE_FP, fp); - else - warn(NOPEN, p); - free(p); - p = (char *)NULL; - } - break; - case ET_TWO: - case ET_TWO + DOUBLE: /* append stderr symbol (2>>)*/ - { - register FILE *fp; - register char *p; - int savetok=Lasttok; - - special = TRUE; - if (altstderr) { -#ifdef _DEBUG2 - _debug2(stderr, "2 >'s in eval command\n"); -#endif - io_close(altstderr); - altstderr = NULL; - } - p = eval_token(instr, EV_TOKEN | IN_BQ); - if (fp = fopen(p, (savetok & DOUBLE) ?"a":"w")) - altstderr = io_open(EV_USE_FP, fp); - else - warn(NOPEN, p); - free(p); - p = (char *)NULL; - } - break; - /* OR symbol */ - case ET_PIPE + DOUBLE: - special = doit = TRUE; - break; - /* AND symbol */ - case ET_AMPERSAND + DOUBLE: - special = doit = TRUE; - break; - /* semicolon (twice in a row) */ - case ET_SEMI + DOUBLE: - special = doit = TRUE; - break; - /* here document */ - case ET_LTHAN + DOUBLE: - break; - - } - if (special) { - free(argv[--argc]); - argv[argc] = (char *)NULL; - special = FALSE; - } - if (doit || argc >= MAXARGS - 1) { - register int n; - - doit = FALSE; - if (!skip && !Cur_intr.skip_eval && argc > 0) /* abs */ - { - argv[argc] = NULL; - EV_retcode = evalargv(argc, argv, mystdin, - altstdout ? altstdout : mystdout, - altstderr); - /* - * if there is a syntax error in the - * conditional statement then terminate - * evaluation - */ - if (conditional && (EV_retcode == FAIL)) - Lasttok = ET_EOF; - } - skip = (EV_retcode && Lasttok == ET_AMPERSAND + DOUBLE) - || (!EV_retcode && Lasttok == ET_PIPE + DOUBLE); - for (n = 0; n < argc; n++) - if (argv[n]) { /* ehr3 */ - free(argv[n]); - argv[n] = (char *)NULL; - } - argc = 0; - io_close(mystdin); - if (piped) { - mystdin = altstdout; - io_seek(mystdin, 0); - piped = FALSE; - } - else { - mystdin = io_open(EV_USE_STRING, NULL); - if (altstdout) - io_close(altstdout); - } - if (altstderr) - { - io_close(altstderr); - altstderr = NULL; - } - altstdout = NULL; - if (Lasttok == ET_EOF || Lasttok == ET_BQUOTE) - break; - } - } - if ((argc = unputac(mystdout)) && argc != '\n') - putac(argc, mystdout); - if (flags & EV_GROUP) - putac('\n', mystdout); - io_seek(mystdout, 0); - io_flags(mystdout, io_flags(mystdout, 0) | FROM_BQ); - io_push(instr, mystdout); -} |