static char rcsid[] ATTR_UNUSED = "$Id$";
#endif
-/*
- * $Log$
- * Revision 1.1.1.1 1999/05/26 13:06:26 short
- * First alpha release.
- *
- */
-
#include "setup.h"
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
+#include <time.h>
#ifdef HAVE_GETOPT_LONG
#include <getopt.h>
#include "getopt.h"
#endif
-#if 0
-char *strdup(const char *s);
-int kill(pid_t pid,int sig);
-int snprintf(char *str,size_t n,const char *format,...);
-int vsnprintf(char *str,size_t n,const char *format,va_list ap);
-void usleep(unsigned long usec);
-#endif
-
#define NELEM(x) (sizeof((x))/sizeof(*(x)))
#ifndef DEBUG
#define d3(n1,n2,n3) dB((dO,n1,n2,n3 ))
#define d4(n1,n2,n3,n4) dB((dO,n1,n2,n3,n4))
-static const char version[]="This is MobilDock SMS sender (" PACKAGE " " VERSION ")\n";
+static const char version[]="This is Nokia 9110 logo SMS sender (" PACKAGE " " VERSION ")\n";
static int verbose
#ifdef DEBUG
static char *pname;
static int dis_cleanup=0,devfd=-1;
-static char *phone,*body,*device,*lockfile,*smsc,*chartime,*cmdtime;
-static int readbody;
-static long chartimen=DEF_CHARTIME,cmdtimen=DEF_CMDTIME;
-static size_t bodylen;
+static char *phone,*logoname,*device,*logname,*lockfile,*smsc,*maxretry,*readtime,*chartime,*cmdtime,*baud,*gsmnet;
+static long maxretryn=DEF_MAXRETRY,readtimen=DEF_READTIME,chartimen=DEF_CHARTIME,cmdtimen=DEF_CMDTIME,baudn=DEF_BAUD;
static char *devicename; /* path stripped */
static char lockreal[512],locked;
-static struct termios restios;
+static struct termios restios,tios;
static char restios_yes;
+static FILE *logf;
+
+static void vlogmsg(
+#ifndef PRINTF_WORKS_PM
+ char outerr,
+#endif
+ const char *fmt,va_list ap)
+{
+time_t stamp;
+char *ctm,*s;
+pid_t mypid=-1;
+char host[LINE_MAX];
+
+ if (!logf) return;
+ if (mypid==-1) {
+ mypid=getpid();
+ if (gethostname(host,sizeof(host))) strcpy(host,"<ERROR>");
+ }
+ time(&stamp);
+ ctm=ctime(&stamp);
+ if ((s=strchr(ctm,'\n'))) *s='\0';
+ fprintf(logf,"%s %s %s[%d]: ",ctm,host,pname,mypid);
+ vfprintf(logf,fmt,ap);
+#ifndef PRINTF_WORKS_PM
+ if (outerr) fputs(strerror(errno),logf);
+#endif
+ fputc('\n',logf);
+ fflush(logf);
+}
+
+static void logmsg(const char *fmt,...)
+{
+va_list ap;
+ va_start(ap,fmt);
+ vlogmsg(
+#ifndef PRINTF_WORKS_PM
+ 0,
+#endif
+ fmt,ap);
+ va_end(ap);
+}
static void error(const char *fmt,...)
{
nfmt
#endif
,ap);
+ if (fatal=='!') vlogmsg(
+#ifdef PRINTF_WORKS_PM
+ fmt
+#else
+ pm,nfmt
+#endif
+ ,ap);
va_end(ap);
#ifndef PRINTF_WORKS_PM
%s\
\n\
Usage: " PACKAGE " [-c|--config <cfgfile>] [-d|--device <device>]\n\
- [-l|--lockfile <lock>] [-s|--smsc <smsc #>]\n\
- [-t|--chartime <msec>] [-T|--cmdtime <msec>]\n\
- [-f|--file] [-v|--verbose] [-h|--help] [-V|--version]\n\
- <dest. phone> <msg text|msg filename>\n\
+ [-L|--log <file>] [-b|--baud <rate>]\n\
+ [-l|--lockfile <lock>] [-s|--smsc <smsc #>] [-m|--maxretry <#>]\n\
+ [-r|--readtime <sec>] [-t|--chartime <msec>] [-T|--cmdtime <msec>]\n\
+ [-v|--verbose] [-h|--help] [-V|--version]\n\
+ <dest. phone> <logo filename> [<GSMnet id>]\n\
\n\
-c, --config\tRead this additional config file\n\
\t\t(def. \"" CONFIG_MAIN "\" and \"$HOME" CONFIG_HOME "\")\n\
- -d, --device\tMobilDock on this serial device (def. \"" DEF_DEVICE "\")\n\
+ -d, --device\tNokia on this serial device (def. \"" DEF_DEVICE "\")\n\
+ -L, --log\tLog all important messages to this file (def. \"" DEF_LOGNAME "\")\n\
+ -b, --baud\tSet baudrate, 2400-57600 supported (def. %d)\n\
-l, --lockfile\tLock serial port by this file, \"%%s\" is basename of device\n\
\t\t(def. \"%s\")\n\
- -s, --smsc\tUse this SMS Center number (def. query from Siemens A1)\n\
- -t, --chartime\tMilliseconds between each char on baud 19200 (def. %dms)\n\
+ -s, --smsc\tUse this SMS Center number (def. query from Nokia 9110)\n\
+ -m, --maxretry\tMaximum retries of any command before giving up (def. %d)\n\
+ -r, --readtime\tSeconds for maximum wait time for response (def. %ds)\n\
+ -t, --chartime\tMilliseconds between each char (def. %dms)\n\
-T, --cmdtime\tMilliseconds before each whole AT command (def. %dms)\n\
- -f, --file\tRead contents of message from file instead\n\
-v, --verbose\tIncrease verbosity level, more \"-v\"s give more messages\n\
-h, --help\tPrint a summary of the options\n\
-V, --version\tPrint the version number\n\
-\n",version,DEF_LOCKFILE,DEF_CHARTIME,DEF_CMDTIME);
+ <GSMnet id>\t* Oper. logo: Enter custom network code MccMnc, e.g. 23002\n\
+\t\t* Oper. logo: Specify \"" WORD_NET "\" to read network code from NOL file\n\
+\t\t* Group gfx : Specify \"" WORD_GROUP "\" to send logo as group graphics\n\
+\n",version,DEF_BAUD,DEF_LOCKFILE,DEF_MAXRETRY,DEF_READTIME,DEF_CHARTIME,DEF_CMDTIME);
exit(EXIT_FAILURE);
}
static const struct option longopts[]={
{"config" ,1,0,'c'},
{"device" ,1,0,'d'},
+{"log" ,1,0,'L'},
+{"baud" ,1,0,'b'},
{"lockfile",1,0,'l'},
{"smsc" ,1,0,'s'},
+{"maxretry",1,0,'m'},
+{"readtime",1,0,'r'},
{"chartime",1,0,'t'},
{"cmdtime" ,1,0,'T'},
-{"file" ,0,0,'f'},
{"verbose" ,0,0,'v'},
{"help" ,0,0,'h'},
{"version" ,0,0,'V'}};
unsigned stamp;
} optset[]={
{ 'd',&device },
+ { 'L',&logname },
+ { 'b',&baud },
{ 'l',&lockfile },
{ 's',&smsc },
+ { 'm',&maxretry },
+ { 'r',&readtime },
{ 't',&chartime },
{ 'T',&cmdtime },
};
seq++;
optarg=NULL; optind=0; /* FIXME: Possible portability problem. */
- while ((optc=getopt_long(argp,args,"c:d:l:s:t:T:fvhV",longopts,NULL))!=EOF) switch (optc) {
+ while ((optc=getopt_long(argp,args,"c:d:L:l:s:m:r:t:T:fvhV",longopts,NULL))!=EOF) switch (optc) {
case 'c':
if (cfgstacki>=NELEM(cfgstack)) {
error("Looping (%d) during attempt to read config file \"%s\", break-out",NELEM(cfgstack),optind);
}
chk(cfgstack[cfgstacki++]=strdup(optarg));
break;
- case 'd': case 'l': case 's': case 't': case 'T':
+ case 'd': case 'L': case 'b': case 'l': case 's': case 'm': case 'r': case 't': case 'T':
for (i=0;i<NELEM(optset);i++)
if (optset[i].c==optc) {
if (optset[i].stamp && optset[i].stamp!=seq) {
}
assert(i<NELEM(optset));
break;
- case 'f':
- readbody++;
- break;
case 'v':
verbose++;
break;
usage();
break;
}
- if (!phone && optind<argp)
- chk(phone=strdup(args[optind++]));
- if (!body && optind<argp) {
-char *d;
-int i;
+ if (!phone && optind<argp) {
+char *s,*s1;
- for (i=optind,bodylen=argp-optind;i<argp;i++)
- bodylen+=strlen(args[i]);
- chk(body=malloc(bodylen));
- for (d=body,i=optind;i<argp;i++) {
-size_t l=strlen(args[i]);
- memcpy(d,args[i],l);
- d+=l;
- *d++=' ';
- assert(d<=body+bodylen);
+ chk(phone=strdup(args[optind++]));
+ s=(s1=phone)+(*phone=='+');
+ while (*s && s-s1<MAXNUMLEN)
+ if (!isdigit(*s))
+ error("!Invalid digit '%c' in destination phone number - at offset %d of option %d from \"%s\": %s",
+ *s,s-phone,optind,from,args[optind]);
+ if (*s)
+ error("!Destination phone number too long, max. %d digits allowed in option %d from \"%s\": %s",
+ s-s1,optind,from,args[optind]);
+ }
+ if (!logoname && optind<argp)
+ chk(logoname=strdup(args[optind++]));
+ if (!gsmnet && optind<argp) {
+char *s,*d,e=0;
+
+ chk(gsmnet=strdup(args[optind++]));
+ if (strcasecmp(gsmnet,WORD_NET) && strcasecmp(gsmnet,WORD_GROUP)) {
+ for (d=s=gsmnet;*s;s++) {
+ if (isdigit(*s)) { *d++=*s; continue; }
+ if (isspace(*s)) continue;
+ error("\nInvalid characted '%c' in GSMnet at offs %d: %s",
+ *s,s-gsmnet,args[optind]);
+ e=1;
+ break;
+ }
+ if ((d-gsmnet)!=5) {
+ error("\nGSMnet is required to have exactly 5 digits or to be\n\
+either \"" WORD_NET "\" or \"" WORD_GROUP "\", but found length %d: %s",
+ d-gsmnet,args[optind]);
+ e=1;
+ }
+ if (!e) *d='\0';
+ else {
+ error("\nGSMnet option %d from \"%s\" rejected due to previous errors: %s",
+ optind,from,args[optind]);
+ free(gsmnet);
+ gsmnet=NULL;
+ }
}
- assert(d==body+bodylen);
- d[-1]='\0';
- bodylen--;
}
+ while (optind<argp)
+ error("\nExcessive option %d from \"%s\" ignored: %s",optind,from,args[optind]);
while (cfgstacki) {
char *s=cfgstack[--cfgstacki];
} nullcheck[]={
{&phone,"destination phone number"},
#if 0
- {&body ,"body text"},
+ {&logoname,"logo filename"},
+ {&gsmnet,"GSM operator network code"},
{&device,"device for communication"},
#endif
};
-static char **emptycheck[]={&smsc,&body};
+static char **emptycheck[]={&logname,&smsc,&logoname,&gsmnet};
static void lockclose(int fd)
{
lockclose(fd);
}
+static char wasalarm=0;
static void sigalarm(int signo)
{
+ signal(SIGALRM,(RETSIGTYPE (*)(int))sigalarm);
+ wasalarm=1;
if (verbose>=1) error("Timed out");
}
assert(catchdatal<=catchdatasiz);
}
+static int retrycnt=0;
+static void retrying(void)
+{
+ if (++retrycnt>maxretryn) error("!Maximum command retry count (%d) exceeded",maxretryn);
+ if (verbose>=2) error(".Retrying phase, %d out of %d..",retrycnt,maxretryn);
+}
+
static char *devcmd(const char *term,const char *catch,const char *send,...)
{
size_t l,bufl,terml,catchl,fragl,offs;
char buf[LINE_MAX];
ssize_t got;
-RETSIGTYPE (*origsig)(int);
char *hit,*s;
va_list ap;
char errout;
if ((errout=(*send=='!'))) send++;
if (0) {
err:
+ alarm(0);
if (errout) return(NULL);
- if (verbose>=2) error(".Retrying last device command..");
+ retrying();
}
catchdatal=0;
va_start(ap,send);
if (bufl>=sizeof(buf)-1) error("!Command too big (%d>%d)",bufl,sizeof(buf)-1);
if (verbose>=2) error(".devcmd(send=\"%s\",term=\"%s\",catch=\"%s\")",buf,term,catch);
buf[l]='\r'; buf[l+1]='\n';
- origsig=signal(SIGALRM,(RETSIGTYPE (*)(int))sigalarm);
for (offs=0,got=0;offs<bufl;offs++) {
alarm(MAXSENDTIME);
usleep((offs?chartimen:cmdtimen)*1000);
error("Error forcing output of char %d of cmd \"%s\": %m",offs,buf);
}
alarm(0);
- signal(SIGALRM,origsig);
if (got!=bufl) {
error("Wrote only %d of %d bytes of command: %m",got,bufl);
goto err;
fragl=MAX(fragl,MAX(strlen(ERROR_SUBSTR1),strlen(ERROR_SUBSTR2)));
bufl=0;
record=NULL;
+ wasalarm=0;
+ alarm(readtimen);
for (;;) {
blocking(0);
errno=0;
got=read(devfd,buf+bufl,1);
}
if (got<=0) {
- error("Could read device data (ret=%d): %m",got);
+ if (wasalarm) error("!Maximum response timeout (%ds) exceeded",readtimen);
+ error("Couldn't read device data (ret=%d): %m",got);
goto err;
}
s=buf+bufl;
if (record) record=buf+bufl;
}
}
+ alarm(0);
if (!catchdatal) {
if (!catch) return(NULL);
error("Data requested on command \"%s\" but no found after term \"%s\"",send,term);
return(catchdata);
}
-static int prepaddr(unsigned char *d,const char *addr)
-{
-int tot=0;
-char flip=0,plus;
-unsigned char n;
-
- if ((plus=(*addr=='+'))) addr++;
- *++d=(plus?ADDR_INT:ADDR_NAT);
- while (*addr) {
- if (*addr<'0' || *addr>'9')
- error("!Error during conversion of number at: %s",addr);
- tot++;
- n=(*addr++)-'0';
- if ((flip=!flip)) *++d=0xF0|n;
- else *d=(*d&0x0F)|(n<<4U);
- }
- return(tot);
-}
-
-static char *finalsmsc;
-#define SMSCBINSIZE (1+1+(MAXNUMLEN+1)/2)
-static char pdusmsc[SMSCBINSIZE*2+1];
-
static inline char tohex(unsigned char x)
{
x&=0x0F;
return(x-10+'A');
}
-static void textconv(char *d,unsigned char *s,size_t len)
+static inline void textconv(char *d,unsigned char *s,size_t len)
{
while (len--) {
*d++=tohex(*s>>4U);
{
char *s,*t,*e,*serr;
long l;
-unsigned char bin[2+(MAXNUMLEN+1)/2];
if (smsc) devcmd(NULL,NULL,"\r\nAT+CSCA=\"%s\"",smsc);
s=devcmd(NULL,"\n+CSCA:","\r\nAT+CSCA?");
while (isspace(*s)) s++;
if (!*s || !strcmp(s,"EMPTY"))
- error("!No SMS set in A1 found");
- if (verbose>=1) error("\nFound default SMSC in A1: %s",s);
+ error("!No SMS set in Nokia found");
+ if (verbose>=1) error("\nFound default SMSC in Nokia: %s",s);
if (*s!='"') error("!No left-quote found in: %s",s);
if (!(t=strrchr(s+1,'"'))) error("!No right-quote found in: %s",s);
e=t++;
if (l==ADDR_NAT || s[1]=='+') s++;
else *s='+';
*e='\0';
- chk(finalsmsc=strdup(s));
- if (verbose>=2) error("\nDecoded SMSC address: %s",finalsmsc);
- bin[0]=1+(prepaddr(bin,finalsmsc)+1)/2;
- textconv(pdusmsc,bin,bin[0]+1);
+ if (verbose>=2) error("\nDecoded SMSC address: %s",s);
}
-static char *pdudata;
+/* Logo format shamelessly stolen from GNokii-0.3.0: http://www.gnokii.org/
+ * Beware - Nokia Smart Messaging specification 1.0.0 and 2.0.0 is incompatible
+ * with Nokia current product line implementation
+ * http://www.forum.nokia.com/developers/smartmsg/download/ssm2_0_0.pdf
+ */
-static inline unsigned char charconv(char c,size_t offs)
-{
- if ((c>='A' && c<='Z') || (c>='a' && c<='z') || (c>='0' && c<='9')) return(c);
- switch (c) {
- case '@': return(0);
- case '$': return(2);
- case '"': return(96);
- case ' ':
- return(c);
- case 0: assert(0);
- }
- error("Can't convert character '%c' (0x%02X) at offs %d (0-based), substituted '?'",
- c,(unsigned char)c,offs);
- return('?');
-}
+static char hexdata[140*2+1];
-static inline void genpdu(void)
+static inline void logoread(void)
{
-static unsigned char pdu[64+MAXNUMLEN/2+(MAXBODYLEN*7)/8];
-unsigned char *d=pdu;
-int i;
-char inb=0,outb=0,xb;
-unsigned char inreg;
-size_t offs=0;
-
- *d++=PDU_TYPE;
- *d++=PDU_MR;
- i=prepaddr(d,phone);
- *d=i; d+=1+1+(i+1)/2;
- *d++=PDU_PID;
- *d++=PDU_DCS;
- *d++=PDU_VP;
- if (bodylen>MAXBODYLEN) {
- error("Body too large (%d>%d), cut",bodylen,MAXBODYLEN);
- bodylen=MAXBODYLEN;
- }
- *d=bodylen;
- assert(d<pdu+sizeof(pdu));
- while (bodylen || inb) {
- if (!inb) {
- assert(bodylen>0); assert(!!*body);
- inreg=charconv(*body++,offs++);
- bodylen--;
- inb=7;
- }
- if (!outb) {
- *++d=0x00;
- outb=8;
+FILE *f;
+char buf[32+140*8+1];
+unsigned char bin[140]={
+ 0x06, /* UDH length */
+ 0x05, /* IEI */
+ 0x04, /* IEDL */
+ 0x15, 0x83, /* dest port (group gfx) */
+ 0x00, 0x00 /* src port (unused) */
+ };
+size_t got,r,w;
+ssize_t chars,bits;
+char gsmnetf[10];
+int sizex,sizey,bit;
+
+#define WORD(n) (((unsigned char)buf[(n)])|(((unsigned char)buf[(n)+1])<<8))
+
+ if (!(f=fopen(logoname,"rb")))
+ error("!Cannot open logo file \"%s\" for r/o: %m",logoname);
+ got=fread(buf,1,sizeof(buf),f);
+ if (got>=20 && !memcmp(buf,"NOL",4)) {
+ VARPRINTF2(gsmnetf,"%03.3u%02.2u",WORD(6),WORD(8));
+ assert(strlen(gsmnetf)==5);
+ r=10;
+ if (verbose>=1) error(".Reading NOL file \"%s\", GSMnet \"%s\", word@4=%d..",
+ logoname,gsmnetf,WORD(4));
+ }
+ else if (got>=16 && !memcmp(buf,"NGG",4)) {
+ r=6;
+ if (verbose>=1) error(".Reading NGG file \"%s\", word@4=%d..",
+ logoname,gsmnetf,WORD(4));
+ }
+ else error("!Unknown file format of logo file \"%s\"");
+ if (!strcasecmp(gsmnet,WORD_NET)) {
+ if (!*gsmnetf) error("!NOL network code detection requested but NOL file not loaded, please specify network code");
+ gsmnet=gsmnetf;
+ }
+ if (!strcasecmp(gsmnet,WORD_GROUP) || !*gsmnet) {
+ error("\nSending logo as: group graphics");
+ gsmnet=NULL;
+ }
+ else {
+ error("\nSending logo as: operator logo for \"%s\"",gsmnet);
+ bin[4]=0x82; /* dest port 0x1582 */
+ }
+
+ sizex=WORD(r); sizey=WORD(r+2);
+ if (verbose>=2) error(".Magic words: @+4=%d, @+6=%d, @+8=%d",
+ WORD(r+4),WORD(r+6),WORD(r+8));
+ r+=10;
+ if (sizex<1 || sizex>255
+ || sizey<1 || sizey>255) error("!Invalid size: %dx%d",sizex,sizey);
+ chars=((bits=sizex*sizey)+7)/8;
+ if (r+bits>got) error("!Logo file \"%s\" too short - actual=%d, need(%dx%d)=%d",
+ logoname,got,sizex,sizey,r+chars);
+ else if (r+bits<got)
+ if (verbose>=1) error("Ignoring trailing garbage in \"%s\", used only %d bytes",logoname,r+bits);
+ if ((got=(7+(gsmnet?3:0)+4+chars))>140)
+ error("!SMS size would be %d bytes but 140 is maximum",got);
+ w=7;
+ if (gsmnet) {
+ bin[w++]=((gsmnet[1]&0x0F)<<4)|(gsmnet[0]&0x0F);
+ bin[w++]=0xF0 |(gsmnet[2]&0x0F);
+ bin[w++]=((gsmnet[4]&0x0F)<<4)|(gsmnet[3]&0x0F);
+ }
+ bin[w++]=0x00; /* RFU by Nokia */
+ bin[w++]=sizex; bin[w++]=sizey;
+ bin[w++]=0x01; /* one B/W plane */
+ while (chars--) {
+ bin[w]=0;
+ for (bit=0x80;(bits>0) && (bit>0);bits--,bit>>=1) {
+ if (buf[r]!='0' && buf[r]!='1')
+ error("!Invalid character (neither '0' nor '1')in logo file \"%s\" at offset 0x%X",
+ logoname,r);
+ if (buf[r++]=='1') bin[w]|=bit;
}
- xb=MIN(inb,outb);
- d4("inb=%d,outb=%d,xb=%d\n",inb,outb,xb);
- *d|=((inreg>>(unsigned)(7-inb))&((1<<xb)-1))<<(unsigned)(8-outb);
- inb-=xb; outb-=xb;
- }
- d++;
- assert(d<pdu+sizeof(pdu));
- pdudata=malloc(2*(d-pdu)+1);
- textconv(pdudata,pdu,d-pdu);
+ w++;
+ }
+ assert(chars==-1); assert(bits==0); assert(w==got); assert(w<=140);
+ textconv(hexdata,bin,w);
+ if (verbose>=2) error("\nWill send hexdata: %s",hexdata);
}
static struct {
long *ip;
const char *const msg;
} numarg[]={
+ { &maxretry,&maxretryn,"maxretry" },
+ { &readtime,&readtimen,"readtime" },
{ &chartime,&chartimen,"chartime" },
{ &cmdtime ,&cmdtimen ,"cmdtime" },
+ { &baud ,&baudn ,"baud" },
};
int main(int argc,char **argv)
{
-char *s,*finame;
-FILE *fin;
+char *s;
int i;
unsigned fatal=0;
-struct termios tios;
+speed_t portbaud;
- pname=*argv;
+ if ((s=strrchr((pname=*argv),'/'))) pname=s+1;
atexit(cleanup);
signal(SIGTERM,(RETSIGTYPE (*)(int))cleanup);
signal(SIGQUIT,(RETSIGTYPE (*)(int))cleanup);
free(*emptycheck[i]);
*emptycheck[i]=NULL;
}
+ if (!logname) logname=DEF_LOGNAME;
if (!lockfile) lockfile=DEF_LOCKFILE;
if (!device) device=DEF_DEVICE;
- if (body && readbody) {
- finame=body;
- body=NULL;
- }
- else fin=stdin;
- if (!body) {
- readbody=0;
- if (verbose>=1)
- error("\nPlease enter the SMS text body, end with EOF (ctrl-D):");
- chk(body=malloc(BODYLOAD));
- bodylen=fread(body,1,BODYLOAD,fin);
- if (bodylen==-1)
- error("!Error reading stream \"%s\": %m",(finame?finame:"<stdin>"));
- }
- if (fin!=stdin) {
- chkfclose(fin,finame);
- free(finame);
- }
+ logoread();
for (i=0;i<NELEM(numarg);i++) {
char *serr;
}
error("!Invalid format-character '%c' in lockfile format-string, only \"%%s\" allowed",*s);
}
- genpdu();
+
+ if (*logname) {
+ if (!(logf=fopen(logname,"a")))
+ error("!Error opening log \"%s\" for append: %m",logname);
+ logmsg("Starting up: " PACKAGE " " VERSION);
+ }
+ switch (baudn) {
+ case 2400: portbaud= B2400; break;
+ case 4800: portbaud= B4800; break;
+ case 9600: portbaud= B9600; break;
+ case 19200: portbaud=B19200; break;
+ case 38400: portbaud=B38400; break;
+ case 57600: portbaud=B57600; break;
+ default:
+ error("!Specified baudrate %d is not supported",baudn);
+ }
+ if (verbose>=2) error(".Will use baudrate %d with hexval 0x%X",baudn,portbaud);
if (lockfile && *lockfile && VARPRINTF(lockreal,lockfile,devicename)>0) {
+time_t start,end;
if (verbose>=1) error(".Locking device \"%s\" by \"%s\"..",device,lockreal);
+ time(&start);
lockdevice();
+ time(&end);
+ if ((end-=start)>LOCKREPORT)
+ logmsg("Device lock succeeded after %d seconds",end);
}
if (verbose>=1) error(".Opening device \"%s\"..",device);
if ((devfd=open(device,O_RDWR|O_NDELAY))<0)
}
tios.c_iflag=IGNBRK|IGNPAR|IXON|IXOFF;
tios.c_oflag=0;
- tios.c_cflag=CS8|CREAD|CLOCAL|B19200|HUPCL;
+ tios.c_cflag=CS8|CREAD|CLOCAL|HUPCL|portbaud;
tios.c_lflag=IEXTEN|NOFLSH;
memset(tios.c_cc,_POSIX_VDISABLE,sizeof(tios.c_cc));
tios.c_cc[VTIME]=0;
tios.c_cc[VMIN ]=1;
+ cfsetispeed(&tios,portbaud);
+ if (cfsetospeed(&tios,portbaud)|cfsetispeed(&tios,portbaud))
+ error("Error setting termios baudrate on device: %m");
if (tcflush(devfd,TCIOFLUSH))
error("Error flushing termios (TCIOFLUSH) on device: %m");
if (tcsetattr(devfd,TCSANOW,&tios))
- error("!Unable to set initial termios device settings");
+ error("!Unable to set initial termios device settings: %m");
+ signal(SIGALRM,(RETSIGTYPE (*)(int))sigalarm);
do {
- devcmd("",NULL,"\r\nAT\x1A");
+ devcmd("",NULL,"\r\nAT\033");
devcmd(NULL,NULL,"\r\nAT");
smscset();
- devcmd(NULL,NULL,"\r\nAT+CMGF=0");
- devcmd("\n> ",NULL,"\r\nAT+CMGS=%d",(strlen(pdusmsc)+strlen(pdudata))/2);
- s=devcmd(NULL,"\n+CMGS:","!%s%s\x1A",pdusmsc,pdudata);
- } while (!s);
+ devcmd(NULL,NULL,"\r\nAT+CSMP=81,,0,245");
+ devcmd("\n> ",NULL,"\r\nAT+CMGS=\"%s\"",phone);
+ if (!(s=devcmd(NULL,"\n+CMGS:","!%s\032",hexdata))) {
+ retrying();
+ continue;
+ }
+ devcmd(NULL,NULL,"\r\nAT+CSMP=17,,0,0");
+ devcmd(NULL,NULL,"\r\nAT");
+ } while (0);
while (isspace(*s)) s++;
if (verbose>=1) error("\nMessage successfuly sent with MR: %s",s);
devcmd(NULL,NULL,"\r\nAT");
+ logmsg("SMS sent (after %d retries), message reference: %s",retrycnt,s);
return(EXIT_SUCCESS);
}