mirror of https://github.com/OpenIPC/firmware.git
1751 lines
44 KiB
C
1751 lines
44 KiB
C
/*
|
|
* comgt version 0.31 - 3G/GPRS datacard management utility
|
|
*
|
|
* Copyright (C) 2003 Paul Hardwick <paul@peck.org>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
* See comgt.doc for more configuration and usage information.
|
|
*
|
|
*/
|
|
|
|
/***************************************************************************
|
|
* $Id: comgt.c,v 1.4 2006/10/20 14:30:19 pharscape Exp $
|
|
****************************************************************************/
|
|
|
|
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <signal.h>
|
|
#include <termios.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <sys/time.h>
|
|
#include <time.h>
|
|
#include <sys/types.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/wait.h>
|
|
#include <sys/stat.h>
|
|
#include "comgt.h"
|
|
|
|
|
|
|
|
#define MAXLABELS 3000 /* Maximum number of labels */
|
|
#define MAXGOSUBS 128 /* Max depth */
|
|
#define STRINGL 1024 /* String lengths. Also, max script line length */
|
|
#define MAXPATH 1024 /* Max filename length (less or equal to STRINGL) */
|
|
#define MAXTOKEN 20 /* Maximum token or label length */
|
|
#define GTDEVICE "/dev/modem"
|
|
|
|
#define BOOL unsigned char
|
|
#define NVARS 286 /* a-z, a0-z9 == 26*11 */
|
|
|
|
|
|
extern char *optarg;
|
|
extern int optind, opterr;
|
|
FILE *filep;
|
|
char *script;
|
|
int scriptspace;
|
|
BOOL ifres;
|
|
int lastpc,pc; /* program "counters" */
|
|
long resultcode=0; /* result code */
|
|
int ignorecase=1; /* no case sensitivity */
|
|
BOOL comecho=0; /* echo what's comin' in */
|
|
BOOL high_speed=0;
|
|
long senddelay=0; /* 0/100th second character delay for sending */
|
|
long number; /* For getonearg() returning an long */
|
|
char **label; /* Index of labels for goto and gosub */
|
|
int *labelpc; /* Positions of said labels in script */
|
|
int labels; /* Number of labels found in script */
|
|
long intvars[NVARS]; /* [a-z][0-9] integer variables */
|
|
char string[STRINGL]; /* For getstring() returns and misc. use (misuse) */
|
|
char *stringvars[NVARS]; /* $[a-z][0-9] string variables */
|
|
char cspeed[10]; /* Ascii representation of baudrate */
|
|
int speed=B0; /* Set to B110, B150, B300,..., B38400 */
|
|
char device[MAXPATH]; /* Comm device. May be "-" */
|
|
char token[MAXTOKEN]; /* For gettoken() returns */
|
|
char scriptfile[MAXPATH]; /* Script file name */
|
|
char scriptfilepath[MAXPATH]; /* temp storage for full path */
|
|
BOOL verbose=0; /* Log actions */
|
|
struct termios cons, stbuf, svbuf; /* termios: svbuf=before, stbuf=while */
|
|
int comfd=0; /* Communication file descriptor. Defaults to stdin. */
|
|
char msg[STRINGL]; /* Massage messages here */
|
|
int preturn,returns[MAXGOSUBS];
|
|
int clocal=0;
|
|
int parity=0, bits=CS8, stopbits=0;
|
|
unsigned long hstart,hset;
|
|
char NullString[]={ "" };
|
|
BOOL lastcharnl=1; /* Indicate that last char printed from getonebyte
|
|
was a nl, so no new one is needed */
|
|
BOOL tty=1;
|
|
|
|
|
|
//"open com \"/dev/modem\"\nset com 38400n81\nset senddelay 0.05\nsend \"ATi^m\"\nget 2 \" ^m\" $s\nprint \"Response : \",$s,\"\\n\"\nget 2 \" ^m\" $s\nprint \"Response :\",$s,\"\\n\"\nget 2 \" ^m\" $s\nprint \"Response : \",$s,\"\\n\"\n\n";
|
|
/* Prototypes. */
|
|
unsigned long htime(void);
|
|
void dormir(unsigned long microsecs);
|
|
void dotestkey(void);
|
|
void ext(long xtc);
|
|
void vmsg(char *text);
|
|
void skipline(void);
|
|
void printwhere(void);
|
|
void writecom(char *text);
|
|
int getonebyte(void);
|
|
void dodump(void);
|
|
void serror(char *text, int exitcode);
|
|
void skipspaces(void);
|
|
void getopen(void);
|
|
void getclose(void);
|
|
int gettoken(void);
|
|
void skiptoken(void);
|
|
long getvalue(void);
|
|
void getcomma(void);
|
|
void gethardstring(void);
|
|
void getstring(void);
|
|
unsigned long getdvalue(void);
|
|
void dolet(void);
|
|
int dowaitquiet(void);
|
|
int dowaitfor(void);
|
|
BOOL getonoroff(void);
|
|
void setcom(void);
|
|
void doset(void);
|
|
void dogoto(void);
|
|
void dogosub(void);
|
|
unsigned char getonearg(void);
|
|
void doif(void);
|
|
int getindex(void);
|
|
int getintindex(void);
|
|
int getstringindex(void);
|
|
void doget(void);
|
|
void doprint(int channel);
|
|
void doclose(void);
|
|
void opendevice(void);
|
|
void doopen(void);
|
|
int doscript(void);
|
|
|
|
|
|
char GTdevice[4][20] = {"/dev/noz2",
|
|
"/dev/ttyUSB2",
|
|
"/dev/modem",""}; /* default device names to search for */
|
|
|
|
/* Returns hundreds of seconds */
|
|
unsigned long htime(void) {
|
|
struct timeval timenow;
|
|
gettimeofday(&timenow,NULL);
|
|
return(100L*(timenow.tv_sec-hstart)+(timenow.tv_usec)/10000L-hset);
|
|
}
|
|
|
|
/* I use select() 'cause CX/UX 6.2 doesn't have usleep().
|
|
On Linux, usleep() uses select() anyway.
|
|
*/
|
|
void dormir(unsigned long microsecs) {
|
|
struct timeval timeout;
|
|
timeout.tv_sec=microsecs/1000000L;
|
|
timeout.tv_usec=microsecs-(timeout.tv_sec*1000000L);
|
|
select(1,0,0,0,&timeout);
|
|
}
|
|
|
|
/* Tests for ENTER key */
|
|
void dotestkey(void) {
|
|
fd_set fds;
|
|
struct timeval timeout;
|
|
timeout.tv_sec=0L;
|
|
timeout.tv_usec=10000L;
|
|
FD_ZERO(&fds);
|
|
FD_SET(0,&fds); /* Prepare to select() from stdin */
|
|
resultcode=select(1,&fds,0,0,&timeout);
|
|
if(resultcode) getchar();
|
|
}
|
|
|
|
/* Exit after resetting terminal settings */
|
|
void ext(long xtc) {
|
|
ioctl(1, TCSETS, &cons);
|
|
exit(xtc);
|
|
}
|
|
|
|
/* Log message if verbose is on */
|
|
void vmsg(char *text) {
|
|
time_t t;
|
|
char *ct;
|
|
if(verbose) {
|
|
if(lastcharnl==0) {
|
|
fprintf(stderr,"\n");
|
|
lastcharnl=1;
|
|
}
|
|
t=time(0);
|
|
ct=ctime(&t);
|
|
fprintf(stderr,"comgt %c%c:%c%c:%c%c -> %s\n",
|
|
ct[11],ct[12],ct[14],ct[15],ct[17],ct[18],
|
|
text);
|
|
}
|
|
}
|
|
|
|
/* Skip to next statement */
|
|
void skipline(void) {
|
|
while(script[pc]!='\n' && script[pc]!=0) pc++;
|
|
if(script[pc]) pc++;
|
|
}
|
|
|
|
void printwhere(void) {
|
|
int a,b,c;
|
|
sprintf(msg,"@%04d ",pc);
|
|
a=pc;
|
|
skipline();
|
|
b=pc-1;
|
|
pc=a;
|
|
c=strlen(msg);
|
|
for(;a<b;a++) msg[c++]=script[a];
|
|
msg[c]=0;
|
|
vmsg(msg);
|
|
}
|
|
|
|
/* Write a null-terminated string to communication device */
|
|
void writecom(char *text) {
|
|
int res;
|
|
unsigned int a;
|
|
char ch;
|
|
for(a=0;a<strlen(text);a++) {
|
|
ch=text[a];
|
|
res=write(comfd,&ch,1);
|
|
if(senddelay) dormir(senddelay);
|
|
if(res!=1) {
|
|
serror("Could not write to COM device",1);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Gets a single byte from comm. device. Return -1 if none avail. */
|
|
int getonebyte(void) {
|
|
fd_set rfds;
|
|
int res;
|
|
char ch;
|
|
comecho = 1;
|
|
struct timeval timeout;
|
|
timeout.tv_sec=0L;
|
|
timeout.tv_usec=10000;
|
|
FD_ZERO(&rfds);
|
|
FD_SET(comfd, &rfds);
|
|
res=select(comfd+1,&rfds,NULL,NULL,&timeout);
|
|
if(res) {
|
|
res=read(comfd,&ch,1);
|
|
if(res==1) {
|
|
if(comecho) {
|
|
if(ch=='\n') lastcharnl=1;
|
|
else {
|
|
if(ch!='\r') lastcharnl=0;
|
|
}
|
|
/*fputc(ch,stderr);*/
|
|
}
|
|
return(ch);
|
|
}
|
|
}
|
|
else {
|
|
return(-1); /* Nada. */
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
void dodump(void) {
|
|
char lmsg[STRINGL];
|
|
int a,b,c;
|
|
c=verbose;
|
|
verbose=1;
|
|
sprintf(lmsg,"-- Integer variables --"); vmsg(lmsg);
|
|
for(a=0;a<26;a++) {
|
|
for(b=0;b<11;b++) {
|
|
if(intvars[b*26+a]) {
|
|
sprintf(lmsg," = %ld",intvars[b*26+a]);
|
|
lmsg[1]='a'+a;
|
|
lmsg[2]=' ';
|
|
if(b) lmsg[2]='0'+b-1;
|
|
vmsg(lmsg);
|
|
}
|
|
}
|
|
}
|
|
sprintf(lmsg,"-- String variables --"); vmsg(lmsg);
|
|
for(a=0;a<26;a++) {
|
|
for(b=0;b<11;b++) {
|
|
if(stringvars[b*26+a]!=NullString) {
|
|
sprintf(lmsg,"$ = \"%s\"",stringvars[b*26+a]);
|
|
lmsg[1]='a'+a;
|
|
lmsg[2]=' ';
|
|
if(b) lmsg[2]='0'+b-1;
|
|
vmsg(lmsg);
|
|
}
|
|
}
|
|
}
|
|
verbose=c;
|
|
}
|
|
|
|
/* Report script errors and quit */
|
|
void serror(char *text, int exitcode) {
|
|
int a,line;
|
|
char lmsg[STRINGL];
|
|
verbose=1;
|
|
//dodump();
|
|
vmsg("-- Error Report --");
|
|
a=pc;
|
|
pc=lastpc;
|
|
//printwhere();
|
|
pc=a;
|
|
while(pc!=0 && (script[pc]==' ' || script[pc]=='\t')) pc--;
|
|
strcpy(lmsg,"----> ");
|
|
for(a=6;a<STRINGL;a++) lmsg[a]=' ';
|
|
for(a=0;a<pc-lastpc;a++) {
|
|
if(script[a+lastpc]=='\t') lmsg[a+8]='\t';
|
|
}
|
|
a+=6;
|
|
lmsg[a++]='^';
|
|
lmsg[a]=0;
|
|
vmsg(lmsg);
|
|
a=0; line=1;
|
|
while(a<pc) {
|
|
if(script[a++]=='\n') {
|
|
if(a<pc) line++;
|
|
}
|
|
}
|
|
sprintf(lmsg,"Error @%d, line %d, %s. (%d)\n",pc,line,text,exitcode);
|
|
vmsg(lmsg);
|
|
ext(exitcode);
|
|
}
|
|
|
|
void skipspaces(void) {
|
|
while(script[pc]==' ' || script[pc]=='\t' ) pc++;
|
|
}
|
|
|
|
void getopen(void) {
|
|
int a;
|
|
a=pc;
|
|
skipspaces();
|
|
if(script[pc++]!='(') {
|
|
pc=a;
|
|
serror("Function requires open parenthesis",5);
|
|
}
|
|
}
|
|
|
|
void getclose(void) {
|
|
int a;
|
|
a=pc;
|
|
skipspaces();
|
|
if(script[pc++]!=')') {
|
|
pc=a;
|
|
serror("Function requires close parenthesis",5);
|
|
}
|
|
}
|
|
|
|
void skiptoken(void) {
|
|
skipspaces();
|
|
while(script[pc]!=' ' && script[pc]!='\t' && script[pc]!='\n' ) pc++;
|
|
skipspaces();
|
|
}
|
|
|
|
/* Parse script[pc] to get next statement. Resolve comments and labels... */
|
|
int gettoken(void) {
|
|
int tokenp=0;
|
|
skipspaces();
|
|
if(script[pc]=='=' || script[pc]=='<' || script[pc]=='>' || script[pc]=='!') {
|
|
token[0]=0;
|
|
while(script[pc]=='=' || script[pc]=='<' || script[pc]=='>' || script[pc]=='!') {
|
|
token[tokenp++]=script[pc++];
|
|
}
|
|
token[tokenp]=0;
|
|
return(0);
|
|
}
|
|
if(script[pc]=='#') {
|
|
strcpy(token,"rem");
|
|
pc++;
|
|
return(0);
|
|
}
|
|
if(script[pc]=='/' && script[pc+1]=='/') {
|
|
strcpy(token,"rem");
|
|
pc+=2;
|
|
return(0);
|
|
}
|
|
if(script[pc]==':') {
|
|
strcpy(token,"label");
|
|
pc++;
|
|
return(0);
|
|
}
|
|
while(script[pc]!=' ' && script[pc]!='\n' &&
|
|
script[pc]!='\t' && script[pc]!='(') {
|
|
token[tokenp]=script[pc++];
|
|
if(token[tokenp]>='A' && token[tokenp]<='Z') {
|
|
token[tokenp]=token[tokenp]-'A'+'a';
|
|
}
|
|
if(tokenp++==MAXTOKEN-1) serror("Token too long",5);
|
|
}
|
|
token[tokenp]=0;
|
|
if(strcmp(token,"then")==0) return(gettoken()); /* Ignore then for if */
|
|
return(0);
|
|
}
|
|
|
|
/* shitfaced recursive value parser. must write better one */
|
|
long getvalue(void) {
|
|
unsigned long p=0;
|
|
int goone=1;
|
|
unsigned int a;
|
|
int base,amode;
|
|
skipspaces();
|
|
if(script[pc]=='(') {
|
|
pc++;
|
|
p=getvalue();
|
|
getclose();
|
|
}
|
|
else if(script[pc]==')') {
|
|
return(p);
|
|
}
|
|
else if(script[pc]=='"' || script[pc]=='\'' || script[pc]=='$' ) {
|
|
serror("Did not expect a string",7);
|
|
}
|
|
else if( (script[pc]>='a' && script[pc]<='z' &&
|
|
script[pc+1]>='a' && script[pc+1]<='z') ||
|
|
(script[pc]>='A' && script[pc]<='Z' &&
|
|
script[pc+1]>='A' && script[pc+1]<='Z') ) {
|
|
gettoken();
|
|
getopen();
|
|
if(strcmp(token,"len")==0) {
|
|
char toto[STRINGL];
|
|
strcpy(toto,string);
|
|
getstring();
|
|
p=strlen(string);
|
|
strcpy(string,toto);
|
|
}
|
|
else if(strcmp(token,"htime")==0) {
|
|
p=htime();
|
|
}
|
|
else if(strcmp(token,"time")==0) {
|
|
p=time(0);
|
|
}
|
|
else if(strcmp(token,"pid")==0) {
|
|
p=getpid();
|
|
}
|
|
else if(strcmp(token,"ppid")==0) {
|
|
p=getppid();
|
|
}
|
|
else if(strcmp(token,"verbose")==0) {
|
|
p=verbose;
|
|
}
|
|
else if(strcmp(token,"isatty")==0) {
|
|
p=isatty(getvalue());
|
|
}
|
|
else if(strcmp(token,"baud")==0) {
|
|
p=atol(cspeed);
|
|
}
|
|
else if(strcmp(token,"access")==0) {
|
|
char toto[STRINGL];
|
|
char afile[STRINGL];
|
|
strcpy(toto,string);
|
|
getstring();
|
|
strcpy(afile,string);
|
|
getcomma();
|
|
getstring();
|
|
if(string[0]==0) serror("Missing access mode[s]",5);
|
|
amode=0;
|
|
for(a=0;a<strlen(string);a++) {
|
|
switch(string[a]) {
|
|
case 'R' :
|
|
case 'r' : amode|=R_OK; break;
|
|
case 'W' :
|
|
case 'w' : amode|=W_OK; break;
|
|
case 'X' :
|
|
case 'x' : amode|=X_OK; break;
|
|
case 'F' :
|
|
case 'f' : amode|=F_OK; break;
|
|
default : serror("Access modes are r,w,x, and f",5);
|
|
}
|
|
}
|
|
p=access(afile,amode);
|
|
strcpy(string,toto);
|
|
}
|
|
else if(strcmp(token,"val")==0 || strcmp(token,"atol")==0) {
|
|
char toto[STRINGL];
|
|
strcpy(toto,string);
|
|
getstring();
|
|
p=atol(string);
|
|
strcpy(string,toto);
|
|
}
|
|
else serror("Unknown Integer function",5);
|
|
getclose();
|
|
}
|
|
if(script[pc]=='%') {
|
|
pc++;
|
|
skipspaces();
|
|
p=resultcode;
|
|
}
|
|
while(goone) {
|
|
if(script[pc]=='+') {
|
|
pc++;
|
|
p+=getvalue();
|
|
}
|
|
else if(script[pc]=='-') {
|
|
pc++;
|
|
p-=getvalue();
|
|
}
|
|
else if(script[pc]=='^') {
|
|
pc++;
|
|
p^=getvalue();
|
|
}
|
|
else if(script[pc]=='&') {
|
|
pc++;
|
|
p&=getvalue();
|
|
}
|
|
else if(script[pc]=='|') {
|
|
pc++;
|
|
p|=getvalue();
|
|
}
|
|
else if(script[pc]=='*') {
|
|
pc++;
|
|
p*=getvalue();
|
|
}
|
|
else if(script[pc]=='/') {
|
|
pc++;
|
|
a=getvalue();
|
|
if(a==0) serror("Division by zero",6);
|
|
p/=a;
|
|
}
|
|
else if((script[pc]>='a' && script[pc]<='z') ||
|
|
(script[pc]>='A' && script[pc]<='Z') ) {
|
|
p=intvars[getintindex()];
|
|
}
|
|
else if(script[pc]>='0' && script[pc]<='9') {
|
|
base=10;
|
|
if(script[pc]=='0') {
|
|
base=8;
|
|
pc++;
|
|
if(script[pc]=='x' || script[pc]=='X') {
|
|
base=16;
|
|
pc++;
|
|
}
|
|
if(script[pc]=='%') {
|
|
base=2;
|
|
pc++;
|
|
}
|
|
}
|
|
while((script[pc]>='0' && script[pc]<='9') ||
|
|
(script[pc]>='a' && script[pc]<='f') ||
|
|
(script[pc]>='A' && script[pc]<='F')) {
|
|
if(script[pc]>='a' && script[pc]<='f') {
|
|
p=p*base+script[pc++]-'a'+10;
|
|
}
|
|
else if(script[pc]>='A' && script[pc]<='F') {
|
|
p=p*base+script[pc++]-'A'+10;
|
|
}
|
|
else {
|
|
p=p*base+script[pc++]-'0';
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
goone=0;
|
|
}
|
|
}
|
|
return(p);
|
|
}
|
|
|
|
void getcomma(void) {
|
|
skipspaces();
|
|
if(script[pc++]!=',') serror("Comma expected",5);
|
|
}
|
|
|
|
void gethardstring(void) {
|
|
int a=0;
|
|
skipspaces();
|
|
while(script[pc]!=0 && script[pc]!=' ' && script[pc]!='\t' &&
|
|
script[pc]!='\n') {
|
|
string[a++]=script[pc++];
|
|
}
|
|
string[a]=0;
|
|
}
|
|
|
|
/* Parse a string from script[pc] */
|
|
void getstring(void) {
|
|
FILE *fp;
|
|
time_t t;
|
|
unsigned int a,b;
|
|
int c,p=0;
|
|
unsigned char ch,match;
|
|
string[0]=0;
|
|
skipspaces();
|
|
if(script[pc]!='"' && script[pc]!='\'' && script[pc]!='$' ) {
|
|
serror("Expected a string",7);
|
|
}
|
|
while(script[pc]!=' ' && script[pc]!='\t' && script[pc]!='\n' && script[pc]!=',' && script[pc]!=')' && script[pc]!='=' && script[pc]!='<' && script[pc]!='>' && script[pc]!='!' ) {
|
|
if(script[pc]=='+') pc++;
|
|
skipspaces();
|
|
if( (script[pc]=='$' && script[pc+1]>='a' && script[pc+1]<='z' &&
|
|
script[pc+2]>='a' && script[pc+2]<='z') ||
|
|
(script[pc]=='$' && script[pc+1]>='A' && script[pc+1]<='Z' &&
|
|
script[pc+2]>='A' && script[pc+2]<='Z') ) {
|
|
pc++;
|
|
gettoken();
|
|
getopen();
|
|
if(strcmp(token,"time")==0) {
|
|
t=time(0);
|
|
strcat(string,ctime(&t));
|
|
string[strlen(string)-1]=0;
|
|
}
|
|
else if(strcmp(token,"rpipe")==0) {
|
|
char toto[STRINGL];
|
|
strcpy(toto,string);
|
|
getstring();
|
|
if((fp=popen(string,"r"))==NULL) serror("Could not popen!",4);
|
|
fgets(string,STRINGL-1,fp);
|
|
string[strlen(string)-1]=0;
|
|
pclose(fp);
|
|
strcat(toto,string);
|
|
strcpy(string,toto);
|
|
}
|
|
else if(strcmp(token,"env")==0) {
|
|
char toto[STRINGL];
|
|
strcpy(toto,string);
|
|
getstring();
|
|
if(getenv(string)) strcat(toto,(char *)getenv(string));
|
|
strcpy(string,toto);
|
|
}
|
|
else if(strcmp(token,"hms")==0) {
|
|
long sec,min,hour;
|
|
sec=getvalue();
|
|
min=sec/60L;
|
|
sec-=min*60L;
|
|
hour=min/60L;
|
|
min-=hour*60L;
|
|
sprintf(string,"%s%02ld:%02ld:%02ld",string,hour,min,sec);
|
|
}
|
|
else if(strcmp(token,"dev")==0) {
|
|
strcat(string,device);
|
|
}
|
|
else if(strcmp(token,"cwd")==0) {
|
|
getcwd(string,STRINGL);
|
|
}
|
|
else if(strcmp(token,"baud")==0) {
|
|
strcat(string,cspeed);
|
|
}
|
|
else if(strcmp(token,"str")==0 || strcmp(token,"ltoa")==0) {
|
|
sprintf(string,"%s%ld",string,getvalue());
|
|
}
|
|
else if(strcmp(token,"hexu")==0) {
|
|
sprintf(string,"%s%lX",string,getvalue());
|
|
}
|
|
else if(strcmp(token,"hex")==0) {
|
|
sprintf(string,"%s%lx",string,getvalue());
|
|
}
|
|
else if(strcmp(token,"oct")==0) {
|
|
sprintf(string,"%s%lo",string,getvalue());
|
|
}
|
|
else if(strcmp(token,"dirname")==0) {
|
|
char toto[STRINGL];
|
|
strcpy(toto,string);
|
|
getstring();
|
|
b=0;
|
|
for(a=0;a<strlen(string);a++) {
|
|
if(string[a]=='/' || string[a]=='\\') b=a;
|
|
}
|
|
string[b]=0;
|
|
strcat(toto,string);
|
|
strcpy(string,toto);
|
|
}
|
|
else if(strcmp(token,"tolower")==0) {
|
|
char toto[STRINGL];
|
|
strcpy(toto,string);
|
|
getstring();
|
|
for(a=0;a<strlen(string);a++) {
|
|
if(string[a]>='A' && string[a]<='Z' ) string[a]=string[a]-'A'+'a';
|
|
}
|
|
strcat(toto,string);
|
|
strcpy(string,toto);
|
|
}
|
|
else if(strcmp(token,"toupper")==0) {
|
|
char toto[STRINGL];
|
|
strcpy(toto,string);
|
|
getstring();
|
|
for(a=0;a<strlen(string);a++) {
|
|
if(string[a]>='a' && string[a]<='z' ) string[a]=string[a]-'a'+'A';
|
|
}
|
|
strcat(toto,string);
|
|
strcpy(string,toto);
|
|
}
|
|
else if(strcmp(token,"basename")==0) {
|
|
char toto[STRINGL];
|
|
strcpy(toto,string);
|
|
getstring();
|
|
b=0;
|
|
for(a=0;a<strlen(string);a++) {
|
|
if(string[a]=='/' || string[a]=='\\') b=a+1;
|
|
}
|
|
a=strlen(toto);
|
|
while(string[b]) toto[a++]=string[b++];
|
|
toto[a]=0;
|
|
strcpy(string,toto);
|
|
}
|
|
else if(strcmp(token,"script")==0) {
|
|
strcat(string,scriptfile);
|
|
}
|
|
else if(strcmp(token,"right")==0) {
|
|
char toto[STRINGL];
|
|
strcpy(toto,string);
|
|
getstring();
|
|
getcomma();
|
|
b=getvalue();
|
|
if(b>strlen(string)) serror("String is shorter than second argument",7);
|
|
c=strlen(toto);
|
|
a=strlen(string)-b;
|
|
while(b!=0 && string[a]!=0) {
|
|
toto[c++]=string[a++];
|
|
b--;
|
|
}
|
|
toto[c]=0;
|
|
strcpy(string,toto);
|
|
}
|
|
else if(strcmp(token,"left")==0) {
|
|
char toto[STRINGL];
|
|
strcpy(toto,string);
|
|
getstring();
|
|
getcomma();
|
|
b=getvalue();
|
|
if(b>strlen(string)) serror("String is shorter than second argument",7);
|
|
c=strlen(toto);
|
|
a=0;
|
|
while(b!=0 && string[a]!=0) {
|
|
toto[c++]=string[a++];
|
|
b--;
|
|
}
|
|
toto[c]=0;
|
|
strcpy(string,toto);
|
|
}
|
|
else if(strcmp(token,"mid")==0) {
|
|
char toto[STRINGL];
|
|
strcpy(toto,string);
|
|
getstring();
|
|
getcomma();
|
|
a=getvalue();
|
|
getcomma();
|
|
b=getvalue();
|
|
if(a>strlen(string)) serror("String is shorter than second argument",7);
|
|
c=strlen(toto);
|
|
while(b!=0 && string[a]!=0) {
|
|
toto[c++]=string[a++];
|
|
b--;
|
|
}
|
|
toto[c]=0;
|
|
strcpy(string,toto);
|
|
}
|
|
else if(strcmp(token,"sex")==0) {
|
|
strcat(string,"You're a naughty boy, you!");
|
|
}
|
|
else serror("Invalid string funtion",5);
|
|
getclose();
|
|
}
|
|
else if(script[pc]=='$') {
|
|
strcat(string,stringvars[getstringindex()]);
|
|
}
|
|
else if(script[pc]=='"' || script[pc]=='\'') {
|
|
match=script[pc++];
|
|
while(script[pc]!=match) {
|
|
ch=script[pc++];
|
|
if(ch==0) serror("Umatched quote.",5);
|
|
if(ch=='\\') {
|
|
if(script[pc]<='7' && script[pc]>='0' &&
|
|
script[pc+1]<='7' && script[pc+1]>='0' ) {
|
|
ch=0;
|
|
while(script[pc]>='0' && script[pc]<='7') {
|
|
ch=8*ch+script[pc++]-'0';
|
|
}
|
|
}
|
|
else {
|
|
switch(script[pc]) {
|
|
case 'T' :
|
|
case 't' : ch=9; break;
|
|
case 'R' :
|
|
case 'r' : ch=13; break;
|
|
case 'N' :
|
|
case 'n' : ch=10; break;
|
|
case 'B' :
|
|
case 'b' : ch=8; break;
|
|
case 'F' :
|
|
case 'f' : ch=12; break;
|
|
case '"' :
|
|
case '^' :
|
|
case '\'' :
|
|
case '\\' : ch=script[pc]; break;
|
|
default : serror("Malformed escaped character",5);
|
|
}
|
|
pc++;
|
|
}
|
|
}
|
|
else if(ch=='^') {
|
|
ch=script[pc];
|
|
if(ch!='^' && ch!='"' && ch!='\'' && ch!='\\' ) {
|
|
ch=ch&31; /* Control char */
|
|
}
|
|
pc++;
|
|
}
|
|
p=strlen(string);
|
|
string[p++]=ch;
|
|
string[p]=0;
|
|
}
|
|
pc++; /* Space over quote */
|
|
}
|
|
else {
|
|
p=strlen(string);
|
|
string[p++]=script[pc++];
|
|
string[p]=0;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Get a value, multiply by a hundred (for time values) */
|
|
unsigned long getdvalue(void) {
|
|
float f;
|
|
gettoken();
|
|
skipspaces();
|
|
sscanf(token,"%f",&f);
|
|
f+=0.00001; /* Rounding errors */
|
|
return(100.0*f);
|
|
}
|
|
|
|
void dolet(void) {
|
|
int index;
|
|
BOOL svar=0;
|
|
skipspaces();
|
|
if(script[pc]=='$') {
|
|
svar=1;
|
|
index=getstringindex();
|
|
}
|
|
else index=getintindex();
|
|
skipspaces();
|
|
gettoken();
|
|
if(strcmp(token,"=")!=0) serror("Bad LET assignment, '=' missing",5);
|
|
skipspaces();
|
|
if(svar) {
|
|
getstring();
|
|
strcpy(stringvars[index],string);
|
|
}
|
|
else {
|
|
intvars[index]=getvalue();
|
|
}
|
|
}
|
|
|
|
/* See documentation for doXXX() functions */
|
|
int dowaitquiet(void) {
|
|
unsigned long timeout,timequiet,quiet,now;
|
|
int c,quit;
|
|
timeout=htime()+getdvalue();
|
|
quiet=getdvalue();
|
|
timequiet=htime()+quiet;
|
|
quit=1;
|
|
while(quit==1) {
|
|
now=htime();
|
|
c=getonebyte();
|
|
if(c!= -1) timequiet=now+quiet;
|
|
if(now>=timequiet) quit=0;
|
|
if(now>=timeout) quit=255;
|
|
}
|
|
return(quit);
|
|
}
|
|
|
|
int dowaitfor(void) {
|
|
char strings[20][80];
|
|
char buffer[128];
|
|
unsigned long timeout;
|
|
unsigned int a;
|
|
int b,c;
|
|
b=0;
|
|
buffer[127]=0;
|
|
skipspaces();
|
|
timeout=htime()+getdvalue();
|
|
while(script[pc]==',' || script[pc]=='$' || script[pc]=='"' ||
|
|
script[pc]=='\'' ) {
|
|
if(script[pc]==',') pc++;
|
|
getstring();
|
|
skipspaces();
|
|
strcpy(strings[b],string);
|
|
if(ignorecase) {
|
|
for(a=0;a<strlen(strings[b]);a++) {
|
|
if(strings[b][a]>='A' && strings[b][a]<='Z') {
|
|
strings[b][a]=strings[b][a]-'A'+'a';
|
|
}
|
|
}
|
|
}
|
|
b++;
|
|
}
|
|
strings[b][0]=0;
|
|
while(htime()<timeout) {
|
|
c=getonebyte();
|
|
//printf("Byte \"%c\" ",c);
|
|
if(c!= -1) {
|
|
if(ignorecase) {
|
|
if(c>='A' && c<='Z') c=c-'A'+'a';
|
|
}
|
|
for(a=0;a<127;a++) buffer[a]=buffer[a+1]; //shuffle down
|
|
buffer[126]=c;
|
|
b=0;
|
|
while(strings[b][0]) {
|
|
c=strlen(strings[b]);
|
|
if (strcmp(strings[b],&buffer[127-c]) == 0){
|
|
return(b);
|
|
}
|
|
b++;
|
|
}
|
|
}
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
/* Parse script for "on" or "off" wich are tokens, not strings */
|
|
BOOL getonoroff(void) {
|
|
int a,b;
|
|
b=pc;
|
|
gettoken();
|
|
if(strcmp(token,"on")==0) return(1);
|
|
if(strcmp(token,"off")==0) return(0);
|
|
pc=b;
|
|
a=getvalue();
|
|
if(a!=0 && a!=1) serror("Bad value (should be on or off, 1 or 0.)",5);
|
|
return(a);
|
|
}
|
|
|
|
void setcom(void) {
|
|
stbuf.c_cflag &= ~(CBAUD | CSIZE | CSTOPB | CLOCAL | PARENB);
|
|
stbuf.c_cflag |= (speed | bits | CREAD | clocal | parity | stopbits );
|
|
if (tty && ioctl(comfd, TCSETS, &stbuf) < 0) {
|
|
serror("Can't ioctl set device",1);
|
|
}
|
|
}
|
|
|
|
void doset(void) {
|
|
struct termios console;
|
|
int a,b;
|
|
gettoken();
|
|
if(strcmp(token,"echo")==0) {
|
|
a=0;
|
|
if(getonoroff()) a=ECHO|ECHOE;
|
|
if(ioctl(0, TCGETS, &console)<0) {
|
|
serror("Can't ioctl FD zero!\n",2);
|
|
}
|
|
console.c_lflag &= ~(ECHO | ECHOE);
|
|
console.c_lflag |= a;
|
|
ioctl(0, TCSETS, &console);
|
|
}
|
|
else if(strcmp(token,"senddelay")==0) {
|
|
senddelay=10000L*getdvalue();
|
|
}
|
|
else if(strcmp(token,"clocal")==0) {
|
|
clocal=0;
|
|
if(getonoroff()) clocal=CLOCAL;
|
|
setcom();
|
|
}
|
|
else if(strcmp(token,"umask")==0) {
|
|
umask(getvalue()&0777);
|
|
}
|
|
else if(strcmp(token,"verbose")==0) {
|
|
verbose=getonoroff();
|
|
}
|
|
else if(strcmp(token,"comecho")==0) {
|
|
comecho=getonoroff();
|
|
}
|
|
else if(strcmp(token,"ignorecase")==0) {
|
|
ignorecase=getonoroff();
|
|
}
|
|
else if(strcmp(token,"com")==0) {
|
|
skipspaces();
|
|
if(script[pc]=='$' || script[pc]=='\'' || script[pc]=='"') {
|
|
getstring();
|
|
strcpy(token,string);
|
|
}
|
|
else gettoken();
|
|
a=0;
|
|
b=0;
|
|
while(token[b]>='0' && token[b]<='9') {
|
|
a=10*a+token[b++]-'0';
|
|
}
|
|
if(token[b]) {
|
|
switch(token[b]) {
|
|
case 'n': parity=0; break;
|
|
case 'e': parity=PARENB; break;
|
|
case 'o': parity=PARENB|PARODD; break;
|
|
default : serror("Parity can only ben E, N, or O",5);
|
|
}
|
|
b++;
|
|
if(token[b]) {
|
|
switch(token[b]) {
|
|
case '5' : bits=CS5; break;
|
|
case '6' : bits=CS6; break;
|
|
case '7' : bits=CS7; break;
|
|
case '8' : bits=CS8; break;
|
|
default : serror("Bits can only be 5, 6, 7, or 8",5);
|
|
}
|
|
b++;
|
|
if(token[b]) {
|
|
switch(token[b]) {
|
|
case '1': stopbits=0; break;
|
|
case '2': stopbits=CSTOPB; break;
|
|
default : serror("Stop bits can only be 1 or 2",5);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
sprintf(cspeed,"%d",a);
|
|
switch(a) {
|
|
case 0: speed = B0;break;
|
|
case 50: speed = B50;break;
|
|
case 75: speed = B75;break;
|
|
case 110: speed = B110;break;
|
|
case 150: speed = B150;break;
|
|
case 300: speed = B300;break;
|
|
case 600: speed = B600;break;
|
|
case 1200: speed = B1200;break;
|
|
case 2400: speed = B2400;break;
|
|
case 4800: speed = B4800;break;
|
|
case 9600: speed = B9600;break;
|
|
case 19200: speed = B19200;break;
|
|
case 38400: speed = B38400;break;
|
|
case 57600: speed = B57600;break;
|
|
case 115200: {
|
|
if(high_speed == 0) speed = B115200;
|
|
else speed = B57600;
|
|
break;
|
|
}
|
|
case 460800: speed = B460800; break;
|
|
default: serror("Invalid baudrate",1);
|
|
}
|
|
setcom();
|
|
}
|
|
}
|
|
|
|
void dogoto(void) {
|
|
int a,originalpos;
|
|
originalpos=pc;
|
|
gettoken();
|
|
for(a=0;a<labels;a++) {
|
|
if(strcmp(token,label[a])==0) break;
|
|
}
|
|
if(a>=labels) {
|
|
pc=originalpos;
|
|
sprintf(msg,"Label \"%s\" not found",token);
|
|
serror(msg,5);
|
|
}
|
|
else {
|
|
pc=labelpc[a];
|
|
}
|
|
}
|
|
|
|
void dogosub(void) {
|
|
int a;
|
|
if(preturn==MAXGOSUBS) serror("Reached maximum GOSUB depth",3);
|
|
a=pc;
|
|
gettoken();
|
|
returns[preturn++]=pc;
|
|
pc=a;
|
|
dogoto();
|
|
}
|
|
|
|
/* Gets arguments and returns 0 for a string, 1 for an int. Used with if */
|
|
BOOL getonearg(void) {
|
|
if(script[pc]=='"' || script[pc]=='\'' || script[pc]=='$' ) {
|
|
getstring();
|
|
return(0);
|
|
}
|
|
else {
|
|
number=getvalue();
|
|
return(1);
|
|
}
|
|
}
|
|
|
|
void doif(void) {
|
|
char stringarg[STRINGL];
|
|
char tokencopy[MAXTOKEN];
|
|
int intarg;
|
|
skipspaces();
|
|
ifres=0;
|
|
if(getonearg()) {
|
|
intarg=number;
|
|
gettoken();
|
|
skipspaces();
|
|
if(getonearg()!=1) serror("Comparison mis-match",7);
|
|
if(strcmp(token,"<")==0) {
|
|
if(intarg<number) ifres=1;
|
|
}
|
|
if(strcmp(token,"<=")==0) {
|
|
if(intarg<=number) ifres=1;
|
|
}
|
|
else if(strcmp(token,"=")==0) {
|
|
if(intarg==number) ifres=1;
|
|
}
|
|
else if(strcmp(token,">")==0) {
|
|
if(intarg>number) ifres=1;
|
|
}
|
|
else if(strcmp(token,">=")==0) {
|
|
if(intarg>=number) ifres=1;
|
|
}
|
|
else if(strcmp(token,"<>")==0) {
|
|
if(intarg!=number) ifres=1;
|
|
}
|
|
else if(strcmp(token,"!=")==0 || strcmp(token,"<>")==0) {
|
|
if(intarg!=number) ifres=1;
|
|
}
|
|
}
|
|
else {
|
|
strcpy(stringarg,string);
|
|
gettoken();
|
|
strcpy(tokencopy,token);
|
|
skipspaces();
|
|
if(getonearg()!=0) serror("Comparison mis-match",7);
|
|
if(strcmp(tokencopy,"<")==0) {
|
|
if(strcmp(stringarg,string)<0) ifres=1;
|
|
}
|
|
if(strcmp(tokencopy,"<=")==0) {
|
|
if(strcmp(stringarg,string)<=0) ifres=1;
|
|
}
|
|
else if(strcmp(tokencopy,"=")==0) {
|
|
if(strcmp(stringarg,string)==0) ifres=1;
|
|
}
|
|
else if(strcmp(tokencopy,">")==0) {
|
|
if(strcmp(stringarg,string)>0) ifres=1;
|
|
}
|
|
else if(strcmp(tokencopy,">=")==0) {
|
|
if(strcmp(stringarg,string)>=0) ifres=1;
|
|
}
|
|
else if(strcmp(tokencopy,"!=")==0 || strcmp(tokencopy,"<>")==0) {
|
|
if(strcmp(stringarg,string)!=0) ifres=1;
|
|
}
|
|
}
|
|
if(!ifres) skipline();
|
|
}
|
|
|
|
int getindex(void) {
|
|
int index;
|
|
index=script[pc++];
|
|
if(index>='A' && index<='Z') index=index-'A'+'a';
|
|
if(index>'z' || index<'a') serror("Malformed variable name",7);
|
|
index=index-'a';
|
|
if(script[pc]>='0' && script[pc]<='9') {
|
|
index=index+(1+script[pc++]-'0')*26;
|
|
}
|
|
return(index);
|
|
}
|
|
|
|
/* Parse script to find integer variable index */
|
|
int getintindex(void) {
|
|
skipspaces();
|
|
if(script[pc]=='$') serror("Integer variable expected",7);
|
|
return(getindex());
|
|
}
|
|
|
|
/* Parse script to find string variable index and allocate memory for storage
|
|
as needed. */
|
|
int getstringindex(void) {
|
|
int index;
|
|
skipspaces();
|
|
if(script[pc++]!='$') serror("String variable expected",7);
|
|
index=getindex();
|
|
if(stringvars[index]==NullString) {
|
|
stringvars[index]=(char *)malloc(STRINGL);
|
|
if(stringvars[index]==NULL) serror("Could not malloc",3);
|
|
stringvars[index][0]=0;
|
|
}
|
|
return(index);
|
|
}
|
|
|
|
void doget(void) {
|
|
char terminators[STRINGL];
|
|
unsigned int a;
|
|
int b,c,index;
|
|
int goahead=1;
|
|
unsigned long timeout;
|
|
timeout=htime()+getdvalue();
|
|
getstring();
|
|
strcpy(terminators,string);
|
|
index=getstringindex();
|
|
string[0]=0;
|
|
b=0;
|
|
resultcode=0;
|
|
while(goahead && htime()<timeout) {
|
|
c=getonebyte();
|
|
if(c!= -1) {
|
|
for(a=0;a<strlen(terminators);a++) {
|
|
if(c==terminators[a]) goahead=0;
|
|
}
|
|
if(goahead==0 && b==0) goahead=1; /* Ignore terminators if nothing yet */
|
|
else if(goahead) {
|
|
string[b++]=c;
|
|
string[b]=0;
|
|
}
|
|
}
|
|
}
|
|
if(goahead) resultcode= -1;
|
|
strcpy(stringvars[index],string);
|
|
}
|
|
|
|
void doprint(int channel) {
|
|
skipspaces();
|
|
msg[0]=0;
|
|
while(script[pc]!=' ' && script[pc]!='\t' && script[pc]!='\n') {
|
|
if(script[pc]==',') pc++;
|
|
else {
|
|
if(script[pc]=='"' || script[pc]=='\'' || script[pc]=='$' ) {
|
|
getstring();
|
|
strcat(msg,string);
|
|
}
|
|
else {
|
|
sprintf(string,"%ld",getvalue());
|
|
strcat(msg,string);
|
|
}
|
|
}
|
|
}
|
|
switch(channel) {
|
|
case 1: printf("%s",msg); fflush(stdout); break;
|
|
case 2: fputs(msg,stderr); break;
|
|
case 3:
|
|
if(msg[strlen(msg)-1]=='\n') msg[strlen(msg)-1]=0;
|
|
vmsg(msg);
|
|
break;
|
|
case 4:
|
|
if(filep==NULL) serror("File not opened",4);
|
|
fputs(msg,filep);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void doclose(void) {
|
|
gettoken();
|
|
if(strcmp(token,"hardcom")==0) {
|
|
if(comfd== -1) serror("Com device not open",1);
|
|
vmsg("Closing device");
|
|
if (tty && ioctl(comfd, TCSETS, &svbuf) < 0) {
|
|
sprintf(msg,"Can't ioctl set device %s.\n",device);
|
|
serror(msg,1);
|
|
}
|
|
close(comfd);
|
|
comfd= -1;
|
|
}
|
|
else if(strcmp(token,"com")==0) {
|
|
if(comfd== -1) serror("Com device not open",1);
|
|
vmsg("Closing com fd");
|
|
close(comfd);
|
|
comfd= -1;
|
|
}
|
|
else if(strcmp(token,"file")==0) {
|
|
if(filep==NULL) serror("Log file not open",4);
|
|
fclose(filep);
|
|
filep=NULL;
|
|
}
|
|
}
|
|
|
|
void opengt(void) {
|
|
int dcount = 0;
|
|
|
|
if(strcmp(device,"-")==0) { //no device on command line or env so try the list of devices
|
|
printf("Trying list of devices\n");
|
|
do{
|
|
strcpy(device,GTdevice[dcount]);
|
|
if ((comfd = open(device, O_RDWR|O_EXCL|O_NONBLOCK|O_NOCTTY)) >= 0)break;
|
|
dcount++;
|
|
}while(strlen(GTdevice[dcount]));
|
|
if (comfd < 0){
|
|
printf("Unable to locate default devices, try the -d option.\n");
|
|
ext(1);
|
|
}
|
|
}
|
|
else {
|
|
if ((comfd = open(device, O_RDWR|O_EXCL|O_NONBLOCK|O_NOCTTY)) <0) { //O_NONBLOCK|O_NOCTTY)) <0) {//
|
|
sprintf(msg,"Can't open device %s.\n",device);
|
|
printf(msg);
|
|
ext(1);
|
|
}
|
|
}
|
|
if (isatty (comfd))
|
|
tty=1;
|
|
else
|
|
tty=0;
|
|
if (tty && ioctl (comfd, TCGETS, &svbuf) < 0) {
|
|
sprintf(msg,"Can't control %s, please try again.\n",device);
|
|
serror(msg,1);
|
|
}
|
|
setenv("COMGTDEVICE",device,1);
|
|
if (tty)
|
|
ioctl(comfd, TCGETS, &stbuf);
|
|
speed=stbuf.c_cflag & CBAUD;
|
|
if (high_speed == 0) strcpy(cspeed,"115200");
|
|
else strcpy(cspeed,"57600");
|
|
bits=stbuf.c_cflag & CSIZE;
|
|
clocal=stbuf.c_cflag & CLOCAL;
|
|
stopbits=stbuf.c_cflag & CSTOPB;
|
|
parity=stbuf.c_cflag & (PARENB | PARODD);
|
|
stbuf.c_iflag &= ~(IGNCR | ICRNL | IUCLC | INPCK | IXON | IXANY | IGNPAR );
|
|
stbuf.c_oflag &= ~(OPOST | OLCUC | OCRNL | ONLCR | ONLRET);
|
|
stbuf.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHONL);
|
|
stbuf.c_lflag &= ~(ECHO | ECHOE);
|
|
stbuf.c_cc[VMIN] = 1;
|
|
stbuf.c_cc[VTIME] = 0;
|
|
stbuf.c_cc[VEOF] = 1;
|
|
setcom();
|
|
dormir(200000); /* Wait a bit (DTR raise) */
|
|
sprintf(msg,"Opened %s as FD %d",device,comfd);
|
|
vmsg(msg);
|
|
}
|
|
|
|
void opendevice(void) {
|
|
|
|
if(strcmp(device,"-")!=0) {
|
|
if ((comfd = open(device, O_RDWR|O_EXCL|O_NONBLOCK|O_NOCTTY)) <0) { //O_NONBLOCK|O_NOCTTY)) <0) {//
|
|
sprintf(msg,"Can't open device %s.\n",device);
|
|
printf(msg);
|
|
ext(1);
|
|
}
|
|
}
|
|
else comfd=0;
|
|
if (isatty (comfd))
|
|
tty=1;
|
|
else
|
|
tty=0;
|
|
if (tty && ioctl (comfd, TCGETS, &svbuf) < 0) {
|
|
sprintf(msg,"Can't ioctl get device %s.\n",device);
|
|
serror(msg,1);
|
|
}
|
|
if (tty)
|
|
ioctl(comfd, TCGETS, &stbuf);
|
|
speed=stbuf.c_cflag & CBAUD;
|
|
switch(speed) {
|
|
case B0: strcpy(cspeed,"0");break;
|
|
case B50: strcpy(cspeed,"50");break;
|
|
case B75: strcpy(cspeed,"75");break;
|
|
case B110: strcpy(cspeed,"110");break;
|
|
case B300: strcpy(cspeed,"300");break;
|
|
case B600: strcpy(cspeed,"600");break;
|
|
case B1200: strcpy(cspeed,"1200");break;
|
|
case B2400: strcpy(cspeed,"2400");break;
|
|
case B4800: strcpy(cspeed,"4800");break;
|
|
case B9600: strcpy(cspeed,"9600");break;
|
|
case B19200: strcpy(cspeed,"19200");break;
|
|
case B38400: strcpy(cspeed,"38400");break;
|
|
case B115200:
|
|
{
|
|
if (high_speed == 0) strcpy(cspeed,"115200");
|
|
else strcpy(cspeed,"57600");
|
|
break;
|
|
}
|
|
case B460800: strcpy(cspeed, "460800");break;
|
|
}
|
|
bits=stbuf.c_cflag & CSIZE;
|
|
clocal=stbuf.c_cflag & CLOCAL;
|
|
stopbits=stbuf.c_cflag & CSTOPB;
|
|
parity=stbuf.c_cflag & (PARENB | PARODD);
|
|
stbuf.c_iflag &= ~(IGNCR | ICRNL | IUCLC | INPCK | IXON | IXANY | IGNPAR );
|
|
stbuf.c_oflag &= ~(OPOST | OLCUC | OCRNL | ONLCR | ONLRET);
|
|
stbuf.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHONL);
|
|
stbuf.c_lflag &= ~(ECHO | ECHOE);
|
|
stbuf.c_cc[VMIN] = 1;
|
|
stbuf.c_cc[VTIME] = 0;
|
|
stbuf.c_cc[VEOF] = 1;
|
|
setcom();
|
|
dormir(200000); /* Wait a bit (DTR raise) */
|
|
sprintf(msg,"Opened %s as FD %d",device,comfd);
|
|
vmsg(msg);
|
|
}
|
|
|
|
void doopen(void) {
|
|
gettoken();
|
|
if(strcmp(token,"com")==0) {
|
|
skipspaces();
|
|
if(script[pc]=='$' || script[pc]=='\'' || script[pc]=='"') {
|
|
getstring();
|
|
}
|
|
else gethardstring();
|
|
strcpy(device,string);
|
|
opendevice();
|
|
}
|
|
else if (strcmp(token,"file")==0) {
|
|
if(filep!=NULL) serror("File already open",4);
|
|
getstring();
|
|
if((filep=fopen(string,"a"))==NULL) serror("Could not open file",4);
|
|
}
|
|
else serror("OPEN only takes com or file argument",5);
|
|
}
|
|
|
|
int doscript(void) {
|
|
int a,b;
|
|
int exitcode=0;
|
|
char line[STRINGL];
|
|
pc=0;
|
|
while(script[pc]) {
|
|
if(script[pc]=='\n') pc++;
|
|
lastpc=pc;
|
|
skipspaces();
|
|
if(verbose) printwhere();
|
|
if(gettoken()) serror("Could not gettoken()",5);
|
|
if(strcmp(token,"rem")==0) {
|
|
skipline();
|
|
}
|
|
else if (strcmp(token,"label")==0) {
|
|
skiptoken(); /* Get rid of keyword */
|
|
}
|
|
else if(strcmp(token,"open")==0) {
|
|
doopen();
|
|
}
|
|
else if(strcmp(token,"opengt")==0) {
|
|
opengt();
|
|
}
|
|
else if(strcmp(token,"close")==0) {
|
|
doclose();
|
|
}
|
|
else if(strcmp(token,"exec")==0) {
|
|
getstring();
|
|
strcpy(msg,"exec ");
|
|
strcat(msg,string); /* Let sh do all the command line work! */
|
|
execl("/bin/sh","sh","-c",msg,(char *)0);
|
|
serror("Could not execl /bin/sh!",8);
|
|
}
|
|
else if(strcmp(token,"exit")==0) {
|
|
ext(getvalue());
|
|
}
|
|
else if(strcmp(token,"testkey")==0) {
|
|
dotestkey();
|
|
}
|
|
else if(strcmp(token,"kill")==0) {
|
|
a=getvalue();
|
|
resultcode=kill(getvalue(),a);
|
|
}
|
|
else if(strcmp(token,"fork")==0) {
|
|
resultcode=fork();
|
|
}
|
|
else if(strcmp(token,"hset")==0) {
|
|
hset=0;
|
|
hstart=time(0);
|
|
hset=htime()-getvalue();
|
|
}
|
|
else if(strcmp(token,"cd")==0) {
|
|
getstring();
|
|
resultcode=chdir(string);
|
|
}
|
|
else if(strcmp(token,"putenv")==0) {
|
|
getstring();
|
|
strcpy(line,string);
|
|
resultcode=putenv(line); /* putenv can't read from global string[] */
|
|
}
|
|
else if(strcmp(token,"wait")==0) {
|
|
resultcode=wait(0);
|
|
}
|
|
else if(strcmp(token,"system")==0) {
|
|
getstring();
|
|
system(string);
|
|
}
|
|
else if(strcmp(token,"input")==0) {
|
|
FILE *infd = fdopen(0,"r");
|
|
fgets(stringvars[getstringindex()],1024,infd);
|
|
//fclose(infd);
|
|
}
|
|
else if(strcmp(token,"get")==0) {
|
|
doget();
|
|
}
|
|
else if(strcmp(token,"print")==0) {
|
|
doprint(1);
|
|
}
|
|
else if(strcmp(token,"eprint")==0) {
|
|
doprint(2);
|
|
}
|
|
else if(strcmp(token,"lprint")==0) {
|
|
doprint(3);
|
|
}
|
|
else if(strcmp(token,"fprint")==0) {
|
|
doprint(4);
|
|
}
|
|
else if(strcmp(token,"if")==0) {
|
|
doif();
|
|
}
|
|
else if(strcmp(token,"else")==0) {
|
|
if(ifres) skipline();
|
|
}
|
|
else if(strcmp(token,"gosub")==0) {
|
|
dogosub();
|
|
}
|
|
else if(strcmp(token,"return")==0) {
|
|
if(preturn==0) serror("RETURN without gosub",5);
|
|
pc=returns[--preturn];
|
|
}
|
|
else if(strcmp(token,"goto")==0) {
|
|
dogoto();
|
|
}
|
|
else if(strcmp(token,"waitfor")==0) {
|
|
resultcode=dowaitfor();
|
|
}
|
|
else if(strcmp(token,"waitquiet")==0) {
|
|
resultcode=dowaitquiet();
|
|
}
|
|
else if(strcmp(token,"set")==0) {
|
|
doset();
|
|
}
|
|
else if(strcmp(token,"dec")==0) {
|
|
intvars[getintindex()]--;
|
|
}
|
|
else if(strcmp(token,"inc")==0) {
|
|
intvars[getintindex()]++;
|
|
}
|
|
else if(strcmp(token,"let")==0) {
|
|
dolet();
|
|
}
|
|
else if(strcmp(token,"dump")==0) {
|
|
dodump();
|
|
}
|
|
else if(strcmp(token,"abort")==0) {
|
|
vmsg("Aborting");
|
|
abort();
|
|
}
|
|
else if(strcmp(token,"send")==0) {
|
|
getstring();
|
|
writecom(string);
|
|
}
|
|
else if(strcmp(token,"flash")==0) {
|
|
b=speed;
|
|
speed=0;
|
|
setcom();
|
|
a=getdvalue();
|
|
dormir(10000L*a);
|
|
speed=b;
|
|
setcom();
|
|
}
|
|
else if(strcmp(token,"sleep")==0) {
|
|
a=getdvalue();
|
|
if(a<10000) dormir(10000L*a);
|
|
else sleep(a/100); /* I guess it's the same. Oh well, past 100 secs,
|
|
use sleep instead. */
|
|
}
|
|
else {
|
|
/* Humour is the spice of life. */
|
|
switch(time(0)&7) {
|
|
case 0 : serror("That's human mumbo-jumbo to me",5); break;
|
|
case 1 : serror("Lovely but incomprehensible",5); break;
|
|
case 2 : serror("What's that, governor?",5); break;
|
|
case 3 : serror("Very funny. I don't get it",5); break;
|
|
case 4 : serror("Huh?",5); break;
|
|
case 5 : serror("comgt doesn't speak spanish",5); break;
|
|
case 6 : serror("Mais, qu'est-ce que vous dites?",5); break;
|
|
default: serror("%E-6837-% : Corrupted human data detected",5); break;
|
|
}
|
|
}
|
|
skipspaces();
|
|
while(script[pc]=='\n') pc++;
|
|
}
|
|
return(exitcode);
|
|
}
|
|
|
|
int main(int argc,char **argv) {
|
|
unsigned int a;
|
|
int aa,b,i,skip_default;
|
|
unsigned char ch;
|
|
unsigned char terminator='\n';
|
|
char *devenv,line[STRINGL];
|
|
|
|
//Load up the COMGT device env variable if it exists
|
|
devenv = getenv("COMGTDEVICE");
|
|
if (devenv != NULL && strlen(devenv)){
|
|
strcpy(device,devenv);
|
|
}
|
|
else strcpy(device,"-");
|
|
|
|
FILE *fp;
|
|
hstart=time(0);
|
|
hset=htime();
|
|
preturn=0;
|
|
skip_default=0;
|
|
filep=NULL;
|
|
scriptspace=4096;
|
|
ioctl(1, TCGETS, &cons);
|
|
if((script=( char *)malloc(scriptspace))==NULL) {
|
|
serror("Could not malloc()",3);
|
|
}
|
|
for(a=0;a<NVARS;a++) {
|
|
intvars[a]=0;
|
|
stringvars[a]=NullString;
|
|
}
|
|
strcpy(cspeed,"0");
|
|
scriptfile[0]=0;
|
|
b=0; a=0;
|
|
for(a=0;a<strlen(argv[0]);a++) {
|
|
if(argv[0][a]=='/') b=a+1;
|
|
}
|
|
while((aa=getopt(argc,argv,"xheVvd:t:sb:"))!= -1) {
|
|
switch(aa) {
|
|
case 0:
|
|
ext(0);
|
|
break;
|
|
case 't':
|
|
terminator=optarg[0];
|
|
sprintf(msg,"Alternate line terminator set to \"%c\"",terminator);
|
|
vmsg(msg);
|
|
break;
|
|
case 'd':
|
|
strcpy(device,optarg);
|
|
//opendevice();
|
|
break;
|
|
case 'e':
|
|
comecho=1;
|
|
vmsg("Communication echo turned on");
|
|
break;
|
|
case 'v':
|
|
verbose=1;
|
|
vmsg("Verbose output enabled");
|
|
break;
|
|
case 's':
|
|
skip_default=1;
|
|
break;
|
|
case 'V':
|
|
printf("comgt version %s Copyright Paul Hardwick (c) %s\n",COMGT_VERSION,YEARS);
|
|
ext(1);
|
|
break;
|
|
case 'h':
|
|
printf("comgt version %s Copyright Paul Hardwick (c) %s\n",COMGT_VERSION,YEARS);
|
|
printf("\nType 'comgt help' for more information\n");
|
|
ext(1);
|
|
break;
|
|
case 'x':
|
|
printf("High speed overide (115200 is now 57600).\n");
|
|
high_speed =1;
|
|
break;
|
|
default:
|
|
ext(1);
|
|
}
|
|
}
|
|
if(optind<argc) {
|
|
strcpy(scriptfile,argv[optind++]);
|
|
sprintf(msg,"Script file: %s",scriptfile);
|
|
vmsg(msg);
|
|
}
|
|
|
|
char * code;
|
|
code = get_code(scriptfile);
|
|
if (code != NULL){
|
|
scriptspace=strlen(code)+2;
|
|
if((script=( char *)realloc(script,scriptspace))==0) {
|
|
serror("Could not allocate memory for script.",3);
|
|
}
|
|
strcpy(script,code);
|
|
for(aa=0;aa<scriptspace;aa++) {
|
|
if(script[aa]==terminator) script[aa]='\n';
|
|
}
|
|
//scriptfile[0] = '\0';
|
|
}
|
|
else if (scriptfile[0]) {
|
|
code = get_code("default");
|
|
if (code != NULL && !skip_default){
|
|
scriptspace=strlen(code)+2;
|
|
if((script=( char *)realloc(script,scriptspace))==0) {
|
|
serror("Could not malloc()",3);
|
|
}
|
|
strcpy(script,code);
|
|
for(aa=0;aa<scriptspace;aa++) {
|
|
if(script[aa]==terminator) script[aa]='\n';
|
|
}
|
|
//scriptfile[0] = '\0';
|
|
}
|
|
if((fp=fopen(scriptfile,"r"))==NULL) {
|
|
strcpy(scriptfilepath,"/etc/comgt/");
|
|
strcat(scriptfilepath,scriptfile);
|
|
if((fp=fopen(scriptfilepath,"r"))==NULL) {
|
|
sprintf(msg,"Could not open scriptfile \"%s\".\n",scriptfile);
|
|
serror(msg,1);
|
|
}
|
|
}
|
|
i=strlen(script);
|
|
if(i) {
|
|
script[i++]='\n'; script[i]=0;
|
|
}
|
|
while((fgets(line,STRINGL-1,fp))!=NULL) {
|
|
b=strlen(line);
|
|
if((scriptspace-i)<STRINGL) {
|
|
scriptspace+=STRINGL+STRINGL;
|
|
if((script=(char *)realloc(script,scriptspace))==NULL) {
|
|
serror("Could not realloc()",3);
|
|
}
|
|
}
|
|
for(aa=0;aa<b;aa++) {
|
|
script[i]=line[aa];
|
|
if(script[i]==terminator) script[i]='\n';
|
|
i++;
|
|
}
|
|
}
|
|
script[i]=0;
|
|
fclose(fp);
|
|
}
|
|
|
|
if(script[0]) {
|
|
i=strlen(script)-1;
|
|
while((script[i]=='\n' || script[i]==' ' || script[i]=='\t') && i!=0) i--;
|
|
script[++i]='\n';
|
|
script[++i]=0;
|
|
}
|
|
i=strlen(script); /* Script is one huge string */
|
|
/* Indexing labels */
|
|
label=(char **)malloc(sizeof(char *)*MAXLABELS);
|
|
labelpc=(int *)malloc(sizeof(int *)*MAXLABELS);
|
|
if(label==NULL || labelpc==NULL) {
|
|
serror("Can't malloc",3);
|
|
}
|
|
labels=0;
|
|
pc=0;
|
|
while(script[pc]) {
|
|
lastpc=pc;
|
|
gettoken();
|
|
if(strcmp(token,"label")==0) {
|
|
gettoken();
|
|
for(aa=0;aa<labels;aa++) {
|
|
if(strcmp(token,label[aa])==0) {
|
|
pc=lastpc;
|
|
serror("Duplicate label",5);
|
|
}
|
|
}
|
|
if(labels==MAXLABELS) serror("Maximum number of labels reached",3);
|
|
labelpc[labels]=lastpc;
|
|
label[labels]=(char *)malloc(strlen(token)+1);
|
|
if(label[labels]==NULL) serror("Can't malloc one label",3);
|
|
strcpy(label[labels],token);
|
|
labels++;
|
|
}
|
|
skipline();
|
|
}
|
|
//printf(script);
|
|
if(verbose) {
|
|
sprintf(msg,"argc:%d",argc);
|
|
vmsg(msg);
|
|
for(aa=0;aa<argc;aa++) {
|
|
sprintf(msg,"argv[%d]=%s",aa,argv[aa]);
|
|
vmsg(msg);
|
|
}
|
|
vmsg(" ---Script---");
|
|
aa=0; b=0; ch='\n';
|
|
while(aa<i) {
|
|
if(ch=='\n' && script[aa]!=0) {
|
|
fprintf(stderr,"%4d@%04d ",++b,aa);
|
|
}
|
|
ch=script[aa++];
|
|
fputc(ch,stderr);
|
|
}
|
|
vmsg(" ---End of script---");
|
|
}
|
|
|
|
if(script[0]==0) {
|
|
fprintf(stderr,"No script!\n");
|
|
ext(1);
|
|
}
|
|
|
|
a=doscript();
|
|
dormir(200000);
|
|
if(comfd!= -1) close(comfd);
|
|
sprintf(msg,"Exit with code %d.\n",a);
|
|
vmsg(msg);
|
|
ext(a);
|
|
}
|