|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Runscript Run a login-or-something script.
|
|
Packit |
15a96c |
* A basic like "programming language".
|
|
Packit |
15a96c |
* This program also looks like a basic interpreter :
|
|
Packit |
15a96c |
* a bit messy. (But hey, I'm no compiler writer :-))
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* Author: Miquel van Smoorenburg, miquels@drinkel.ow.nl
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* Bugs: The "expect" routine is, unlike gosub, NOT reentrant !
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* This file is part of the minicom communications package,
|
|
Packit |
15a96c |
* Copyright 1991-1995 Miquel van Smoorenburg,
|
|
Packit |
15a96c |
* 1997-1999 Jukka Lahtinen
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* This program is free software; you can redistribute it and/or
|
|
Packit |
15a96c |
* modify it under the terms of the GNU General Public License
|
|
Packit |
15a96c |
* as published by the Free Software Foundation; either version
|
|
Packit |
15a96c |
* 2 of the License, or (at your option) any later version.
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* You should have received a copy of the GNU General Public License along
|
|
Packit |
15a96c |
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
Packit |
15a96c |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* 10.07.98 jl Added the log command
|
|
Packit |
15a96c |
* 05.04.99 jl The logfile name should also be passed as a parameter
|
|
Packit |
15a96c |
* 04.03.2002 jl Treat the ^ character between quotes as control code prefix
|
|
Packit |
15a96c |
* 10.09.2013 ts Support sending the null character
|
|
Packit |
15a96c |
* 10.10.2013 ts Add the pipedshell command
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
#ifdef HAVE_CONFIG_H
|
|
Packit |
15a96c |
#include <config.h>
|
|
Packit |
15a96c |
#endif
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
#include <stdarg.h>
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
#include "port.h"
|
|
Packit |
15a96c |
#include "minicom.h"
|
|
Packit |
15a96c |
#include "intl.h"
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
#define OK 0
|
|
Packit |
15a96c |
#define ERR -1
|
|
Packit |
15a96c |
#define RETURN 1
|
|
Packit |
15a96c |
#define BREAK 2
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
enum {
|
|
Packit |
15a96c |
NULL_CHARACTER = 254,
|
|
Packit |
15a96c |
SKIP_NEWLINE = 255,
|
|
Packit |
15a96c |
};
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
struct line {
|
|
Packit |
15a96c |
char *line;
|
|
Packit |
15a96c |
int labelcount;
|
|
Packit |
15a96c |
int lineno;
|
|
Packit |
15a96c |
struct line *next;
|
|
Packit |
15a96c |
};
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
struct var {
|
|
Packit |
15a96c |
char *name;
|
|
Packit |
15a96c |
int value;
|
|
Packit |
15a96c |
struct var *next;
|
|
Packit |
15a96c |
};
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Structure describing the script we are currently executing.
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
struct env {
|
|
Packit |
15a96c |
struct line *lines; /* Start of all lines */
|
|
Packit |
15a96c |
struct var *vars; /* Start of all variables */
|
|
Packit |
15a96c |
const char *scriptname; /* Name of this script */
|
|
Packit |
15a96c |
int verbose; /* Are we verbose? */
|
|
Packit |
15a96c |
jmp_buf ebuf; /* For exit */
|
|
Packit |
15a96c |
int exstat; /* For exit */
|
|
Packit |
15a96c |
};
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
struct env *curenv; /* Execution environment */
|
|
Packit |
15a96c |
int gtimeout = 120; /* Global Timeout */
|
|
Packit |
15a96c |
int etimeout = 0; /* Timeout in expect routine */
|
|
Packit |
15a96c |
jmp_buf ejmp; /* To jump to if expect times out */
|
|
Packit |
15a96c |
int inexpect = 0; /* Are we in the expect routine */
|
|
Packit |
15a96c |
const char *newline; /* What to print for '\n'. */
|
|
Packit |
15a96c |
const char *s_login = "name"; /* User's login name */
|
|
Packit |
15a96c |
const char *s_pass = "password";/* User's password */
|
|
Packit |
15a96c |
struct line *thisline; /* Line to be executed */
|
|
Packit |
15a96c |
int laststatus = 0; /* Status of last command */
|
|
Packit |
15a96c |
char homedir[256]; /* Home directory */
|
|
Packit |
15a96c |
char logfname[PARS_VAL_LEN]; /* Name of logfile */
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
static char inbuf[65]; /* Input buffer. */
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/* Forward declarations */
|
|
Packit |
15a96c |
int s_exec(char *);
|
|
Packit |
15a96c |
int execscript(const char *);
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Walk through the environment, see if LOGIN and/or PASS are present.
|
|
Packit |
15a96c |
* If so, delete them. (Someone using "ps" might see them!)
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
void init_env(void)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
extern char **environ;
|
|
Packit |
15a96c |
char **e;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
for (e = environ; *e; e++) {
|
|
Packit |
15a96c |
if (!strncmp(*e, "LOGIN=", 6)) {
|
|
Packit |
15a96c |
s_login = *e + 6;
|
|
Packit |
15a96c |
*e = "LOGIN=";
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
if (!strncmp(*e, "PASS=", 5)) {
|
|
Packit |
15a96c |
s_pass = *e + 5;
|
|
Packit |
15a96c |
*e = "PASS=";
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Return an environment variable.
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
const char *mygetenv(char *env)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
if (!strcmp(env, "LOGIN"))
|
|
Packit |
15a96c |
return s_login;
|
|
Packit |
15a96c |
if (!strcmp(env, "PASS"))
|
|
Packit |
15a96c |
return s_pass;
|
|
Packit |
15a96c |
return getenv(env);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Display a syntax error and exit.
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
void syntaxerr(const char *s)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
fprintf(stderr, _("script \"%s\": syntax error in line %d %s%s\n"),
|
|
Packit |
15a96c |
curenv->scriptname, thisline->lineno, s, "\r");
|
|
Packit |
15a96c |
exit(1);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Skip all space
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
void skipspace(char **s)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
while (**s == ' ' || **s == '\t')
|
|
Packit |
15a96c |
(*s)++;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Our clock. This gets called every second.
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
void myclock(int dummy)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
(void)dummy;
|
|
Packit |
15a96c |
signal(SIGALRM, myclock);
|
|
Packit |
15a96c |
alarm(1);
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
if (--gtimeout == 0) {
|
|
Packit |
15a96c |
fprintf(stderr, _("script \"%s\": global timeout%s\n"),
|
|
Packit |
15a96c |
curenv->scriptname,"\r");
|
|
Packit |
15a96c |
exit(1);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
if (inexpect && etimeout && --etimeout == 0)
|
|
Packit |
15a96c |
siglongjmp(ejmp, 1);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
static char *buffer; /* The buffer is only growing and never freed... */
|
|
Packit |
15a96c |
static unsigned buffersize;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
static void buf_wr(unsigned idx, char val)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
if (idx >= buffersize)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
buffersize += 64;
|
|
Packit |
15a96c |
buffer = realloc(buffer, buffersize);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
buffer[idx] = val;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
static inline char buf_rd(unsigned idx)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
return buffer[idx];
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
static unsigned bufsize()
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
return buffersize;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
static inline char *buf()
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
return buffer;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Read a word and advance pointer.
|
|
Packit |
15a96c |
* Also processes quoting, variable substituting, and \ escapes.
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
char *getword(char **s)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
unsigned int len;
|
|
Packit |
15a96c |
int f;
|
|
Packit |
15a96c |
int idx = 0;
|
|
Packit |
15a96c |
const char *t = *s;
|
|
Packit |
15a96c |
int sawesc = 0;
|
|
Packit |
15a96c |
int sawq = 0;
|
|
Packit |
15a96c |
const char *env;
|
|
Packit |
15a96c |
char envbuf[32];
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
if (**s == 0)
|
|
Packit |
15a96c |
return NULL;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
for (len = 0; ; len++) {
|
|
Packit |
15a96c |
if (sawesc && t[len]) {
|
|
Packit |
15a96c |
sawesc = 0;
|
|
Packit |
15a96c |
if (t[len] <= '7' && t[len] >= '0') {
|
|
Packit |
15a96c |
buf_wr(idx, 0);
|
|
Packit |
15a96c |
for (f = 0; f < 4 && len < bufsize() && t[len] <= '7' &&
|
|
Packit |
15a96c |
t[len] >= '0'; f++)
|
|
Packit |
15a96c |
buf_wr(idx, 8 * buf_rd(idx) + t[len++] - '0');
|
|
Packit |
15a96c |
if (buf_rd(idx) == 0)
|
|
Packit |
15a96c |
buf_wr(idx, NULL_CHARACTER);
|
|
Packit |
15a96c |
idx++;
|
|
Packit |
15a96c |
len--;
|
|
Packit |
15a96c |
continue;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
switch (t[len]) {
|
|
Packit |
15a96c |
case 'r':
|
|
Packit |
15a96c |
buf_wr(idx++, '\r');
|
|
Packit |
15a96c |
break;
|
|
Packit |
15a96c |
case 'n':
|
|
Packit |
15a96c |
buf_wr(idx++, '\n');
|
|
Packit |
15a96c |
break;
|
|
Packit |
15a96c |
case 'b':
|
|
Packit |
15a96c |
buf_wr(idx++, '\b');
|
|
Packit |
15a96c |
break;
|
|
Packit |
15a96c |
case 'a':
|
|
Packit |
15a96c |
buf_wr(idx++, '\a');
|
|
Packit |
15a96c |
break;
|
|
Packit |
15a96c |
case 'f':
|
|
Packit |
15a96c |
buf_wr(idx++, '\f');
|
|
Packit |
15a96c |
break;
|
|
Packit |
15a96c |
case 'c':
|
|
Packit |
15a96c |
buf_wr(idx++, SKIP_NEWLINE);
|
|
Packit |
15a96c |
break;
|
|
Packit |
15a96c |
default:
|
|
Packit |
15a96c |
buf_wr(idx++, t[len]);
|
|
Packit |
15a96c |
break;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
sawesc = 0;
|
|
Packit |
15a96c |
continue;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
if (t[len] == '\\') {
|
|
Packit |
15a96c |
sawesc = 1;
|
|
Packit |
15a96c |
continue;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
if (t[len] == '"') {
|
|
Packit |
15a96c |
if (sawq == 1) {
|
|
Packit |
15a96c |
sawq = 0;
|
|
Packit |
15a96c |
len++;
|
|
Packit |
15a96c |
break;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
sawq = 1;
|
|
Packit |
15a96c |
continue;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
if (t[len] == '$' && t[len + 1] == '(') {
|
|
Packit |
15a96c |
for(f = len; t[f] && t[f] != ')'; f++)
|
|
Packit |
15a96c |
;
|
|
Packit |
15a96c |
if (t[f] == ')') {
|
|
Packit |
15a96c |
strncpy(envbuf, &t[len + 2], f - len - 2);
|
|
Packit |
15a96c |
envbuf[f - len - 2] = 0;
|
|
Packit |
15a96c |
len = f;
|
|
Packit |
15a96c |
env = mygetenv(envbuf);
|
|
Packit |
15a96c |
if (env == NULL)
|
|
Packit |
15a96c |
env = "";
|
|
Packit |
15a96c |
while (*env)
|
|
Packit |
15a96c |
buf_wr(idx++, *env++);
|
|
Packit |
15a96c |
continue;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
/* ^ prefix for control chars - jl 3.2002 */
|
|
Packit |
15a96c |
if (sawq == 1 && t[len] == '^' && t[len + 1] != 0) {
|
|
Packit |
15a96c |
char c = toupper(t[len + 1]);
|
|
Packit |
15a96c |
if (c >= 'A' && c <= '_') {
|
|
Packit |
15a96c |
len++;
|
|
Packit |
15a96c |
buf_wr(idx++, c - 'A' + 1);
|
|
Packit |
15a96c |
continue;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
if ((!sawq && (t[len] == ' ' || t[len] == '\t')) || t[len] == 0)
|
|
Packit |
15a96c |
break;
|
|
Packit |
15a96c |
buf_wr(idx++, t[len]);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
buf_wr(idx, 0);
|
|
Packit |
15a96c |
*s += len;
|
|
Packit |
15a96c |
skipspace(s);
|
|
Packit |
15a96c |
if (sawesc || sawq)
|
|
Packit |
15a96c |
syntaxerr(_("(word contains ESC or quote)"));
|
|
Packit |
15a96c |
return buf();
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Save a string to memory. Strip trailing '\n'.
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
char *strsave(char *s)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
char *t;
|
|
Packit |
15a96c |
int len;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
len = strlen(s);
|
|
Packit |
15a96c |
if (len && s[len - 1] == '\n')
|
|
Packit |
15a96c |
s[--len] = 0;
|
|
Packit |
15a96c |
if (!(t = malloc(len + 1)))
|
|
Packit |
15a96c |
return t;
|
|
Packit |
15a96c |
strcpy(t, s);
|
|
Packit |
15a96c |
return t;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Throw away all malloced memory.
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
void freemem(void)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
struct line *l, *nextl;
|
|
Packit |
15a96c |
struct var *v, *nextv;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
for (l = curenv->lines; l; l = nextl) {
|
|
Packit |
15a96c |
nextl = l->next;
|
|
Packit |
15a96c |
free(l->line);
|
|
Packit |
15a96c |
free(l);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
for (v = curenv->vars; v; v = nextv) {
|
|
Packit |
15a96c |
nextv = v->next;
|
|
Packit |
15a96c |
free(v->name);
|
|
Packit |
15a96c |
free(v);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Read a script into memory.
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
static int readscript(const char *s)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
FILE *fp;
|
|
Packit |
15a96c |
struct line *tl, *prev = NULL;
|
|
Packit |
15a96c |
char *t;
|
|
Packit |
15a96c |
char buf[500]; /* max length of a line - this should be dynamically! */
|
|
Packit |
15a96c |
int lineno = 0;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
if ((fp = fopen(s, "r")) == NULL) {
|
|
Packit |
15a96c |
fprintf(stderr, _("runscript: couldn't open \"%s\"%s\n"), s, "\r");
|
|
Packit |
15a96c |
exit(1);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/* Read all the lines into a linked list in memory. */
|
|
Packit |
15a96c |
while ((t = fgets(buf, sizeof(buf), fp)) != NULL) {
|
|
Packit |
15a96c |
lineno++;
|
|
Packit |
15a96c |
if (strlen(t) == sizeof(buf) - 1) {
|
|
Packit |
15a96c |
/* Wow, this is really braindead, once upon a time buf was 81 chars
|
|
Packit |
15a96c |
* big and triggered nice errors for too long input lines, now
|
|
Packit |
15a96c |
* we just enlarge the buffer and add a sanity check. This code
|
|
Packit |
15a96c |
* needs to allocate memory dynamically... */
|
|
Packit |
15a96c |
fprintf(stderr, "Input line %u too long, aborting (and fix me!)!\n",
|
|
Packit |
15a96c |
lineno);
|
|
Packit |
15a96c |
exit(1);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
skipspace(&t);
|
|
Packit |
15a96c |
if (*t == '\n' || *t == '#')
|
|
Packit |
15a96c |
continue;
|
|
Packit |
15a96c |
if (((tl = (struct line *)malloc(sizeof (struct line))) == NULL) ||
|
|
Packit |
15a96c |
((tl->line = strsave(t)) == NULL)) {
|
|
Packit |
15a96c |
fprintf(stderr, _("script \"%s\": out of memory%s\n"), s, "\r");
|
|
Packit |
15a96c |
exit(1);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
if (prev)
|
|
Packit |
15a96c |
prev->next = tl;
|
|
Packit |
15a96c |
else
|
|
Packit |
15a96c |
curenv->lines = tl;
|
|
Packit |
15a96c |
tl->next = NULL;
|
|
Packit |
15a96c |
tl->labelcount = 0;
|
|
Packit |
15a96c |
tl->lineno = lineno;
|
|
Packit |
15a96c |
prev = tl;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
fclose(fp);
|
|
Packit |
15a96c |
return 0;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/* Read one character, and store it in the buffer. */
|
|
Packit |
15a96c |
void readchar(void)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
char c;
|
|
Packit |
15a96c |
int n;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
while ((n = read(0, &c, 1)) != 1)
|
|
Packit |
15a96c |
if (errno != EINTR)
|
|
Packit |
15a96c |
break;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
if (n <= 0)
|
|
Packit |
15a96c |
return;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/* Shift character into the buffer. */
|
|
Packit |
15a96c |
#ifdef _SYSV
|
|
Packit |
15a96c |
memcpy(inbuf, inbuf + 1, 63);
|
|
Packit |
15a96c |
#else
|
|
Packit |
15a96c |
# ifdef _BSD43
|
|
Packit |
15a96c |
bcopy(inbuf + 1, inbuf, 63);
|
|
Packit |
15a96c |
# else
|
|
Packit |
15a96c |
/* This is Posix, I believe. */
|
|
Packit |
15a96c |
memmove(inbuf, inbuf + 1, 63);
|
|
Packit |
15a96c |
# endif
|
|
Packit |
15a96c |
#endif
|
|
Packit |
15a96c |
if (curenv->verbose)
|
|
Packit |
15a96c |
fputc(c, stderr);
|
|
Packit |
15a96c |
inbuf[63] = c;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/* See if a string just came in. */
|
|
Packit |
15a96c |
int expfound(const char *word)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
int len;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
if (word == NULL) {
|
|
Packit |
15a96c |
fprintf(stderr, "NULL paramenter to %s!", __func__);
|
|
Packit |
15a96c |
exit(1);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
len = strlen(word);
|
|
Packit |
15a96c |
if (len > 64)
|
|
Packit |
15a96c |
len = 64;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
return !strcmp(inbuf + 64 - len, word);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Send text to a file (stdout or stderr).
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
int output(char *text, FILE *fp)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
unsigned char *w;
|
|
Packit |
15a96c |
int first = 1;
|
|
Packit |
15a96c |
int donl = 1;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
while ((w = (unsigned char *)getword(&text)) != NULL) {
|
|
Packit |
15a96c |
if (!first)
|
|
Packit |
15a96c |
fputc(' ', fp);
|
|
Packit |
15a96c |
first = 0;
|
|
Packit |
15a96c |
for(; *w; w++) {
|
|
Packit |
15a96c |
if (*w == SKIP_NEWLINE) {
|
|
Packit |
15a96c |
donl = 0;
|
|
Packit |
15a96c |
continue;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
if (*w == '\n')
|
|
Packit |
15a96c |
fputs(newline, fp);
|
|
Packit |
15a96c |
else if (*w == NULL_CHARACTER)
|
|
Packit |
15a96c |
fputc('\0', fp);
|
|
Packit |
15a96c |
else
|
|
Packit |
15a96c |
fputc(*w, fp);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
if (donl)
|
|
Packit |
15a96c |
fputs(newline, fp);
|
|
Packit |
15a96c |
fflush(fp);
|
|
Packit |
15a96c |
return OK;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Find a variable in the list.
|
|
Packit |
15a96c |
* If it is not there, create it.
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
struct var *getvar(char *name, int cr)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
struct var *v, *end = NULL;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
for (v = curenv->vars; v; v = v->next) {
|
|
Packit |
15a96c |
end = v;
|
|
Packit |
15a96c |
if (!strcmp(v->name, name))
|
|
Packit |
15a96c |
return v;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
if (!cr) {
|
|
Packit |
15a96c |
fprintf(stderr, _("script \"%s\" line %d: unknown variable \"%s\"%s\n"),
|
|
Packit |
15a96c |
curenv->scriptname, thisline->lineno, name, "\r");
|
|
Packit |
15a96c |
exit(1);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
if ((v = (struct var *)malloc(sizeof(struct var))) == NULL ||
|
|
Packit |
15a96c |
(v->name = strsave(name)) == NULL) {
|
|
Packit |
15a96c |
fprintf(stderr, _("script \"%s\": out of memory%s\n"),
|
|
Packit |
15a96c |
curenv->scriptname, "\r");
|
|
Packit |
15a96c |
exit(1);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
if (end)
|
|
Packit |
15a96c |
end->next = v;
|
|
Packit |
15a96c |
else
|
|
Packit |
15a96c |
curenv->vars = v;
|
|
Packit |
15a96c |
v->next = NULL;
|
|
Packit |
15a96c |
v->value = 0;
|
|
Packit |
15a96c |
return v;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Read a number or variable.
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
int getnum(char *text)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
int val;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
if (!strcmp(text, "$?"))
|
|
Packit |
15a96c |
return laststatus;
|
|
Packit |
15a96c |
if ((val = atoi(text)) != 0 || *text == '0')
|
|
Packit |
15a96c |
return val;
|
|
Packit |
15a96c |
return getvar(text, 0)->value;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Get the lines following "expect" into memory.
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
struct line **buildexpect(void)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
static struct line *seq[17];
|
|
Packit |
15a96c |
int f;
|
|
Packit |
15a96c |
char *w, *t;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
for(f = 0; f < 16; f++) {
|
|
Packit |
15a96c |
if (thisline == NULL) {
|
|
Packit |
15a96c |
fprintf(stderr, _("script \"%s\": unexpected end of file%s\n"),
|
|
Packit |
15a96c |
curenv->scriptname, "\r");
|
|
Packit |
15a96c |
exit(1);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
t = thisline->line;
|
|
Packit |
15a96c |
w = getword(&t);
|
|
Packit |
15a96c |
if (!strcmp(w, "}")) {
|
|
Packit |
15a96c |
if (*t)
|
|
Packit |
15a96c |
syntaxerr(_("(garbage after })"));
|
|
Packit |
15a96c |
seq[f] = NULL;
|
|
Packit |
15a96c |
return seq;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
seq[f] = thisline;
|
|
Packit |
15a96c |
thisline = thisline->next;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
if (f == 16)
|
|
Packit |
15a96c |
syntaxerr(_("(too many arguments)"));
|
|
Packit |
15a96c |
return seq;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Our "expect" function.
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
int expect(char *text)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
char *s, *w;
|
|
Packit |
15a96c |
struct line **volatile seq;
|
|
Packit |
15a96c |
struct line oneline;
|
|
Packit |
15a96c |
struct line *dflseq[2];
|
|
Packit |
15a96c |
char *volatile toact = "exit 1";
|
|
Packit |
15a96c |
volatile int found = 0;
|
|
Packit |
15a96c |
int f, val, c;
|
|
Packit |
15a96c |
char *action = NULL;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
if (inexpect) {
|
|
Packit |
15a96c |
fprintf(stderr, _("script \"%s\" line %d: nested expect%s\n"),
|
|
Packit |
15a96c |
curenv->scriptname, thisline->lineno, "\r");
|
|
Packit |
15a96c |
exit(1);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
etimeout = 120;
|
|
Packit |
15a96c |
inexpect = 1;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
s = getword(&text);
|
|
Packit |
15a96c |
if (!strcmp(s, "{")) {
|
|
Packit |
15a96c |
if (*text)
|
|
Packit |
15a96c |
syntaxerr(_("(garbage after {)"));
|
|
Packit |
15a96c |
thisline = thisline->next;
|
|
Packit |
15a96c |
seq = buildexpect();
|
|
Packit |
15a96c |
} else {
|
|
Packit |
15a96c |
oneline.line = s;
|
|
Packit |
15a96c |
oneline.next = NULL;
|
|
Packit |
15a96c |
dflseq[0] = &oneline;
|
|
Packit |
15a96c |
dflseq[1] = NULL;
|
|
Packit |
15a96c |
seq = dflseq;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
/* Seek a timeout command */
|
|
Packit |
15a96c |
for (f = 0; seq[f]; f++) {
|
|
Packit |
15a96c |
if (!strncmp(seq[f]->line, "timeout", 7)) {
|
|
Packit |
15a96c |
c = seq[f]->line[7];
|
|
Packit |
15a96c |
if (c == 0 || (c != ' ' && c != '\t'))
|
|
Packit |
15a96c |
continue;
|
|
Packit |
15a96c |
s = seq[f]->line + 7;
|
|
Packit |
15a96c |
/* seq[f] = NULL; */
|
|
Packit |
15a96c |
skipspace(&s);
|
|
Packit |
15a96c |
w = getword(&s);
|
|
Packit |
15a96c |
if (w == NULL)
|
|
Packit |
15a96c |
syntaxerr(_("(argument expected)"));
|
|
Packit |
15a96c |
val = getnum(w);
|
|
Packit |
15a96c |
if (val == 0)
|
|
Packit |
15a96c |
syntaxerr(_("(invalid argument)"));
|
|
Packit |
15a96c |
etimeout = val;
|
|
Packit |
15a96c |
skipspace(&s);
|
|
Packit |
15a96c |
if (*s != 0)
|
|
Packit |
15a96c |
toact = s;
|
|
Packit |
15a96c |
break;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
if (sigsetjmp(ejmp, 1) != 0) {
|
|
Packit |
15a96c |
f = s_exec(toact);
|
|
Packit |
15a96c |
inexpect = 0;
|
|
Packit |
15a96c |
return f;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/* Allright. Now do the expect. */
|
|
Packit |
15a96c |
c = OK;
|
|
Packit |
15a96c |
while (!found) {
|
|
Packit |
15a96c |
action = NULL;
|
|
Packit |
15a96c |
readchar();
|
|
Packit |
15a96c |
for (f = 0; seq[f]; f++) {
|
|
Packit |
15a96c |
s = seq[f]->line;
|
|
Packit |
15a96c |
w = getword(&s);
|
|
Packit |
15a96c |
if (expfound(w)) {
|
|
Packit |
15a96c |
action = s;
|
|
Packit |
15a96c |
found = 1;
|
|
Packit |
15a96c |
break;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
if (action != NULL && *action) {
|
|
Packit |
15a96c |
found = 0;
|
|
Packit |
15a96c |
/* Maybe BREAK or RETURN */
|
|
Packit |
15a96c |
if ((c = s_exec(action)) != OK)
|
|
Packit |
15a96c |
found = 1;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
inexpect = 0;
|
|
Packit |
15a96c |
etimeout = 0;
|
|
Packit |
15a96c |
return c;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Jump to a shell and run a command.
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
int shell(char *text)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
laststatus = system(text);
|
|
Packit |
15a96c |
return OK;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Run a command and send its stdout to stdout ( = modem).
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
int pipedshell(char *text)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
FILE *fp = popen(text, "r");
|
|
Packit |
15a96c |
if (fp == NULL) {
|
|
Packit |
15a96c |
laststatus = errno;
|
|
Packit |
15a96c |
return OK;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
char received[64];
|
|
Packit |
15a96c |
size_t read = 0;
|
|
Packit |
15a96c |
while ((read = fread(received, sizeof(char), 64, fp))) {
|
|
Packit |
15a96c |
#ifdef HAVE_USLEEP
|
|
Packit |
15a96c |
/* 200 ms delay. */
|
|
Packit |
15a96c |
usleep(200000);
|
|
Packit |
15a96c |
#endif
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
char *sent = received;
|
|
Packit |
15a96c |
while (read-- > 0)
|
|
Packit |
15a96c |
fputc(*sent++, stdout);
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
fflush(stdout);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
int status = pclose(fp);
|
|
Packit |
15a96c |
if (WIFEXITED(status))
|
|
Packit |
15a96c |
laststatus = WEXITSTATUS(status);
|
|
Packit |
15a96c |
else if (WIFSIGNALED(status))
|
|
Packit |
15a96c |
laststatus = WTERMSIG(status);
|
|
Packit |
15a96c |
else
|
|
Packit |
15a96c |
laststatus = status;
|
|
Packit |
15a96c |
return OK;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Send output to stdout ( = modem)
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
int dosend(char *text)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
#ifdef HAVE_USLEEP
|
|
Packit |
15a96c |
/* 200 ms delay. */
|
|
Packit |
15a96c |
usleep(200000);
|
|
Packit |
15a96c |
#endif
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/* Before we send anything, flush input buffer. */
|
|
Packit |
15a96c |
m_flush(0);
|
|
Packit |
15a96c |
memset(inbuf, 0, sizeof(inbuf));
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
newline = "\r";
|
|
Packit |
15a96c |
return output(text, stdout);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Exit from the script, possibly with a value.
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
int doexit(char *text)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
char *w;
|
|
Packit |
15a96c |
int ret = 0;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
w = getword(&text);
|
|
Packit |
15a96c |
if (w != NULL)
|
|
Packit |
15a96c |
ret = getnum(w);
|
|
Packit |
15a96c |
curenv->exstat = ret;
|
|
Packit |
15a96c |
longjmp(curenv->ebuf, 1);
|
|
Packit |
15a96c |
return 0;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Goto a specific label.
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
int dogoto(char *text)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
char *w;
|
|
Packit |
15a96c |
struct line *l;
|
|
Packit |
15a96c |
char buf[32];
|
|
Packit |
15a96c |
int len;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
w = getword(&text);
|
|
Packit |
15a96c |
if (w == NULL || *text)
|
|
Packit |
15a96c |
syntaxerr(_("(in goto/gosub label)"));
|
|
Packit |
15a96c |
snprintf(buf, sizeof(buf), "%s:", w);
|
|
Packit |
15a96c |
len = strlen(buf);
|
|
Packit |
15a96c |
for (l = curenv->lines; l; l = l->next)
|
|
Packit |
15a96c |
if (!strncmp(l->line, buf, len))
|
|
Packit |
15a96c |
break;
|
|
Packit |
15a96c |
if (l == NULL) {
|
|
Packit |
15a96c |
fprintf(stderr, _("script \"%s\" line %d: label \"%s\" not found%s\n"),
|
|
Packit |
15a96c |
curenv->scriptname, thisline->lineno, w, "\r");
|
|
Packit |
15a96c |
exit(1);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
thisline = l;
|
|
Packit |
15a96c |
/* We return break, to automatically break out of expect loops. */
|
|
Packit |
15a96c |
return BREAK;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Goto a subroutine.
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
int dogosub(char *text)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
struct line *oldline;
|
|
Packit |
15a96c |
int ret = OK;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
oldline = thisline;
|
|
Packit |
15a96c |
dogoto(text);
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
while (ret != ERR) {
|
|
Packit |
15a96c |
if ((thisline = thisline->next) == NULL) {
|
|
Packit |
15a96c |
fprintf(stderr, _("script \"%s\": no return from gosub%s\n"),
|
|
Packit |
15a96c |
curenv->scriptname, "\r");
|
|
Packit |
15a96c |
exit(1);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
ret = s_exec(thisline->line);
|
|
Packit |
15a96c |
if (ret == RETURN) {
|
|
Packit |
15a96c |
ret = OK;
|
|
Packit |
15a96c |
thisline = oldline;
|
|
Packit |
15a96c |
break;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
return ret;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Return from a subroutine.
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
int doreturn(char *text)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
(void)text;
|
|
Packit |
15a96c |
return RETURN;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Print text to stderr.
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
int print(char *text)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
newline = "\r\n";
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
return output(text, stderr);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Declare a variable (integer)
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
int doset(char *text)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
char *w;
|
|
Packit |
15a96c |
struct var *v;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
w = getword(&text);
|
|
Packit |
15a96c |
if (w == NULL)
|
|
Packit |
15a96c |
syntaxerr(_("(missing var name)"));
|
|
Packit |
15a96c |
v = getvar(w, 1);
|
|
Packit |
15a96c |
if (*text)
|
|
Packit |
15a96c |
v->value = getnum(getword(&text));
|
|
Packit |
15a96c |
return OK;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Lower the value of a variable.
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
int dodec(char *text)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
char *w;
|
|
Packit |
15a96c |
struct var *v;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
w = getword(&text);
|
|
Packit |
15a96c |
if (w == NULL)
|
|
Packit |
15a96c |
syntaxerr(_("(expected variable)"));
|
|
Packit |
15a96c |
v = getvar(w, 0);
|
|
Packit |
15a96c |
v->value--;
|
|
Packit |
15a96c |
return OK;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Increase the value of a variable.
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
int doinc(char *text)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
char *w;
|
|
Packit |
15a96c |
struct var *v;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
w = getword(&text);
|
|
Packit |
15a96c |
if (w == NULL)
|
|
Packit |
15a96c |
syntaxerr(_("(expected variable)"));
|
|
Packit |
15a96c |
v = getvar(w, 0);
|
|
Packit |
15a96c |
v->value++;
|
|
Packit |
15a96c |
return OK;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* If syntax: if n1 [><=] n2 command.
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
int doif(char *text)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
char *w;
|
|
Packit |
15a96c |
int n1;
|
|
Packit |
15a96c |
int n2;
|
|
Packit |
15a96c |
char op;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
if ((w = getword(&text)) == NULL)
|
|
Packit |
15a96c |
syntaxerr("(if)");
|
|
Packit |
15a96c |
n1 = getnum(w);
|
|
Packit |
15a96c |
if ((w = getword(&text)) == NULL)
|
|
Packit |
15a96c |
syntaxerr("(if)");
|
|
Packit |
15a96c |
if (strcmp(w, "!=") == 0)
|
|
Packit |
15a96c |
op = '!';
|
|
Packit |
15a96c |
else {
|
|
Packit |
15a96c |
if (*w == 0 || w[1] != 0)
|
|
Packit |
15a96c |
syntaxerr("(if)");
|
|
Packit |
15a96c |
op = *w;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
if ((w = getword(&text)) == NULL)
|
|
Packit |
15a96c |
syntaxerr("(if)");
|
|
Packit |
15a96c |
n2 = getnum(w);
|
|
Packit |
15a96c |
if (!*text)
|
|
Packit |
15a96c |
syntaxerr(_("(expected command after if)"));
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
if (op == '=') {
|
|
Packit |
15a96c |
if (n1 != n2)
|
|
Packit |
15a96c |
return OK;
|
|
Packit |
15a96c |
} else if (op == '!') {
|
|
Packit |
15a96c |
if (n1 == n2)
|
|
Packit |
15a96c |
return OK;
|
|
Packit |
15a96c |
} else if (op == '>') {
|
|
Packit |
15a96c |
if (n1 <= n2)
|
|
Packit |
15a96c |
return OK;
|
|
Packit |
15a96c |
} else if (op == '<') {
|
|
Packit |
15a96c |
if (n1 >= n2)
|
|
Packit |
15a96c |
return OK;
|
|
Packit |
15a96c |
} else
|
|
Packit |
15a96c |
syntaxerr(_("(unknown operator)"));
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
return s_exec(text);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Set the global timeout-time.
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
int dotimeout(char *text)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
char *w;
|
|
Packit |
15a96c |
int val;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
w = getword(&text);
|
|
Packit |
15a96c |
if (w == NULL)
|
|
Packit |
15a96c |
syntaxerr(_("(argument expected)"));
|
|
Packit |
15a96c |
if ((val = getnum(w)) == 0)
|
|
Packit |
15a96c |
syntaxerr(_("(invalid argument)"));
|
|
Packit |
15a96c |
gtimeout = val;
|
|
Packit |
15a96c |
return OK;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Turn verbose on/off (= echo stdin to stderr)
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
int doverbose(char *text)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
char *w;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
curenv->verbose = 1;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
if ((w = getword(&text)) != NULL) {
|
|
Packit |
15a96c |
if (!strcmp(w, "on"))
|
|
Packit |
15a96c |
return OK;
|
|
Packit |
15a96c |
if (!strcmp(w, "off")) {
|
|
Packit |
15a96c |
curenv->verbose = 0;
|
|
Packit |
15a96c |
return OK;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
syntaxerr(_("(unexpected argument)"));
|
|
Packit |
15a96c |
return ERR;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Sleep for a certain number of seconds.
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
int dosleep(char *text)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
int foo, tm;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
tm = getnum(text);
|
|
Packit |
15a96c |
foo = gtimeout - tm;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/* The alarm goes off every second.. */
|
|
Packit |
15a96c |
while (gtimeout != foo)
|
|
Packit |
15a96c |
pause();
|
|
Packit |
15a96c |
return OK;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Break out of an expect loop.
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
int dobreak(char *dummy)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
(void)dummy;
|
|
Packit |
15a96c |
if (!inexpect) {
|
|
Packit |
15a96c |
fprintf(stderr, _("script \"%s\" line %d: break outside of expect%s\n"),
|
|
Packit |
15a96c |
curenv->scriptname, thisline->lineno, "\r");
|
|
Packit |
15a96c |
exit(1);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
return BREAK;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Call another script!
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
int docall(char *text)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
struct line *oldline;
|
|
Packit |
15a96c |
struct env *oldenv;
|
|
Packit |
15a96c |
int er;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
if (*text == 0)
|
|
Packit |
15a96c |
syntaxerr(_("(argument expected)"));
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
if (inexpect) {
|
|
Packit |
15a96c |
fprintf(stderr, _("script \"%s\" line %d: call inside expect%s\n"),
|
|
Packit |
15a96c |
curenv->scriptname, thisline->lineno, "\r");
|
|
Packit |
15a96c |
exit(1);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
oldline = thisline;
|
|
Packit |
15a96c |
oldenv = curenv;
|
|
Packit |
15a96c |
if ((er = execscript(text)) != 0)
|
|
Packit |
15a96c |
exit(er);
|
|
Packit |
15a96c |
/* freemem(); */
|
|
Packit |
15a96c |
thisline = oldline;
|
|
Packit |
15a96c |
curenv = oldenv;
|
|
Packit |
15a96c |
return 0;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
static int do_log_wrapper(char *s)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
do_log("%s", s);
|
|
Packit |
15a96c |
return 0;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/* KEYWORDS */
|
|
Packit |
15a96c |
struct kw {
|
|
Packit |
15a96c |
const char *command;
|
|
Packit |
15a96c |
int (*fn)(char *);
|
|
Packit |
15a96c |
} keywords[] = {
|
|
Packit |
15a96c |
{ "expect", expect },
|
|
Packit |
15a96c |
{ "send", dosend },
|
|
Packit |
15a96c |
{ "!<", pipedshell },
|
|
Packit |
15a96c |
{ "!", shell },
|
|
Packit |
15a96c |
{ "goto", dogoto },
|
|
Packit |
15a96c |
{ "gosub", dogosub },
|
|
Packit |
15a96c |
{ "return", doreturn },
|
|
Packit |
15a96c |
{ "exit", doexit },
|
|
Packit |
15a96c |
{ "print", print },
|
|
Packit |
15a96c |
{ "set", doset },
|
|
Packit |
15a96c |
{ "inc", doinc },
|
|
Packit |
15a96c |
{ "dec", dodec },
|
|
Packit |
15a96c |
{ "if", doif },
|
|
Packit |
15a96c |
{ "timeout", dotimeout },
|
|
Packit |
15a96c |
{ "verbose", doverbose },
|
|
Packit |
15a96c |
{ "sleep", dosleep },
|
|
Packit |
15a96c |
{ "break", dobreak },
|
|
Packit |
15a96c |
{ "call", docall },
|
|
Packit |
15a96c |
{ "log", do_log_wrapper },
|
|
Packit |
15a96c |
{ NULL, (int(*)(char *))0 }
|
|
Packit |
15a96c |
};
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Execute one line.
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
int s_exec(char *text)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
char *w;
|
|
Packit |
15a96c |
struct kw *k;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
w = getword(&text);
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/* If it is a label or a comment, skip it. */
|
|
Packit |
15a96c |
if (w == NULL || *w == '#' || w[strlen(w) - 1] == ':')
|
|
Packit |
15a96c |
return OK;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/* See which command it is. */
|
|
Packit |
15a96c |
for (k = keywords; k->command; k++)
|
|
Packit |
15a96c |
if (!strcmp(w, k->command))
|
|
Packit |
15a96c |
break;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/* Command not found? */
|
|
Packit |
15a96c |
if (k->command == NULL) {
|
|
Packit |
15a96c |
fprintf(stderr, _("script \"%s\" line %d: unknown command \"%s\"%s\n"),
|
|
Packit |
15a96c |
curenv->scriptname, thisline->lineno, w, "\r");
|
|
Packit |
15a96c |
exit(1);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
return (*(k->fn))(text);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Run the script by continously executing "thisline".
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
int execscript(const char *s)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
volatile int ret = OK;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
curenv = (struct env *)malloc(sizeof(struct env));
|
|
Packit |
15a96c |
curenv->lines = NULL;
|
|
Packit |
15a96c |
curenv->vars = NULL;
|
|
Packit |
15a96c |
curenv->verbose = 1;
|
|
Packit |
15a96c |
curenv->scriptname = s;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
if (readscript(s) < 0) {
|
|
Packit |
15a96c |
freemem();
|
|
Packit |
15a96c |
free(curenv);
|
|
Packit |
15a96c |
return ERR;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
signal(SIGALRM, myclock);
|
|
Packit |
15a96c |
alarm(1);
|
|
Packit |
15a96c |
if (setjmp(curenv->ebuf) == 0) {
|
|
Packit |
15a96c |
thisline = curenv->lines;
|
|
Packit |
15a96c |
while (thisline != NULL && (ret = s_exec(thisline->line)) != ERR)
|
|
Packit |
15a96c |
thisline = thisline->next;
|
|
Packit |
15a96c |
} else
|
|
Packit |
15a96c |
ret = curenv->exstat ? ERR : 0;
|
|
Packit |
15a96c |
free(curenv);
|
|
Packit |
15a96c |
return ret;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
void do_args(int argc, char **argv)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
if (argc > 1 && !strcmp(argv[1], "--version")) {
|
|
Packit |
15a96c |
printf(_("runscript, part of minicom version %s\n"), VERSION);
|
|
Packit |
15a96c |
exit(0);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
if (argc < 2) {
|
|
Packit |
15a96c |
fprintf(stderr, _("Usage: runscript <scriptfile> [logfile [homedir]]%s\n"),"\r");
|
|
Packit |
15a96c |
exit(1);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
int main(int argc, char **argv)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
char *s;
|
|
Packit |
15a96c |
#if 0 /* Shouldn't need this.. */
|
|
Packit |
15a96c |
signal(SIGHUP, SIG_IGN);
|
|
Packit |
15a96c |
#endif
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/* initialize locale support */
|
|
Packit |
15a96c |
setlocale(LC_ALL, "");
|
|
Packit |
15a96c |
bindtextdomain(PACKAGE, LOCALEDIR);
|
|
Packit |
15a96c |
textdomain(PACKAGE);
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
init_env();
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
do_args(argc, argv);
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
memset(inbuf, 0, sizeof(inbuf));
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
if (argc > 2) {
|
|
Packit |
15a96c |
strncpy(logfname, argv[2], sizeof(logfname));
|
|
rpm-build |
c8e99c |
logfname[sizeof(logfname) - 1] = '\0';
|
|
Packit |
15a96c |
if (argc > 3)
|
|
Packit |
15a96c |
strncpy(homedir, argv[3], sizeof(homedir));
|
|
Packit |
15a96c |
else if ((s = getenv("HOME")) != NULL)
|
|
Packit |
15a96c |
strncpy(homedir, s, sizeof(homedir));
|
|
Packit |
15a96c |
else
|
|
Packit |
15a96c |
homedir[0] = 0;
|
|
rpm-build |
c8e99c |
homedir[sizeof(homedir) - 1] = '\0';
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
else
|
|
Packit |
15a96c |
logfname[0] = 0;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
return execscript(argv[1]) != OK;
|
|
Packit |
15a96c |
}
|