xtscrpt.c
上传用户:duobangkj
上传日期:2007-01-07
资源大小:70k
文件大小:44k
- /* xtscrpt.c -- scripting for XT
- This file uses 4-character tabstops
- Author: larry gensch, December 1987
- Major rewrite: fred buck, Jan 1989
- Binding code: larry gensch, September 1991
- This code is released to the public domain
- */
- #include <stdio.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/timeb.h>
- #include <time.h>
- #include <ctype.h>
- #include <signal.h>
- #include <setjmp.h>
- #include <sys/stat.h>
- #include "xt.h"
- jmp_buf here;
- extern FILE *cfp;
- short ttyflag, debugflag, scriptflag,
- mrbstart, /* ring buffer start pointer */
- mrbcount, /* ring buffer counter */
- BREAK = 0; /* a hook for a later 'trap' keyword */
- extern short eofflag;
- extern int s_set(), s_exit();
- extern void divert(), set_onoff();
- int my_escape = 1; /* Control-A; resettable at run-time */
- char mringbuf[LG_BUFF]; /* ring buffer for modem input */
- static S_abort();
- static void unsetall(), S_bombout(), S_call();
- static char *NO_ARG = "%s command must have an argument";
- static bindfunc_t find_function(); /* bindfunc_t : see xt.h */
- binding_t *first_binding = NIL(binding_t);
- static bindstr_t function_list[] = {
- {ENDCHAR, "endchar", "Exit terminal mode"},
- {QUITCHR, "quitchr", "Quit program"},
- {CAPTYES, "captyes", "Turn on terminal mode capture"},
- {CAPTEND, "captend", "Turn off terminal mode capture"},
- {DIVCHAR, "divchar", "Send file through modem"},
- {SCRPCHR, "scrpchr", "Prompt for script file"},
- {HLPCHAR, "hlpchar", "Display terminal mode key bindings"},
- {EMITSTR, "emitstr", "Emit string"},
- {DOSCRPT, "doscrpt", "Execute script file"}
- };
- #define FUNCTION_COUNT (sizeof(function_list) / sizeof(function_list[0]))
- static RETSIGTYPE
- newsigint(junk)
- int junk;
- {
- eofflag++;
- show_abort();
- S_bombout();
- longjmp(here,1);
- }
- void
- do_script(file)
- char *file;
- {
- RETSIGTYPE (*oldvec)();
- capture = eofflag = FALSE;
- scriptflag = TRUE;
- oldvec = signal(SIGINT, newsigint);
- if (!setjmp(here))
- S_call(file);
- unsetall();
- if (capture)
- capture = FALSE,
- fclose(cfp);
- scriptflag = FALSE;
- signal(SIGINT, oldvec);
- }
- static
- k_seen(bytes,fword)
- long bytes;
- char *fword;
- {
- int i, j, k=0;
- char *ptr;
- sprintf(line,""%s"",fword);
- lptr = line;
- getword();
- lc_word(word);
- ptr = fword;
- if (!fword || !*fword){
- sprintf(Msg,NO_ARG,"SEEN");
- S2(Msg);
- return FAILURE;
- }
- j = mrbstart - 1;
- if (bytes>0 && bytes<LG_BUFF)
- k = mrbcount - bytes; /* check only most recent 'bytes' bytes */
- i = 0;
- while ((i++)<mrbcount){
- ++j;
- j = j % LG_BUFF;
- if (i<k)
- continue;
- if (tolower(mringbuf[j]) != *ptr){
- ptr = word;
- continue;
- }
- if (*(++ptr)==' ')
- return SUCCESS;
- }
- return FAILURE;
- }
- k_waitfor(interval,fword)
- long interval;
- char *fword;
- {
- register int c, i = -1 ;
- register time_t limit, waitfor_msec = 0;
- char *ptr;
- mrbstart = mrbcount = 0;
- sprintf(line,""%s"",fword);
- lptr = line;
- getword();
- lc_word(word);
- ptr = word;
- if (interval < -1){
- waitfor_msec = -interval;
- goto SPITOUT;
- }
- if (!fword || word[0] == ' '){
- sprintf(Msg,NO_ARG,"WAITFOR");
- S2(Msg);
- return FAILURE;
- }
- waitfor_msec = 1000 * ((interval > 0) ? interval : 30);
- eofflag = FALSE;
- SPITOUT: limit = mtime() + waitfor_msec;
- while (limit >= mtime() && !eofflag){
- if ((c = readbyte(1)) == -1)
- continue;
- if (cismode && c==ENQ){
- s_cis();
- goto SPITOUT;
- }
- ++i;
- i = i % LG_BUFF;
- mringbuf[i] = c;
- mrbstart = mrbstart % LG_BUFF;
- if (mrbcount<LG_BUFF)
- ++mrbcount;
- else
- ++mrbstart,
- mrbstart = mrbstart % LG_BUFF;
- if (ttyflag)
- fputc(c,tfp);
- if (capture && c != 'r')
- fputc(c,cfp);
- if (tolower(c) != *ptr){
- ptr = word;
- continue;
- }
- if (*++ptr == ' ')
- return SUCCESS;
- }
- return FAILURE;
- }
- static
- k_transmit(junk,fword)
- long junk;
- char *fword;
- {
- sprintf(line,""%s"",fword);
- lptr = line;
- getword();
- if (!fword || word[0] == ' '){
- sprintf(Msg,NO_ARG,"TRANSMIT");
- S2(Msg);
- return FAILURE;
- }
- send_string(word, strlen(word));
- return SUCCESS;
- }
- static
- k_pause(pause_time,junk)
- long pause_time;
- char *junk;
- {
- pause_time = pause_time ? pause_time : 5;
- sleep((unsigned)pause_time);
- return SUCCESS;
- }
- static
- k_host(junk,fword)
- long junk;
- char *fword;
- {
- sprintf(line,""%s"",fword);
- lptr = line;
- getword();
- if (!fword || word[0] == ' '){
- sprintf(Msg,NO_ARG,"HOST");
- S2(Msg);
- return FAILURE;
- }
- sprintf(hostname,"%s",word);
- xttn();
- return SUCCESS;
- }
- static
- k_capture(junk,fword)
- long junk;
- char *fword;
- {
- int val = capture;
- sprintf(word,"capture");
- sprintf(line,"%s",fword);
- lptr = line;
- set_onoff(&capture);
- if (val == capture)
- return SUCCESS;
- if (!capture)
- fclose(cfp);
- else {
- if (!(cfp = fopen(captfile, "a"))){
- sprintf(Msg,"Can't open capture file %s",captfile);
- S2(Msg);
- eofflag++;
- return FAILURE;
- }
- }
- return SUCCESS;
- }
- static
- k_debug(junk,fword)
- long junk;
- char *fword;
- {
- sprintf(word,"debug");
- sprintf(line,"%s",fword);
- lptr = line;
- set_onoff(&debugflag);
- return SUCCESS;
- }
- static
- k_tty(junk,fword)
- long junk;
- char *fword;
- {
- sprintf(word,"tty");
- sprintf(line,"%s",fword);
- lptr = line;
- set_onoff(&ttyflag);
- return SUCCESS;
- }
- static
- k_type(junk,fword)
- long junk;
- char *fword;
- {
- sprintf(line,"%s",fword);
- lptr = line;
- getword();
- if (!fword || word[0] == ' '){
- sprintf(Msg,NO_ARG,"TYPE");
- S2(Msg);
- return FAILURE;
- }
- divert(TRUE);
- return SUCCESS;
- }
- /* unbind_key() removes the binding attached to the keycode specified by (c).*/
- static void
- unbind_key(c)
- int c;
- {
- binding_t *ptr = first_binding, *prev = NIL(binding_t);
- if (!ptr)
- return;
- while (ptr) {
- if (ptr->bs_c == c) {
- if (ptr->bs_string)
- free(ptr->bs_string);
- if (prev)
- prev->bs_next = ptr->bs_next;
- else
- first_binding->bs_next = ptr->bs_next;
- free(ptr);
- return;
- }
- prev = ptr;
- ptr = ptr->bs_next;
- }
- }
- /* bind_key() binds the key whose ASCII code is specified by (c) to the
- function whose code is specified by (function). Emit strings
- (for EMITSTR) and script names (for DOSCRPT) are specified by (string).
- */
- static void
- bind_key(c,function,string)
- int c;
- int function;
- char *string;
- {
- binding_t *ptr = (binding_t *) malloc(sizeof(binding_t)), *curr, *prev;
- if (!ptr) {
- S2("BIND_KEY allocation error");
- S_abort();
- }
- unbind_key(c);
- ptr->bs_c = c;
- ptr->bs_function = function;
- ptr->bs_string = strdup(string);
- /* The following is an insertion sort to ensure that the bindings are
- stored in ascending sequence by key code. This makes
- show_bindings()'s display easier to read. -lg
- */
- for (prev = NIL(binding_t), curr = first_binding;
- curr != NIL(binding_t);
- prev = curr, curr = curr->bs_next) {
- if (ptr->bs_c < curr->bs_c) {
- if (!prev) {
- ptr->bs_next = first_binding;
- first_binding = ptr;
- break;
- } else {
- ptr->bs_next = curr;
- prev->bs_next = ptr;
- break;
- }
- }
- }
- if (curr == NIL(binding_t)) {
- if (!prev)
- first_binding = ptr;
- else
- prev->bs_next = ptr;
- ptr->bs_next = NIL(binding_t);
- }
- }
- /* bind_function() Binds the key whose code is represented by the value in
- (n) to execute the XT builtin function whose name is pointed to be (cptr).
- Any previous binding of the specified keycode is forgotten.
- This routine is designed to be an XT script builtin.
- */
- static
- bind_function(n,cptr)
- long n;
- char *cptr;
- {
- int c;
- bindfunc_t code;
- if (n < 1L || n > 127L) {
- sprintf(Msg,"Invalid key code %d in BIND_FUNCTION command",n);
- S2(Msg);
- return FAILURE;
- }
- c = tolower((int) n);
- sprintf(line, ""%s"", cptr);
- lptr = line;
- getword();
- if (cptr && cptr[0] != ' ') {
- lc_word(word);
- code = find_function(word);
- if (code == BADFUNC) {
- sprintf(Msg,"Invalid function name '%s' in BIND_FUNCTION command",
- word);
- S2(Msg);
- return FAILURE;
- }
- bind_key(c, code, word);
- } else {
- sprintf(Msg,NO_ARG,"BIND_FUNCTION");
- S2(Msg);
- return FAILURE;
- }
- return SUCCESS;
- }
- /* bind_string() binds the key whose code is represented by the
- decimal value in (n) to emit the string pointed to by (cptr).
- Any previous binding of the specified keycode is forgotten.
- This routine is designed to be an XT script builtin.
- */
- static
- bind_string(n,cptr)
- long n;
- char *cptr;
- {
- int c;
- if (n < 1L || n > 127L) {
- sprintf(Msg,"Invalid key code %d in BIND_STRING command",n);
- S2(Msg);
- return FAILURE;
- }
- c = tolower((int) n);
- sprintf(line, ""%s"", cptr);
- lptr = line;
- getword();
- if (cptr && cptr[0] != ' ')
- bind_key(c, EMITSTR, word);
- else {
- sprintf(Msg,NO_ARG,"BIND_STRING");
- S2(Msg);
- return FAILURE;
- }
- return SUCCESS;
- }
- /* bind_script() binds the key whose code is represented by the value in
- (n) to execute the XT script whose name is pointed to by (cptr).
- Any previous binding of the specified keycode is forgotten.
- This routine is designed to be an XT script builtin.
- */
- static
- bind_script(n,cptr)
- long n;
- char *cptr;
- {
- int c;
- if (n < 1L || n > 127L) {
- sprintf(Msg,"Invalid key code %d in BIND_STRING command",n);
- S2(Msg);
- return FAILURE;
- }
- c = tolower((int) n);
- sprintf(line, ""%s"", cptr);
- lptr = line;
- getword();
- if (cptr && cptr[0] != ' ')
- bind_key(c, DOSCRPT, word);
- else {
- sprintf(Msg,NO_ARG,"BIND_SCRIPT");
- S2(Msg);
- return FAILURE;
- }
- return SUCCESS;
- }
- /* Variables Section */
- /* Most of the variable-handling logic is credit: Steve Manes 1987 */
- #define VNAMELEN 16 /* maximum name length for variables */
- #define VMAXSIZE 256 /* maximum length for CHAR variable */
- #define VMAXVARS 30 /* maximum number of user variables */
- #define VCHAR 'C' /* CHARACTER variable type */
- #define VNUM 'N' /* NUMERIC variable type (always 'long') */
- /* Variable structure */
- typedef struct var {
- char name[VNAMELEN+1]; /* variable name */
- struct var *next; /* ptr to next structure in var_list */
- char type; /* variable type */
- union { /* pointer to CHAR or NUM/DATE */
- char str[VMAXSIZE+1];
- long num;
- } u;
- } VAR;
- static VAR *Varlist = NIL(VAR); /* top of variable list */
- static VAR *Lastvar = NIL(VAR); /* bottom of variable list */
- /* Valid variable name characters */
- unchar
- OKname[]= {
- /* control characters */
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- /* ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ */
- 1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,
- /* A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ ] ^ _ ` */
- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,
- /* a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ */
- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0
- };
- /* Return pointer to VAR structure for User or System variable
- 'name', otherwise return NIL(VAR).
- Variable contents in vp->u.[str|num]
- */
- static VAR *
- findvar(name)
- char *name;
- {
- static VAR *vp; /* pointer to output structure */
- if (!name || !*name || !Varlist)
- return NIL(VAR);
- vp = Varlist;
- while (vp){
- if (!strncmp(name, vp->name, VNAMELEN) )
- return vp;
- vp = vp->next;
- }
- return NIL(VAR); /* not found */
- }
- /* Delete User variable 'name' from VAR list.
- If variable doesn't exist, no error is returned
- */
- static void
- unsetvar(name)
- char *name;
- {
- VAR *p;
- VAR *lastp;
- if (!name || !*name)
- return;
- for (p=Varlist; p; lastp = p, p = p->next){
- if (!strncmp(name, p->name, VNAMELEN) ){ /* name match? */
- if (Varlist == Lastvar) /* only 1 variable */
- Varlist = Lastvar = NIL(VAR); /* in list */
- else if (p == Varlist) /* first variable */
- Varlist = p->next;
- else {
- lastp->next = p->next; /* dump variable in middle
- of list */
- if (p == Lastvar) /* or last object */
- Lastvar = lastp; /* in list */
- }
- free(p); /* reclaim memory */
- break;
- }
- }
- }
- /* Set the value of User variable 'name' to 'val' with 'type'.
- If variable exists, change its contents. Otherwise, create it.
- Returns: FAILURE or SUCCESS
- */
- static
- setvar(name,type,str,val)
- char *name;
- char type;
- char *str;
- long *val;
- {
- VAR *vp;
- short i;
- if (!name || !*name)
- return FAILURE;
- if (!(vp = findvar(name))){ /* create new variable */
- for (i=0; i < VNAMELEN && name[i]; i++){
- if( !OKname[(name[i] & 0x7F)] || isdigit(name[0]) ){
- sprintf(Msg,"Illegal variable name '%s'",name);
- S_abort();
- }
- }
- if (!(vp = (VAR *)malloc(sizeof(VAR)))){
- sprintf(Msg,"%s: allocation error",name);
- S2(Msg);
- return FAILURE;
- }
- lc_word(name);
- strncpy(vp->name, name, VNAMELEN); /* set vari name */
- vp->next = NIL(VAR); /* flag 'no next' */
- if (!Varlist)
- Varlist = vp; /* first variable */
- else
- Lastvar->next = vp; /* add this to the list */
- Lastvar = vp; /* set 'last' pointer */
- }
- if (type == VCHAR)
- strncpy(vp->u.str, str, VMAXSIZE);
- else
- vp->u.num = *val;
- vp->type = type;
- return SUCCESS;
- }
- /* Unset all user variables, deallocating memory.
- No error returned
- */
- static void
- unsetall()
- {
- VAR *p;
- VAR *nextp;
- if (!Varlist)
- return;
- p = Varlist;
- while (p->next){
- nextp = p->next;
- free(p);
- p = nextp;
- }
- Varlist = Lastvar = NIL(VAR);
- }
- /* end variables section */
- /* Action Primitives */
- static struct {
- char *name;
- int (*funcptr)();
- } s_acttab[] = {
- {"beep", beep},
- {"bind_function", bind_function},
- {"bind_script", bind_script},
- {"bind_string", bind_string},
- {"capture", k_capture},
- {"debug", k_debug},
- {"host", k_host},
- {"pause", k_pause},
- {"quit", s_exit},
- {"seen", k_seen},
- {"transmit", k_transmit},
- {"tty", k_tty},
- {"type", k_type},
- {"waitfor", k_waitfor},
- {NIL(char), 0}
- };
- /* end of primitives */
- /* token types */
- typedef enum {
- NULLTOK, /* terminating ' ' in script buffer */
- ACTION, /* an action (primitive or script cmd) */
- AFFIRM, /* script 'affirm' */
- BACKQUOT, /* script command substitution */
- SBREAK, /* script 'break' */
- CALL, /* script 'call' */
- COMMENT, /* comment */
- SCONTNUE, /* script 'continue' */
- DECR, /* script 'decr' */
- DO, /* script 'do' */
- DONE, /* script 'done' */
- ECHOS, /* script 'echo' */
- EFLAG, /* '-n' switch for script 'echo' cmd */
- ELSE, /* script 'else' */
- ENDIF, /* script 'endif' */
- ENDTRAP, /* script 'endtrap' */
- EQ, /* operator "equals" */
- EXIT, /* script 'exit' */
- SFILE, /* script 'file' */
- SFALSE, /* script 'false' */
- IF, /* script 'if' */
- INCR, /* script 'incr' */
- LESSTHAN, /* operator "less than" */
- LITERAL, /* a literal string (e.g. "abcde") */
- MORETHAN, /* operator "greater than" */
- NEGATE, /* negation operator for comparisons */
- NEQ, /* operator "not equal to" */
- NUMBER, /* a numeric constant (e.g. 12345) */
- PIPE, /* script 'pipe' */
- READ, /* script 'read' */
- SHELL, /* script 'shell' */
- SET, /* script 'assign' */
- STRAP, /* script 'trap' */
- TERMINAT, /* statement terminators (';' and 'n') */
- THEN, /* script 'then' */
- STRUE, /* script 'true' */
- UNSET, /* script 'unset' */
- UNTRAP, /* script 'untrap' */
- XTSET, /* xt 'set' command */
- VARNAME, /* a variable name */
- WHILE, /* script 'while' */
- TTERROR, /* unrecognizable token */
- TIMEOUT /* script 'timeout' */
- } TOK_TYPE;
- /* token table */
- static struct {
- char *name;
- TOK_TYPE token;
- } s_toktab[] = {
- {"NULLTOK", NULLTOK},
- {"ACTION", ACTION},
- {"affirm", AFFIRM},
- {"BACKQUOT", BACKQUOT},
- {"break", SBREAK},
- {"call", CALL},
- {"COMMENT", COMMENT},
- {"continue", SCONTNUE},
- {"decr", DECR},
- {"do", DO},
- {"done", DONE},
- {"echo", ECHOS},
- {"-n", EFLAG},
- {"else", ELSE},
- {"endif", ENDIF},
- {"fi", ENDIF},
- {"ENDTRAP", ENDTRAP},
- {"eq", EQ},
- {"exit", EXIT},
- {"false", SFALSE},
- {"file", SFILE},
- {"if", IF},
- {"incr", INCR},
- {"lessthan", LESSTHAN},
- {"LITERAL", LITERAL},
- {"morethan", MORETHAN},
- {"!", NEGATE},
- {"neq", NEQ},
- {"NUMBER", NUMBER},
- {"pipe", PIPE},
- {"read", READ},
- {"assign", SET},
- {"shell", SHELL},
- {"TRAP", STRAP}, /* 'trap' keyword left for later dev't */
- {"TERMINAT", TERMINAT},
- {"then", THEN},
- {"timeout", TIMEOUT},
- {"true", STRUE},
- {"unassign", UNSET},
- {"UNTRAP", UNTRAP},
- {"set", XTSET},
- {"VARNAME", VARNAME},
- {"while", WHILE},
- {"