summaryrefslogtreecommitdiff
path: root/smsd
diff options
context:
space:
mode:
Diffstat (limited to 'smsd')
-rw-r--r--smsd/core.c106
-rw-r--r--smsd/core.h6
-rw-r--r--smsd/main.c4
-rw-r--r--smsd/services/odbc.c7
-rw-r--r--smsd/services/sql-core.h4
-rw-r--r--smsd/services/sql.c149
-rwxr-xr-xsmsd/test-smsd.sh.in14
-rw-r--r--smsd/uid.c4
8 files changed, 249 insertions, 45 deletions
diff --git a/smsd/core.c b/smsd/core.c
index 80bbe3c..ff99f1b 100644
--- a/smsd/core.c
+++ b/smsd/core.c
@@ -139,6 +139,7 @@ void SMSD_SendSMSStatusCallback (GSM_StateMachine *sm, int status, int mr, void
} else {
Config->SendingSMSStatus = ERR_UNKNOWN;
}
+ Config->StatusCode = status;
}
/**
@@ -385,6 +386,7 @@ void SMSD_Log_Function(const char *text, void *data)
GSM_SMSDConfig *SMSD_NewConfig(const char *name)
{
GSM_SMSDConfig *Config;
+ int i;
Config = (GSM_SMSDConfig *)malloc(sizeof(GSM_SMSDConfig));
if (Config == NULL) return Config;
@@ -418,6 +420,10 @@ GSM_SMSDConfig *SMSD_NewConfig(const char *name)
Config->conn.pg = NULL;
#endif
+ for (i = 0; i < GSM_MAX_MULTI_SMS; i++) {
+ Config->SkipMessage[i] = FALSE;
+ }
+
/* Prepare lists */
GSM_StringArray_New(&(Config->IncludeNumbersList));
GSM_StringArray_New(&(Config->ExcludeNumbersList));
@@ -862,6 +868,7 @@ GSM_Error SMSD_ReadConfig(const char *filename, GSM_SMSDConfig *Config, gboolean
Config->RunOnReceive = INI_GetValue(Config->smsdcfgfile, "smsd", "runonreceive", FALSE);
Config->RunOnFailure = INI_GetValue(Config->smsdcfgfile, "smsd", "runonfailure", FALSE);
Config->RunOnSent = INI_GetValue(Config->smsdcfgfile, "smsd", "runonsent", FALSE);
+ Config->RunOnIncomingCall = INI_GetValue(Config->smsdcfgfile, "smsd", "runonincomingcall", FALSE);
str = INI_GetValue(Config->smsdcfgfile, "smsd", "smsc", FALSE);
if (str) {
@@ -1061,6 +1068,9 @@ void SMSD_RunOnReceiveEnvironment(GSM_MultiSMSMessage *sms, GSM_SMSDConfig *Conf
sprintf(buffer, "%d", sms->SMS[i].Class);
sprintf(name, "SMS_%d_CLASS", i + 1);
setenv(name, buffer, 1);
+ sprintf(buffer, "%d", sms->SMS[i].MessageReference);
+ sprintf(name, "SMS_%d_REFERENCE", i + 1);
+ setenv(name, buffer, 1);
sprintf(name, "SMS_%d_NUMBER", i + 1);
setenv(name, DecodeUnicodeConsole(sms->SMS[i].Number), 1);
if (sms->SMS[i].Coding != SMS_Coding_8bit && sms->SMS[i].UDH.Type != UDH_UserUDH) {
@@ -1113,7 +1123,7 @@ void SMSD_RunOnReceiveEnvironment(GSM_MultiSMSMessage *sms, GSM_SMSDConfig *Conf
*
* This is Windows variant.
*/
-gboolean SMSD_RunOn(const char *command, GSM_MultiSMSMessage *sms, GSM_SMSDConfig *Config, const char *locations)
+gboolean SMSD_RunOn(const char *command, GSM_MultiSMSMessage *sms, GSM_SMSDConfig *Config, const char *locations, const char *event)
{
BOOL ret;
STARTUPINFO si;
@@ -1131,7 +1141,7 @@ gboolean SMSD_RunOn(const char *command, GSM_MultiSMSMessage *sms, GSM_SMSDConfi
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
- SMSD_Log(DEBUG_INFO, Config, "Starting run on command: %s", cmdline);
+ SMSD_Log(DEBUG_INFO, Config, "Starting run on %s: %s", event, cmdline);
ret = CreateProcess(NULL, /* No module name (use command line) */
cmdline, /* Command line */
@@ -1160,7 +1170,7 @@ gboolean SMSD_RunOn(const char *command, GSM_MultiSMSMessage *sms, GSM_SMSDConfi
*
* This is POSIX variant.
*/
-gboolean SMSD_RunOn(const char *command, GSM_MultiSMSMessage *sms, GSM_SMSDConfig *Config, const char *locations)
+gboolean SMSD_RunOn(const char *command, GSM_MultiSMSMessage *sms, GSM_SMSDConfig *Config, const char *locations, const char *event)
{
int pid;
int pipefd[2];
@@ -1253,7 +1263,7 @@ out:
/* Calculate command line */
cmdline = SMSD_RunOnCommand(locations, command);
- SMSD_Log(DEBUG_INFO, Config, "Starting run on receive: %s", cmdline);
+ SMSD_Log(DEBUG_INFO, Config, "Starting run on %s: %s", event, cmdline);
/* Close all file descriptors */
for (i = 0; i < 255; i++) {
@@ -1363,7 +1373,7 @@ GSM_Error SMSD_ProcessSMS(GSM_SMSDConfig *Config, GSM_MultiSMSMessage *sms)
error = Config->Service->SaveInboxSMS(sms, Config, &locations);
/* RunOnReceive handling */
if (Config->RunOnReceive != NULL && error == ERR_NONE) {
- SMSD_RunOn(Config->RunOnReceive, sms, Config, locations);
+ SMSD_RunOn(Config->RunOnReceive, sms, Config, locations, "receive");
}
/* Free memory allocated by SaveInboxSMS */
free(locations);
@@ -1653,6 +1663,7 @@ GSM_Error SMSD_SendSMS(GSM_SMSDConfig *Config)
GSM_Error error;
unsigned int j;
int i, z;
+ char destinationnumber[3 * GSM_MAX_NUMBER_LENGTH + 1];
/* Clean structure before use */
for (i = 0; i < GSM_MAX_MULTI_SMS; i++) {
@@ -1683,6 +1694,10 @@ GSM_Error SMSD_SendSMS(GSM_SMSDConfig *Config)
if (Config->SMSID[0] != 0 && (Config->retries > Config->maxretries)) {
SMSD_Log(DEBUG_NOTICE, Config, "Moved to errorbox, reached MaxRetries: %s", Config->SMSID);
for (i=0;i<sms.Number;i++) {
+ if (Config->SkipMessage[i] == TRUE) {
+ SMSD_Log(DEBUG_NOTICE, Config, "Skipping %s:%d message for errorbox", Config->SMSID, i+1);
+ continue;
+ }
Config->Status->Failed++;
Config->Service->AddSentSMSInfo(&sms, Config, Config->SMSID, i + 1, SMSD_SEND_SENDING_ERROR, Config->TPMR);
}
@@ -1694,6 +1709,11 @@ GSM_Error SMSD_SendSMS(GSM_SMSDConfig *Config)
}
for (i = 0; i < sms.Number; i++) {
+ if (Config->SkipMessage[i] == TRUE) {
+ SMSD_Log(DEBUG_NOTICE, Config, "Skipping %s:%d message for delivery", Config->SMSID, i+1);
+ continue;
+ }
+
/* No SMSC set in message */
if (sms.SMS[i].SMSC.Location == 0 && UnicodeLength(sms.SMS[i].SMSC.Number) == 0 && Config->SMSC.Location == 0) {
SMSD_Log(DEBUG_INFO, Config, "Message without SMSC, using configured one");
@@ -1739,7 +1759,22 @@ GSM_Error SMSD_SendSMS(GSM_SMSDConfig *Config)
SMSD_PhoneStatus(Config);
Config->TPMR = -1;
Config->SendingSMSStatus = ERR_TIMEOUT;
- error = GSM_SendSMS(Config->gsm, &sms.SMS[i]);
+ Config->StatusCode = -1;
+ Config->Part = i + 1;
+ if (sms.SMS[i].Class == GSM_SMS_USSD) {
+ EncodeUTF8(destinationnumber, sms.SMS[i].Number);
+ SMSD_Log(DEBUG_NOTICE, Config, "Sending USSD request to %s", destinationnumber);
+ error = GSM_DialService(Config->gsm, destinationnumber);
+ /* Fallback to voice call, it can work with some phones */
+ if (error == ERR_NOTIMPLEMENTED || error == ERR_NOTSUPPORTED) {
+ error = GSM_DialVoice(Config->gsm, destinationnumber, GSM_CALL_DefaultNumberPresence);
+ }
+ if (error == ERR_NONE) {
+ Config->SendingSMSStatus = ERR_NONE;
+ }
+ } else {
+ error = GSM_SendSMS(Config->gsm, &sms.SMS[i]);
+ }
if (error != ERR_NONE) {
SMSD_LogError(DEBUG_INFO, Config, "Error sending SMS", error);
Config->TPMR = -1;
@@ -1787,13 +1822,13 @@ GSM_Error SMSD_SendSMS(GSM_SMSDConfig *Config)
}
if (Config->RunOnSent != NULL && error == ERR_NONE) {
- SMSD_RunOn(Config->RunOnSent, &sms, Config, Config->SMSID);
+ SMSD_RunOn(Config->RunOnSent, &sms, Config, Config->SMSID, "sent");
}
return ERR_NONE;
failure_unsent:
if (Config->RunOnFailure != NULL) {
- SMSD_RunOn(Config->RunOnFailure, NULL, Config, Config->SMSID);
+ SMSD_RunOn(Config->RunOnFailure, NULL, Config, Config->SMSID, "failure");
}
Config->Status->Failed++;
@@ -1924,6 +1959,7 @@ GSM_Error SMSD_FreeSharedMemory(GSM_SMSDConfig *Config, gboolean writable)
*/
void SMSD_IncomingCallCallback(GSM_StateMachine *s, GSM_Call *call, void *user_data) {
GSM_SMSDConfig *Config = user_data;
+ GSM_Error error;
switch (call->Status) {
case GSM_CALL_IncomingCall: {
time_t now = time(NULL);
@@ -1933,9 +1969,26 @@ void SMSD_IncomingCallCallback(GSM_StateMachine *s, GSM_Call *call, void *user_d
SMSD_Log(DEBUG_INFO, Config, "Incoming call! # hanging up @%ld %ld.\n", now, lastRing);
lastRing = now;
if (call->CallIDAvailable) {
- GSM_CancelCall(s, call->CallID, TRUE);
- } else {
- GSM_CancelCall(s, 0, TRUE);
+ error = GSM_CancelCall(s, call->CallID, TRUE);
+ }
+ if (!call->CallIDAvailable || error == ERR_NOTSUPPORTED) {
+ error = GSM_CancelCall(s, 0, TRUE);
+ }
+ if (error != ERR_NONE) {
+ SMSD_LogError(DEBUG_ERROR, Config, "Failed call hangup!", error);
+ }
+
+ if (Config->RunOnIncomingCall != NULL) {
+#define BUFS 1024
+ char buf[BUFS];
+ int ret=0;
+ snprintf(buf, BUFS,"%s '%s'",
+ Config->RunOnIncomingCall,
+ DecodeUnicodeString(call->PhoneNumber));
+ ret = system(buf);
+ if (ret<0) {
+ SMSD_Log(DEBUG_ERROR, Config, "Incoming call - could not run script: %s\n", strerror(errno) );
+ }
}
}
break;
@@ -1950,6 +2003,29 @@ void SMSD_IncomingCallCallback(GSM_StateMachine *s, GSM_Call *call, void *user_d
}
}
+void SMSD_IncomingUSSDCallback(GSM_StateMachine *sm UNUSED, GSM_USSDMessage *ussd, void *user_data)
+{
+ GSM_MultiSMSMessage sms;
+ GSM_Error error;
+ GSM_SMSDConfig *Config = user_data;
+
+ SMSD_Log(DEBUG_NOTICE, Config, "%s", __FUNCTION__);
+
+ memset(&sms, 0, sizeof(GSM_MultiSMSMessage));
+ sms.Number = 1;
+ sms.SMS[0].Class = GSM_SMS_USSD;
+ memcpy(&sms.SMS[0].Text, ussd->Text, UnicodeLength(ussd->Text)*2);
+ sms.SMS[0].PDU = SMS_Deliver;
+ sms.SMS[0].Coding = SMS_Coding_Unicode_No_Compression;
+ GSM_GetCurrentDateTime(&sms.SMS[0].DateTime);
+ sms.SMS[0].DeliveryStatus = ussd->Status;
+
+ error = SMSD_ProcessSMS(Config, &sms);
+ if (error != ERR_NONE) {
+ SMSD_LogError(DEBUG_INFO, Config, "Error processing USSD", error);
+ }
+}
+
/**
* Main loop which takes care of connection to phone and processing of
* messages.
@@ -2010,7 +2086,7 @@ GSM_Error SMSD_MainLoop(GSM_SMSDConfig *Config, gboolean exit_on_failure, int ma
error = GSM_InitConnection_Log(Config->gsm, 2, SMSD_Log_Function, Config);
/* run on error */
if (error != ERR_NONE && Config->RunOnFailure != NULL) {
- SMSD_RunOn(Config->RunOnFailure, NULL, Config, "INIT");
+ SMSD_RunOn(Config->RunOnFailure, NULL, Config, "INIT", "failure");
}
switch (error) {
case ERR_NONE:
@@ -2029,6 +2105,9 @@ GSM_Error SMSD_MainLoop(GSM_SMSDConfig *Config, gboolean exit_on_failure, int ma
/* We use polling so store messages to SIM */
GSM_SetIncomingSMS(Config->gsm, TRUE);
+ GSM_SetIncomingUSSDCallback(Config->gsm, SMSD_IncomingUSSDCallback, Config);
+ GSM_SetIncomingUSSD(Config->gsm, TRUE);
+
GSM_SetSendSMSStatusCallback(Config->gsm, SMSD_SendSMSStatusCallback, Config);
/* On first start we need to initialize some variables */
if (first_start) {
@@ -2039,7 +2118,7 @@ GSM_Error SMSD_MainLoop(GSM_SMSDConfig *Config, gboolean exit_on_failure, int ma
error = Config->Service->InitAfterConnect(Config);
if (error!=ERR_NONE) {
if (Config->RunOnFailure != NULL) {
- SMSD_RunOn(Config->RunOnFailure, NULL, Config, "INIT");
+ SMSD_RunOn(Config->RunOnFailure, NULL, Config, "INIT", "failure");
}
SMSD_Terminate(Config, "Post initialisation failed, stopping Gammu smsd", error, TRUE, -1);
goto done_connected;
@@ -2150,6 +2229,7 @@ GSM_Error SMSD_MainLoop(GSM_SMSDConfig *Config, gboolean exit_on_failure, int ma
SMSD_InterruptibleSleep(Config, Config->loopsleep - lastsleep);
}
}
+ GSM_SetIncomingUSSD(Config->gsm, FALSE);
Config->Service->Free(Config);
done_connected:
diff --git a/smsd/core.h b/smsd/core.h
index 9e7928e..de3476e 100644
--- a/smsd/core.h
+++ b/smsd/core.h
@@ -17,7 +17,7 @@
#define SMSD_SHM_VERSION (2)
#define SMSD_SHM_KEY (0xfa << 16 || SMSD_SHM_VERSION)
-#define SMSD_DB_VERSION (16)
+#define SMSD_DB_VERSION (17)
#include "log.h"
@@ -87,6 +87,7 @@ struct _GSM_SMSDConfig {
const char *RunOnReceive;
const char *RunOnFailure; /* run this command on phone communication failure */
const char *RunOnSent; /* run this command when an SMS has been sent successfully */
+ const char *RunOnIncomingCall; /* run this command when a phone call has been canceled */
gboolean checksecurity;
gboolean hangupcalls;
gboolean checkbattery;
@@ -109,6 +110,7 @@ struct _GSM_SMSDConfig {
GSM_SMSC SMSC, SMSCCache;
const char *skipsmscnumber;
int IgnoredMessages;
+ gboolean SkipMessage[GSM_MAX_MULTI_SMS];
#if defined(HAVE_MYSQL_MYSQL_H) || defined(HAVE_POSTGRESQL_LIBPQ_FE_H) || defined(LIBDBI_FOUND) || defined(ODBC_FOUND)
/* options for SQL database */
@@ -195,6 +197,8 @@ struct _GSM_SMSDConfig {
* Message reference set by callback from libGammu.
*/
volatile int TPMR;
+ volatile int StatusCode;
+ volatile int Part;
/**
* Multipart messages processing.
diff --git a/smsd/main.c b/smsd/main.c
index c3e4c3e..afde2aa 100644
--- a/smsd/main.c
+++ b/smsd/main.c
@@ -247,13 +247,13 @@ void process_commandline(int argc, char **argv, SMSD_Parameters * params)
#ifdef HAVE_UID
case 'U':
if (!fill_uid(params, optarg)) {
- fprintf(stderr, "Wrong user name/ID!\n");
+ fprintf(stderr, "Wrong user name or ID: %s\n", optarg);
exit(1);
}
break;
case 'G':
if (!fill_gid(params, optarg)) {
- fprintf(stderr, "Wrong group name/ID!\n");
+ fprintf(stderr, "Wrong group name or ID: %s\n", optarg);
exit(1);
}
break;
diff --git a/smsd/services/odbc.c b/smsd/services/odbc.c
index a57a1a0..e3c385e 100644
--- a/smsd/services/odbc.c
+++ b/smsd/services/odbc.c
@@ -125,9 +125,14 @@ const char *SMSDODBC_GetString(GSM_SMSDConfig * Config, SQL_result *res, unsigne
gboolean SMSDODBC_GetBool(GSM_SMSDConfig * Config, SQL_result *res, unsigned int field)
{
- long long intval;
+ long long intval = 0;
const char * charval;
+ /* Try bit field */
+ if (SQL_SUCCEEDED(SQLGetData(res->odbc, field + 1, SQL_C_BIT, &intval, 0, NULL))) {
+ return intval ? TRUE : FALSE;
+ }
+
/* Try to get numeric value first */
intval = SMSDODBC_GetNumber(Config, res, field);
if (intval == -1) {
diff --git a/smsd/services/sql-core.h b/smsd/services/sql-core.h
index 0383b9a..16e395e 100644
--- a/smsd/services/sql-core.h
+++ b/smsd/services/sql-core.h
@@ -119,6 +119,10 @@ enum {
SQL_QUERY_DELETE_OUTBOX_MULTIPART,
SQL_QUERY_CREATE_OUTBOX,
SQL_QUERY_CREATE_OUTBOX_MULTIPART,
+ SQL_QUERY_UPDATE_OUTBOX,
+ SQL_QUERY_UPDATE_OUTBOX_MULTIPART,
+ SQL_QUERY_UPDATE_OUTBOX_STATUSCODE,
+ SQL_QUERY_UPDATE_OUTBOX_MULTIPART_STATUSCODE,
SQL_QUERY_ADD_SENT_INFO,
SQL_QUERY_UPDATE_SENT,
SQL_QUERY_REFRESH_PHONE_STATUS,
diff --git a/smsd/services/sql.c b/smsd/services/sql.c
index 9e3ef33..1a2da63 100644
--- a/smsd/services/sql.c
+++ b/smsd/services/sql.c
@@ -49,7 +49,7 @@ const char now_plus_pgsql[] = "now() + interval '%d seconds'";
const char now_plus_sqlite[] = "datetime('now', '+%d seconds', 'localtime')";
const char now_plus_freetds[] = "DATEADD('second', %d, CURRENT_TIMESTAMP)";
const char now_plus_access[] = "now()+#00:00:%d#";
-const char now_plus_oracle[] = "CURRENT_TIMESTAMP + INTERVAL '%d' SECOND'";
+const char now_plus_oracle[] = "CURRENT_TIMESTAMP + INTERVAL '%d' SECOND";
const char now_plus_fallback[] = "NOW() + INTERVAL %d SECOND";
@@ -99,7 +99,9 @@ static const char *SMSDSQL_EscapeChar(GSM_SMSDConfig * Config)
return escape_char_pgsql;
} else if (strncasecmp(driver_name, "sqlite", 6) == 0) {
return escape_char_sqlite;
- } else if (strcasecmp(driver_name, "oracle") == 0 || strcasecmp(driver_name, "freetds") == 0 || strcasecmp(driver_name, "mssql") == 0 || strcasecmp(driver_name, "sybase") == 0) {
+ } else if (strcasecmp(driver_name, "oracle") == 0) {
+ return escape_char_fallback;
+ } else if (strcasecmp(driver_name, "freetds") == 0 || strcasecmp(driver_name, "mssql") == 0 || strcasecmp(driver_name, "sybase") == 0) {
return escape_char_freetds;
} else if (strcasecmp(Config->driver, "odbc") == 0 || strcasecmp(Config->driver, "mssql") == 0) {
return escape_char_odbc;
@@ -222,9 +224,9 @@ static const char *SMSDSQL_Now(GSM_SMSDConfig * Config)
return now_pgsql;
} else if (strncasecmp(driver_name, "sqlite", 6) == 0) {
return now_sqlite;
- } else if (strcasecmp(Config->driver, "oracle") == 0 || strcasecmp(driver_name, "freetds") == 0 || strcasecmp(driver_name, "mssql") == 0 || strcasecmp(driver_name, "sybase") == 0) {
+ } else if (strcasecmp(driver_name, "oracle") == 0 || strcasecmp(driver_name, "freetds") == 0 || strcasecmp(driver_name, "mssql") == 0 || strcasecmp(driver_name, "sybase") == 0) {
return now_freetds;
- } else if (strcasecmp(Config->driver, "access") == 0) {
+ } else if (strcasecmp(driver_name, "access") == 0) {
return now_access;
} else if (strcasecmp(Config->driver, "odbc") == 0) {
return now_odbc;
@@ -384,7 +386,16 @@ static GSM_Error SMSDSQL_NamedQuery(GSM_SMSDConfig * Config, const char *sql_que
if (sms != NULL) {
switch (c) {
case 'R':
- EncodeUTF8(static_buff, sms->Number);
+ /*
+ * Always store international numnbers with + prefix
+ * to allow easy matching later.
+ */
+ if (sms->Number[0] == '0' && sms->Number[1] == '0') {
+ static_buff[0] = '+';
+ EncodeUTF8(static_buff + 1, sms->Number + 2);
+ } else {
+ EncodeUTF8(static_buff, sms->Number);
+ }
to_print = static_buff;
break;
case 'F':
@@ -674,8 +685,8 @@ static GSM_Error SMSDSQL_SaveInboxSMS(GSM_MultiSMSMessage * sms, GSM_SMSDConfig
found = FALSE;
while (db->NextRow(Config, &res)) {
- smsc = db->GetString(Config, &res, 4);
state = db->GetString(Config, &res, 1);
+ smsc = db->GetString(Config, &res, 4);
SMSD_Log(DEBUG_NOTICE, Config, "Checking for delivery report, SMSC=%s, state=%s", smsc, state);
if (strcmp(smsc, smsc_message) != 0) {
@@ -814,12 +825,18 @@ static GSM_Error SMSDSQL_UpdateRetries(GSM_SMSDConfig * Config, char *ID)
{
SQL_result res;
GSM_Error error;
+ size_t query_type;
struct GSM_SMSDdbobj *db = Config->db;
- SQL_Var vars[3] = {
+ /* 1 = ID, 2 = Retries, 3 = StatusCode, 4 = SequencePosition */
+ SQL_Var vars[5] = {
{SQL_TYPE_STRING, {ID}},
{SQL_TYPE_INT, {NULL}},
+ {SQL_TYPE_INT, {NULL}},
+ {SQL_TYPE_INT, {NULL}},
{SQL_TYPE_NONE, {NULL}}};
vars[1].v.i = Config->retries;
+ vars[2].v.i = Config->StatusCode;
+ vars[3].v.i = Config->Part;
error = SMSDSQL_NamedQuery(Config, Config->SMSDSQL_queries[SQL_QUERY_UPDATE_RETRIES], NULL, vars, &res);
if (error != ERR_NONE) {
@@ -833,6 +850,17 @@ static GSM_Error SMSDSQL_UpdateRetries(GSM_SMSDConfig * Config, char *ID)
}
db->FreeResult(Config, &res);
+
+ if (Config->StatusCode != -1) {
+ query_type = (Config->Part == 1) ? SQL_QUERY_UPDATE_OUTBOX_STATUSCODE : SQL_QUERY_UPDATE_OUTBOX_MULTIPART_STATUSCODE;
+ error = SMSDSQL_NamedQuery(Config, Config->SMSDSQL_queries[query_type], NULL, vars, &res);
+ if (error != ERR_NONE) {
+ SMSD_Log(DEBUG_INFO, Config, "Error updating StatusCode (%s)", __FUNCTION__);
+ return error;
+ }
+ db->FreeResult(Config, &res);
+ }
+
return ERR_NONE;
}
@@ -844,6 +872,7 @@ static GSM_Error SMSDSQL_FindOutboxSMS(GSM_MultiSMSMessage * sms, GSM_SMSDConfig
SQL_result res;
struct GSM_SMSDdbobj *db = Config->db;
int i;
+ gboolean last;
time_t timestamp;
const char *coding;
const char *text;
@@ -852,6 +881,7 @@ static GSM_Error SMSDSQL_FindOutboxSMS(GSM_MultiSMSMessage * sms, GSM_SMSDConfig
const char *destination;
const char *udh;
const char *q;
+ const char *status;
size_t udh_len;
SQL_Var vars[3];
GSM_Error error;
@@ -917,21 +947,33 @@ static GSM_Error SMSDSQL_FindOutboxSMS(GSM_MultiSMSMessage * sms, GSM_SMSDConfig
return ERR_NONE;
}
- coding = db->GetString(Config, &res, 1);
+ status = db->GetString(Config, &res, i == 1 ? 12 : 7);
+ if (status != NULL && strncmp(status, "SendingOK", 9) == 0) {
+ SMSD_Log(DEBUG_NOTICE, Config, "Marking %s:%d message for skip", ID, i);
+ Config->SkipMessage[sms->Number] = TRUE;
+ } else {
+ Config->SkipMessage[sms->Number] = FALSE;
+ }
+
text = db->GetString(Config, &res, 0);
+ coding = db->GetString(Config, &res, 1);
if (text == NULL) {
text_len = 0;
} else {
text_len = strlen(text);
}
- text_decoded = db->GetString(Config, &res, 4);
udh = db->GetString(Config, &res, 2);
+ sms->SMS[sms->Number].Class = (int)db->GetNumber(Config, &res, 3);
+ text_decoded = db->GetString(Config, &res, 4);
if (udh == NULL) {
udh_len = 0;
} else {
udh_len = strlen(udh);
}
+ /* ID, we don't need it, but some ODBC backend need to fetch all values */
+ db->GetNumber(Config, &res, 5);
+
sms->SMS[sms->Number].Coding = GSM_StringToSMSCoding(coding);
if (sms->SMS[sms->Number].Coding == 0) {
if (text == NULL || text_len == 0) {
@@ -996,26 +1038,24 @@ static GSM_Error SMSDSQL_FindOutboxSMS(GSM_MultiSMSMessage * sms, GSM_SMSDConfig
}
}
- sms->SMS[sms->Number].Class = (int)db->GetNumber(Config, &res, 3);
sms->SMS[sms->Number].PDU = SMS_Submit;
sms->Number++;
if (i == 1) {
- strncpy(Config->CreatorID, db->GetString(Config, &res, 10), sizeof(Config->CreatorID));
- Config->CreatorID[sizeof(Config->CreatorID) - 1] = 0;
+ /* Is this a multipart message? */
+ last = !db->GetBool(Config, &res, 7);
Config->relativevalidity = (int)db->GetNumber(Config, &res, 8);
Config->currdeliveryreport = db->GetBool(Config, &res, 9);
+ strncpy(Config->CreatorID, db->GetString(Config, &res, 10), sizeof(Config->CreatorID));
+ Config->CreatorID[sizeof(Config->CreatorID) - 1] = 0;
Config->retries = (int)db->GetNumber(Config, &res, 11);
-
- /* Is this a multipart message? */
- if (!db->GetBool(Config, &res, 7)) {
- db->FreeResult(Config, &res);
- break;
- }
-
}
db->FreeResult(Config, &res);
+ if (last) {
+ last = FALSE;
+ break;
+ }
}
return ERR_NONE;
@@ -1110,9 +1150,10 @@ static GSM_Error SMSDSQL_AddSentSMSInfo(GSM_MultiSMSMessage * sms, GSM_SMSDConfi
SQL_result res;
struct GSM_SMSDdbobj *db = Config->db;
GSM_Error error;
+ size_t query_type;
const char *message_state;
- SQL_Var vars[6];
+ SQL_Var vars[7];
char smsc[GSM_MAX_NUMBER_LENGTH + 1];
char destination[GSM_MAX_NUMBER_LENGTH + 1];
@@ -1150,6 +1191,22 @@ static GSM_Error SMSDSQL_AddSentSMSInfo(GSM_MultiSMSMessage * sms, GSM_SMSDConfi
vars[4].v.s = Config->DT;
vars[5].type = SQL_TYPE_NONE;
+ query_type = (Part == 1) ? SQL_QUERY_FIND_OUTBOX_BODY : SQL_QUERY_FIND_OUTBOX_MULTIPART;
+ error = SMSDSQL_NamedQuery(Config, Config->SMSDSQL_queries[query_type], NULL, vars, &res);
+ if (error != ERR_NONE) {
+ SMSD_Log(DEBUG_ERROR, Config, "Error reading from database (%s)", __FUNCTION__);
+ return error;
+ }
+ if (db->NextRow(Config, &res) != 1) {
+ db->FreeResult(Config, &res);
+ return ERR_NONE;
+ }
+ /* 6 = StatusCode */
+ vars[5].type = SQL_TYPE_INT;
+ vars[5].v.i = (int)db->GetNumber(Config, &res, Part == 1 ? 13 : 8);
+ vars[6].type = SQL_TYPE_NONE;
+ db->FreeResult(Config, &res);
+
error = SMSDSQL_NamedQuery(Config, Config->SMSDSQL_queries[SQL_QUERY_ADD_SENT_INFO], &sms->SMS[Part - 1], vars, &res);
if (error != ERR_NONE) {
SMSD_Log(DEBUG_INFO, Config, "Error writing to database (%s)", __FUNCTION__);
@@ -1164,6 +1221,16 @@ static GSM_Error SMSDSQL_AddSentSMSInfo(GSM_MultiSMSMessage * sms, GSM_SMSDConfi
}
db->FreeResult(Config, &res);
+ if (sms->Number != 1) {
+ query_type = (Part == 1) ? SQL_QUERY_UPDATE_OUTBOX : SQL_QUERY_UPDATE_OUTBOX_MULTIPART;
+ error = SMSDSQL_NamedQuery(Config, Config->SMSDSQL_queries[query_type], &sms->SMS[Part - 1], vars, &res);
+ if (error != ERR_NONE) {
+ SMSD_Log(DEBUG_INFO, Config, "Error updating status of multipart messages (%s)", __FUNCTION__);
+ return error;
+ }
+ db->FreeResult(Config, &res);
+ }
+
return ERR_NONE;
}
@@ -1426,8 +1493,9 @@ GSM_Error SMSDSQL_ReadConfiguration(GSM_SMSDConfig *Config)
", ", ESCAPE_FIELD("UDH"),
", ", ESCAPE_FIELD("Class"),
", ", ESCAPE_FIELD("TextDecoded"),
- ", ", ESCAPE_FIELD("RecipientID"), ")"
- " VALUES (%d, %E, %R, %c, %F, %u, %x, %T, %P)", NULL) != ERR_NONE) {
+ ", ", ESCAPE_FIELD("RecipientID"),
+ ", ", ESCAPE_FIELD("Status"), ")",
+ " VALUES (%d, %E, %R, %c, %F, %u, %x, %T, %P, %e)", NULL) != ERR_NONE) {
return ERR_UNKNOWN;
}
@@ -1486,6 +1554,8 @@ GSM_Error SMSDSQL_ReadConfiguration(GSM_SMSDConfig *Config)
", ", ESCAPE_FIELD("DeliveryReport"),
", ", ESCAPE_FIELD("CreatorID"),
", ", ESCAPE_FIELD("Retries"),
+ ", ", ESCAPE_FIELD("Status"),
+ ", ", ESCAPE_FIELD("StatusCode"),
" FROM ", Config->table_outbox, " WHERE ",
ESCAPE_FIELD("ID"), "=%1", NULL) != ERR_NONE) {
return ERR_UNKNOWN;
@@ -1500,6 +1570,8 @@ GSM_Error SMSDSQL_ReadConfiguration(GSM_SMSDConfig *Config)
", ", ESCAPE_FIELD("TextDecoded"),
", ", ESCAPE_FIELD("ID"),
", ", ESCAPE_FIELD("SequencePosition"),
+ ", ", ESCAPE_FIELD("Status"),
+ ", ", ESCAPE_FIELD("StatusCode"),
" FROM ", Config->table_outbox_multipart, " WHERE ",
ESCAPE_FIELD("ID"), "=%1 AND ",
ESCAPE_FIELD("SequencePosition"), "=%2", NULL) != ERR_NONE) {
@@ -1547,6 +1619,36 @@ GSM_Error SMSDSQL_ReadConfiguration(GSM_SMSDConfig *Config)
return ERR_UNKNOWN;
}
+ if (SMSDSQL_option(Config, SQL_QUERY_UPDATE_OUTBOX, "update_outbox",
+ "UPDATE ", Config->table_outbox, " SET ",
+ ESCAPE_FIELD("Status"), "=%3 WHERE ",
+ ESCAPE_FIELD("ID"), "=%1", NULL) != ERR_NONE) {
+ return ERR_UNKNOWN;
+ }
+
+ if (SMSDSQL_option(Config, SQL_QUERY_UPDATE_OUTBOX_MULTIPART, "update_outbox_multipart",
+ "UPDATE ", Config->table_outbox_multipart, " SET ",
+ ESCAPE_FIELD("Status"), "=%3 WHERE ",
+ ESCAPE_FIELD("ID"), "=%1 AND ",
+ ESCAPE_FIELD("SequencePosition"), "=%2", NULL) != ERR_NONE) {
+ return ERR_UNKNOWN;
+ }
+
+ if (SMSDSQL_option(Config, SQL_QUERY_UPDATE_OUTBOX_STATUSCODE, "update_outbox_statuscode",
+ "UPDATE ", Config->table_outbox, " SET ",
+ ESCAPE_FIELD("StatusCode"), "=%3 WHERE ",
+ ESCAPE_FIELD("ID"), "=%1", NULL) != ERR_NONE) {
+ return ERR_UNKNOWN;
+ }
+
+ if (SMSDSQL_option(Config, SQL_QUERY_UPDATE_OUTBOX_MULTIPART_STATUSCODE, "update_outbox_multipart_statuscode",
+ "UPDATE ", Config->table_outbox_multipart, " SET ",
+ ESCAPE_FIELD("StatusCode"), "=%3 WHERE ",
+ ESCAPE_FIELD("ID"), "=%1 AND ",
+ ESCAPE_FIELD("SequencePosition"), "=%4", NULL) != ERR_NONE) {
+ return ERR_UNKNOWN;
+ }
+
if (SMSDSQL_option(Config, SQL_QUERY_ADD_SENT_INFO, "add_sent_info",
"INSERT INTO ", Config->table_sentitems, " "
"(", ESCAPE_FIELD("CreatorID"),
@@ -1565,10 +1667,11 @@ GSM_Error SMSDSQL_ReadConfiguration(GSM_SMSDConfig *Config)
", ", ESCAPE_FIELD("TextDecoded"),
", ", ESCAPE_FIELD("InsertIntoDB"),
", ", ESCAPE_FIELD("RelativeValidity"),
+ ", ", ESCAPE_FIELD("StatusCode"),
") "
" VALUES (%A, %1, %2, %3, ",
SMSDSQL_Now(Config),
- ", %F, %4, %P, %E, %R, %c, %u, %x, %T, %5, %V)", NULL) != ERR_NONE) {
+ ", %F, %4, %P, %E, %R, %c, %u, %x, %T, %5, %V, %6)", NULL) != ERR_NONE) {
return ERR_UNKNOWN;
}
diff --git a/smsd/test-smsd.sh.in b/smsd/test-smsd.sh.in
index 0350565..f319382 100755
--- a/smsd/test-smsd.sh.in
+++ b/smsd/test-smsd.sh.in
@@ -9,7 +9,8 @@ SMSD_CMD="$2"
SMSD_INJECT_CMD="$3"
SMSD_MONITOR_CMD="$4"
-TEST_MATCH=";999999999999999;994299429942994;3;9;0;100;42"
+TEST_MATCH=";999999999999999;994299429942994;4;10;0;100;42"
+INCOMING_USSD=1
if [ "x@HAVE_KILL@" = x1 ] ; then
SMSD_EXTRA_PARAMS="-p @CMAKE_CURRENT_BINARY_DIR@/smsd-test-$SERVICE/smsd.pid"
@@ -115,6 +116,7 @@ EOT
;;
null)
TEST_MATCH=";999999999999999;994299429942994;0;9;0;100;42"
+ INCOMING_USSD=0
cat >> .smsdrc <<EOT
service = null
EOT
@@ -194,7 +196,8 @@ case $SERVICE in
esac
$SMSD_INJECT_CMD -c "$CONFIG_PATH" TEXT 123465 -text "Lorem ipsum." &
-$SMSD_INJECT_CMD -c "$CONFIG_PATH" TEXT 123465 -text "Lorem ipsum."
+$SMSD_INJECT_CMD -c "$CONFIG_PATH" TEXT 123465 -text "Lorem ipsum." &
+$SMSD_INJECT_CMD -c "$CONFIG_PATH" USSD 123465
$SMSD_CMD -c "$CONFIG_PATH" $SMSD_EXTRA_PARAMS &
SMSD_PID=$!
@@ -222,7 +225,7 @@ sleep 5
$SMSD_MONITOR_CMD -C -c "$CONFIG_PATH" -n 1 -d 0
-if [ `wc -l < @CMAKE_CURRENT_BINARY_DIR@/smsd-test-$SERVICE/received.log` -ne 8 ] ; then
+if [ `wc -l < @CMAKE_CURRENT_BINARY_DIR@/smsd-test-$SERVICE/received.log` -ne $((8 + $INCOMING_USSD)) ] ; then
echo "ERROR: Wrong number of messages received!"
exit 1
fi
@@ -231,3 +234,8 @@ if ! grep -q -F 'MMS_ADDRESS=http://mmscz/?m=m5da5a9jn210ma56q20' @CMAKE_CURRENT
echo "ERROR: Wrong MMS message received!"
exit 1
fi
+
+if [ $INCOMING_USSD -gt 0 ] && ! grep -q -F 'Reply for 123465' @CMAKE_CURRENT_BINARY_DIR@/smsd-test-$SERVICE/env.log ; then
+ echo "ERROR: Got no correct USSD reply!"
+ exit 1
+fi
diff --git a/smsd/uid.c b/smsd/uid.c
index 17900c0..1041513 100644
--- a/smsd/uid.c
+++ b/smsd/uid.c
@@ -54,7 +54,7 @@ gboolean fill_uid(SMSD_Parameters *params, const char *name)
if (pwd == NULL) {
/* Try to handle it as a number */
uid = strtol(name, &endptr, 10);
- if (*endptr == 0 && uid > 0) {
+ if (*endptr == 0 && uid >= 0) {
pwd = getpwuid(uid);
}
}
@@ -85,7 +85,7 @@ gboolean fill_gid(SMSD_Parameters *params, const char *name)
/* Try to handle it as a number */
if (grp == NULL) {
gid = strtol(name, &endptr, 10);
- if (*endptr == 0 && gid > 0) {
+ if (*endptr == 0 && gid >= 0) {
grp = getgrgid(gid);
}
}