1 /*
2 SMS Server Tools 3
3 Copyright (C) 2006- Keijo Kasvi
4 http://smstools3.kekekasvi.com/
5 
6 Based on SMS Server Tools 2, http://stefanfrings.de/smstools/
7 SMS Server Tools version 2 and below are Copyright (C) Stefan Frings.
8 
9 This program is free software unless you got it under another license directly
10 from the author. You can redistribute it and/or modify it under the terms of
11 the GNU General Public License as published by the Free Software Foundation.
12 Either version 2 of the License, or (at your option) any later version.
13 */
14 
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <fcntl.h>
18 #include <termios.h>
19 #include <regex.h>
20 #include <ctype.h>
21 #include <time.h>
22 #include "logging.h"
23 #include "alarm.h"
24 
25 #ifdef SOLARIS
26 #include <sys/filio.h>
27 #include <strings.h> // for bzero().
28 #endif
29 
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h>
34 #include <syslog.h>
35 #include <sys/ioctl.h>
36 #include <errno.h>
37 
38 #ifndef DISABLE_INET_SOCKET
39 // HG
40 #include <sys/socket.h>
41 #include <netinet/in.h>
42 #include <netdb.h>
43 #endif
44 
45 #include "extras.h"
46 #include "modeminit.h"
47 #include "smsd_cfg.h"
48 #include "version.h"
49 #include "pdu.h"
50 #include "stats.h"
51 
52 // Define a dummy if the OS does not support hardware handshake
53 #ifndef CRTSCTS
54 #define CRTSCTS 0
55 #endif
56 
57 // 3.1.16beta:
58 typedef struct {
59   char *keyword;
60   int value;
61   char *comment;
62 } _read_timeout;
63 
64 _read_timeout read_timeouts[] =
65 {
66   {"askpin",	2,	"Asking if PIN is required."},
67   {"atd",	24,	"Initiating a voice call."},
68   {"ath",	1,	"Ending a voice call using ATH or AT+CHUP."},
69   {"clcc",	24,	"Listing current calls during a voice call."},
70   {"cmd",	1,	"Sending regular_run command to modem."},
71   {"cmgd",	1,	"Deleting a message, checking messages using +CMGD."},
72   {"cmgf",	1,	"Selecting a PDU mode."},
73   {"cmgl",	12,	"Listing messages."},
74   {"cmgr",	1,	"Reading message."},
75   {"cmgs",	2,	"Initiating a sending."},
76   {"cpas",	24,	"Checking activity during a voice call."},
77   {"cpbr",	1,	"Reading phonebook entry, check limits."},
78   {"cpbw",	1,	"Writing (deleting) a phonebook entry."},
79   {"cpms",	1,	"Selecting preferred memory, checking size."},
80   {"creg",	2,	"Reading registration report."},
81   {"csca",	1,	"Changing SMSC."},
82   {"csq",	2,	"Reading signal quality."},
83   {"cusd",	3,	"Sending USSD string."},
84   {"default",	1,	"Default for basic commands: AT, ATE0, etc."},
85   {"enterpin",	6,	"Entering a PIN."},
86   {"init",	2,	"Sending init or init2 string."},
87   {"pdu",	12,	"Sending a PDU."},
88   {"preinit",	2,	"Sending pre_init string."},
89   {"start",	2,	"Sending start string."},
90   {"stop",	2,	"Sending stop string."}
91 };
92 // -------
93 
94 typedef struct {
95   int code;
96   char *text;
97 } _gsm_general_error;
98 
99 _gsm_general_error gsm_cme_errors[] =
100 {
101   // 3GPP TS 07.07 version 7.8.0 Release 1998 (page 90) ETSI TS 100 916 V7.8.0 (2003-03)
102   {0,	"Phone failure"},
103   {1,	"No connection to phone"},
104   {2,	"Phone-adaptor link reserved"},
105   {3,	"Operation not allowed"},
106   {4,	"Operation not supported"},
107   {5,	"PH-SIM PIN required"},
108   {6,	"PH-FSIM PIN required"},
109   {7,	"PH-FSIM PUK required"},
110   {10,	"SIM not inserted"},
111   {11,	"SIM PIN required"},
112   {12,	"SIM PUK required"},
113   {13,	"SIM failure"},
114   {14,	"SIM busy"},
115   {15,	"SIM wrong"},
116   {16,	"Incorrect password"},
117   {17,	"SIM PIN2 required"},
118   {18,	"SIM PUK2 required"},
119   {20,	"Memory full"},
120   {21,	"Invalid index"},
121   {22,	"Not found"},
122   {23,	"Memory failure"},
123   {24,	"Text string too long"},
124   {25,	"Invalid characters in text string"},
125   {26,	"Dial string too long"},
126   {27,	"Invalid characters in dial string"},
127   {30,	"No network service"},
128   {31,	"Network timeout"},
129   {32,	"Network not allowed - emergency calls only"},
130   {40,	"Network personalisation PIN required"},
131   {41,	"Network personalisation PUK required"},
132   {42,	"Network subset personalisation PIN required"},
133   {43,	"Network subset personalisation PUK required"},
134   {44,	"Service provider personalisation PIN required"},
135   {45,	"Service provider personalisation PUK required"},
136   {46,	"Corporate personalisation PIN required"},
137   {47,	"Corporate personalisation PUK required"},
138   {48,  "PH-SIM PUK required"},
139 
140   {100, "Unknown"},
141 
142   {103, "Illegal MS"},
143   {106, "Illegal ME"},
144   {107, "GPRS services not allowed"},
145   {111, "PLMN not allowed"},
146   {112, "Location area not allowed"},
147   {113, "Roaming not allowed in this location area"},
148   {126, "Operation temporary not allowed"},
149   {132, "Service operation not supported"},
150   {133, "Requested service option not subscribed"},
151   {134, "Service option temporary out of order"},
152   {148, "Unspecified GPRS error"},
153   {149, "PDP authentication failure"},
154   {150, "Invalid mobile class"},
155 
156   {256, "Operation temporarily not allowed"},
157   {257, "Call barred"},
158   {258, "Phone is busy"},
159   {259, "User abort"},
160   {260, "Invalid dial string"},
161   {261, "SS not executed"},
162   {262, "SIM Blocked"},
163   {263, "Invalid block"},
164 
165   {515, "Device busy"},
166 
167   {772, "SIM powered down"}
168 
169 };
170 
171 _gsm_general_error gsm_cms_errors[] =
172 {
173   // Table 8.4/GSM 04.11 (part 1):
174   {1,	"Unassigned (unallocated) number"},
175   {8,	"Operator determined barring"},
176   {10,	"Call barred"},
177   {21,	"Short message transfer rejected"},
178   {27,	"Destination out of order"},
179   {28,	"Unindentified subscriber"},
180   {29,	"Facility rejected"},
181   {30,	"Unknown subscriber"},
182   {38,	"Network out of order"},
183   {41,	"Temporary failure"},
184   {42,	"Congestion"},
185   {47,	"Recources unavailable, unspecified"},
186   {50,	"Requested facility not subscribed"},
187   {69,	"Requested facility not implemented"},
188   {81,	"Invalid short message transfer reference value"},
189   {95,	"Semantically incorrect message"},
190   {96,	"Invalid mandatory information"},
191   {97,	"Message type non-existent or not implemented"},
192   {98,	"Message not compatible with short message protocol state"},
193   {99,	"Information element non-existent or not implemented"},
194   {111,	"Protocol error, unspecified"},
195   {127,	"Internetworking , unspecified"},
196   // Table 8.4/GSM 04.11 (part 2):
197   {22,	"Memory capacity exceeded"},
198   // GSM 03.40 subclause 9.2.3.22 values.
199   {128,	"Telematic internetworking not supported"},
200   {129,	"Short message type 0 not supported"},
201   {130,	"Cannot replace short message"},
202   {143,	"Unspecified TP-PID error"},
203   {144,	"Data code scheme (alphabet) not supported"},
204   {145,	"Message class not supported"},
205   {159,	"Unspecified TP-DCS error"},
206   {160,	"Command cannot be actioned"},
207   {161,	"Command unsupported"},
208   {175,	"Unspecified TP-Command error"},
209   {176,	"Transfer Protocol Data Unit (TPDU) not supported"},
210   {192,	"Service Center (SC) busy"},
211   {193,	"No SC subscription"},
212   {194,	"SC System failure"},
213   {195,	"Invalid Short Message Entity (SME) address"},
214   {196,	"Destination SME barred"},
215   {197,	"SM Rejected-Duplicate SM"},
216   {198,	"Validity Period Format (TP-VPF) not supported"},
217   {199,	"Validity Period) TP-VP not supported"},
218   {208,	"SIM SMS Storage full"},
219   {209,	"No SMS Storage capability in SIM"},
220   {210,	"Error in MS"},
221   {211,	"Memory capacity exceeded"},
222   {212,	"Sim Application Toolkit busy"},
223   {213,	"SIM data download error"},
224   {255,	"Unspecified error cause"},
225   // 3GPP TS 27.005 subclause 3.2.5 values /3/.
226   {300,	"ME Failure"},
227   {301,	"SMS service of ME reserved"},
228   {302,	"Operation not allowed"},
229   {303,	"Operation not supported"},
230   {304,	"Invalid PDU mode parameter"},
231   {305,	"Invalid Text mode parameter"},
232   {310,	"(U)SIM not inserted"},
233   {311,	"(U)SIM PIN required"},
234   {312,	"PH-(U)SIM PIN required"},
235   {313,	"(U)SIM failure"},
236   {314,	"(U)SIM busy"},
237   {315,	"(U)SIM wrong"},
238   {316,	"(U)SIM PUK required"},
239   {317,	"(U)SIM PIN2 required"},
240   {318,	"(U)SIM PUK2 required"},
241   {320,	"Memory failure"},
242   {321,	"Invalid memory index"},
243   {322,	"Memory full"},
244   {330,	"SMSC address unknown"},
245   {331,	"No network service"},
246   {332,	"Network timeout"},
247   {340,	"No +CNMA acknowledgement expected"},
248   {500,	"Unknown error"},
249 
250   // 3.1.5: This error occurs when you try to send a message and the module is receiving another one at the same time.
251   // This causes a collision in the message transfer protocol resulting in failure in sending the SMS.
252   // Sometimes, +CMS ERROR: 512 may also occur when the module is receiving weak signal and is loosing connection.
253   {512, "MM establishment failure / weak signal, loosing connection"},
254 
255   // 3.1.5: ack for 28s after transmission or 42s after channel establishment
256   {513, "Lower layer failure: receiving of an acknowledgement timed out or lost the radio link."},
257 
258   // 3.1.5:
259   {514, "Network error. Congestion in the network."},
260 
261   {515, "Please wait, service is not available, init in progress"}
262 };
263 
get_gsm_cme_error(int code)264 char *get_gsm_cme_error(int code)
265 {
266   int i;
267   int m = sizeof gsm_cme_errors / sizeof *gsm_cme_errors;
268 
269   for (i = 0; i < m; i++)
270     if (code == gsm_cme_errors[i].code)
271       return gsm_cme_errors[i].text;
272 
273   return "";
274 }
275 
get_gsm_cms_error(int code)276 char *get_gsm_cms_error(int code)
277 {
278   int i;
279   int m = sizeof gsm_cms_errors / sizeof *gsm_cms_errors;
280 
281   for (i = 0; i < m; i++)
282     if (code == gsm_cms_errors[i].code)
283       return gsm_cms_errors[i].text;
284 
285   return "";
286 }
287 
get_gsm_error(char * answer)288 char *get_gsm_error(char *answer)
289 {
290   char *p;
291 
292   if (answer && *answer)
293   {
294     if ((p = strstr(answer, "+CME ERROR: ")))
295       return get_gsm_cme_error(atoi(p +12));
296     if ((p = strstr(answer, "+CMS ERROR: ")))
297       return get_gsm_cms_error(atoi(p +12));
298   }
299 
300   return "";
301 }
302 
get_read_timeout(char * keyword)303 int get_read_timeout(char *keyword)
304 {
305   int i;
306   int m = sizeof read_timeouts / sizeof *read_timeouts;
307   int result = 1;
308 
309   if (!keyword)
310     return 0;
311 
312   for (i = 0; i < m; i++)
313     if (!strcmp(keyword, read_timeouts[i].keyword))
314       result = read_timeouts[i].value;
315 
316   // Accept direct value:
317   if ((i = atoi(keyword)) > 0)
318     result = i;
319 
320   if (log_read_timing)
321     writelogfile(LOG_DEBUG, 0, "read_timeout for %s is %i sec", keyword, DEVICE.read_timeout * result);
322 
323   return result;
324 }
325 
set_read_timeout(char * error,int size_error,char * keyword,int value)326 int set_read_timeout(char *error, int size_error, char *keyword, int value)
327 {
328   int result = 0;
329   int i;
330   int m = sizeof read_timeouts / sizeof *read_timeouts;
331 
332   *error = 0;
333 
334   for (i = 0; i < m; i++)
335     if (!strcmp(keyword, read_timeouts[i].keyword))
336       break;
337 
338   if (i < m)
339   {
340     if (value < 1)
341       snprintf(error, size_error, "Cannot set read_timeout_%s to less than 1.", keyword);
342     else
343     {
344       read_timeouts[i].value = value;
345       result = 1;
346     }
347   }
348   else
349     snprintf(error, size_error, "Unknown setting read_timeout_%s.", keyword);
350 
351   return result;
352 }
353 
log_read_timeouts(int level)354 void log_read_timeouts(int level)
355 {
356   int i;
357   int m = sizeof read_timeouts / sizeof *read_timeouts;
358 
359   writelogfile(level, 0, "Using read_timeout %i seconds.", DEVICE.read_timeout);
360 
361   for (i = 0; i < m; i++)
362     writelogfile(level, 0, "Using read_timeout_%s %i * read_timeout = %i seconds. %s",
363                  read_timeouts[i].keyword, read_timeouts[i].value,
364                  read_timeouts[i].value * DEVICE.read_timeout,
365                  read_timeouts[i].comment);
366 
367 }
368 
explain_csq_buffer(char * buffer,int short_form,int ssi,int ber,int signal_quality_ber_ignore)369 char *explain_csq_buffer(char *buffer, int short_form, int ssi, int ber, int signal_quality_ber_ignore)
370 {
371 
372   strcpy(buffer, (short_form)? "ssi: " : "Signal Strength Indicator: ");
373   if (ssi == 99 || ssi > 31 || ssi < 0)
374     strcat(buffer, (short_form)? "??" : "not present of not measurable");
375   else
376   {
377     // 3.1.12: explain level:
378     int dbm;
379     char *level = "";
380 
381     dbm = -113 + 2 * ssi;
382 
383     if (dbm <= -95)
384       level = " (Marginal)"; // Marginal - Levels of -95dBm or lower.
385     else if (dbm <= -85)
386       level = " (Workable)"; // Workable under most conditions - Levels of -85dBm to -95dBm.
387     else if (dbm <= -75)
388       level = " (Good)"; // Good - Levels between -75dBm and -85dBm.
389     else
390       level = " (Excellent)"; // Excellent - levels above -75dBm.
391 
392     if (short_form)
393       sprintf(strchr(buffer, 0), "%i dBm%s", dbm, level);
394     else
395       sprintf(strchr(buffer, 0), "(%d,%d) %i dBm%s%s", ssi, ber, dbm, level, (ssi == 0)? " or less" : "");
396   }
397 
398   if (!signal_quality_ber_ignore)
399   {
400     strcat(buffer, (short_form)? ", ber: " : ", Bit Error Rate: ");
401     switch (ber)
402     {
403       case 0:
404         strcat(buffer, (short_form)? "< 0.2 %" : "less than 0.2 %");
405         break;
406 
407       case 1:
408         strcat(buffer, "0.2 - 0.4 %");
409         break;
410 
411       case 2:
412         strcat(buffer, "0.4 - 0.8 %");
413         break;
414 
415       case 3:
416         strcat(buffer, "0.8 - 1.6 %");
417         break;
418 
419       case 4:
420         strcat(buffer, "1.6 - 3.2 %");
421         break;
422 
423       case 5:
424         strcat(buffer, "3.2 - 6.4 %");
425         break;
426 
427       case 6:
428         strcat(buffer, "6.4 - 12.8 %");
429         break;
430 
431       case 7:
432         strcat(buffer, (short_form)? "> 12.8 %" : "more than 12.8 %");
433         break;
434 
435       default:
436         strcat(buffer, (short_form)? "??" : "not known or not detectable");
437         break;
438     }
439   }
440 
441   return buffer;
442 }
443 
explain_csq(int loglevel,int short_form,char * answer,int signal_quality_ber_ignore)444 void explain_csq(int loglevel, int short_form, char *answer, int signal_quality_ber_ignore)
445 {
446   int ssi;
447   int ber = 99;
448   char *p;
449   char buffer[1024];
450 
451   if (strstr(answer, "ERROR"))
452     return;
453 
454   // 3.1.12: Allow "echo on":
455   //if (strncmp(answer, "+CSQ:", 5))
456   //  return;
457   if (!(p = strstr(answer, "+CSQ:")))
458     return;
459 
460   //ssi = atoi(answer +5);
461   ssi = atoi(p +5);
462   //if ((p = strchr(answer, ',')))
463   if ((p = strchr(p, ',')))
464     ber = atoi(p +1);
465 
466   explain_csq_buffer(buffer, short_form, ssi, ber, signal_quality_ber_ignore);
467 
468   writelogfile0(loglevel, 0, buffer);
469 }
470 
write_to_modem(char * command,int timeout,int log_command,int print_error)471 int write_to_modem(char *command, int timeout, int log_command, int print_error)
472 {
473   int status=0;
474   int timeoutcounter=0;
475   int x=0;
476   struct termios tio;
477 
478   if (command && command[0])
479   {
480     if (log_command)
481       writelogfile(LOG_DEBUG, 0, "-> %s",command);
482 
483     // 3.1.9:
484     if (DEVICE.send_handshake_select)
485     {
486       size_t r = 0, bs, n;
487       ssize_t got;
488       fd_set writefds;
489 
490       n = strlen(command);
491       while (n > 0)
492       {
493         bs = (DEVICE.send_delay < 1) ? n : 1;
494         got = write(modem_handle, command + r, bs);
495         if (got < 0)
496         {
497           if (errno == EINTR)
498             continue;
499 
500           if (errno != EAGAIN)
501           {
502             writelogfile0(LOG_ERR, 1, tb_sprintf("write_to_modem: error %d: %s", errno, strerror(errno)));
503             alarm_handler0(LOG_ERR, tb);
504             return 0;
505           }
506 
507           // 3.1.16beta: Do not log "device busy":
508           //writelogfile0(LOG_DEBUG, 0, tb_sprintf("write_to_modem: device busy, waiting"));
509           //alarm_handler0(LOG_DEBUG, tb);
510 
511           FD_ZERO(&writefds);
512           FD_SET(modem_handle, &writefds);
513           select(modem_handle + 1, NULL, &writefds, NULL, NULL);
514           continue;
515         }
516 
517         n -= got;
518         r += got;
519 
520         if (DEVICE.send_delay > 0)
521           usleep_until(time_usec() + DEVICE.send_delay * 1000);
522 
523         tcdrain(modem_handle);
524       }
525     }
526     else
527     {
528       tcgetattr(modem_handle, &tio);
529 
530       if (!DEVICE_IS_SOCKET && tio.c_cflag & CRTSCTS)
531       {
532         ioctl(modem_handle, TIOCMGET, &status);
533         while (!(status & TIOCM_CTS))
534         {
535           usleep_until(time_usec() + 100000);
536           timeoutcounter++;
537           ioctl(modem_handle, TIOCMGET, &status);
538           if (timeoutcounter>timeout)
539           {
540             if (print_error)
541               printf("\nModem is not clear to send.\n");
542             else
543             {
544               writelogfile0(LOG_ERR, 1, tb_sprintf("Modem is not clear to send"));
545               alarm_handler0(LOG_ERR, tb);
546             }
547             return 0;
548           }
549         }
550       }
551 
552       // 3.1.5:
553       if (DEVICE.send_delay < 1)
554       {
555         if ((size_t)write(modem_handle, command, strlen(command)) != strlen(command))
556         {
557           writelogfile0(LOG_ERR, 1, tb_sprintf("Could not send string, cause: %s", strerror(errno)));
558           alarm_handler0(LOG_ERR, tb);
559           return 0;
560         }
561 
562         if (DEVICE.send_delay < 0)
563           tcdrain(modem_handle);
564       }
565       else
566       {
567         for(x=0;(size_t)x<strlen(command);x++)
568         {
569           if (write(modem_handle, command +x, 1) < 1)
570           {
571             if (print_error)
572               printf("\nCould not send character %c, cause: %s\n",command[x],strerror(errno));
573             else
574             {
575               writelogfile0(LOG_ERR, 1, tb_sprintf("Could not send character %c, cause: %s", command[x], strerror(errno)));
576               alarm_handler0(LOG_ERR, tb);
577             }
578             return 0;
579           }
580           usleep_until(time_usec() + DEVICE.send_delay *1000);
581           tcdrain(modem_handle);
582         }
583       }
584     }
585   }
586 
587   return 1;
588 }
589 
590 // 3.1.12:
negotiate_with_telnet(char * answer,int * len)591 void negotiate_with_telnet(char *answer, int *len)
592 {
593 #define IAC  '\xFF' /* Interpret as command: */
594 #define DONT '\xFE' /* You are not to use option */
595 #define DO   '\xFD' /* Please, you use option */
596 #define WONT '\xFC' /* I won't use option */
597 #define WILL '\xFB' /* I will use option */
598 #define SB   '\xFA' /* Interpret as subnegotiation */
599 #define SE   '\xF0' /* End sub negotiation */
600 
601   char *title = "Telnet";
602   int idx;
603   int i;
604   int count;
605   char response[128];
606   char command;
607   int got_option;
608   char option;
609   const char *eol = DEVICE.telnet_crlf ? "\r\n" : "\n";
610 
611   idx = 0;
612   while (idx < *len)
613   {
614     if (answer[idx] == IAC && idx +1 < *len)
615     {
616       *response = 0;
617       count = 3;
618       command = answer[idx +1];
619       got_option = idx +2 < *len;
620       option = (got_option)? answer[idx +2] : 0;
621 
622       if (command == DO && got_option)
623       {
624         snprintf(response, sizeof(response), "%c%c%c", IAC, WONT, option);
625         writelogfile(LOG_DEBUG, 0, "%s: Got DO for %i (0x%02X), answering WONT.", title, (int)option, option);
626       }
627       else if (command == WILL && got_option)
628       {
629         snprintf(response, sizeof(response), "%c%c%c", IAC, DONT, option);
630         writelogfile(LOG_DEBUG, 0, "%s: Got WILL for %i (0x%02X), answering DONT.", title, (int)option, option);
631       }
632       else if (command == WONT && got_option)
633       {
634         writelogfile(LOG_DEBUG, 0, "%s: Got WONT for %i (0x%02X), ignoring.", title, (int)option, option);
635       }
636       // 3.1.16beta: Fixed a Telnet subnegotiation processing method.
637       //else if (command == SB && got_option)
638       //{
639       //  writelogfile(LOG_DEBUG, 0, "%s: Got SB for %i (0x%02X), ignoring.", title, (int)option, option);
640       //  count = 4;
641       //}
642       //else if (command == SE)
643       //{
644       //  writelogfile(LOG_DEBUG, 0, "%s: Got SE, ignoring.", title);
645       //  count = 2;
646       //}
647       else if (command == SB)
648       {
649         char commands[1024];
650 
651         *commands = 0;
652 
653         count = 2;
654         for (i = idx +2; i < *len; i++)
655         {
656           if (answer[i] == IAC && answer[i +1] == SE)
657           {
658             writelogfile(LOG_DEBUG, 0, "%s: Got subnegotiation for %i (0x%02X): %s - ignoring.", title, (int)option, option, commands);
659             count = i +2 -idx;
660             break;
661           }
662 
663           if (i > idx +2 && strlen(commands) < sizeof(commands) - 6)
664             sprintf(strchr(commands, 0), "%s%i (0x%02X)", (*commands)? ", " : "", (int)answer[i], answer[i]);
665         }
666       }
667 
668       if (*response)
669         if ((size_t)write(modem_handle, response, strlen(response)) != strlen(response))
670           writelogfile(LOG_ERR, 1, "%s: Failed to send response.", title);
671 
672       for (i = idx; i +count < *len; i++)
673         answer[i] = answer[i +count];
674 
675       *len -= count;
676     }
677     else
678       idx++;
679   }
680 
681   answer[*len] = 0;
682 
683   // 3.1.16beta: Now remove 0x00's from the answer:
684   if (strlen(answer) < (size_t)*len)
685   {
686     int i, j, l;
687 
688     for (i = 0, j = 0, l = *len; i < *len; i++)
689     {
690       if (answer[i] == '\0')
691       {
692         l--;
693         continue;
694       }
695 
696       if (i > j)
697         answer[j] = answer[i];
698       j++;
699     }
700 
701     answer[l] = 0;
702     *len = l;
703   }
704 
705   // 3.1.16beta: If login/password or cmd is sent, remove the prompt.
706   char *p;
707   int l = 0;
708   char *info = 0;
709 
710   *response = 0;
711   if (DEVICE.telnet_login_prompt[0] && (p = strstr(answer, DEVICE.telnet_login_prompt)) && DEVICE.telnet_login[0])
712   {
713     if (DEVICE.telnet_login_prompt_ignore[0] == 0 || !strstr(answer, DEVICE.telnet_login_prompt_ignore))
714     {
715       snprintf(response, sizeof(response), "%s%s", DEVICE.telnet_login, eol);
716       l = strlen(DEVICE.telnet_login_prompt);
717       info = "login";
718     }
719   }
720   else if (DEVICE.telnet_password_prompt[0] && (p = strstr(answer, DEVICE.telnet_password_prompt)) && DEVICE.telnet_password[0])
721   {
722     snprintf(response, sizeof(response), "%s%s", DEVICE.telnet_password, eol);
723     l = strlen(DEVICE.telnet_password_prompt);
724     info = "password";
725   }
726   else if (DEVICE.telnet_cmd_prompt[0] && (p = strstr(answer, DEVICE.telnet_cmd_prompt)) && DEVICE.telnet_cmd[0])
727   {
728     snprintf(response, sizeof(response), "%s%s", DEVICE.telnet_cmd, eol);
729     l = strlen(DEVICE.telnet_cmd_prompt);
730     info = DEVICE.telnet_cmd;
731   }
732 
733   if (l)
734   {
735     for (i = (int)(p -answer) +l; i <= *len; i++)
736       answer[i -l] = answer[i];
737     *len -= l;
738   }
739 
740   if (*response)
741   {
742     if ((size_t)write(modem_handle, response, strlen(response)) != strlen(response))
743       writelogfile(LOG_ERR, 1, "%s: Failed to send response: %s", title, info);
744     else
745       writelogfile(LOG_DEBUG, 0, "%s: Sent %s", title, info);
746   }
747 
748 #undef IAC
749 #undef DONT
750 #undef DO
751 #undef WONT
752 #undef WILL
753 #undef SB
754 #undef SE
755 }
756 
read_from_modem(char * answer,int max,int timeout)757 int read_from_modem(char *answer, int max, int timeout)
758 {
759 
760   return read_from_modem0(answer, max, timeout, 0, 0);
761 }
762 
read_from_modem0(char * answer,int max,int timeout,regex_t * re,char * expect)763 int read_from_modem0(char *answer, int max, int timeout, regex_t *re, char *expect)
764 {
765   int count=0;
766   int got=0;
767   int timeoutcounter=0;
768   int success=0;
769   int toread=0;
770 
771   // Cygwin does not support TIOC functions, so we cannot use it.
772   // ioctl(modem,FIONREAD,&available);	// how many bytes are available to read?
773 
774   // 3.1.16beta: Cannot use strlen(answer) in the loop when 0x00's are not removed here.
775   int answer_length = strlen(answer);
776 
777   // 3.1.16beta2: If regular expression is defined, poll faster and stop as soon as regex matches.
778   char *check_answer = NULL;
779   int i;
780   int sleep_time = 100000;
781   int poll_faster = DEVICE.poll_faster;
782 
783   if (re && poll_faster > 0)
784   {
785     check_answer = (char *)malloc(max);
786     timeout *= poll_faster;
787     sleep_time /= poll_faster;
788   }
789 
790   if (log_read_timing)
791     writelogfile(LOG_DEBUG, 0, "read_from_modem, %i, '%s', %s", timeout, answer, (expect)? expect : "");
792 
793   do
794   {
795     if (check_answer && success)
796     {
797       *check_answer = '\0';
798       for (i = 0; i < answer_length; i++)
799         check_answer[i] = (answer[i] == '\0')? '\n' : answer[i];
800       check_answer[i] = '\0';
801       if (log_read_timing)
802         writelogfile(LOG_DEBUG, 0, "answer now: %s", check_answer);
803       if (regexec(re, check_answer, (size_t) 0, NULL, 0) == 0)
804       {
805         if (log_read_timing)
806           writelogfile(LOG_DEBUG, 0, "answer is what expected, go ahead");
807         break;
808       }
809     }
810 
811     // How many bytes do I want to read maximum? Not more than buffer size -1 for termination character.
812     count = answer_length; //count=strlen(answer);
813     toread=max-count-1;
814     if (toread<=0)
815       break;
816     // read data
817     got = read(modem_handle, answer +count, toread);
818 
819     if (log_read_timing)
820       writelogfile(LOG_DEBUG, 0, "read, got %i", got);
821 
822     // if nothing received ...
823     if (got<=0)
824     {
825       // wait a litte bit and then repeat this loop
826       got=0;
827       // 3.1.16beta: Do not sleep if the loop will not continue:
828       timeoutcounter++;
829       if (timeoutcounter < timeout)
830       {
831         if (log_read_timing)
832           writelogfile(LOG_DEBUG, 0, "sleeping %i us (%i)", sleep_time, timeoutcounter);
833         usleep_until(time_usec() + sleep_time /*100000*/);
834       }
835     }
836     else
837     {
838       if (log_read_from_modem)
839       {
840         char tmp[SIZE_LOG_LINE];
841         int i;
842 
843         snprintf(tmp, sizeof(tmp), "read_from_modem: count=%i, got=%i:", count, got);
844         for (i = count; i < count + got; i++)
845         {
846           if (strlen(tmp) >= sizeof(tmp) - 6)
847           {
848             strcpy(tmp, "ERROR: too much data");
849             break;
850           }
851 
852           sprintf(strchr(tmp, 0), " %02X[%c]", (unsigned char) answer[i], ((unsigned char) answer[i] >= ' ') ? answer[i] : '.');
853         }
854 
855         writelogfile0(LOG_CRIT, 0, tmp);
856       }
857 
858       // restart timout counter
859       timeoutcounter=0;
860       // append a string termination character
861       answer[count+got]=0;
862       answer_length = count +got;
863       success=1;
864 
865       // 3.1.12: With Multitech network modem (telnet) there can be 0x00 inside the string:
866       // 3.1.16beta: Clean the string after telnet commands are handled, moved to negotiate_with_telnet.
867       //if (strlen(answer) < (size_t)count + got)
868       //{
869       //  int i, j, len;
870       //
871       //  len = count + got;
872       //  j = 0;
873       //  for (i = 0; i < count + got; i++)
874       //  {
875       //    if (answer[i] == '\0')
876       //    {
877       //      len--;
878       //      continue;
879       //    }
880       //
881       //    if (i > j)
882       //      answer[j] = answer[i];
883       //    j++;
884       //  }
885       //
886       //  answer[len] = 0;
887       //}
888 
889     }
890   }
891   while (timeoutcounter < timeout);
892 
893   // 3.1.12:
894   if (success && DEVICE_IS_SOCKET)
895   {
896     count += got;
897     negotiate_with_telnet(answer, &count);
898   }
899 
900   free(check_answer);
901 
902   return success;
903 }
904 
905 // 3.1.1:
change_crlf(char * str,char ch)906 char *change_crlf(char *str, char ch)
907 {
908   char *p;
909 
910   while ((p = strchr(str, '\r')))
911     *p = ch;
912   while ((p = strchr(str, '\n')))
913     *p = ch;
914 
915   return str;
916 }
917 
detect_routed_message(char * answer)918 int detect_routed_message(char *answer)
919 {
920   int result = 0;
921   // keywords must have same length:
922   int keyword_length = 5;
923   char *keyword    = "+CMT:";
924   char *keyword_sr = "+CDS:";
925   char *p;
926   char *term;
927   int pdu_length;
928   int can_handle;
929   int is_sr;
930   int send_ack = 0;
931   char *p1;
932   char *p2;
933 
934   if (*answer)
935   {
936     // We can have answer which contains only routed message, or there can be answer like:
937     // +CPMS: "SM",0,20,"SM",0,20,"SM",0,20 OK ... +CMT: ,59 07915348150110...
938 
939     is_sr = 0;
940     if (!(p1 = strstr(answer, keyword)))
941       if ((p1 = strstr(answer, keyword_sr)))
942         is_sr = 1;
943 
944     if (p1)
945     {
946       if (!is_sr || !DEVICE.using_routed_status_report)
947         writelogfile(LOG_ERR, DEVICE.unexpected_input_is_trouble, "Routed %s detected:\n%s", (is_sr) ? "status report" : "message", p1);
948 
949       if (DEVICE.routed_status_report_cnma)
950         send_ack = 1;
951 
952       while (p1)
953       {
954         result++;
955         can_handle = 0;
956 
957         if ((term = strchr(p1, '\r')))
958         {
959           p = term +1;
960           if (*p == '\n')
961             p++;
962           if (octet2bin(p) >= 0)
963           {
964             if ((term = strchr(p, '\r')))
965             {
966               // Original answer remains intact. Count the length and check that PDU does not contain delimiter character:
967               pdu_length = (int)(term - p);
968               p2 = strchr(p, ',');
969               if (!p2 || p2 > term)
970               {
971                 // PDU is handled later. If it has some errors, explanation will be printed to the message file.
972 
973                 if (!routed_pdu_store)
974                 {
975                   if ((routed_pdu_store = (char *)malloc(pdu_length +2)))
976                     *routed_pdu_store = 0;
977                 }
978                 else
979                   routed_pdu_store = (char *)realloc((void *)routed_pdu_store, strlen(routed_pdu_store) +pdu_length +2);
980 
981                 if (routed_pdu_store)
982                 {
983                   // For easier handling, delimiter in routed_pdu_store is '\n'.
984                   sprintf(strchr(routed_pdu_store, 0), "%.*s\n", pdu_length, p);
985                   can_handle = 1;
986                 }
987               }
988             }
989           }
990         }
991 
992         p = (is_sr)? "status report" : "message";
993         if (can_handle)
994         {
995           if (is_sr && DEVICE.using_routed_status_report)
996             writelogfile0(LOG_INFO, 0, tb_sprintf("Saved routed %s for later handling.", p));
997           else
998           {
999             writelogfile0(LOG_ERR, 0, tb_sprintf("Saved routed %s for later handling. However, you MUST DISABLE %s routing with modem settings.", p, p));
1000             alarm_handler0(LOG_ERR, tb);
1001           }
1002         }
1003         else
1004         {
1005           writelogfile0(LOG_ERR, 0, tb_sprintf("Cannot handle this routed %s. You MUST DISABLE %s routing with modem settings.", p, p));
1006           alarm_handler0(LOG_ERR, tb);
1007         }
1008 
1009         is_sr = 0;
1010         p = p1 +keyword_length;
1011         if (!(p1 = strstr(p, keyword)))
1012           if ((p1 = strstr(p, keyword_sr)))
1013             is_sr = 1;
1014       }
1015     }
1016 
1017     // TODO: more than one ack if more than one messsage received?
1018     if (send_ack)
1019     {
1020       char loganswer[1024];
1021 
1022       writelogfile(LOG_DEBUG, 0, "Sending acknowledgement");
1023       write_to_modem("AT+CNMA\r", 30, 1, 0);
1024 
1025       *loganswer = 0;
1026       read_from_modem(loganswer, sizeof(loganswer), 2);
1027       if (log_single_lines)
1028         change_crlf(loganswer, ' ');
1029 
1030       writelogfile(LOG_DEBUG, 0, "<- %s", loganswer);
1031     }
1032   }
1033 
1034   return result;
1035 }
1036 
do_hangup(char * answer)1037 void do_hangup(char *answer)
1038 {
1039 
1040 	if (DEVICE.hangup_incoming_call == 1 || (DEVICE.hangup_incoming_call == -1 && hangup_incoming_call == 1) || DEVICE.phonecalls == 2)
1041 	{
1042 		char *command = "AT+CHUP\r";
1043 		char tmpanswer[1024];
1044 		int timeoutcounter;
1045 
1046 		if (DEVICE.voicecall_hangup_ath == 1 || (DEVICE.voicecall_hangup_ath == -1 && voicecall_hangup_ath == 1))
1047 			command = "ATH\r";
1048 
1049 		writelogfile(LOG_NOTICE, 0, "Ending incoming call: %s", answer);
1050 
1051 		write_to_modem(command, 30, 1, 0);
1052 
1053 		timeoutcounter = 0;
1054 		*tmpanswer = 0;
1055 
1056 		do
1057 		{
1058 			read_from_modem(tmpanswer, sizeof(tmpanswer), 2);
1059 
1060 			// Any answer is ok:
1061 			if (*tmpanswer)
1062 				break;
1063 
1064 			timeoutcounter++;;
1065 		}
1066 		while (timeoutcounter < 5);
1067 
1068 		if (!log_unmodified)
1069 		{
1070 			cutspaces(tmpanswer);
1071 			cut_emptylines(tmpanswer);
1072 
1073 			if (log_single_lines)
1074 				change_crlf(tmpanswer, ' ');
1075 		}
1076 		writelogfile(LOG_DEBUG, 0, "<- %s", tmpanswer);
1077 
1078 		if (DEVICE.communication_delay > 0)
1079 			usleep_until(time_usec() + DEVICE.communication_delay * 1000);
1080 	}
1081 }
1082 
handlephonecall_clip(char * answer)1083 int handlephonecall_clip(char *answer)
1084 {
1085 	int result = 0;
1086 	char *p, *e_start, *e_end;
1087 	int len;
1088 	char entry_number[SIZE_PB_ENTRY];
1089 	//int entry_type;
1090 
1091 	if (DEVICE.phonecalls != 2)
1092 		return 0;
1093 
1094 	*entry_number = 0;
1095 	//entry_type = 0;
1096 
1097 	if ((p = strstr(answer, "+CLIP:")))
1098 	{
1099 		do_hangup(answer);
1100 		result = -1;
1101 
1102 		if ((e_start = strchr(p, '"')))
1103 		{
1104 			e_start++;
1105 			if ((e_end = strchr(e_start, '"')))
1106 			{
1107 		                if ((len = e_end -e_start) < SIZE_PB_ENTRY)
1108 				{
1109 					sprintf(entry_number, "%.*s", len, e_start);
1110 					cutspaces(entry_number);
1111 					if (*entry_number == '+')
1112 						strcpyo(entry_number, entry_number +1);
1113 
1114 					if (strlen(e_end) >= 3)
1115 					{
1116 						e_end += 2;
1117 						writelogfile(LOG_INFO, 0, "Got phonecall from %s", entry_number);
1118 						savephonecall(entry_number, atoi(e_end), "");
1119 						result = 1;
1120 					}
1121 				}
1122 			}
1123 		}
1124 
1125 		if (result == -1)
1126 		{
1127 			writelogfile0(LOG_ERR, 1, tb_sprintf("Error while trying to handle +CLIP."));
1128 			alarm_handler0(LOG_ERR, tb);
1129 		}
1130 	}
1131 
1132 	return result;
1133 }
1134 
ignore_unexpected_input(char * answer)1135 int ignore_unexpected_input(char *answer)
1136 {
1137   int result = 0;
1138   char *p;
1139 
1140   if (DEVICE.ignore_unexpected_input[0])
1141   {
1142     p = DEVICE.ignore_unexpected_input;
1143     while (*p && !result)
1144     {
1145       if (strstr(answer, p))
1146         result = 1;
1147       p = strchr(p, 0) + 1;
1148     }
1149   }
1150 
1151   return result;
1152 }
1153 
1154 // 3.1beta7: Not waiting any answer if answer is NULL. Return value is then 1/0.
1155 // 3.1.5: In case of timeout return value is -2.
1156 
put_command(char * command,char * answer,int max,char * timeout_count,char * expect)1157 int put_command(char *command, char *answer, int max, char *timeout_count, char *expect)
1158 {
1159 
1160   return put_command0(command, answer, max, timeout_count, expect, 0);
1161 }
1162 
put_command0(char * command,char * answer,int max,char * timeout_count,char * expect,int silent)1163 int put_command0(char *command, char *answer, int max, char *timeout_count, char *expect, int silent)
1164 {
1165   char loganswer[SIZE_LOG_LINE];
1166   time_t start_time; // 3.1.16beta2: Changed timeout counter to use time(0).
1167   regex_t re;
1168   int got_timeout = 0;
1169   int regex_allocated = 0;
1170   int timeout;
1171   int i;
1172   static unsigned long long last_command_ended = 0;
1173   int last_length;
1174   // 3.1.16beta:
1175   unsigned long long got_answer;
1176   unsigned long long write_started;
1177 
1178   if (DEVICE.communication_delay > 0)
1179     if (last_command_ended)
1180       usleep_until(last_command_ended +DEVICE.communication_delay *1000);
1181 
1182   // compile regular expressions
1183   if (expect && expect[0])
1184   {
1185     if (regcomp(&re, expect, REG_EXTENDED|REG_NOSUB) != 0)
1186     {
1187       fprintf(stderr, "Programming error: Expected answer %s is not a valid regepr\n", expect);
1188       writelogfile(LOG_CRIT, 1, "Programming error: Expected answer %s is not a valid regepr", expect);
1189       exit(1);
1190     }
1191     regex_allocated = 1;
1192   }
1193 
1194   // 3.1.5: Detect and handle routed message. Detect unexpected input.
1195   if ((DEVICE.incoming && DEVICE.detect_message_routing) || DEVICE.detect_unexpected_input)
1196   {
1197     if (log_read_timing)
1198       writelogfile(LOG_DEBUG, 0, "Detecting%s%s",
1199                    (DEVICE.incoming && DEVICE.detect_message_routing)? " message_routing" : "",
1200                    (DEVICE.detect_unexpected_input)? " unexpected_input" : "");
1201 
1202     *loganswer = 0;
1203     do
1204     {
1205       i = strlen(loganswer);
1206       read_from_modem(loganswer, sizeof(loganswer), 2);
1207     }
1208     while (strlen(loganswer) > (size_t)i);
1209 
1210     i = 0;
1211     if (DEVICE.incoming && DEVICE.detect_message_routing)
1212       i = detect_routed_message(loganswer);
1213 
1214     if (!i && *loganswer && DEVICE.detect_unexpected_input)
1215     {
1216       if (!log_unmodified)
1217       {
1218         cutspaces(loganswer);
1219         cut_emptylines(loganswer);
1220 
1221         if (log_single_lines)
1222           change_crlf(loganswer, ' ');
1223       }
1224 
1225       if (*loganswer)
1226       {
1227         // Some modems send unsolicited result code even when status report is stored for future
1228         // reading. This and SMS-DELIVER indication is not logged.
1229         if (!strstr(loganswer, "+CDSI:") && !strstr(loganswer, "+CMTI:"))
1230           if (!(strstr(loganswer, "+CLIP:") && DEVICE.phonecalls == 2))
1231             if (!(strstr(loganswer, "+CREG:") && get_loglevel() >= DEVICE.loglevel_lac_ci)) // 3.1.14.
1232               if (!ignore_unexpected_input(loganswer))  // 3.1.16beta2.
1233                 writelogfile(LOG_ERR, DEVICE.unexpected_input_is_trouble, "Unexpected input: %s", loganswer);
1234 
1235 	if (handlephonecall_clip(loganswer) != 1)
1236           if (strstr(loganswer, "RING") && DEVICE.phonecalls != 2)
1237             do_hangup(loganswer);
1238       }
1239     }
1240   }
1241 
1242   // clean input buffer
1243   // It seems that this command does not do anything because actually it
1244   // does not clear the input buffer.
1245   tcflush(modem_handle, TCIFLUSH);
1246 
1247   // 3.1.16beta:
1248   write_started = time_usec();
1249 
1250   // send command
1251   if (write_to_modem(command, 30, 1, 0) == 0)
1252   {
1253     t_sleep(errorsleeptime);
1254     // Free memory used by regexp
1255     if (regex_allocated)
1256       regfree(&re);
1257 
1258     last_command_ended = time_usec();
1259 
1260     return 0;
1261   }
1262 
1263   if (!answer)
1264   {
1265     if (!silent)
1266       writelogfile(LOG_DEBUG, 0, "Command is sent");
1267   }
1268   else
1269   {
1270     // 3.1.16beta:
1271     put_command_sent = time_usec();
1272 
1273     // read_timeout is in seconds.
1274     if (!timeout_count)
1275       timeout = 0;
1276     else
1277       timeout = DEVICE.read_timeout * get_read_timeout(timeout_count);
1278 
1279     if (!silent)
1280     {
1281       char tmp[64] = {0};
1282 
1283       if (log_response_time)
1284         snprintf(tmp, sizeof(tmp), "time %i ms ", (int)((put_command_sent - write_started) / 1000));
1285 
1286       writelogfile(LOG_DEBUG, 0, "%sCommand is sent, waiting for the answer. (%i)", tmp, timeout);
1287     }
1288 
1289     // 3.1.16beta2: Give some time to modem, before start reading (read_delay).
1290     if (DEVICE.read_delay > 0)
1291     {
1292       if (log_read_timing)
1293         writelogfile(LOG_DEBUG, 0, "Spending read_delay (%i ms)", DEVICE.read_delay);
1294       usleep_until(time_usec() + DEVICE.read_delay * 1000);
1295     }
1296 
1297     // wait for the modem-answer
1298     answer[0] = 0;
1299     got_timeout = 1;
1300     last_length = 0;
1301     start_time = time(0);
1302 
1303     do
1304     {
1305       if (regex_allocated)
1306         read_from_modem0(answer, max, 2, &re, expect);
1307       else
1308         read_from_modem(answer, max, 2);
1309 
1310       // check if it's the expected answer
1311       if (expect && expect[0] && (regexec(&re, answer, (size_t) 0, NULL, 0) == 0))
1312       {
1313         got_timeout = 0;
1314         put_command_timeouts = 0;
1315         break;
1316       }
1317 
1318       // 3.1.1: Some modem does not give "OK" in the answer for CPMS:
1319       // +CPMS: "SM",0,30,"SM",0,30,"SM",0,30
1320       if (strstr(answer, "+CPMS:"))
1321       {
1322         int i = 0;
1323         char *p = answer;
1324 
1325         while ((p = strchr(p +1, ',')))
1326           i++;
1327 
1328         if (i >= 8)
1329         {
1330           // 8 commas is enough
1331           got_timeout = 0;
1332           put_command_timeouts = 0;
1333           break;
1334         }
1335       }
1336       // ------------------------------------------------------------
1337 
1338       // 3.1.12: If got something from the modem, do not count timeout:
1339       i = strlen(answer);
1340       if (i != last_length)
1341       {
1342         last_length = i;
1343         start_time = time(0);
1344       }
1345     }
1346     // repeat until timeout
1347     while (time(0) - start_time < timeout);
1348 
1349     // 3.1.16beta:
1350     got_answer = time_usec();
1351 
1352     if (got_timeout)
1353     {
1354       put_command_timeouts++;
1355 
1356       // 3.1.16beta:
1357       //if (expect && expect[0])
1358       //  writelogfile(LOG_DEBUG, 1, "put_command expected %s, timeout occurred. %i.", expect, put_command_timeouts);
1359       if (expect && expect[0])
1360       {
1361         if (!terminate)
1362           writelogfile(LOG_DEBUG, 1, "%s answer, put_command expected %s, timeout occurred. %i.", (*answer)? "Incorrect" : "No", expect, put_command_timeouts);
1363         else
1364           writelogfile(LOG_DEBUG, 1, "%s answer, put_command expected %s, process is terminating. %i.", (*answer)? "Incorrect" : "No", expect, put_command_timeouts);
1365       }
1366     }
1367 
1368     if (DEVICE.incoming && DEVICE.detect_message_routing)
1369       detect_routed_message(answer);
1370 
1371     // 3.1.5: Some modems (like Westermo GDW-11) start answer with extra <CR><LF>, check and remove it:
1372     while (!got_timeout && !strncmp(answer, "\r\n", 2))
1373       strcpyo(answer, answer +2);
1374 
1375     // 3.1.4: error explanation should be included in the answer.
1376     if (!got_timeout && strstr(answer, "ERROR"))
1377     {
1378       char *p;
1379 
1380       p = get_gsm_error(answer);
1381       if (*p)
1382         if (max /*sizeof(answer)*/ -strlen(answer) > strlen(p) +3)
1383           sprintf(strchr(answer, 0), " (%s)", p);
1384     }
1385 
1386     snprintf(loganswer, sizeof(loganswer), "%s", answer);
1387 
1388     if (!log_unmodified)
1389     {
1390       cutspaces(loganswer);
1391       cut_emptylines(loganswer);
1392 
1393       if (log_single_lines)
1394         change_crlf(loganswer, ' ');
1395     }
1396 
1397     // 3.1.16beta:
1398     //writelogfile(LOG_DEBUG, 0, "<- %s", loganswer);
1399     if (log_response_time)
1400     {
1401       char tmp[64];
1402 
1403       snprintf(tmp, sizeof(tmp), "time %i ms ", (int)((got_answer - put_command_sent) / 1000));
1404       writelogfile(LOG_DEBUG, 0, "%s<- %s", tmp, loganswer);
1405     }
1406     else
1407       writelogfile(LOG_DEBUG, 0, "<- %s", loganswer);
1408 
1409     // 3.1.12: Check if the answer contains a phonecall:
1410     if (DEVICE.detect_unexpected_input)
1411     {
1412       if (handlephonecall_clip(loganswer) != 1)
1413         if (strstr(loganswer, "RING") && DEVICE.phonecalls != 2)
1414           do_hangup(loganswer);
1415     }
1416   }
1417 
1418   // Free memory used by regexp
1419   if (regex_allocated)
1420     regfree(&re);
1421 
1422   last_command_ended = time_usec();
1423 
1424   if (got_timeout)
1425     return -2;
1426   if (answer)
1427     return strlen(answer);
1428   return 1;
1429 }
1430 
setmodemparams()1431 void setmodemparams()
1432 {
1433   struct termios newtio;
1434   int baudrate;
1435 
1436   if (DEVICE_IS_SOCKET)
1437     return;
1438 
1439   bzero(&newtio, sizeof(newtio));
1440   newtio.c_cflag = CS8 | CLOCAL | CREAD | O_NDELAY | O_NONBLOCK;
1441   if (DEVICE.rtscts)
1442     newtio.c_cflag |= CRTSCTS;
1443   newtio.c_iflag = IGNPAR;
1444   newtio.c_oflag = 0;
1445   newtio.c_lflag = 0;
1446   newtio.c_cc[VTIME] = 0;
1447   newtio.c_cc[VMIN] = 0;
1448 
1449   baudrate = DEVICE.baudrate;
1450 
1451   switch (baudrate)
1452   {
1453 #ifdef B50
1454     case 50: baudrate = B50; break;
1455 #endif
1456 #ifdef B75
1457     case 75: baudrate = B75; break;
1458 #endif
1459 #ifdef B110
1460     case 110: baudrate = B110; break;
1461 #endif
1462 #ifdef B134
1463     case 134: baudrate = B134; break;
1464 #endif
1465 #ifdef B150
1466     case 150: baudrate = B150; break;
1467 #endif
1468 #ifdef B200
1469     case 200: baudrate = B200; break;
1470 #endif
1471     case 300: baudrate = B300; break;
1472 #ifdef B600
1473     case 600: baudrate = B600; break;
1474 #endif
1475     case 1200: baudrate = B1200; break;
1476 #ifdef B1800
1477     case 1800: baudrate = B1800; break;
1478 #endif
1479     case 2400: baudrate = B2400; break;
1480 #ifdef B4800
1481     case 4800: baudrate = B4800; break;
1482 #endif
1483     case 9600: baudrate = B9600; break;
1484     case 19200: baudrate = B19200; break;
1485     case 38400: baudrate = B38400; break;
1486 #ifdef B57600
1487     case 57600: baudrate = B57600; break;
1488 #endif
1489 #ifdef B115200
1490     case 115200: baudrate = B115200; break;
1491 #endif
1492 #ifdef B230400
1493     case 230400: baudrate = B230400; break;
1494 #endif
1495 #ifdef B460800
1496     case 460800: baudrate = B460800; break;
1497 #endif
1498 #ifdef B500000
1499     case 500000: baudrate = B500000; break;
1500 #endif
1501 #ifdef B576000
1502     case 576000: baudrate = B576000; break;
1503 #endif
1504 #ifdef B921600
1505     case 921600: baudrate = B921600; break;
1506 #endif
1507 #ifdef B1000000
1508     case 1000000: baudrate = B1000000; break;
1509 #endif
1510 #ifdef B1152000
1511     case 1152000: baudrate = B1152000; break;
1512 #endif
1513 #ifdef B1500000
1514     case 1500000: baudrate = B1500000; break;
1515 #endif
1516 #ifdef B2000000
1517     case 2000000: baudrate = B2000000; break;
1518 #endif
1519 #ifdef B2500000
1520     case 2500000: baudrate = B2500000; break;
1521 #endif
1522 #ifdef B3000000
1523     case 3000000: baudrate = B3000000; break;
1524 #endif
1525 #ifdef B3500000
1526     case 3500000: baudrate = B3500000; break;
1527 #endif
1528 #ifdef B4000000
1529     case 4000000: baudrate = B4000000; break;
1530 #endif
1531 
1532     default:
1533       writelogfile(LOG_ERR, 0, "Baudrate %d not supported, using 19200", baudrate);
1534       baudrate = B19200;
1535       DEVICE.baudrate = 19200;
1536   }
1537   cfsetispeed(&newtio, baudrate);
1538   cfsetospeed(&newtio, baudrate);
1539   tcsetattr(modem_handle, TCSANOW, &newtio);
1540 }
1541 
initmodem(char * new_smsc,int receiving)1542 int initmodem(char *new_smsc, int receiving)
1543 {
1544   char command[100];
1545   char answer[500];
1546   int retries=0;
1547   char *p;
1548 
1549   static int reading_checked = 0;
1550 
1551   STATISTICS->last_init = time(0);
1552 
1553   // 3.1beta7: terminating is only checked in case of errors.
1554 
1555   // -----------------------------------------------------------------------------------------------
1556   writelogfile(LOG_INFO, 0, "Checking if modem is ready");
1557 
1558   // 3.1.16beta: If wakeup_init is defined, send it to the modem:
1559   if (DEVICE.wakeup_init[0])
1560   {
1561     writelogfile(LOG_INFO, 0, "Sending wakeup_init (%s)", DEVICE.wakeup_init);
1562     snprintf(command, sizeof(command), "%s%s", DEVICE.wakeup_init, (DEVICE_IS_SOCKET && DEVICE.telnet_crlf)? "\r\n" : "\n");
1563     put_command(command, 0, 0, "default", 0);
1564     usleep_until(time_usec() + 100000);
1565     read_from_modem(answer, sizeof(answer), 2);
1566   }
1567 
1568   // 3.1.7: After being idle, some modems do not answer to the first AT command.
1569   // With BenQ M32, there can be OK answer, but in many times there is not.
1570   // To avoid error messages, first send AT and read the answer if it's available.
1571   if (DEVICE.needs_wakeup_at)
1572   {
1573     put_command("AT\r", 0, 0, "default", 0);
1574     usleep_until(time_usec() + 100000);
1575     read_from_modem(answer, sizeof(answer), 2);
1576   }
1577 
1578   if (terminate)
1579     return 7;
1580 
1581   // 3.1.16beta: Allow numeric result codes at this stage.
1582 
1583   retries=0;
1584   do
1585   {
1586     flush_smart_logging();
1587 
1588     retries++;
1589     //put_command("AT\r", answer, sizeof(answer), 1, EXPECT_OK_ERROR);
1590     put_command("AT\r", answer, sizeof(answer), "default", EXPECT_OK_ERROR_0_4);
1591     //if (!strstr(answer, "OK") && !strstr(answer, "ERROR"))
1592     if (!is_ok_error_0_4_answer(answer))
1593     {
1594       if (terminate)
1595         return 7;
1596 
1597       // if Modem does not answer, try to send a PDU termination character
1598       //put_command("\x1A\r", answer, sizeof(answer), 1, EXPECT_OK_ERROR);
1599       put_command("\x1A\r", answer, sizeof(answer), "default", EXPECT_OK_ERROR_0_4);
1600 
1601       if (terminate)
1602         return 7;
1603     }
1604 
1605     // 3.1.7: If it looks like modem does not respond, try to close and open the port:
1606     //if (retries >= 5 && !strstr(answer, "OK"))
1607     if (retries >= 5 && !is_ok_0_answer(answer))
1608     {
1609       int save_timeouts;
1610       int opened;
1611 
1612       // 3.1.16beta: Keep the value of timeouts:
1613       save_timeouts = put_command_timeouts;
1614 
1615       try_closemodem(1);
1616       t_sleep(1);
1617 
1618       // If open fails, nothing can be done. Error is already logged. Will return 1.
1619       //if (!try_openmodem())
1620       //  break;
1621       opened = try_openmodem();
1622       put_command_timeouts = save_timeouts;
1623       if (!opened)
1624         break;
1625     }
1626   }
1627   //while (retries <= 10 && !strstr(answer,"OK"));
1628   while (retries <= 10 && !is_ok_0_answer(answer));
1629 
1630   //if (!strstr(answer,"OK"))
1631   if (!is_ok_0_answer(answer))
1632   {
1633     // 3.1: more detailed error message:
1634     p = get_gsm_error(answer);
1635     // 3.1.5:
1636     writelogfile0(LOG_ERR, 1, tb_sprintf("Modem is not ready to answer commands%s%s (Timeouts: %i)",
1637                   (*p)? ", " : "", p, put_command_timeouts));
1638     alarm_handler0(LOG_ERR, tb);
1639     return 1;
1640   }
1641 
1642   // 3.1.16beta: Switch modem to use verbose mode if necessary:
1643   if (terminate)
1644     return 7;
1645 
1646   if (!is_ok_answer(answer))
1647   {
1648     put_command("ATV1\r", answer, sizeof(answer), "default", EXPECT_OK_ERROR);
1649     if (is_ok_answer(answer))
1650       writelogfile(LOG_NOTICE, 0, "Switched modem to use verbose result codes");
1651     else
1652       writelogfile(LOG_ERR, 1, "Failed to switch modem to use verbose result codes");
1653   }
1654 
1655   // -----------------------------------------------------------------------------------------------
1656   if (terminate)
1657     return 7;
1658 
1659   if (DEVICE.check_sim) // 3.1.21
1660   {
1661     char reset_cmd[sizeof(DEVICE.check_sim_reset)];
1662     int sim_ok = 0;
1663     char save_status = STATISTICS->status;
1664 
1665     writelogfile(LOG_INFO, 0, "Checking the SIM");
1666 
1667     sprintf(command, "%s\r", (DEVICE.check_sim_cmd[0])? DEVICE.check_sim_cmd : "AT+CPIN?");
1668 
1669     if (!strcasecmp(DEVICE.check_sim_reset, "RADIO_OFF_ON"))
1670       strcpy(reset_cmd, "AT+CFUN=0;+CFUN=1");
1671     else
1672     if (!strcasecmp(DEVICE.check_sim_reset, "RADIO_OFF_ON_SLOW"))
1673       strcpy(reset_cmd, "AT+CFUN=0[3]AT+CFUN=1[5]");
1674     else
1675       strcpy(reset_cmd, DEVICE.check_sim_reset);
1676 
1677     retries = 0;
1678 
1679     while (DEVICE.check_sim_retries < 0 || retries <= DEVICE.check_sim_retries)
1680     {
1681       if (try_openmodem())
1682       {
1683         if (retries > 0 && *reset_cmd)
1684         {
1685           char cmd[sizeof(command)];
1686           char *p1, *p2;
1687 
1688           writelogfile(LOG_INFO, 0, "Trying to reset the modem");
1689 
1690           p1 = reset_cmd;
1691 
1692           while (*p1)
1693           {
1694             if (*p1 == '[')
1695             {
1696               if ((p2 = strchr(p1, ']')))
1697               {
1698                 writelogfile(LOG_DEBUG, 0, "Sleeping %i sec", atoi(p1 + 1));
1699 
1700                 if (t_sleep(atoi(p1 + 1)))
1701                   return 7;
1702 
1703                 p1 = p2 + 1;
1704                 continue;
1705               }
1706               else
1707               break;
1708             }
1709 
1710             if ((p2 = strchr(p1, '[')))
1711             {
1712               memset(cmd, 0, sizeof(cmd));
1713               strncpy(cmd, p1, (int)(p2 - p1));
1714             }
1715             else
1716               strcpy(cmd, p1);
1717 
1718             p1 += strlen(cmd);
1719             strcat(cmd, "\r");
1720             put_command(cmd, answer, sizeof(answer), "init", EXPECT_OK_ERROR);
1721           }
1722         }
1723 
1724         put_command(command, answer, sizeof(answer), "init", EXPECT_OK_ERROR);
1725 
1726         if (!strstr(answer, "ERROR"))
1727         {
1728           sim_ok = 1;
1729           break;
1730         }
1731       }
1732 
1733       retries++;
1734       STATISTICS->status = 't';
1735 
1736       if (modem_handle >= 0)
1737         tb_sprintf("Check SIM returned ERROR, try: %i", retries);
1738       else
1739         tb_sprintf("Check SIM could not open the modem, try: %i", retries);
1740 
1741       writelogfile0(LOG_ERR, 1, tb);
1742       alarm_handler0(LOG_ERR, tb);
1743 
1744       if (DEVICE.check_sim_retries < 0 || retries <= DEVICE.check_sim_retries)
1745       {
1746         if (DEVICE.check_sim_keep_open == 0)
1747           try_closemodem(1);
1748 
1749         writelogfile(LOG_DEBUG, 0, "Sleeping %i sec before retrying", DEVICE.check_sim_wait);
1750         if (t_sleep(DEVICE.check_sim_wait))
1751           return 7;
1752       }
1753     }
1754 
1755     if (!sim_ok)
1756     {
1757       writelogfile0(LOG_ERR, 1, tb_sprintf("Check SIM failed and not retrying anymore"));
1758       alarm_handler0(LOG_ERR, tb);
1759       abnormal_termination(0);
1760     }
1761 
1762     STATISTICS->status = save_status;
1763 
1764     if (DEVICE.check_sim == 2)
1765       DEVICE.check_sim = 0;
1766   }
1767 
1768   // -----------------------------------------------------------------------------------------------
1769   if (terminate)
1770     return 7;
1771 
1772   // 3.1.21: Originally pre_init was containing "echo off" and "CMEE=1". If pre_init
1773   // is set to no, CLIP=1 and/or CREG=2 are still sent if required.
1774 
1775   if (DEVICE.pre_init > 0 ||
1776       DEVICE.phonecalls == 2 || get_loglevel() >= DEVICE.loglevel_lac_ci)
1777   {
1778     // 3.1.21: Do not concatenate ATE0 and extended commands in pre_initialization.
1779 
1780     writelogfile(LOG_INFO, 0, "Pre-initializing modem");
1781 
1782     if (DEVICE.pre_init > 0)
1783       put_command("ATE0\r", answer, sizeof(answer), "preinit", EXPECT_OK_ERROR);
1784 
1785     *command = 0;
1786 
1787     if (DEVICE.pre_init > 0)
1788       strcpy(command, "AT+CMEE=1");
1789 
1790     if (DEVICE.phonecalls == 2)
1791       sprintf(strchr(command, 0), "%s+CLIP=1", (*command)? ";" : "AT");
1792 
1793     if (get_loglevel() >= DEVICE.loglevel_lac_ci)
1794       sprintf(strchr(command, 0), "%s+CREG=2", (*command)? ";" : "AT");
1795 
1796     strcat(command, "\r");
1797 
1798     put_command(command, answer, sizeof(answer), "preinit", EXPECT_OK_ERROR);
1799 
1800     if (!strstr(answer,"OK"))
1801       writelogfile(LOG_ERR, 1, "Modem did not accept the pre-init string");
1802   }
1803 
1804   // -----------------------------------------------------------------------------------------------
1805   if (terminate)
1806     return 7;
1807 
1808   // 3.1.1:
1809   //if (pin[0])
1810   if (strcasecmp(DEVICE.pin, "ignore"))
1811   {
1812     // 3.1.20: Accept OK answer for PIN:
1813     //char *cpin_expect = "(READY)|( PIN)|( PUK)|(ERROR)"; // Previously: "(\\+CPIN:.*OK)|(ERROR)"
1814     char *cpin_expect = "(OK)|(READY)|( PIN)|( PUK)|(ERROR)";
1815 
1816     writelogfile(LOG_INFO, 0, "Checking if modem needs PIN");
1817     // 3.1.5: timeout from 50 to 100:
1818     put_command("AT+CPIN?\r", answer, sizeof(answer), "askpin", cpin_expect);
1819 
1820     // 3.1.7: Some modems include quotation marks in the answer, like +CPIN: "READY".
1821     while ((p = strchr(answer, '"')))
1822       strcpyo(p, p +1);
1823 
1824     // 3.1.12: Allow "echo on":
1825     if ((p = strstr(answer, "+CPIN:")))
1826       if (p > answer)
1827         strcpyo(answer, p);
1828 
1829     // 3.1.7: Some modems may leave a space away after +CPIN:
1830     if (!strncmp(answer, "+CPIN:", 6) && strncmp(answer, "+CPIN: ", 7))
1831     {
1832       if ((p = strdup(answer)))
1833       {
1834         snprintf(answer, sizeof(answer), "+CPIN: %s", p + 6);
1835         free(p);
1836       }
1837     }
1838 
1839     if (strstr(answer,"+CPIN: SIM PIN") && !strstr(answer, "PIN2"))
1840     {
1841       // 3.1.1:
1842       if (DEVICE.pin[0] == 0)
1843         writelogfile(LOG_NOTICE, 1, "Modem needs PIN, but it's not defined for this modem");
1844       else
1845       {
1846         writelogfile(LOG_NOTICE, 0, "Modem needs PIN, entering PIN...");
1847         sprintf(command, "AT+CPIN=\"%s\"\r", DEVICE.pin);
1848         put_command(command, answer, sizeof(answer), "enterpin", EXPECT_OK_ERROR);
1849         if (strstr(answer, "ERROR"))
1850         {
1851           p = get_gsm_error(answer);
1852           writelogfile(LOG_NOTICE, 1, "PIN entering: modem answered %s%s%s",
1853                        change_crlf(cut_emptylines(cutspaces(answer)), ' '), (*p)? ", " : "", p);
1854         }
1855         else
1856         // After a PIN is entered, some modems need some time before next commands are processed.
1857         if (DEVICE.pinsleeptime > 0)
1858         {
1859           writelogfile(LOG_INFO, 0, "Spending sleep time after PIN entering (%i sec)", DEVICE.pinsleeptime);
1860           t_sleep(DEVICE.pinsleeptime);
1861         }
1862 
1863         put_command("AT+CPIN?\r", answer, sizeof(answer), "askpin", cpin_expect);
1864         if (strstr(answer,"+CPIN: SIM PIN") && !strstr(answer, "PIN2"))
1865         {
1866           writelogfile0(LOG_ERR, 1, tb_sprintf("Modem did not accept this PIN"));
1867           alarm_handler0(LOG_ERR, tb);
1868           abnormal_termination(0);
1869         }
1870         // 3.1.20: Accept OK answer for PIN:
1871         if (strstr(answer,"+CPIN: READY") || strstr(answer, "OK"))
1872           writelogfile(LOG_INFO, 0, "PIN Ready");
1873       }
1874     }
1875 
1876     if (strstr(answer,"+CPIN: SIM PUK"))
1877     {
1878       writelogfile0(LOG_CRIT, 1, tb_sprintf("Your SIM is locked. Unlock it manually"));
1879       alarm_handler0(LOG_CRIT, tb);
1880       abnormal_termination(0);
1881     }
1882 
1883     // 3.1.20: Accept OK answer for PIN:
1884     if (!strstr(answer, "+CPIN: READY") && !strstr(answer, "OK"))
1885     {
1886       p = get_gsm_error(answer);
1887       writelogfile0(LOG_CRIT, 1, tb_sprintf("PIN handling: expected READY or OK, modem answered %s%s%s",
1888         change_crlf(cut_emptylines(cutspaces(answer)), ' '), (*p)? ", " : "", p));
1889       alarm_handler0(LOG_CRIT, tb);
1890       abnormal_termination(0);
1891     }
1892 
1893     // 3.1.1:
1894     if (DEVICE.pin[0] == 0)
1895       strcpy(DEVICE.pin, "ignore");
1896   }
1897 
1898   // -----------------------------------------------------------------------------------------------
1899   if (terminate)
1900     return 7;
1901 
1902   if (DEVICE.initstring[0] || DEVICE.initstring2[0])
1903     writelogfile(LOG_INFO, 0, "Initializing modem");
1904 
1905   if (DEVICE.initstring[0])
1906   {
1907     retries=0;
1908     do
1909     {
1910       retries++;
1911       put_command(DEVICE.initstring, answer, sizeof(answer), "init", EXPECT_OK_ERROR);
1912       if (!strstr(answer, "OK"))
1913         if (retries < 2)
1914           if (t_sleep(errorsleeptime))
1915             return 7;
1916     }
1917     while (retries < 2 && !strstr(answer,"OK"));
1918     if (strstr(answer,"OK")==0)
1919     {
1920       // 3.1: more detailed error message:
1921       p = get_gsm_error(answer);
1922       writelogfile0(LOG_ERR, 1, tb_sprintf("Modem did not accept the init string%s%s", (*p)? ", " : "", p));
1923       alarm_handler0(LOG_ERR, tb);
1924       return 3;
1925     }
1926   }
1927 
1928   if (DEVICE.initstring2[0])
1929   {
1930     retries=0;
1931     do
1932     {
1933       retries++;
1934       put_command(DEVICE.initstring2, answer, sizeof(answer), "init", EXPECT_OK_ERROR);
1935       if (strstr(answer, "ERROR"))
1936         if (retries < 2)
1937           if (t_sleep(errorsleeptime))
1938             return 7;
1939     }
1940     while (retries < 2 && !strstr(answer,"OK"));
1941     if (!strstr(answer,"OK"))
1942     {
1943       // 3.1: more detailed error message:
1944       p = get_gsm_error(answer);
1945       writelogfile0(LOG_ERR, 1, tb_sprintf("Modem did not accept the second init string%s%s", (*p)? ", " : "", p));
1946       alarm_handler0(LOG_ERR, tb);
1947       return 3;
1948     }
1949     // 3.1.5:
1950     else
1951       explain_csq(LOG_INFO, 0, answer, DEVICE.signal_quality_ber_ignore);
1952   }
1953 
1954   // -----------------------------------------------------------------------------------------------
1955   if (terminate)
1956     return 7;
1957 
1958   if (DEVICE.status_signal_quality == 1 ||
1959       (DEVICE.status_signal_quality == -1 && status_signal_quality == 1))
1960   {
1961     retries=0;
1962     do
1963     {
1964       retries++;
1965       put_command("AT+CSQ\r", answer, sizeof(answer), "csq", EXPECT_OK_ERROR);
1966       if (!strstr(answer, "OK"))
1967         if (retries < 2)
1968           if (t_sleep(errorsleeptime))
1969             return 7;
1970     }
1971     while (retries < 2 && !strstr(answer,"OK"));
1972 
1973     // 3.1.12: Allow "echo on":
1974     //if (!strncmp(answer, "+CSQ:", 5))
1975     if ((p = strstr(answer, "+CSQ:")))
1976     {
1977       //STATISTICS->ssi = atoi(answer +5);
1978       STATISTICS->ssi = atoi(p +5);
1979       //if ((p = strchr(answer, ',')))
1980       if ((p = strchr(p, ',')))
1981         STATISTICS->ber = atoi(p +1);
1982       else
1983         STATISTICS->ber = -2;
1984 
1985       // 3.1.7: Explain signal quality to the log:
1986       explain_csq(LOG_INFO, 0, answer, DEVICE.signal_quality_ber_ignore);
1987     }
1988     else
1989     {
1990       STATISTICS->ssi = -2;
1991       STATISTICS->ber = -2;
1992     }
1993   }
1994 
1995   // -----------------------------------------------------------------------------------------------
1996   if (terminate)
1997     return 7;
1998 
1999   // With check_network value 2 network is NOT checked when initializing for receiving:
2000   if (DEVICE.check_network == 1 ||
2001       (DEVICE.check_network == 2 && !receiving))
2002   {
2003     switch (wait_network_registration(1, 100))
2004     {
2005       case -1:
2006         return 4;
2007 
2008       case -2:
2009         return 7;
2010     }
2011   }
2012 
2013   // -----------------------------------------------------------------------------------------------
2014   if (terminate)
2015     return 7;
2016 
2017   if (DEVICE.select_pdu_mode)   // 3.1.16beta2.
2018   {
2019     writelogfile(LOG_INFO, 0, "Selecting PDU mode");
2020     strcpy(command,"AT+CMGF=0\r");
2021     retries=0;
2022     do
2023     {
2024       retries++;
2025       put_command(command, answer, sizeof(answer), "cmgf", EXPECT_OK_ERROR);
2026       if (!strstr(answer, "OK"))
2027         if (retries < 2)
2028           if (t_sleep(errorsleeptime))
2029             return 7;
2030     }
2031     while (retries < 2 && !strstr(answer,"OK"));
2032     if (strstr(answer,"ERROR"))
2033     {
2034       // 3.1: more detailed error message:
2035       p = get_gsm_error(answer);
2036       writelogfile0(LOG_ERR, 1, tb_sprintf("Error: Modem did not accept mode selection%s%s", (*p)? ", " : "", p));
2037       alarm_handler0(LOG_ERR, tb);
2038       return 5;
2039     }
2040   }
2041 
2042   // -----------------------------------------------------------------------------------------------
2043   if (terminate)
2044     return 7;
2045 
2046   if (!DEVICE.smsc_pdu && (new_smsc[0] || DEVICE.smsc[0]))
2047   {
2048     writelogfile(LOG_INFO, 0, "Changing SMSC");
2049 
2050     // 3.1.7: clean + character(s) from the setting:
2051     //sprintf(command, "AT+CSCA=\"+%s\"\r", (new_smsc[0]) ? new_smsc : DEVICE.smsc);
2052     snprintf(answer, sizeof(answer), "%s", (new_smsc[0]) ? new_smsc : DEVICE.smsc);
2053     while (*answer == '+')
2054       strcpyo(answer, answer + 1);
2055     sprintf(command, "AT+CSCA=\"+%s\"\r", answer);
2056 
2057     retries=0;
2058     do
2059     {
2060       retries++;
2061       put_command(command, answer, sizeof(answer), "csca", EXPECT_OK_ERROR);
2062       if (!strstr(answer, "OK"))
2063         if (retries < 2)
2064           if (t_sleep(errorsleeptime))
2065             return 7;
2066     }
2067     while (retries < 2 && !strstr(answer,"OK"));
2068     if (strstr(answer,"ERROR"))
2069     {
2070       // 3.1: more detailed error message:
2071       p = get_gsm_error(answer);
2072       writelogfile0(LOG_ERR, 1, tb_sprintf("Error: Modem did not accept SMSC%s%s", (*p)? ", " : "", p));
2073       alarm_handler0(LOG_ERR, tb);
2074       return 6;
2075     }
2076   }
2077 
2078   // -----------------------------------------------------------------------------------------------
2079   if (terminate)
2080     return 7;
2081 
2082   // 3.1.16beta: Ask IMEI once.
2083   if (DEVICE.imei[0] == 0)
2084   {
2085     sprintf(command,"AT+CGSN\r");
2086     put_command(command, answer, sizeof(answer), "default", EXPECT_OK_ERROR);
2087 
2088     if (!strstr(answer, "ERROR"))
2089       while (answer[0] && !isdigitc(answer[0]))
2090         strcpyo(answer, answer +1);
2091 
2092     if ((p = strstr(answer, "OK")))
2093       *p = 0;
2094     cut_ctrl(answer);
2095     cutspaces(answer);
2096     snprintf(DEVICE.imei, sizeof(DEVICE.imei), "%s", answer);
2097     writelogfile(LOG_NOTICE, 0, "IMEI: %s", DEVICE.imei);
2098   }
2099 
2100   // -----------------------------------------------------------------------------------------------
2101   if (terminate)
2102     return 7;
2103 
2104   // 3.1beta7, 3.0.9: International Mobile Subscriber Identity is asked once.
2105   if (DEVICE.identity[0] == 0)
2106   {
2107     sprintf(command,"AT+CIMI\r");
2108     put_command(command, DEVICE.identity, SIZE_IDENTITY, "default", EXPECT_OK_ERROR);
2109 
2110     // 3.1.5: do not remove ERROR text:
2111     if (!strstr(DEVICE.identity, "ERROR"))
2112       while (DEVICE.identity[0] && !isdigitc(DEVICE.identity[0]))
2113         strcpyo(DEVICE.identity, DEVICE.identity +1);
2114 
2115     // 3.1beta7: If CIMI is not supported, try CGSN (Product Serial Number)
2116     // TODO: is IMSI title still good?
2117     if (strstr(DEVICE.identity, "ERROR"))
2118       strcpy(DEVICE.identity, DEVICE.imei);
2119 
2120     if (!strstr(DEVICE.identity, "ERROR"))
2121     {
2122       if ((p = strstr(DEVICE.identity, "OK")))
2123         *p = 0;
2124       cut_ctrl(DEVICE.identity);
2125       cutspaces(DEVICE.identity);
2126       writelogfile(LOG_NOTICE, 0, "IMSI: %s", DEVICE.identity);
2127     }
2128     else
2129       writelogfile(LOG_NOTICE, 1, "IMSI/CGSN not supported");
2130   }
2131 
2132   // -----------------------------------------------------------------------------------------------
2133   if (terminate)
2134     return 7;
2135 
2136   // 3.1.5: Check once if reading of messages is not supported:
2137   // 3.1.7: Do not check if not reading incoming messages:
2138   if (DEVICE.incoming && !reading_checked)
2139   {
2140     reading_checked = 1;
2141     writelogfile(LOG_INFO, 0, "Checking if reading of messages is supported");
2142 
2143     sprintf(command,"AT+CPMS?\r");
2144     put_command(command, answer, sizeof(answer), "cpms", EXPECT_OK_ERROR);
2145 
2146     if (strstr(answer, "+CPMS: ,,,,,,,,"))
2147     {
2148       sprintf(command,"AT+CPMS=?\r");
2149       put_command(command, answer, sizeof(answer), "cpms", EXPECT_OK_ERROR);
2150 
2151       if (strstr(answer, "+CPMS: (),(),()"))
2152       {
2153         writelogfile0(LOG_ERR, 1, tb_sprintf("Error: Looks like your device does not support reading of messages"));
2154         alarm_handler0(LOG_ERR, tb);
2155       }
2156     }
2157   }
2158 
2159   // -----------------------------------------------------------------------------------------------
2160   if (terminate)
2161     return 7;
2162 
2163   // 3.1.7: Report details of device once:
2164   if (DEVICE.report_device_details)
2165   {
2166     int save_log_single_lines = log_single_lines;
2167     int i;
2168     char tmp[256];
2169     char *commands[] = {
2170       "AT+CGMI", "Manufacturer identification",
2171       "AT+CGMM", "Model identification",
2172       "AT+CGMR", "Revision identification",
2173       "AT+CNMI=?", "New message indications, list of supported modes",
2174       "AT+CNMI?", "New message indications, current settings",
2175       "AT+CPMS=?", "Preferred message storage, list of supported mem's",
2176       //"AT+CPMS?", "Preferred message storage, current mem's and counters",
2177       "AT+CPBS=?", "Phonebook storage, available mem's",
2178       //"AT+CPBS?", "Phonebook storage, current storage and counters",
2179       "AT+CMGL=?", "List messages, list of supported stat's",
2180       "AT+CMGD=?", "Delete message, list of supported values",
2181       "AT+CPAS=?", "Phone activity status, list of supported stat's",
2182       "AT+CSCS=?", "TE character set, list of supported charset's",
2183       "AT+CSCS?", "TE character set, current setting",
2184       "" // end marker
2185     };
2186 
2187     DEVICE.report_device_details = 0;
2188     log_single_lines = 0;
2189     change_loglevel(LOG_DEBUG);
2190 
2191     writelogfile(LOG_DEBUG, 0, "## Start of device details");
2192 
2193     for (i = 0; commands[i][0]; i += 2)
2194     {
2195       if (terminate)
2196         break;
2197 
2198       snprintf(tmp, sizeof(tmp), "# %s:", commands[i + 1]);
2199       writelogfile0(LOG_DEBUG, 0, tmp);
2200       sprintf(command, "%s\r", commands[i]);
2201       put_command0(command, answer, sizeof(answer), "default", EXPECT_OK_ERROR, 1);
2202     }
2203 
2204     writelogfile(LOG_DEBUG, 0, "## End of device details");
2205 
2206     log_single_lines = save_log_single_lines;
2207     restore_loglevel();
2208   }
2209 
2210   // -----------------------------------------------------------------------------------------------
2211   // TODO: Check if AT+CMGD=? is supported.
2212 
2213   if (terminate)
2214     return 7;
2215 
2216   return 0;
2217 }
2218 
initialize_modem_sending(char * new_smsc)2219 int initialize_modem_sending(char *new_smsc)
2220 {
2221   // 3.1.17: Check if modem is disabled here, and log it:
2222   if (DEVICE.modem_disabled)
2223   {
2224     writelogfile(LOG_DEBUG, 0, "initialize_modem_sending");
2225     return 0;
2226   }
2227 
2228   return initmodem(new_smsc, 0);
2229 }
2230 
initialize_modem_receiving()2231 int initialize_modem_receiving()
2232 {
2233   // 3.1.17: Check if modem is disabled here, and log it:
2234   if (DEVICE.modem_disabled)
2235   {
2236     writelogfile(LOG_DEBUG, 0, "initialize_modem_receiving");
2237     return 0;
2238   }
2239 
2240   return initmodem("", 1);
2241 }
2242 
2243 #ifndef DISABLE_INET_SOCKET
2244 
2245 /* Start Changes by Hubert Gilch, SEP Logistik AG
2246  *
2247  * 2 functions for connecting to a socket instead of a serial device
2248  * in order to use ethernet GPRS-modems
2249  *
2250  * Code was "stolen" from interceptty by Scott W. Gifford
2251  *
2252  */
2253 
inet_resolve(const char * sockname)2254 struct sockaddr_in inet_resolve(const char *sockname)
2255 {
2256   struct sockaddr_in sa;
2257   char *hostname, *netport;
2258   struct hostent *he;
2259 
2260   if (!(hostname = strdup(sockname)))
2261     writelogfile(LOG_CRIT, 0, "Couldn't dup string: %s", strerror(errno));
2262 
2263   netport = strchr(hostname, ':');
2264   *netport = '\0';
2265   netport++;
2266 
2267   sa.sin_family = AF_INET;
2268 
2269   if (!(he = gethostbyname(hostname)))
2270     writelogfile(LOG_ERR, 0, "Couldn't resolve name '%s': %s.", hostname,
2271       (h_errno == HOST_NOT_FOUND) ? "Host not found" :
2272       ((h_errno == NO_ADDRESS) || (h_errno == NO_DATA)) ? "No data available" :
2273       (h_errno == NO_RECOVERY) ? "A non-recoverable name server error occured" : (h_errno == TRY_AGAIN) ? "A temporary error occured." : "An unknown error occured");
2274 
2275   memcpy(&(sa.sin_addr), he->h_addr, he->h_length);
2276 
2277 #if 0
2278   if (!(se = getservbyname(netport)))
2279     writelogfile(LOG_ERR, 0, "Couldn't resolve port.");
2280 
2281   host_port = htons(se->s_port);
2282 #endif
2283 
2284   if (!(sa.sin_port = htons(atoi(netport))))
2285     writelogfile(LOG_ERR, 0, "Couldn't figure out port number.");
2286 
2287   free(hostname);
2288 
2289   return sa;
2290 }
2291 
open_inet_socket(char * backend)2292 int open_inet_socket(char *backend)
2293 {
2294   struct sockaddr_in sa;
2295   int fd;
2296   int socketflags;
2297   int retries = 0;
2298 
2299   sa = inet_resolve(backend + 1);	// cut first character @
2300   if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 3)
2301   {
2302     tb_sprintf("Couldn't open socket: %s: %s", backend, strerror(errno));
2303     writelogfile0(LOG_ERR, 0, tb);
2304     alarm_handler0(LOG_ERR, tb);
2305     return -1;
2306   }
2307 
2308   while (connect(fd, (struct sockaddr *) &sa, sizeof(sa)) != 0)
2309   {
2310     retries++;
2311 
2312     if (terminate || (DEVICE.socket_connection_retries != -1 && retries > DEVICE.socket_connection_retries))
2313     {
2314       close(fd);
2315       return (terminate)? -2 : -1;
2316     }
2317 
2318     tb_sprintf("Couldn't connect socket %s, error: %s, waiting %i sec.", backend, strerror(errno), DEVICE.socket_connection_errorsleeptime);
2319 
2320     if (retries - 1 == DEVICE.socket_connection_alarm_after)
2321     {
2322       writelogfile0(LOG_ERR, 0, tb);
2323       alarm_handler0(LOG_ERR, tb);
2324     }
2325     else
2326     {
2327       // Do not log the first failure:
2328       if (retries > 1)
2329         writelogfile0(LOG_INFO, 0, tb);
2330     }
2331 
2332     t_sleep(DEVICE.socket_connection_errorsleeptime);
2333   }
2334 
2335   socketflags = fcntl(fd, F_GETFL);
2336   fcntl(fd, F_SETFL, socketflags | O_NONBLOCK);
2337 
2338   return fd;
2339 }
2340 
2341 /*
2342  * End Changes by Hubert Gilch
2343  */
2344 
2345 #endif
2346 
openmodem()2347 int openmodem()
2348 {
2349   int retries = 0;
2350 
2351   // 3.1.7:
2352   //modem_handle = open(DEVICE.device, O_RDWR | O_NOCTTY | O_NONBLOCK);
2353 
2354   /*
2355    * if devicename starts with "@" it is not a serial device but
2356    * a socket, so open a socket instead a device file
2357    *
2358    * Change by Hubert Gilch, SEP Logistik AG
2359    */
2360 #ifndef DISABLE_INET_SOCKET
2361   if (DEVICE_IS_SOCKET)
2362     modem_handle = open_inet_socket(DEVICE.device);
2363   else
2364 #endif
2365   {
2366     // 3.1.12:
2367     if (DEVICE.modem_disabled)
2368     {
2369       struct stat statbuf;
2370 
2371       if (stat(DEVICE.device, &statbuf) != 0)
2372       {
2373         FILE *fp;
2374 
2375         if ((fp = fopen(DEVICE.device, "w")))
2376           fclose(fp);
2377       }
2378     }
2379 
2380     // 3.1.7:
2381     while ((modem_handle = open(DEVICE.device, O_RDWR | O_NOCTTY | O_NONBLOCK)) < 0)
2382     {
2383       retries++;
2384 
2385       if (terminate || (DEVICE.device_open_retries != -1 && retries > DEVICE.device_open_retries))
2386         break;
2387 
2388       tb_sprintf("Couldn't open serial port %s, error: %s, waiting %i sec.", DEVICE.device, strerror(errno), DEVICE.device_open_errorsleeptime);
2389 
2390       if (retries - 1 == DEVICE.device_open_alarm_after)
2391       {
2392         writelogfile0(LOG_ERR, 0, tb);
2393         alarm_handler0(LOG_ERR, tb);
2394       }
2395       else
2396         writelogfile0(LOG_INFO, 0, tb);
2397 
2398       t_sleep(DEVICE.device_open_errorsleeptime);
2399     }
2400   }
2401 
2402   if (modem_handle < 0)
2403   {
2404     if (modem_handle == -1)
2405     {
2406       writelogfile0(LOG_ERR, 1, tb_sprintf((DEVICE_IS_SOCKET)? "Cannot open socket %s, error: %s" : "Cannot open serial port %s, error: %s", DEVICE.device, strerror(errno)));
2407       alarm_handler0(LOG_ERR, tb);
2408     }
2409     return -1;
2410   }
2411 
2412   if (strstr(smsd_version, "beta"))
2413   {
2414     if (DEVICE_IS_SOCKET)
2415       writelogfile(LOG_INFO, 0, "Socket %s opened as %i", DEVICE.device, modem_handle);
2416     else
2417       writelogfile(LOG_INFO, 0, "Serial port %s opened as %i, rtscts: %i, baudrate: %i", DEVICE.device, modem_handle, DEVICE.rtscts, DEVICE.baudrate);
2418   }
2419 
2420   return modem_handle;
2421 }
2422 
test_openmodem()2423 int test_openmodem()
2424 {
2425   int result = 1;
2426   int save_device_open_retries = DEVICE.device_open_retries;
2427   int save_socket_connection_retries = DEVICE.socket_connection_retries;
2428 
2429   DEVICE.device_open_retries = 0;
2430   DEVICE.socket_connection_retries = 0;
2431 
2432   try_closemodem(1);
2433 
2434   if (openmodem() < 0)
2435     result = 0;
2436 
2437   try_closemodem(1);
2438 
2439   DEVICE.device_open_retries = save_device_open_retries;
2440   DEVICE.socket_connection_retries = save_socket_connection_retries;
2441 
2442   return result;
2443 }
2444 
show_a_commands()2445 void show_a_commands()
2446 {
2447   int i;
2448 
2449   for (i = 0; i < COMMUNICATE_A_KEY_COUNT; i++)
2450   {
2451     if (communicate_a_keys[i][0])
2452     {
2453       printf("Alt shortcuts:\n");
2454 
2455       while (i < COMMUNICATE_A_KEY_COUNT)
2456       {
2457         if (communicate_a_keys[i][0])
2458           printf("Alt-%i = %s\n", i, communicate_a_keys[i]);
2459 
2460         i++;
2461       }
2462       printf("-- \n");
2463       fflush(stdout);
2464       break;
2465     }
2466   }
2467 }
2468 
talk_with_modem()2469 int talk_with_modem()
2470 {
2471   int result = 0;
2472   int n;
2473   char tmp[256];
2474   struct termios newtset, oldtset;
2475   char newdevice[PATH_MAX];
2476   int stdinflags;
2477   int set_nonblock = 0;
2478   int idle;
2479   int echo_on = 0;
2480 
2481   modem_handle = -1;
2482 
2483   stdinflags = fcntl(STDIN_FILENO, F_GETFL);
2484 
2485   if (!(stdinflags & O_NONBLOCK))
2486   {
2487     if (fcntl(STDIN_FILENO, F_SETFL, stdinflags | O_NONBLOCK) == -1)
2488       printf("Failed to set STDIN nonblock.\n");
2489     else
2490       set_nonblock = 1;
2491   }
2492 
2493   tcgetattr(STDIN_FILENO, &oldtset);
2494   newtset = oldtset;
2495   newtset.c_lflag &= ~(ECHO | ICANON);
2496   newtset.c_iflag &= ~ICRNL;
2497   newtset.c_cc[VMIN] = 1;
2498   newtset.c_cc[VTIME] = 0;
2499   tcsetattr(STDIN_FILENO, TCSAFLUSH, &newtset);
2500 
2501   printf("Communicating with %s. ( Press Ctrl-C to abort. )\n", process_title);
2502 
2503   // 3.1.20: Ctrl-Z can be sent with Alt-Z:
2504   //printf("( If you need to send Ctrl-Z, change the suspend character first, like stty susp \\^N )\n");
2505   printf("( If you need to send Ctrl-Z, use Alt-Z )\n");
2506 
2507   writelogfile(LOG_CRIT, 0, "Communicating with terminal.");
2508 
2509   printf("Default device is %s\n", DEVICE.device);
2510   printf("Press Enter to start or type an another device name.\n");
2511   *newdevice = 0;
2512 
2513   while (!terminate)
2514   {
2515     idle = 0;
2516 
2517     // 3.1.16beta: Automatically set echo on when talking with modem. 3.1.16beta2: Not with network modems which may require login and/or password.
2518     if (!DEVICE_IS_SOCKET && modem_handle != -1 && !echo_on)
2519     {
2520       write_to_modem("ATE1\r", 5, 0, 1);
2521       echo_on = 1;
2522     }
2523 
2524     if ((n = read(STDIN_FILENO, tmp, (modem_handle != -1)? sizeof(tmp) -1 : 1)) > 0)
2525     {
2526       if (modem_handle != -1)
2527       {
2528         tmp[n] = 0;
2529 
2530         // 3.1.20: Handle Alt-0...9, Alt-Z and Alt-?:
2531         if (n == 2 && tmp[0] == 0x1B)
2532         {
2533           if (tmp[1] >= 0x30 && tmp[1] <= 0x39)
2534             strcpy(tmp, communicate_a_keys[tmp[1] - 0x30]);
2535           else if (tmp[1] == 0x5A || tmp[1] == 0x7A)
2536             sprintf(tmp, "%c", 0x1A);
2537           else if (tmp[1] == 0x3F)
2538           {
2539             show_a_commands();
2540             *tmp = 0;
2541           }
2542         }
2543 
2544         if (*tmp)
2545           write_to_modem(tmp, 5, 0, 1);
2546       }
2547       else
2548       {
2549         if (*tmp == 13)
2550         {
2551           printf("\n");
2552           fflush(stdout);
2553           if (*newdevice)
2554             strcpy(DEVICE.device, newdevice);
2555           printf("Opening device %s\n", DEVICE.device);
2556           if (openmodem() == -1)
2557           {
2558             printf("Cannot open device %s, cause: %s.\n", DEVICE.device, strerror(errno));
2559             *newdevice = 0;
2560             continue;
2561           }
2562           setmodemparams();
2563           printf("Ready.\n");
2564 
2565           // 3.1.20: Show Alt commands if any defined:
2566           show_a_commands();
2567 
2568           fflush(stdout);
2569 
2570           result = 1;
2571         }
2572         else if (*tmp)
2573         {
2574           printf("%c", *tmp);
2575           fflush(stdout);
2576           if (*tmp == 127 || *tmp == 8)
2577           {
2578             if (*newdevice)
2579               newdevice[strlen(newdevice) -1] = 0;
2580           }
2581           else
2582           {
2583             if (strlen(newdevice) < sizeof(newdevice) -1)
2584               sprintf(strchr(newdevice, 0), "%c", *tmp);
2585             else
2586             {
2587               printf("\nDevice name too long.\n");
2588               *newdevice = 0;
2589               continue;
2590             }
2591           }
2592         }
2593       }
2594     }
2595     else
2596       idle = 1;
2597 
2598     if (modem_handle != -1)
2599     {
2600       if ((n = read(modem_handle, tmp, sizeof(tmp) -1)) > 0)
2601       {
2602         // 3.1.12:
2603         if (log_read_from_modem)
2604         {
2605           char temp[SIZE_LOG_LINE];
2606           int i;
2607           char *answer = tmp;
2608 
2609           snprintf(temp, sizeof(temp), "read_from_modem: got=%i:", n);
2610           for (i = 0; i < n; i++)
2611           {
2612             if (strlen(temp) >= sizeof(temp) - 6)
2613             {
2614               strcpy(temp, "ERROR: too much data");
2615               break;
2616             }
2617 
2618             sprintf(strchr(temp, 0), " %02X[%c]", (unsigned char) answer[i], ((unsigned char) answer[i] >= ' ') ? answer[i] : '.');
2619           }
2620 
2621           writelogfile0(LOG_CRIT, 0, temp);
2622         }
2623 
2624         // 3.1.12:
2625         if (DEVICE_IS_SOCKET)
2626           negotiate_with_telnet(tmp, &n);
2627 
2628         write(STDOUT_FILENO, tmp, n);
2629         idle = 0;
2630       }
2631     }
2632 
2633     if (idle)
2634       usleep_until(time_usec() + 100000);
2635   }
2636 
2637   if (modem_handle >= 0)
2638     close(modem_handle);
2639 
2640   if (set_nonblock)
2641     fcntl(STDIN_FILENO, F_SETFL, stdinflags & ~O_NONBLOCK);
2642   tcsetattr(STDIN_FILENO, TCSANOW, &oldtset);
2643 
2644   return result;
2645 }
2646 
2647 // Return value:
2648 // -2 = terminated
2649 // -1 = modem is not registered
2650 // >= 0 = number of retries, modem is registered
wait_network_registration(int waitnetwork_errorsleeptime,int retry_count)2651 int wait_network_registration(int waitnetwork_errorsleeptime, int retry_count)
2652 {
2653   char answer[500];
2654   int success = 0;
2655   int retries = 0;
2656   int registration_denied = 0;
2657   static int registration_ok = 0;
2658   char *p;
2659   // 3.1.14:
2660   static char prev_lac[32] = "";
2661   static char prev_ci[32] = "";
2662   char lac[32];
2663   char ci[32];
2664 
2665   writelogfile(LOG_INFO, 0, "Checking if Modem is registered to the network");
2666 
2667   do
2668   {
2669     flush_smart_logging();
2670 
2671     // 3.1: signal quality is logged:
2672     // 3.1.16beta: only if logging "not registered":
2673     //if (retries > 0)
2674     if (retries > 0 && retries >= DEVICE.log_not_registered_after)
2675     {
2676       put_command("AT+CSQ\r", answer, sizeof(answer), "csq", EXPECT_OK_ERROR);
2677 
2678       // 3.1.5: ...with details:
2679       explain_csq(LOG_NOTICE, 0, answer, DEVICE.signal_quality_ber_ignore);
2680     }
2681 
2682     put_command("AT+CREG?\r", answer, sizeof(answer), "creg", "(\\+CREG:.*OK)|(ERROR)");
2683 
2684     // 3.1.16beta: Remove everything before "+CREG:"
2685     if ((p = strstr(answer, "+CREG:")))
2686       memmove(answer, p, strlen(p) + 1);
2687 
2688     // 3.1.14:
2689     if (get_loglevel() >= DEVICE.loglevel_lac_ci)
2690     {
2691       if ((p = strchr(answer, '\r')))
2692         *p = ',';
2693       getfield(answer, 3, lac, sizeof(lac));
2694       getfield(answer, 4, ci, sizeof(ci));
2695       if (strlen(ci) > 4)
2696         memmove(ci, ci +strlen(ci) -4, 5);
2697     }
2698 
2699     // 3.1.1: Some modem include spaces in the response:
2700     while ((p = strchr(answer, ' ')))
2701       strcpyo(p, p +1);
2702 
2703     // 3.1.1: Drop additional fields:
2704     if ((p = strchr(answer, ',')))
2705       if ((p = strchr(p +1, ',')))
2706         *p = 0;
2707 
2708     // 3.1.1: Some modem (Motorola) gives values using three digits like "000,001":
2709     if ((p = strstr(answer, ",00")))
2710       strcpyo(p +1, p +3);
2711 
2712     // 3.1:
2713     // Second field is tested.
2714     if (strstr(answer, ",1"))
2715     {
2716       writelogfile(LOG_INFO, 0, "Modem is registered to the network");
2717       success = 1;
2718     }
2719     else if (strstr(answer, ",5"))
2720     {
2721       writelogfile(LOG_INFO, 0, "Modem is registered to a roaming partner network");
2722       success = 1;
2723     }
2724     // 3.1.1: 3 - Registration denied is handled
2725     else if (strstr(answer, ",3"))
2726     {
2727       // 3.1.5: After a SIM has once been successfully registered to the network, failure with registration
2728       // does not stop the modem process.
2729       //if (registration_denied < 2)
2730       if (registration_ok || registration_denied < 2)
2731       {
2732         writelogfile(LOG_INFO, 1, "Modem said: registration denied. Retrying.");
2733         registration_denied++;
2734         if (t_sleep(waitnetwork_errorsleeptime))
2735           return -2;
2736       }
2737       else
2738       {
2739         writelogfile0(LOG_ERR, 1, tb_sprintf("Error: registration is denied."));
2740         alarm_handler0(LOG_ERR, tb);
2741         abnormal_termination(0);
2742       }
2743     }
2744     else if (strstr(answer,"ERROR"))
2745     {
2746       writelogfile(LOG_INFO, 1, "Ignoring that modem does not support +CREG command.");
2747       success = 1;
2748       DEVICE.check_network = 0;
2749     }
2750     else if (strstr(answer,"+CREG:"))
2751     {
2752       // 3.1.14: Skip logging if defined. Call alarmhandler.
2753       if (retries >= DEVICE.log_not_registered_after)
2754       {
2755         writelogfile0(LOG_NOTICE, 1, tb_sprintf("MODEM IS NOT REGISTERED, WAITING %i SEC. BEFORE RETRYING %i. TIME", waitnetwork_errorsleeptime, retries +1));
2756         alarm_handler0(LOG_NOTICE, tb);
2757       }
2758       else
2759       {
2760         // 3.1.16beta: log with level 7, start trouble logging:
2761         writelogfile0(LOG_DEBUG, 1, tb_sprintf("MODEM IS NOT REGISTERED, WAITING %i SEC. BEFORE RETRYING %i. TIME", waitnetwork_errorsleeptime, retries +1));
2762       }
2763 
2764       if (t_sleep(waitnetwork_errorsleeptime))
2765         return -2;
2766     }
2767     else
2768     {
2769       writelogfile0(LOG_ERR, 1, tb_sprintf("Error: Unexpected answer from Modem after +CREG?, waiting %i sec. before retrying", waitnetwork_errorsleeptime));
2770       alarm_handler0(LOG_ERR, tb);
2771       if (t_sleep(waitnetwork_errorsleeptime))
2772         return -2;
2773     }
2774 
2775     if (!success)
2776       retries++;
2777   }
2778   while (!success && retries < retry_count);
2779 
2780   if (!success)
2781   {
2782     writelogfile0(LOG_ERR, 1, tb_sprintf("Error: Modem is not registered to the network"));
2783     alarm_handler0(LOG_ERR, tb);
2784     return -1;
2785   }
2786 
2787   // 3.1.14:
2788   if (get_loglevel() >= DEVICE.loglevel_lac_ci && *lac && *ci)
2789   {
2790     if (*prev_lac && *prev_ci)
2791     {
2792       if (strcmp(prev_lac, lac))
2793         writelogfile(DEVICE.loglevel_lac_ci, 0, "Location area code changed: %s -> %s", prev_lac, lac);
2794 
2795       if (strcmp(prev_ci, ci))
2796         writelogfile(DEVICE.loglevel_lac_ci, 0, "Cell ID changed: %s -> %s", prev_ci, ci);
2797 
2798       if (strcmp(prev_lac, lac) || strcmp(prev_ci, ci))
2799       {
2800         put_command("AT+CSQ\r", answer, sizeof(answer), "csq", EXPECT_OK_ERROR);
2801         explain_csq(DEVICE.loglevel_lac_ci, 0, answer, DEVICE.signal_quality_ber_ignore);
2802       }
2803     }
2804     else
2805     {
2806       writelogfile(DEVICE.loglevel_lac_ci, 0, "Location area code: %s, Cell ID: %s", lac, ci);
2807       put_command("AT+CSQ\r", answer, sizeof(answer), "csq", EXPECT_OK_ERROR);
2808       explain_csq(DEVICE.loglevel_lac_ci, 0, answer, DEVICE.signal_quality_ber_ignore);
2809     }
2810 
2811     snprintf(prev_lac, sizeof(prev_lac), "%s", lac);
2812     snprintf(prev_ci, sizeof(prev_ci), "%s", ci);
2813   }
2814 
2815   registration_ok = 1;
2816 
2817   return retries;
2818 }
2819 
try_closemodem(int force)2820 int try_closemodem(int force)
2821 {
2822   int keep_open;
2823 
2824   if (force)
2825     keep_open = 0;
2826   else
2827     keep_open = DEVICE.keep_open;
2828 
2829   if (modem_handle >= 0 && !keep_open)
2830   {
2831     if (1 && strstr(smsd_version, "beta"))
2832     {
2833       writelogfile(LOG_INFO, 0, "Device %s (%i) closed", DEVICE.device, modem_handle);
2834       writelogfile(LOG_INFO, 0, "***********");
2835     }
2836 #ifdef DEBUGMSG
2837   printf("!! Closing device %s\n", DEVICE.device);
2838 #endif
2839 
2840     // 3.1.16beta: Flush required when select() was used and there was no modem connected,
2841     // without flush the close() has 30 sec. delay:
2842     tcflush(modem_handle, TCIOFLUSH);
2843 
2844     close(modem_handle);
2845     modem_handle = -2;
2846   }
2847 
2848   return (modem_handle >= 0);
2849 }
2850 
try_openmodem()2851 int try_openmodem()
2852 {
2853   int result = 1;
2854 
2855   if (modem_handle >= 0)
2856   {
2857 #ifdef DEBUGMSG
2858   printf("!! Opening device %s: already open\n", DEVICE.device);
2859 #endif
2860     return 1;
2861   }
2862 
2863 #ifdef DEBUGMSG
2864   printf("!! Opening device %s\n", DEVICE.device);
2865 #endif
2866   if (openmodem() == -1)
2867   {
2868     result = 0;
2869 #ifdef DEBUGMSG
2870   printf("!! Opening FAILED\n");
2871 #endif
2872   }
2873   else
2874   {
2875 #ifdef DEBUGMSG
2876   printf("!! Setting modem parameters\n");
2877 #endif
2878     put_command_timeouts = 0;
2879     setmodemparams();
2880   }
2881 
2882   return result;
2883 }
2884