📄 script.c
字号:
/* * This file is part of the Minicom Communications Program, * written by Miquel van Smoorenburg 1991/1992/1993. * * 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 :-)) * * Version: 1.01 * * Author: Miquel van Smoorenburg, miquels@maestro.htsa.aha.nl * * Bugs: The "expect" routine is, unlike gosub, NOT reentrant ! * */#include <sys/types.h>#if defined (_POSIX_SOURCE) || defined(_BSD43)#include <stdlib.h>#include <unistd.h>#elsechar *getenv();#endif#include <string.h>#include <signal.h>#include <setjmp.h>#undef NULL#include <stdio.h>/* * Run a script. */ #define OK 0#define ERR -1#define RETURN 1#define BREAK 2#ifndef lintchar *Version = "@(#)Runscript V1.1 1992";#endifstruct line { char *line; int labelcount; int lineno; struct line *next;};struct var { char *name; int value; struct var *next;};#define LNULL ((struct line *)0)#define VNULL ((struct var *)0)#ifndef CNULL#define CNULL ((char *)0)#endif/* * Structure describing the script we are currently executing. */struct env { struct line *lines; /* Start of all lines */ struct var *vars; /* Start of all variables */ 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 */char *newline; /* What to print for '\n'. */char *s_login = "name"; /* User's login name */char *s_pass = "password"; /* User's password */struct line *thisline; /* Line to be executed */ int laststatus = 0; /* Status of last command *//* Forward declarations */int s_exec();int execscript();/* * Print something formatted to stderr. *//*VARARGS*/ void s_error(fmt, a1, a2, a3)char *fmt;char *a1, *a2, *a3;{ fprintf(stderr, fmt, a1, a2, a3);}/* * 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(){ 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. */char *mygetenv(env)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(s)char *s;{ s_error("script \"%s\": syntax error in line %d %s\r\n", curenv->scriptname, thisline->lineno, s); exit(1); }/* * Skip all space */void skipspace(s)char **s;{ while(**s == ' ' || **s == '\t') (*s)++;} /* * Our clock. This gets called every second. *//*ARGSUSED*/void myclock(dummy)int dummy;{ signal(SIGALRM, myclock); alarm(1); if (--gtimeout == 0) { s_error("script \"%s\": global timeout\r\n", curenv->scriptname); exit(1); } if (inexpect && etimeout && --etimeout == 0) longjmp(ejmp, 1);}/* * Read a word and advance pointer. * Also processes quoting, variable substituting, and \ escapes. */char *getword(s)char **s;{ static char buf[81]; int len, f; int idx = 0; char *t = *s; int sawesc = 0; int sawq = 0; char *env, envbuf[32]; if (**s == 0) return(CNULL); for(len = 0; len < 81; len++) { if (sawesc && t[len]) { sawesc = 0; if (t[len] <= '7' && t[len] >= '0') { buf[idx] = 0; for(f = 0; f < 4 && len < 81 && 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 == CNULL) env = ""; while(*env) buf[idx++] = *env++; 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("(badly formed word)"); return(buf);}/* * Save a string to memory. Strip trailing '\n'. */char *strsave(s)char *s;{ char *t; int len; len = strlen(s); if (len && s[len - 1] == '\n') s[--len] = 0; if ((t = (char *)malloc(len + 1)) == (char *)0) return(t); strcpy(t, s); return(t);}/* * Throw away all malloced memory. */void freemem(){ struct line *l; struct var *v; for(l = curenv->lines; l; l = l->next) { free((char *)l->line); free((char *)l); } for(v = curenv->vars; v; v = v->next) { free(v->name); free((char *)v); }}/* * Read a script into memory. */int readscript(s)char *s;{ FILE *fp; struct line *tl, *prev = LNULL; char *t; char buf[81]; int no = 0; if ((fp = fopen(s, "r")) == (FILE *)0) { s_error("runscript: couldn't open %s\r\n", s); exit(1); } /* Read all the lines into a linked list in memory. */ while((t = fgets(buf, 80, fp)) != CNULL) { no++; skipspace(&t); if (*t == '\n') continue; if ( ((tl = (struct line *)malloc(sizeof (struct line))) == LNULL) || ((tl->line = strsave(t)) == CNULL)) { s_error("script %s: out of memory\r\n", s); exit(1); } if (prev) prev->next = tl; else curenv->lines = tl; tl->next = (struct line *)0; tl->labelcount = 0; tl->lineno = no; prev = tl; } return(0);}/* * Read the next character, and return a string of characters last read. */char *readchar(){ static char buf[65]; static int bufp = 64; char c; buf[64] = 0; #ifdef _SYSV memcpy(buf, buf + 1, 63);#else /* This is Posix, I believe. */ memmove(buf, buf + 1, 63);#endif if (bufp) bufp--; while(read(0, &c, 1) != 1) ; if (curenv->verbose) fputc(c, stderr); buf[63] = c; return(buf + bufp);}/* * See if an expected string has yet been seen. */int expfound(already, seek)char *already, *seek;{ int len1, len2; int start = 0; len1 = strlen(already); len2 = strlen(seek); if (len1 > len2) start = len1 - len2; return(!strcmp(already + start, seek));}/* * Send text to a file (stdout or stderr). */int output(text, fp)char *text;FILE *fp;{ unsigned char *w; int first = 1; int donl = 1; while((w = (unsigned char *)getword(&text)) != (unsigned char *)0) { 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(name, cr)char *name;int cr;{ struct var *v, *end = VNULL; for(v = curenv->vars; v; v = v->next) { end = v; if (!strcmp(v->name, name)) return(v); } if (!cr) { s_error("script \"%s\" line %d: unknown variable \"%s\"\r\n", curenv->scriptname, thisline->lineno, name); exit(1); } if ((v = (struct var *)malloc(sizeof(struct var))) == VNULL || (v->name = strsave(name)) == CNULL) { s_error("script \"%s\": out of memory\r\n", curenv->scriptname); exit(1); } if (end) end->next = v; else curenv->vars = v; v->next = VNULL; v->value = 0; return(v);}/* * Read a number or variable. */int getnum(text)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(){ static struct line *seq[17]; int f; char *w, *t; for(f = 0; f < 16; f++) { if (thisline == LNULL) { s_error("script \"%s\": unexpected end of file\r\n", curenv->scriptname); exit(1); } t = thisline->line; w = getword(&t); if (!strcmp(w, "}")) { if (*t) syntaxerr("(garbage after })"); return(seq);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -