script.c
上传用户:tianjinjs
上传日期:2007-01-05
资源大小:309k
文件大小:18k
源码类别:

Modem编程

开发平台:

Unix_Linux

  1. /*
  2.  * Runscript    Run a login-or-something script.
  3.  * A basic like "programming language".
  4.  * This program also looks like a basic interpreter :
  5.  * a bit messy. (But hey, I'm no compiler writer :-))
  6.  *
  7.  * Version: 1.22
  8.  *
  9.  * Author: Miquel van Smoorenburg, miquels@drinkel.ow.nl
  10.  *
  11.  * Bugs: The "expect" routine is, unlike gosub, NOT reentrant !
  12.  *
  13.  * This file is part of the minicom communications package,
  14.  * Copyright 1991-1995 Miquel van Smoorenburg,
  15.  * 1997-1999 Jukka Lahtinen
  16.  *
  17.  * This program is free software; you can redistribute it and/or
  18.  * modify it under the terms of the GNU General Public License
  19.  * as published by the Free Software Foundation; either version
  20.  * 2 of the License, or (at your option) any later version.
  21.  *
  22.  * 10.07.98 jl  Added the log command
  23.  * 05.04.99 jl  The logfile name should also be passed as a parameter
  24.  */
  25. #include "port.h"
  26. #include "minicom.h"
  27. #include "intl.h"
  28.  
  29. #define OK 0
  30. #define ERR -1
  31. #define RETURN 1
  32. #define BREAK 2
  33. #ifndef lint
  34. char *Version = "@(#)runscript 1.23 31-May-1999 JL";
  35. #endif
  36. struct line {
  37.   char *line;
  38.   int labelcount;
  39.   int lineno;
  40.   struct line *next;
  41. };
  42. struct var {
  43.   char *name;
  44.   int value;
  45.   struct var *next;
  46. };
  47. #define LNULL ((struct line *)0)
  48. #define VNULL ((struct var  *)0)
  49. #ifndef CNULL
  50. #define CNULL ((char *)0)
  51. #endif
  52. /*
  53.  * Structure describing the script we are currently executing.
  54.  */
  55. struct env {
  56.   struct line *lines; /* Start of all lines */
  57.   struct var *vars; /* Start of all variables */
  58.   char *scriptname; /* Name of this script */
  59.   int verbose; /* Are we verbose? */
  60.   jmp_buf ebuf; /* For exit */
  61.   int exstat; /* For exit */
  62. };
  63.   
  64. struct env *curenv; /* Execution environment */  
  65. int gtimeout = 120; /* Global Timeout */
  66. int etimeout = 0; /* Timeout in expect routine */
  67. jmp_buf ejmp; /* To jump to if expect times out */
  68. int inexpect = 0; /* Are we in the expect routine */
  69. char *newline; /* What to print for 'n'. */
  70. char *s_login = "name"; /* User's login name */
  71. char *s_pass = "password"; /* User's password */
  72. struct line *thisline; /* Line to be executed */ 
  73. int laststatus = 0; /* Status of last command */
  74. char homedir[256]; /* Home directory */
  75. char logfname[PARS_VAL_LEN]; /* Name of logfile */
  76. static char inbuf[65]; /* Input buffer. */
  77. /* Forward declarations */
  78. int s_exec();
  79. int execscript();
  80. /*
  81.  * Print something formatted to stderr.
  82.  */
  83. /*VARARGS*/ 
  84. void s_error(fmt, a1, a2, a3, a4)
  85. char *fmt;
  86. char *a1, *a2, *a3, *a4;
  87. {
  88.   fprintf(stderr, fmt, a1, a2, a3, a4);
  89. }
  90. /*
  91.  * Walk through the environment, see if LOGIN and/or PASS are present.
  92.  * If so, delete them. (Someone using "ps" might see them!)
  93.  */
  94. void init_env()
  95. {
  96.   extern char **environ;
  97.   char **e;
  98.   for(e = environ; *e; e++) {
  99. if (!strncmp(*e, "LOGIN=", 6)) {
  100. s_login = (*e) + 6;
  101. *e = "LOGIN=";
  102. }
  103. if (!strncmp(*e, "PASS=", 5)) {
  104. s_pass = (*e) + 5;
  105. *e = "PASS=";
  106. }
  107.   }
  108. }
  109. /*
  110.  * Return an environment variable.
  111.  */
  112. char *mygetenv(env)
  113. char *env;
  114. {
  115.   if (!strcmp(env, "LOGIN")) return(s_login);
  116.   if (!strcmp(env, "PASS")) return(s_pass);
  117.   return(getenv(env));
  118. }
  119. /*
  120.  * Display a syntax error and exit.
  121.  */
  122. void syntaxerr(s)
  123. char *s;
  124. {
  125.   s_error(_("script "%s": syntax error in line %d %s%sn"),
  126.   curenv->scriptname, thisline->lineno, s, "r");
  127.   exit(1);
  128. }
  129. /*
  130.  * Skip all space
  131.  */
  132. void skipspace(s)
  133. char **s;
  134. {
  135.   while(**s == ' ' || **s == 't') (*s)++;
  136. }
  137.   
  138. /*
  139.  * Our clock. This gets called every second.
  140.  */
  141. /*ARGSUSED*/
  142. void myclock(dummy)
  143. int dummy;
  144. {
  145.   (void)dummy;
  146.   signal(SIGALRM, myclock);
  147.   alarm(1);
  148.   if (--gtimeout == 0) {
  149.    s_error(_("script "%s": global timeout%sn"),
  150. curenv->scriptname,"r");
  151.    exit(1);
  152.   }
  153.   if (inexpect && etimeout && --etimeout == 0) siglongjmp(ejmp, 1);
  154. }
  155. /*
  156.  * Read a word and advance pointer.
  157.  * Also processes quoting, variable substituting, and  escapes.
  158.  */
  159. char *getword(s)
  160. char **s;
  161. {
  162.   static char buf[81];
  163.   int len, f;
  164.   int idx = 0;
  165.   char *t = *s;
  166.   int sawesc = 0;
  167.   int sawq = 0;
  168.   char *env, envbuf[32];
  169.   if (**s == 0) return(CNULL);
  170.   for(len = 0; len < 81; len++) {
  171.    if (sawesc && t[len]) {
  172.    sawesc = 0;
  173.    if (t[len] <= '7' && t[len] >= '0') {
  174.    buf[idx] = 0;
  175.    for(f = 0; f < 4 && len < 81 && t[len] <= '7' &&
  176.        t[len] >= '0'; f++) 
  177.    buf[idx] = 8*buf[idx] + t[len++] - '0';
  178.    if (buf[idx] == 0) buf[idx] = '@';
  179.    idx++; len--;
  180.    continue;
  181.    }
  182.    switch(t[len]) {
  183.    case 'r':
  184.    buf[idx++] = 'r';
  185.    break;
  186.    case 'n':
  187.    buf[idx++] = 'n';
  188.    break;
  189.    case 'b':
  190.    buf[idx++] = 'b';
  191.    break;
  192. #ifndef _HPUX_SOURCE
  193.    case 'a':
  194.    buf[idx++] = 'a';
  195.    break;
  196. #endif
  197.    case 'f':
  198.    buf[idx++] = 'f';
  199.    break;
  200.    case 'c':
  201.    buf[idx++] = 255;
  202.    break;
  203.    default:
  204.    buf[idx++] = t[len];
  205.    break;
  206.    }
  207.    sawesc = 0;
  208.    continue;
  209.    }
  210.    if (t[len] == '\') {
  211.    sawesc = 1;
  212.    continue;
  213.    }
  214.    if (t[len] == '"') {
  215.    if (sawq == 1) {
  216.    sawq = 0;
  217.    len++;
  218.    break;
  219.    }
  220.    sawq = 1;
  221.    continue;
  222.    }
  223.    if (t[len] == '$' && t[len + 1] == '(') {
  224.    for(f = len; t[f] && t[f] != ')'; f++)
  225.    ;
  226.    if (t[f] == ')') {
  227.    strncpy(envbuf, &t[len + 2], f - len - 2);
  228.    envbuf[f - len - 2] = 0;
  229.    len = f;
  230.    env = mygetenv(envbuf);
  231.    if (env == CNULL) env = "";
  232.    while(*env) buf[idx++] = *env++;
  233.    continue;
  234.    }
  235.    }
  236.    if((!sawq && (t[len] == ' ' || t[len] == 't')) || t[len] == 0) break;
  237.    buf[idx++] = t[len];
  238.   }
  239.   buf[idx] = 0;
  240.   (*s) += len;
  241.   skipspace(s);
  242.   if (sawesc || sawq) syntaxerr(_("(word contains ESC or quote)"));
  243.   return(buf);
  244. }
  245. /*
  246.  * Save a string to memory. Strip trailing 'n'.
  247.  */
  248. char *strsave(s)
  249. char *s;
  250. {
  251.   char *t;
  252.   int len;
  253.   len = strlen(s);
  254.   if (len && s[len - 1] == 'n') s[--len] = 0;
  255.   if ((t = (char *)malloc(len + 1)) == (char *)0) return(t);
  256.   strcpy(t, s);
  257.   return(t);
  258. }
  259. /*
  260.  * Throw away all malloced memory.
  261.  */
  262. void freemem()
  263. {
  264.   struct line *l, *nextl;
  265.   struct var *v, *nextv;
  266.   for(l = curenv->lines; l; l = nextl) {
  267. nextl = l->next;
  268.    free((char *)l->line);
  269.    free((char *)l);
  270.   }
  271.   for(v = curenv->vars; v; v = nextv) {
  272. nextv = v->next;
  273.    free(v->name);
  274.    free((char *)v);
  275.   }
  276. }
  277. /*
  278.  * Read a script into memory.
  279.  */
  280. int readscript(s)
  281. char *s;
  282. {
  283.   FILE *fp;
  284.   struct line *tl, *prev = LNULL;
  285.   char *t;
  286.   char buf[81];
  287.   int no = 0;
  288.   if ((fp = fopen(s, "r")) == (FILE *)0) {
  289.    s_error(_("runscript: couldn't open %s%sn"), s, "r");
  290.    exit(1);
  291.   }
  292.   
  293.   /* Read all the lines into a linked list in memory. */
  294.   while((t = fgets(buf, 80, fp)) != CNULL) {
  295.    no++;
  296.    skipspace(&t);
  297.    if (*t == 'n') continue;
  298.    if (  ((tl = (struct line *)malloc(sizeof (struct line))) == LNULL) ||
  299.          ((tl->line = strsave(t)) == CNULL)) {
  300.    s_error(_("script %s: out of memory%sn"), s, "r");
  301.    exit(1);
  302.    }
  303.    if (prev)
  304.    prev->next = tl;
  305.    else
  306.    curenv->lines = tl;
  307.    tl->next = (struct line *)0;
  308.    tl->labelcount = 0;
  309.    tl->lineno = no;
  310.    prev = tl;
  311.   }
  312.   return(0);
  313. }
  314. /* Read one character, and store it in the buffer. */
  315. void readchar()
  316. {
  317.   char c;
  318.   int n;
  319.   while((n = read(0, &c, 1)) != 1)
  320.    if (errno != EINTR) break;
  321.   
  322.   if (n <= 0) return;
  323.   /* Shift character into the buffer. */
  324. #ifdef _SYSV
  325.   memcpy(inbuf, inbuf + 1, 63);
  326. #else
  327. #  ifdef _BSD43
  328.   bcopy(inbuf + 1, inbuf, 63);
  329. #  else
  330.   /* This is Posix, I believe. */
  331.   memmove(inbuf, inbuf + 1, 63);
  332. #  endif
  333. #endif
  334.   if (curenv->verbose) fputc(c, stderr);
  335.   inbuf[63] = c;
  336. }
  337. /* See if a string just came in. */
  338. int expfound(word)
  339. char *word;
  340. {
  341.   int len;
  342.   len = strlen(word);
  343.   if (len > 64) len = 64;
  344.   return(!strcmp(inbuf + 64 - len, word));
  345. }
  346. /*
  347.  * Send text to a file (stdout or stderr).
  348.  */
  349. int output(text, fp)
  350. char *text;
  351. FILE *fp;
  352. {
  353.   unsigned char *w;
  354.   int first = 1;
  355.   int donl = 1;
  356.   while((w = (unsigned char *)getword(&text)) != (unsigned char *)0) {
  357.    if (!first) fputc(' ', fp);
  358.    first = 0;
  359.    for(; *w; w++) {
  360.    if (*w == 255) {
  361.    donl = 0;
  362.    continue;
  363.    }
  364.    if (*w == 'n')
  365.    fputs(newline, fp);
  366.    else
  367.    fputc(*w, fp);
  368.    }
  369.   }
  370.   if (donl) fputs(newline, fp);
  371.   fflush(fp);
  372.   return(OK);
  373. }
  374. /*
  375.  * Find a variable in the list.
  376.  * If it is not there, create it.
  377.  */
  378. struct var *getvar(name, cr)
  379. char *name;
  380. int cr;
  381. {
  382.   struct var *v, *end = VNULL;
  383.   
  384.   for(v = curenv->vars; v; v = v->next) {
  385.    end = v;
  386.    if (!strcmp(v->name, name)) return(v);
  387.   }
  388.   if (!cr) {
  389.    s_error(_("script "%s" line %d: unknown variable "%s"%sn"),
  390.    curenv->scriptname, thisline->lineno, name, "r");
  391.    exit(1);
  392.   }
  393.   if ((v = (struct var *)malloc(sizeof(struct var))) == VNULL ||
  394.       (v->name = strsave(name)) == CNULL) {
  395.    s_error(_("script "%s": out of memory%sn"),
  396. curenv->scriptname, "r");
  397.    exit(1);
  398.   }
  399.   if (end)
  400. end->next = v;
  401.   else
  402.    curenv->vars = v;
  403.   v->next = VNULL;
  404.   v->value = 0;
  405.   return(v);
  406. }
  407. /*
  408.  * Read a number or variable.
  409.  */
  410. int getnum(text)
  411. char *text;
  412. {
  413.   int val;
  414.   if (!strcmp(text, "$?")) return(laststatus);
  415.   if ((val = atoi(text)) != 0 || *text == '0') return(val);
  416.   return(getvar(text, 0)->value);
  417. }
  418.   
  419. /*
  420.  * Get the lines following "expect" into memory.
  421.  */
  422. struct line **buildexpect()
  423. {
  424.   static struct line *seq[17];
  425.   int f;
  426.   char *w, *t;
  427.   
  428.   for(f = 0; f < 16; f++) {
  429.    if (thisline == LNULL) {
  430.    s_error(_("script "%s": unexpected end of file%sn"), 
  431.    curenv->scriptname, "r");
  432.    exit(1);
  433.    }
  434.    t = thisline->line;
  435.    w = getword(&t);
  436.    if (!strcmp(w, "}")) {
  437.    if (*t) syntaxerr(_("(garbage after })")); 
  438. seq[f] = NULL;
  439.    return(seq);
  440.    }
  441.    seq[f] = thisline;
  442.    thisline = thisline->next;
  443.   }
  444.   if (f == 16) syntaxerr(_("(too many arguments)"));
  445.   return(seq);
  446. }
  447. /*
  448.  * Our "expect" function.
  449.  */
  450. int expect(text)
  451. char *text;
  452. {
  453.   char *s, *w;
  454.   struct line **seq;
  455.   struct line oneline;
  456.   struct line *dflseq[2];
  457.   char *toact = "exit 1";
  458.   int found = 0, f, val, c;
  459.   char *action = CNULL;
  460.   if (inexpect) {
  461.     s_error(_("script "%s" line %d: nested expect%sn"),
  462.     curenv->scriptname, thisline->lineno, "r");
  463.     exit(1);
  464.   }
  465.   etimeout = 120;
  466.   inexpect = 1;
  467.   s = getword(&text);
  468.   if (!strcmp(s, "{")) {
  469.    if (*text) syntaxerr(_("(garbage after {)"));
  470.    thisline = thisline->next;
  471.    seq = buildexpect();
  472.   } else {
  473.   dflseq[1] = LNULL;
  474.   dflseq[0] = &oneline;
  475.   oneline.line = text;
  476.   oneline.next = LNULL;
  477. seq = dflseq;
  478.   }
  479.   /* Seek a timeout command */
  480.   for(f = 0; seq[f]; f++) {
  481.    if (!strncmp(seq[f]->line, "timeout", 7)) {
  482.    c = seq[f]->line[7];
  483.    if (c == 0 || (c != ' ' && c != 't')) continue;
  484.    s = seq[f]->line + 7;
  485.    seq[f] = LNULL;
  486.    skipspace(&s);
  487.    w = getword(&s);
  488.    if (w == CNULL) syntaxerr(_("(argument expected)"));
  489.    val = getnum(w);
  490.    if (val == 0) syntaxerr(_("(invalid argument)"));
  491.    etimeout = val;
  492.    skipspace(&s);
  493.    if (*s != 0) toact = s;
  494.    break;
  495. }
  496.   }
  497.   if (sigsetjmp(ejmp,1) != 0) {
  498.    f = s_exec(toact);
  499.    inexpect = 0;
  500.    return(f);
  501.   }
  502.   /* Allright. Now do the expect. */
  503.   c = OK;
  504.   while(!found) {
  505.    action = CNULL;
  506.    readchar();
  507.    for(f = 0; seq[f]; f++) {
  508.    s = seq[f]->line;
  509.    w = getword(&s);
  510.    if (expfound(w)) {
  511.    action = s;
  512.    found = 1;
  513.    break;
  514.    }
  515.    }
  516.    if (action != CNULL && *action) {
  517.    found = 0;
  518.    /* Maybe BREAK or RETURN */
  519.    if ((c = s_exec(action)) != OK) found = 1;
  520.    }
  521.   }
  522.   inexpect = 0;
  523.   etimeout = 0;
  524.   return(c);
  525. }
  526. /*
  527.  * Jump to a shell and run a command.
  528.  */
  529. int shell(text)
  530. char *text;
  531. {
  532.   laststatus = system(text);
  533.   return(OK);
  534. }
  535. /*
  536.  * Send output to stdout ( = modem)
  537.  */
  538. int dosend(text)
  539. char *text;
  540. {
  541. #ifdef __linux__
  542.   /* 200 ms delay. */
  543.   usleep(200000);
  544. #endif
  545.   /* Before we send anything, flush input buffer. */
  546.   m_flush(0);
  547.   memset(inbuf, 0, sizeof(inbuf));
  548.   newline = "r";
  549.   return(output(text, stdout));
  550. }
  551. /*
  552.  * Exit from the script, possibly with a value.
  553.  */
  554. int doexit(text)
  555. char *text;
  556. {
  557.   char *w;
  558.   int ret = 0;
  559.   w = getword(&text);
  560.   if (w != CNULL) ret = getnum(w);
  561.   curenv->exstat = ret;
  562.   longjmp(curenv->ebuf, 1);
  563.   return(0);
  564. }
  565. /*
  566.  * Goto a specific label.
  567.  */
  568. int dogoto(text)
  569. char *text;
  570. {
  571.   char *w;
  572.   struct line *l;
  573.   char buf[32];
  574.   int len;
  575.   w = getword(&text);
  576.   if (w == CNULL || *text) syntaxerr(_("(in goto/gosub label)"));
  577.   snprintf(buf, sizeof(buf), "%s:", w);
  578.   len = strlen(buf);
  579.   for(l = curenv->lines; l; l = l->next) if (!strncmp(l->line, buf, len)) break;
  580.   if (l == LNULL) {
  581.    s_error(_("script "%s" line %d: label "%s" not found%sn"),
  582.    curenv->scriptname, thisline->lineno, w, "r");
  583.    exit(1);
  584.   }
  585.   thisline = l;
  586.   /* We return break, to automatically break out of expect loops. */
  587.   return(BREAK);
  588. }
  589. /*
  590.  * Goto a subroutine.
  591.  */
  592. int dogosub(text)
  593. char *text;
  594. {
  595.   struct line *oldline;
  596.   int ret = OK;
  597.   oldline = thisline;
  598.   dogoto(text);
  599.   
  600.   while(ret != ERR) {
  601. if ((thisline = thisline->next) == LNULL) {
  602. s_error(_("script "%s": no return from gosub%sn"), 
  603. curenv->scriptname, "r");
  604. exit(1);
  605. }
  606. ret = s_exec(thisline->line);
  607. if (ret == RETURN) {
  608. ret = OK;
  609. thisline = oldline;
  610. break;
  611. }
  612.   }
  613.   return(ret);
  614. }
  615. /*
  616.  * Return from a subroutine.
  617.  */
  618. /*ARGSUSED*/
  619. int doreturn(text)
  620. char *text;
  621. {
  622.   (void)text;
  623.   return(RETURN);
  624. }
  625. /*
  626.  * Print text to stderr.
  627.  */
  628. int print(text)
  629. char *text;
  630. {
  631.   newline = "rn";
  632.   return(output(text, stderr));
  633. }
  634. /*
  635.  * Declare a variable (integer)
  636.  */
  637. int doset(text)
  638. char *text;
  639. {
  640.   char *w;
  641.   struct var *v;
  642.   w = getword(&text);
  643.   if (w == CNULL) syntaxerr(_("(missing var name)"));
  644.   v = getvar(w, 1);
  645.   if (*text) v->value = getnum(getword(&text));
  646.   return(OK);
  647. /*
  648.  * Lower the value of a variable.
  649.  */
  650. int dodec(text)
  651. char *text;
  652. {
  653.   char *w;
  654.   struct var *v;
  655.   
  656.   w = getword(&text);
  657.   if (w == CNULL)  syntaxerr(_("(expected variable)"));
  658.   v = getvar(w, 0);
  659.   v->value--;
  660.   return(OK);
  661. }
  662. /*
  663.  * Increase the value of a variable.
  664.  */
  665. int doinc(text)
  666. char *text;
  667. {
  668.   char *w;
  669.   struct var *v;
  670.   
  671.   w = getword(&text);
  672.   if (w == CNULL)  syntaxerr(_("(expected variable)"));
  673.   v = getvar(w, 0);
  674.   v->value++;
  675.   return(OK);
  676. }
  677. /*
  678.  * If syntax: if n1 [><=] n2 command.
  679.  */
  680. int doif(text)
  681. char *text;
  682. {
  683.   char *w;
  684.   int n1;
  685.   int n2;
  686.   char op;
  687.   
  688.   if ((w = getword(&text)) == CNULL) syntaxerr("(if)");
  689.   n1 = getnum(w);
  690.   if ((w = getword(&text)) == CNULL) syntaxerr("(if)");
  691.   if (strcmp(w, "!=") == 0)
  692. op = '!';
  693.   else {
  694. if (*w == 0 || w[1] != 0) syntaxerr("(if)");
  695. op = *w;
  696.   }
  697.   if ((w = getword(&text)) == CNULL) syntaxerr("(if)");
  698.   n2 = getnum(w);
  699.   if (!*text) syntaxerr(_("(expected command after if)"));
  700.   
  701.   if (op == '=') {
  702.    if (n1 != n2) return(OK);
  703.   } else if (op == '!') {
  704. if (n1 == n2) return(OK);
  705.   } else if (op == '>') {
  706.    if (n1 <= n2) return(OK);
  707.   } else if (op == '<') {
  708.    if (n1 >= n2) return(OK);
  709.   } else {
  710.    syntaxerr(_("(unknown operator)"));
  711.   }
  712.   return(s_exec(text));
  713. }
  714. /*
  715.  * Set the global timeout-time.
  716.  */
  717. int dotimeout(text)
  718. char *text;
  719. {
  720.   char *w;
  721.   int val;
  722.   w = getword(&text);
  723.   if(w == CNULL) syntaxerr(_("(argument expected)"));
  724.   if ((val = getnum(w)) == 0) syntaxerr(_("(invalid argument)"));
  725.   gtimeout = val;
  726.   return(OK);
  727. }
  728. /*
  729.  * Turn verbose on/off (= echo stdin to stderr)
  730.  */
  731. int doverbose(text)
  732. char *text;
  733. {
  734.   char *w;
  735.   curenv->verbose = 1;
  736.   if ((w = getword(&text)) != CNULL) {
  737. if (!strcmp(w, "on")) return(OK);
  738. if (!strcmp(w, "off")) {
  739. curenv->verbose = 0;
  740. return(OK);
  741. }
  742.   }
  743.   syntaxerr(_("(unexpected argument)"));
  744.   return(ERR);
  745. }
  746. /*
  747.  * Sleep for a certain number of seconds.
  748.  */
  749. int dosleep(text)
  750. char *text;
  751. {
  752.   int foo, tm;
  753.   
  754.   tm = getnum(text);
  755.   
  756.   foo = gtimeout - tm;
  757.   
  758.   /* The alarm goes off every second.. */
  759.   while(gtimeout != foo) pause();
  760.   return(OK);
  761. }
  762. /*
  763.  * Break out of an expect loop.
  764.  */
  765. int dobreak()
  766. {
  767.   if (!inexpect) {
  768.    s_error(_("script "%s" line %d: break outside of expect%sn"),
  769.    curenv->scriptname, thisline->lineno, "r");
  770.    exit(1);
  771.   }
  772.   return(BREAK);
  773. }
  774. /*
  775.  * Call another script!
  776.  */
  777. int docall(text)
  778. char *text;
  779. {
  780.   struct line *oldline;
  781.   struct env *oldenv;
  782.   int er;
  783.   if (*text == 0) syntaxerr(_("(argument expected)"));
  784.   if (inexpect) {
  785.    s_error(_("script "%s" line %d: call inside expect%sn"),
  786.    curenv->scriptname, "r");
  787.    exit(1);
  788.   }
  789.   oldline = thisline;
  790.   oldenv = curenv;
  791.   if ((er = execscript(text)) != 0) exit(er);
  792.   /* freemem(); */
  793.   thisline = oldline;
  794.   curenv = oldenv;
  795.   return(0);
  796. }
  797.   
  798. /* KEYWORDS */
  799. struct kw {
  800.   char *command;
  801.   int (*fn)();
  802. } keywords[] = {
  803.   { "expect", expect },
  804.   { "send", dosend },
  805.   { "!", shell },
  806.   { "goto", dogoto },
  807.   { "gosub", dogosub },
  808.   { "return", doreturn },
  809.   { "exit", doexit },
  810.   { "print", print },
  811.   { "set", doset },
  812.   { "inc", doinc },
  813.   { "dec", dodec },
  814.   { "if", doif },
  815.   { "timeout", dotimeout },
  816.   { "verbose", doverbose },
  817.   { "sleep", dosleep },
  818.   { "break", dobreak },
  819.   { "call", docall },
  820.   { "log", (int(*)())do_log },
  821.   { (char *)0, (int(*)())0 }
  822. };
  823.  
  824. /*
  825.  * Execute one line.
  826.  */
  827. int s_exec(text)
  828. char *text;
  829. {
  830.   char *w;
  831.   struct kw *k;
  832.   w = getword(&text);
  833.   /* If it is a label or a comment, skip it. */
  834.   if (w == CNULL || *w == '#' || w[strlen(w) - 1] == ':') return(OK);
  835.   
  836.   /* See which command it is. */
  837.   for(k = keywords; k->command; k++)
  838.    if (!strcmp(w, k->command)) break;
  839.   /* Command not found? */
  840.   if (k->command == (char *)NULL) {
  841. s_error(_("script "%s" line %d: unknown command "%s"%sn"),
  842.    curenv->scriptname, thisline->lineno, w, "r");
  843. exit(1);
  844.   }
  845.   return((*(k->fn))(text));
  846. }
  847. /*
  848.  * Run the script by continously executing "thisline".
  849.  */
  850. int execscript(s)
  851. char *s;
  852. {
  853.   int ret = OK;
  854.   curenv = (struct env *)malloc(sizeof(struct env));
  855.   curenv->lines = LNULL;
  856.   curenv->vars  = VNULL;
  857.   curenv->verbose = 1;
  858.   curenv->scriptname = s;
  859.   if (readscript(s) < 0) {
  860.    freemem();
  861. free(curenv);
  862.    return(ERR);
  863.   }
  864.   
  865.   signal(SIGALRM, myclock);
  866.   alarm(1);
  867.   if (setjmp(curenv->ebuf) == 0) {
  868. thisline = curenv->lines;
  869. while(thisline != LNULL && (ret = s_exec(thisline->line)) != ERR)
  870.    thisline = thisline->next;
  871.   } else
  872.    ret = curenv->exstat ? ERR : 0;
  873.   free(curenv);
  874.   return(ret);
  875. }
  876. int main(argc, argv)
  877. int argc;
  878. char **argv;
  879. {
  880.   char *s;
  881. #if 0 /* Shouldn't need this.. */
  882.   signal(SIGHUP, SIG_IGN);
  883. #endif
  884. #ifdef _I18N_
  885.   bindtextdomain("minicom", "/usr/share/locale");
  886.   textdomain("minicom");
  887. #endif
  888.   init_env();
  889.   memset(inbuf, 0, sizeof(inbuf));
  890.   if (argc < 2) {
  891.     s_error(_("Usage: runscript <scriptfile> [logfile [homedir]]%sn"),"r");
  892.     return(1);
  893.   }
  894.   if (argc > 2) {
  895.     strncpy(logfname, argv[2], sizeof(logfname));
  896.     if (argc > 3)
  897.       strncpy(homedir, argv[3], sizeof(homedir));
  898.     else if ((s = getenv("HOME")) != CNULL)
  899.       strncpy(homedir, s, sizeof(homedir));
  900.     else
  901.       homedir[0]=0;
  902.   }
  903.   else
  904.     logfname[0] = 0;
  905.   return(execscript(argv[1]) != OK);
  906. }