📄 script.c
字号:
/* * Runscript Run a login-or-something script. * A basic like "programming language". * This program also looks like a basic interpreter : * a bit messy. (But hey, I'm no compiler writer :-)) * * Author: Miquel van Smoorenburg, miquels@drinkel.ow.nl * * Bugs: The "expect" routine is, unlike gosub, NOT reentrant ! * * This file is part of the minicom communications package, * Copyright 1991-1995 Miquel van Smoorenburg, * 1997-1999 Jukka Lahtinen * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * 10.07.98 jl Added the log command * 05.04.99 jl The logfile name should also be passed as a parameter * 04.03.2002 jl Treat the ^ character between quotes as control code prefix */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <stdarg.h>#include "rcsid.h"RCSID(PKG_VER "$Id: script.c,v 1.14 2007-10-10 20:18:20 al-guest Exp $")#include "port.h"#include "minicom.h"#include "intl.h"#define OK 0#define ERR -1#define RETURN 1#define BREAK 2struct line { char *line; int labelcount; int lineno; struct line *next;};struct var { char *name; int value; struct var *next;};/* * Structure describing the script we are currently executing. */struct env { struct line *lines; /* Start of all lines */ struct var *vars; /* Start of all variables */ const char *scriptname; /* Name of this script */ int verbose; /* Are we verbose? */ jmp_buf ebuf; /* For exit */ int exstat; /* For exit */};struct env *curenv; /* Execution environment */int gtimeout = 120; /* Global Timeout */int etimeout = 0; /* Timeout in expect routine */jmp_buf ejmp; /* To jump to if expect times out */int inexpect = 0; /* Are we in the expect routine */const char *newline; /* What to print for '\n'. */const char *s_login = "name"; /* User's login name */const char *s_pass = "password";/* User's password */struct line *thisline; /* Line to be executed */int laststatus = 0; /* Status of last command */char homedir[256]; /* Home directory */char logfname[PARS_VAL_LEN]; /* Name of logfile */static char inbuf[65]; /* Input buffer. *//* Forward declarations */int s_exec(char *);int execscript(const char *);/* * Walk through the environment, see if LOGIN and/or PASS are present. * If so, delete them. (Someone using "ps" might see them!) */void init_env(void){ extern char **environ; char **e; for (e = environ; *e; e++) { if (!strncmp(*e, "LOGIN=", 6)) { s_login = *e + 6; *e = "LOGIN="; } if (!strncmp(*e, "PASS=", 5)) { s_pass = *e + 5; *e = "PASS="; } }}/* * Return an environment variable. */const char *mygetenv(char *env){ if (!strcmp(env, "LOGIN")) return s_login; if (!strcmp(env, "PASS")) return s_pass; return getenv(env);}/* * Display a syntax error and exit. */void syntaxerr(const char *s){ fprintf(stderr, _("script \"%s\": syntax error in line %d %s%s\n"), curenv->scriptname, thisline->lineno, s, "\r"); exit(1);}/* * Skip all space */void skipspace(char **s){ while (**s == ' ' || **s == '\t') (*s)++;}/* * Our clock. This gets called every second. */void myclock(int dummy){ (void)dummy; signal(SIGALRM, myclock); alarm(1); if (--gtimeout == 0) { fprintf(stderr, _("script \"%s\": global timeout%s\n"), curenv->scriptname,"\r"); exit(1); } if (inexpect && etimeout && --etimeout == 0) siglongjmp(ejmp, 1);}/* * Read a word and advance pointer. * Also processes quoting, variable substituting, and \ escapes. */char *getword(char **s){ static char buf[90]; unsigned int len; int f; int idx = 0; const char *t = *s; int sawesc = 0; int sawq = 0; const char *env; char envbuf[32]; if (**s == 0) return NULL; for (len = 0; len < sizeof(buf); len++) { if (sawesc && t[len]) { sawesc = 0; if (t[len] <= '7' && t[len] >= '0') { buf[idx] = 0; for (f = 0; f < 4 && len < sizeof(buf) && t[len] <= '7' && t[len] >= '0'; f++) buf[idx] = 8 * buf[idx] + t[len++] - '0'; if (buf[idx] == 0) buf[idx] = '@'; idx++; len--; continue; } switch (t[len]) { case 'r': buf[idx++] = '\r'; break; case 'n': buf[idx++] = '\n'; break; case 'b': buf[idx++] = '\b'; break;#ifndef _HPUX_SOURCE case 'a': buf[idx++] = '\a'; break;#endif case 'f': buf[idx++] = '\f'; break; case 'c': buf[idx++] = 255; break; default: buf[idx++] = t[len]; break; } sawesc = 0; continue; } if (t[len] == '\\') { sawesc = 1; continue; } if (t[len] == '"') { if (sawq == 1) { sawq = 0; len++; break; } sawq = 1; continue; } if (t[len] == '$' && t[len + 1] == '(') { for(f = len; t[f] && t[f] != ')'; f++) ; if (t[f] == ')') { strncpy(envbuf, &t[len + 2], f - len - 2); envbuf[f - len - 2] = 0; len = f; env = mygetenv(envbuf); if (env == NULL) env = ""; while (*env) buf[idx++] = *env++; continue; } } /* ^ prefix for control chars - jl 3.2002 */ if (sawq == 1 && t[len] == '^' && t[len + 1] != 0) { char c = toupper(t[len + 1]); if (c >= 'A' && c <= '_') { len++; buf[idx++] = c - 'A' + 1; continue; } } if ((!sawq && (t[len] == ' ' || t[len] == '\t')) || t[len] == 0) break; buf[idx++] = t[len]; } buf[idx] = 0; *s += len; skipspace(s); if (sawesc || sawq) syntaxerr(_("(word contains ESC or quote)")); return buf;}/* * Save a string to memory. Strip trailing '\n'. */char *strsave(char *s){ char *t; int len; len = strlen(s); if (len && s[len - 1] == '\n') s[--len] = 0; if (!(t = malloc(len + 1))) return t; strcpy(t, s); return t;}/* * Throw away all malloced memory. */void freemem(void){ struct line *l, *nextl; struct var *v, *nextv; for (l = curenv->lines; l; l = nextl) { nextl = l->next; free(l->line); free(l); } for (v = curenv->vars; v; v = nextv) { nextv = v->next; free(v->name); free(v); }}/* * Read a script into memory. */static int readscript(const char *s){ FILE *fp; struct line *tl, *prev = NULL; char *t; char buf[500]; /* max length of a line - this should be dynamically! */ int lineno = 0; if ((fp = fopen(s, "r")) == NULL) { fprintf(stderr, _("runscript: couldn't open \"%s\"%s\n"), s, "\r"); exit(1); } /* Read all the lines into a linked list in memory. */ while ((t = fgets(buf, sizeof(buf), fp)) != NULL) { lineno++; if (strlen(t) == sizeof(buf) - 1) { /* Wow, this is really braindead, once upon a time buf was 81 chars * big and triggered nice errors for too long input lines, now * we just enlarge the buffer and add a sanity check. This code * needs to allocate memory dynamically... */ fprintf(stderr, "Input line %u too long, aborting (and fix me!)!\n", lineno); exit(1); } skipspace(&t); if (*t == '\n' || *t == '#') continue; if (((tl = (struct line *)malloc(sizeof (struct line))) == NULL) || ((tl->line = strsave(t)) == NULL)) { fprintf(stderr, _("script \"%s\": out of memory%s\n"), s, "\r"); exit(1); } if (prev) prev->next = tl; else curenv->lines = tl; tl->next = NULL; tl->labelcount = 0; tl->lineno = lineno; prev = tl; } fclose(fp); return 0;}/* Read one character, and store it in the buffer. */void readchar(void){ char c; int n; while ((n = read(0, &c, 1)) != 1) if (errno != EINTR) break; if (n <= 0) return; /* Shift character into the buffer. */#ifdef _SYSV memcpy(inbuf, inbuf + 1, 63);#else# ifdef _BSD43 bcopy(inbuf + 1, inbuf, 63);# else /* This is Posix, I believe. */ memmove(inbuf, inbuf + 1, 63);# endif#endif if (curenv->verbose) fputc(c, stderr); inbuf[63] = c;}/* See if a string just came in. */int expfound(const char *word){ int len; if (word == NULL) { fprintf(stderr, "NULL paramenter to %s!", __func__); exit(1); } len = strlen(word); if (len > 64) len = 64; return !strcmp(inbuf + 64 - len, word);}/* * Send text to a file (stdout or stderr). */int output(char *text, FILE *fp){ unsigned char *w; int first = 1; int donl = 1; while ((w = (unsigned char *)getword(&text)) != NULL) { if (!first) fputc(' ', fp); first = 0; for(; *w; w++) { if (*w == 255) { donl = 0; continue; } if (*w == '\n') fputs(newline, fp); else fputc(*w, fp); } } if (donl) fputs(newline, fp); fflush(fp); return OK;}/* * Find a variable in the list. * If it is not there, create it. */struct var *getvar(char *name, int cr){ struct var *v, *end = NULL; for (v = curenv->vars; v; v = v->next) { end = v; if (!strcmp(v->name, name)) return v; } if (!cr) { fprintf(stderr, _("script \"%s\" line %d: unknown variable \"%s\"%s\n"), curenv->scriptname, thisline->lineno, name, "\r"); exit(1); } if ((v = (struct var *)malloc(sizeof(struct var))) == NULL || (v->name = strsave(name)) == NULL) { fprintf(stderr, _("script \"%s\": out of memory%s\n"), curenv->scriptname, "\r"); exit(1); } if (end) end->next = v; else curenv->vars = v; v->next = NULL; v->value = 0; return v;}/* * Read a number or variable. */int getnum(char *text){ int val; if (!strcmp(text, "$?")) return laststatus; if ((val = atoi(text)) != 0 || *text == '0') return val; return getvar(text, 0)->value;}/* * Get the lines following "expect" into memory. */struct line **buildexpect(void){ static struct line *seq[17]; int f; char *w, *t; for(f = 0; f < 16; f++) { if (thisline == NULL) { fprintf(stderr, _("script \"%s\": unexpected end of file%s\n"), curenv->scriptname, "\r"); exit(1); } t = thisline->line; w = getword(&t); if (!strcmp(w, "}")) { if (*t) syntaxerr(_("(garbage after })")); seq[f] = NULL; return seq; } seq[f] = thisline; thisline = thisline->next; } if (f == 16) syntaxerr(_("(too many arguments)")); return seq;}/* * Our "expect" function. */int expect(char *text){ char *s, *w; struct line **seq; struct line oneline; struct line *dflseq[2]; char *toact = "exit 1"; volatile int found = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -