X-Git-Url: https://git.jankratochvil.net/?p=mdsms.git;a=blobdiff_plain;f=mdsms.c;h=21d69992354c48f2f2e821855dae8778b31085cc;hp=aad2551aa2e4966734ffae8b1a787d1441e77c13;hb=d82a194dafd084eb91d7abffa3ed2e9a33e7c4b6;hpb=daa9220332d7088444851d2d1142e28e3781049f diff --git a/mdsms.c b/mdsms.c index aad2551..21d6999 100644 --- a/mdsms.c +++ b/mdsms.c @@ -1,3 +1,4 @@ +#define WANT_DECLARATIONS 1 #include "config.h" #ifndef lint static char rcsid[] ATTR_UNUSED = "$Id$"; @@ -38,6 +39,9 @@ static char rcsid[] ATTR_UNUSED = "$Id$"; #ifdef HAVE_SYS_TYPES_H #include #endif +#ifdef HAVE_SYS_WAIT_H +#include +#endif #ifdef HAVE_SYS_STAT_H #include #endif @@ -66,6 +70,13 @@ static char rcsid[] ATTR_UNUSED = "$Id$"; #include "getopt.h" #endif + +/* Always override possible system defintions as it is safe (used by glib) */ +#undef MAX +#define MAX(a,b) ((a)>(b)?(a):(b)) +#undef MIN +#define MIN(a,b) ((a)<(b)?(a):(b)) + #define NELEM(x) (sizeof((x))/sizeof(*(x))) #ifndef DEBUG @@ -96,9 +107,29 @@ static int verbose static char *pname; static int dis_cleanup=0,devfd=-1; -static char *phone,*device,*logname,*lockfile,*smsc,*maxretry,*readtime,*chartime,*cmdtime,*baud,*restore; +static char *phone,*device,*logname,*lockfile,*smsmode,*pdusmscmode,*smsc,*maxretry,*readtime,*chartime,*cmdtime,*baud,*restore; static int readbody; static long maxretryn=DEF_MAXRETRY,readtimen=-1,chartimen=DEF_CHARTIME,cmdtimen=DEF_CMDTIME,baudn=DEF_BAUD; +#ifdef HAVE_CRTSCTS +static int handshake_rtscts; +static unsigned handshake_stamp; +#else +#define handshake_rtscts (0) +#endif +static enum { + FSM_AUTO=0, + FSM_PDU, + FSM_TEXT + } force_smsmode=FSM_AUTO; +static enum { + FPSM_AUTO=0, + FPSM_COUNT_IN, + FPSM_COUNT_OUT, + FPSM_NONE + } force_pdusmscmode=FPSM_AUTO, +#define FPSM_MIN (FPSM_COUNT_IN) +#define FPSM_MAX (FPSM_NONE) + try_pdusmscmode=FPSM_MIN; static size_t bodylen; /* --send / --send-mobildock / --receive specific */ static char *body; @@ -235,11 +266,13 @@ static void usage(void) %s\ \n\ Usage: %s [-c|--config ] [-d|--device ]\n\ - {--send | --send-mobildock | --receive | --logo-send}\n\ - [-L|--log ] [-b|--baud ]\n\ - [-l|--lockfile ] [-s|--smsc ] [-m|--maxretry <#>]\n\ + [-L|--log ] [-l|--lockfile ]\n\ + [-b|--baud ] [-x|--xonxoff] [-C|--rtscts]\n\ + [-M|--smsmode ] [-P|--pdusmscmode ]\n\ + [-s|--smsc ] [-m|--maxretry <#>]\n\ [-r|--readtime ] [-t|--chartime ] [-T|--cmdtime ]\n\ [-v|--verbose] [-h|--help] [-V|--version]\n\ + {--send | --send-mobildock | --receive | --logo-send}\n\ --send / --send-mobildock:\n\ [-f|--file] \n\ --receive:\n\ @@ -253,9 +286,13 @@ Usage: %s [-c|--config ] [-d|--device ]\n\ \t\t(def. \"%s\" and \"$HOME%s\")\n\ -d, --device\tMobile on this serial device (def. \"%s\")\n\ -L, --log\tLog all important messages to this file (def. \"%s\")\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\ + -b, --baud\tSet baudrate, 2400-57600 supported (def. %d)\n\ + -x, --xonxoff\tUse XON/XOFF (AKA software) serial port handshaking - default\n\ + -C, --rtscts\tUse RTS/CTS (AKA hardware) serial port handshaking%s\n\ + -M, --smsmode\tForce SMS as: \"pdu\" or 0: PDU mode, \"text\" or 1: text mode\n\ + -P, --pdusmscmode\tForce PDU as: \"count-in\", \"count-out\", \"none\"\n\ -s, --smsc\tUse this SMS Center number (def. query from mobile)\n\ -m, --maxretry\tMaximum retries of any command before giving up (def. %d)\n\ -r, --readtime\tSeconds for maximum wait time for response\n\ @@ -283,9 +320,14 @@ Usage: %s [-c|--config ] [-d|--device ]\n\ \t\t* Group gfx : Specify \"%s\" to send logo as group graphics\n\ \n\ You may need to use the following line to catch all of this help text:\n\ -./mdsms 2>&1|more\n\ -\n"),version,PACKAGE,CONFIG_MAIN,CONFIG_HOME,DEF_DEVICE,DEF_LOGNAME,DEF_BAUD,DEF_LOCKFILE,DEF_MAXRETRY, -DEF_READTIME,DEF_READTIME_MOBILDOCK,EXT_READTIME,DEF_CHARTIME,DEF_CMDTIME, +./mdsms -h 2>&1|more\n\ +\n"),version,PACKAGE,CONFIG_MAIN,CONFIG_HOME,DEF_DEVICE,DEF_LOGNAME,DEF_LOCKFILE,DEF_BAUD, +#ifdef HAVE_CRTSCTS + "", +#else + _("\n\t\t(Not supported on this platform!)"), +#endif +DEF_MAXRETRY,DEF_READTIME,DEF_READTIME_MOBILDOCK,EXT_READTIME,DEF_CHARTIME,DEF_CMDTIME, WORD_NET,WORD_GROUP); exit(EXIT_FAILURE); } @@ -303,20 +345,25 @@ static const struct option longopts[]={ {"recv" ,0,0,MODE_RECEIVE}, {"logo" ,0,0,MODE_LOGO_SEND}, {"ring" ,0,0,MODE_RING_SEND}, -{"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'}}; +{"config" ,1,0,'c'}, +{"device" ,1,0,'d'}, +{"log" ,1,0,'L'}, +{"lockfile" ,1,0,'l'}, +{"baud" ,1,0,'b'}, +{"xonxoff" ,0,0,'x'}, +{"rtscts" ,0,0,'C'}, +{"smsmode" ,1,0,'M'}, +{"pdusmscmode" ,1,0,'P'}, +{"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'}, +{NULL ,0,0,0 }}; static void processargs(int argp,char **args,const char *from); @@ -512,15 +559,17 @@ static struct { char **const var; unsigned stamp; } optset[]={ - { 'd',&device }, - { 'L',&logname }, - { 'b',&baud }, - { 'l',&lockfile }, - { 's',&smsc }, - { 'm',&maxretry }, - { 'r',&readtime }, - { 't',&chartime }, - { 'T',&cmdtime }, + { 'd',&device }, + { 'L',&logname }, + { 'l',&lockfile }, + { 'b',&baud }, + { 'M',&smsmode }, + { 'P',&pdusmscmode }, + { 's',&smsc }, + { 'm',&maxretry }, + { 'r',&readtime }, + { 't',&chartime }, + { 'T',&cmdtime }, }; static void processargs(int argp,char **args,const char *from) @@ -531,7 +580,7 @@ int i; seq++; optarg=NULL; optind=0; /* FIXME: Possible portability problem. */ - while ((optc=getopt_long(argp,args,"c:d:L:b:l:s:m:r:t:T:fvhV",longopts,NULL))!=EOF) switch (optc) { + while ((optc=getopt_long(argp,args,"c:d:L:l:b:xCM:P: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),from); @@ -539,7 +588,7 @@ int i; } chk(cfgstack[cfgstacki++]=strdup(optarg)); break; - case 'd': case 'L': case 'b': case 'l': case 's': case 'm': case 'r': case 't': case 'T': + case 'd': case 'L': case 'b': case 'l': case 'M': case 'P': case 's': case 'm': case 'r': case 't': case 'T': for (i=0;i=0 && ++retrycnt>maxretryn) error(_("!Maximum command retry count (%ld) exceeded"),maxretryn); + if (maxretryn>=0 && ++retrycnt>=maxretryn) error(_("!Maximum command retry count (%ld) exceeded"),maxretryn); if (verbose>=2) error(_(".Retrying phase, %d out of %ld.."),retrycnt,maxretryn); } -static char *reform(const char *s,int slot) +static const char *reform(const char *s,int slot) { static struct formslot { char *s; @@ -880,6 +941,8 @@ off_t o=d-fs->s; return(fs->s); } +static char devcmd_empty_return='\0'; /* returned as catch when only newlines found */ + static char *devcmd(const char *term,const char *catch,const char *send,...) ATTR_PRINTFORMAT(3,4); static char *devcmd(const char *term,const char *catch,const char *send,...) { @@ -889,21 +952,27 @@ static size_t bufl; ssize_t got; char *hit,*s; va_list ap; -char errout,extend,noconvcr,edata; +char errout,extend,catch_any,edata; long alarmtime; const char *osend; static const char emptystring[]=""; +size_t discard; if (!term) term="\nOK\n"; if (!strcmp(send," ")) send=NULL; /* GCC formatstring-check workaround */ + if (verbose>=2) error(_(".devcmd(sendfmt=%s,term=%s,catch=%s)"), + reform(send,0),reform(term,1),reform(catch,2)); if (!(osend=send)) send=""; - if ((noconvcr=(catch && *catch=='@'))) catch++; + if ((catch_any=(catch && !strcmp(catch,"@")))) catch=NULL; if ((errout=(*send=='!'))) send++; errout|=(maxretryn==-1); if ((extend=(*send=='~'))) send++; alarmtime=readtimen*(extend?EXT_READTIME:1); - d8("devcmd(), alarmtime=%ld, errout=%d, extend=%d, noconvcr=%d, osend=%p, bufl=%d, buf: %s\n", - alarmtime,errout,extend,noconvcr,osend,bufl,reform(buf,0)); + buf[bufl]='\0'; /* for d8() below */ + d8("devcmd(), alarmtime=%ld, errout=%d, extend=%d, catch_any=%d, osend=%p, bufl=%d, buf: %s\n", + alarmtime,errout,extend,catch_any,osend,bufl,reform(buf,0)); + assert(!catch || !strchr(catch,'\r')); /* we are no longer supporting 'noconvcr'! */ + assert(!term || !strchr(term ,'\r')); if (0) { err: alarm(0); @@ -918,8 +987,7 @@ err: l=VARVPRINTF(buf,send,ap); bufl=l+(!!osend); va_end(ap); 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,timeout=%ld)"), - reform(buf,0),reform(term,1),reform(catch,2),alarmtime); + if (verbose>=2) error(_(".devcmd formatted send=%s%s"),reform(buf,0),(osend?"+\"\\r\"":"")); if (osend) buf[l]='\r'; for (offs=0,got=0;offs=2) + error(_(".Blank (%d newlines) input read, ignoring it"),bufl); + bufl=0; /* discard newlines */ + return(&devcmd_empty_return); + } if (wasalarm) error(_("Maximum response timeout (%lds) exceeded"),alarmtime); else error(_("^Couldn't read device data (ret=%d)"),got); goto err; } -skipread: bufl2=bufl+got; buf[bufl2]='\0'; s=buf+bufl; while (buf+bufl2>s && (s=memchr(s,'\0',buf+bufl2-s))) *s++=REPL_NULLCHAR; if (verbose>=3) error(_("\nGot chunk of data from device: %s"),reform(buf+bufl,0)); - if (!noconvcr) { + /* convert CR */ { s=buf+bufl; while (buf+bufl2>s && (s=memchr(s,'\r',buf+bufl2-s))) *s++='\n'; } bufl=bufl2; +skipread: catched(buf+bufl,edata); assert(!record || record==buf+bufl); assert(bufl=catchl && (hit=strstr(buf,catch))) { +/* "record" may get NULLed here after successful 'catch' + * but "recordend" will never be NULLed + */ + if (catch && !recordend && bufl>=catchl && (hit=strstr(buf,catch))) { record=hit+catchl; catched(buf+bufl,edata); assert(!record || record==buf+bufl); } - if ( bufl>= terml && (hit=strstr(buf,term))) { + if (catch_any && !recordend && buf[discard=strspn(buf,"\n" /* accept */)]) { + record=buf+discard; + catched(buf+bufl,edata); assert(!record || record==buf+bufl); + } + if (((!catch && !catch_any) || catchdatal) && bufl>= terml + && (hit=strstr((recordend?recordend:buf),term))) { memmove(buf,hit+terml,(bufl2=(buf+bufl)-(hit+terml))); bufl=bufl2; break; } if (bufl=2) error(_(".Returning data %s for cmd %s"),reform(catchdata,0),reform(send,1)); @@ -1060,7 +1144,6 @@ static inline void textconv(char *d,unsigned char *s,size_t len) static inline void smscset(void) { char *s,*t,*e,*serr; -long l; unsigned char bin[2+(MAXNUMLEN+1)/2]; if (smsc) devcmd(NULL,NULL,"\r\nAT+CSCA=\"%s\"",smsc); @@ -1069,19 +1152,22 @@ unsigned char bin[2+(MAXNUMLEN+1)/2]; if (!*s || !strcmp(s,"EMPTY")) error(_("!No SMSC set in mobile station found, please use option \"-s\"")); if (verbose>=1) error(_("\nFound default SMSC in mobile: %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); - if (s+1==t) + if (*s++!='"') error(_("!No left-quote found in: %s"),s); + if (!(t=strrchr(s,'"'))) error(_("!No right-quote found in: %s"),s); + if (s==t) error(_("!No SMS set in mobile station found, please use option \"-s\"")); e=t++; while (isspace(*t)) t++; - if (*t++!=',') error(_("!No comma found after quotes in: %s"),s); - while (isspace(*t)) t++; - l=strtol(t,&serr,10); - if ((l!=ADDR_NAT && l!=ADDR_INT) || (serr && *serr)) - error(_("!Type parse error in: %s"),s); - if (l==ADDR_NAT || s[1]=='+') s++; - else *s='+'; + if (*t) { +long l; + + if (*t++!=',') error(_("!No comma found after quotes in: %s"),s); + while (isspace(*t)) t++; + l=strtol(t,&serr,10); + if ((l!=ADDR_NAT && l!=ADDR_INT) || (serr && *serr)) + error(_("!Type parse error in: %s"),s); + if (l==ADDR_INT && *s!='+') *--s='+'; + } *e='\0'; if (verbose>=2) error(_("\nDecoded SMSC address: %s"),s); if (!NEED_PDUSMSC()) return; @@ -1389,12 +1475,13 @@ fd_set rfds,xfds; assert(devfd>=0); retry: - errno=0; - + if (!immed && verbose>=2) + error(_(".Waiting for device incoming data..")); #ifdef HAVE_POLL ufd.fd=devfd; ufd.events=POLLIN; ufd.revents=0; + errno=0; i=poll(&ufd,1,(immed?0:-1)); #else /* HAVE_POLL */ #ifdef HAVE_FD_SETSIZE @@ -1404,9 +1491,12 @@ retry: #endif /* HAVE_FD_SETSIZE */ FD_ZERO(&rfds); FD_SET(devfd,&rfds); FD_ZERO(&xfds); FD_SET(devfd,&xfds); + errno=0; i=select(devfd+1,&rfds,NULL,&xfds,NULL); #endif /* HAVE_POLL */ if (immed && i==0) return(0); + if (i==-1 && errno==EINTR) + goto retry; /* silent retry, for example SIGCHLD could occur */ if (i!=1) error(_("^Failed (retval %d) while waiting for data, ignoring"),i); @@ -1432,8 +1522,8 @@ retry: static char *check_format(const char *fmt,const char *string) { static char err[LINE_MAX],sub[50]; -char *subp,cf,cs; -const char *sf,*ss; +char cf,cs; +const char *sf,*ss,*subp; for (sf=fmt,ss=string;(cf=*sf) && (cs=*ss);sf++,ss++) { subp=NULL; @@ -1508,6 +1598,7 @@ int i; tm.tm_mon--; d7("mktime(y%dm%dd%dh%dm%ds%d)\n", tm.tm_year,tm.tm_mon,tm.tm_mday,tm.tm_hour,tm.tm_min,tm.tm_sec); + tm.tm_isdst=-1; /* "timezone" info not available */ if ((receive_time=mktime(&tm))==-1) error(_("^mktime(3) failed for %s"),string); } @@ -1550,6 +1641,22 @@ int i; #undef DIGIT2ASC } +static void signal_chld(int signo) +{ +int status; +pid_t pid; + + signal(SIGCHLD,(RETSIGTYPE (*)(int))signal_chld); + /* we don't care about siginterrupt(3) as it doesn't matter how it is set */ + + d2("signal_chld: signo=%d\n",signo); + while (0<(pid=waitpid(-1 /* ANY process */,&status,WNOHANG /* options */))) { + if (verbose>=2) + error(_(".Child process w/PID %d has exited, %s, status=%d"), + pid,(WIFEXITED(status)? _("normally") : _("abnormally")),(WIFEXITED(status) ? WEXITSTATUS(status) : -1)); + } +} + static void receive_text(char *bodyline) { char *buf,*s,*s1,*s2,*s3; @@ -1559,12 +1666,17 @@ int i; FILE *f; d2("receive_text: %s\n",bodyline); + signal(SIGCHLD,(RETSIGTYPE (*)(int))signal_chld); #if RECEIVE_TEST pid=0; #else pid=fork(); #endif - if (pid>0) return; /* parent context */ + if (pid>0) { + if (verbose>=2) + error(_(".Spawned child receive-SMS process w/PID %d"),pid); + return; /* parent context */ + } if (pid==-1) { error(_("Can't fork(2), process spawning may block receive")); } @@ -1622,10 +1734,10 @@ err: exit(EXIT_SUCCESS); /* cleanup() has been disabled */ } -static inline unsigned char fromhex(char c) +static inline unsigned char fromhex(unsigned c) { c&=0xDF; - return(c<'A'?c-'0':(c-'A')+0xA); + return(c<'A'?c-('0'&0xDF):(c-('A'&0xDF))+0xA); } static int teldecode(char *text,unsigned char *bin,size_t digits) @@ -1672,7 +1784,7 @@ int i; static void receive_pdu(char *pduline) { unsigned char pdu[140+0x100],*pdup,*pdue,oalen,inreg; -char text[160+1],*textp,*s; +char text[160+1],*textp,*s,*pdulinescan; size_t pdulinel=strlen(pduline),want; size_t udl,udlb; int inb,outb,xb; @@ -1684,11 +1796,11 @@ int inb,outb,xb; { error(_("PDU length odd (%d): %s"),pdulinel,pduline); return; } if (pdulinel<2*13) { error(_("PDU length %d too small (min. 2*%d): %s"),pdulinel,13,pduline); return; } - for (pdup=pdu;*pduline;pduline+=2) { - if (!isxdigit(pduline[0]) || !(isxdigit(pduline[1]))) + for (pdup=pdu,pdulinescan=pduline;*pdulinescan;pdulinescan+=2) { + if (!isxdigit(pdulinescan[0]) || !(isxdigit(pdulinescan[1]))) { error(_("Invalid hex byte: %c%c on byte %d in: %s"), - pduline[0],pduline[1],pdup-pdu,pduline); return; } - *pdup++=(fromhex(pduline[0])<<4)|fromhex(pduline[1]); + pdulinescan[0],pdulinescan[1],pdup-pdu,pduline); return; } + *pdup++=(fromhex(pdulinescan[0])<<4)|fromhex(pdulinescan[1]); } pdue=pdup; free(receive_smsc); @@ -1703,7 +1815,7 @@ int inb,outb,xb; if (pdu[1]==ADDR_INT) *s++='+'; else { if (pdu[1]!=ADDR_NAT) - error(_("Unknown address type 0x%02X of %s, ignoring in PDU: %s"),_("SMSC"),pdu[1],pduline); return; + error(_("Unknown address type 0x%02X of %s, ignoring in PDU: %s"),pdu[1],_("SMSC"),pduline); return; } if (teldecode(s,pdu+2,2*(*pdu-1)-((pdu[1+(*pdu)]&0xF0)==0xF0))) error(_("Some digits unrecognized in %s \"%s\", ignoring in PDU: %s"),_("SMSC"),receive_smsc,pduline); @@ -1713,8 +1825,8 @@ int inb,outb,xb; error(_("Unrecognized PDU type 0x%02X at offset %d, dropping: %s"),*pdup,pdup-pdu,pduline); pdup++; free(receive_number); - if ((oalen=*pdup++)>10) /* OA len */ - { error(_("Originating number too large (%d, max. %d): %s"),oalen,10,pduline); return; } + if ((oalen=*pdup++)>2*0x10) /* OA len */ + { error(_("Originating number too large (0x%X, max. 2*0x%X): %s"),oalen,0x10,pduline); return; } if (pdup+(want=1+(oalen+1)/2+10)>pdue) { error(_("PDU length too short (want %d, is %d): %s"),(pdup-pdu)+want,pdue-pdu,pduline); return; } chk(receive_number=malloc(1+2*(*pdup)+1)); @@ -1722,7 +1834,7 @@ int inb,outb,xb; if (*pdup==ADDR_INT) *s++='+'; else { if (*pdup!=ADDR_NAT) - error(_("Unknown address type 0x%02X of %s, ignoring in PDU: %s"),_("originating number"),*pdup,pduline); return; + error(_("Unknown address type 0x%02X of %s, ignoring in PDU: %s"),*pdup,_("originating number"),pduline); return; } pdup++; if (teldecode(s,pdup,oalen)) @@ -1752,14 +1864,13 @@ int inb,outb,xb; size_t udl1,udlb1; udlb1=pdue-pdup; - udl1=(udlb*8)/7; + udl1=(udlb1*8)/7; error(_("PDU data length (%d/7->%d/8) longer than data (%d), cut to %d/7->%d/8: %s"), - udl,udlb,pdue-pdup,pduline); + udl,udlb,pdue-pdup,udl1,udlb1,pduline); udl=udl1; udlb=udlb1; } else - error(_("Trailing garbage ignored in PDU data (UDL %d/7->%d/8, got %d) in: %s"), - udl,udlb,pdue-pdup,pduline); + assert(pdup+udlb==pdue); /* should be checked by 'PDU length too short' above */ textp=text; inb=outb=0; inreg=0; /* GCC happiness */ @@ -1777,7 +1888,7 @@ size_t udl1,udlb1; #if 0 d4("inb=%d,outb=%d,xb=%d\n",inb,outb,xb); #endif - *textp|=((inreg>>(unsigned)(7-inb))&((1<>(unsigned)(8-inb))&((1<=1) @@ -2020,8 +2151,18 @@ retryall: s=devcmd(NULL,"\n+CMGS:","!~%s\032",body); } else { - devcmd("\n> ",NULL,"\r\nAT+CMGS=%d",(strlen(pdusmsc)+strlen(pdudata))/2); - s=devcmd(NULL,"\n+CMGS:","!~%s%s\032",pdusmsc,pdudata); + devcmd("\n> ",NULL,"\r\nAT+CMGS=%d",( + (try_pdusmscmode==FPSM_COUNT_IN ? strlen(pdusmsc) : 0) + +strlen(pdudata))/2); + s=devcmd(NULL,"\n+CMGS:","!~%s%s\032", + (try_pdusmscmode!=FPSM_NONE ? pdusmsc : ""), + pdudata); + if (!s && force_pdusmscmode==FPSM_AUTO) { + if (FPSM_MAX==try_pdusmscmode++) + try_pdusmscmode=FPSM_MIN; + else + retrycnt--; + } } break; case MODE_LOGO_SEND: @@ -2042,40 +2183,42 @@ struct hexdata *hd; restore="\r\nAT+CNMI=,0"; devcmd(NULL,NULL,"\r\nAT+CNMI=,2"); devcmd(NULL,NULL,"\r\nAT+CSDH=0"); - unlockdevice(0); - /* Never bail-out when we got up to this point */ - if (maxretryn!=-1 && verbose>=1) - error(_(".Initialization successful, infinite retry count set")); - maxretryn=-1; + for (;;) { +continue_receive: + unlockdevice(0); + /* Never bail-out when we got up to this point */ + if (maxretryn!=-1 && verbose>=1) + error(_(".Initialization successful, infinite retry count set")); + maxretryn=-1; #if RECEIVE_TEST receive_headerparse(" \"+420602123456\",,\"99/10/25,03:21:03-00\""); receive_accept("TESTBODY"); exit(EXIT_SUCCESS); #endif - datawait(0); - if (!lockdevice(1)) { - if (verbose>=1) - error(_(".Dialout detected, waiting for lock..")); - lockdevice(0); - goto retryall; - } - d1("Lock-device succeeded\n"); - do { - d1("Reading a message for us...\n"); - if (!(s=devcmd("\r","@+CMT:"," "))) + datawait(0); + if (!lockdevice(1)) { + if (verbose>=1) + error(_(".Dialout detected, waiting for lock..")); + lockdevice(0); goto retryall; - if (cmgf && !(i=receive_headerparse(s))) - error(_("Receive-header parsing failed on: %s"),s); - if (!(s=devcmd("\r","@\n"," "))) - goto retryall; - if (cmgf) { - if (i) receive_text(s); } - else receive_pdu(s); - if (!devcmd("\n",NULL," ")) /* eat last '\n' */ - goto retryall; - } while (datawait(1)); - goto retryall; + d1("Lock-device succeeded\n"); + do { + d1("Reading a message for us...\n"); + if (!(s=devcmd("\n","+CMT:"," "))) + goto retryall; + if (s==&devcmd_empty_return) /* only newlines found */ + goto continue_receive; + if (cmgf && !(i=receive_headerparse(s))) + error(_("Receive-header parsing failed on: %s"),s); + if (!(s=devcmd("\n","@"," "))) + goto retryall; + if (cmgf) { + if (i) receive_text(s); + } + else receive_pdu(s); + } while (datawait(1)); + } /* return to 'continue receive' point */ break; default: assert(0); } @@ -2088,6 +2231,9 @@ struct hexdata *hd; } devcmd(NULL,NULL,"\r\nAT"); - logmsg(_("SMS sent (after %d retries), %d part(s)"),retrycnt,parts); + if (parts) + logmsg(_("SMS sent (after %d retries), %d part(s)"),retrycnt,parts); + else + logmsg(_("SMS sent (after %d retries)"),retrycnt); return(EXIT_SUCCESS); }