From f090469e2776fea6a27a7ac6612b666d20dc9a05 Mon Sep 17 00:00:00 2001 From: James Maki Date: Fri, 10 Sep 2010 10:49:55 -0500 Subject: sms using text mode --- src/atcmd.c | 117 ++++++++++++++++++--- src/atcmd.h | 3 + src/cmd_options.h | 3 +- src/global.h | 2 + src/pdu.c | 14 +-- src/pdu.h | 10 +- src/pdu_decode.c | 2 +- src/pdu_decode.h | 2 +- src/pdu_encode.c | 2 +- src/pdu_encode.h | 2 +- src/pdu_encoder.c | 4 +- src/sms.config.example | 1 + src/sms_config.c | 9 ++ src/sms_list.c | 274 ++++++++++++++++++++++++++++++++++++++++++++++--- src/sms_main.c | 15 ++- src/sms_send.c | 82 ++++++++++----- 16 files changed, 467 insertions(+), 75 deletions(-) diff --git a/src/atcmd.c b/src/atcmd.c index aad15e9..8c6c3f0 100644 --- a/src/atcmd.c +++ b/src/atcmd.c @@ -674,6 +674,51 @@ int atcmd_plus_cmgw_write(int fd, const char *msg, size_t msg_len) return mem_index; } +int atcmd_plus_cmgw_write_text(int fd, const char *addr, int addr_type, + const char *status, const char *msg, size_t msg_len) +{ + char buf[ATCMD_LINE_SIZE]; + int tmp; + int mem_index; + + atcmd_printf(fd, "AT+CMGW"); + if (addr) { + atcmd_printf(fd, "=\"%s\"", addr); + if (addr_type != SMS_ADDR_UNSPEC) { + atcmd_printf(fd, ",%d", addr_type); + if (status) { + atcmd_printf(fd, ",\"%s\"", status); + } + } + } + atcmd_write_str(fd, ATCMD_EOL); + + tmp = atcmd_read_until(fd, buf, sizeof(buf), "> "); + if (tmp <= 0) { + log_debug("expected > start sequence but it was not received"); + return -1; + } + + tmp = atcmd_write(fd, msg, strlen(msg)); + tmp = atcmd_write_str(fd, CONTROL_Z_STR); + + tmp = atcmd_expect_line(fd, buf, sizeof(buf), "+CMGW: "); + if (tmp <= 0) { + log_debug("expected +CMGW: but it was not received"); + return -1; + } + + mem_index = atoi(buf + strlen("+CMGW: ")); + + tmp = atcmd_expect_line(fd, buf, sizeof(buf), "OK"); + if (tmp <= 0) { + log_debug("expected OK but it was not received"); + return -1; + } + + return mem_index; +} + int atcmd_plus_cmgs_write(int fd, const char *msg, size_t msg_len) { char buf[ATCMD_LINE_SIZE]; @@ -706,6 +751,38 @@ int atcmd_plus_cmgs_write(int fd, const char *msg, size_t msg_len) return msg_ref; } +int atcmd_plus_cmgs_write_text(int fd, const char *addr, const char *msg, size_t msg_len) +{ + char buf[ATCMD_LINE_SIZE]; + int tmp; + int msg_ref; + + atcmd_writeline(fd, "AT+CMGS=\"%s\"", addr); + tmp = atcmd_read_until(fd, buf, sizeof(buf), "> "); + if (tmp <= 0) { + log_debug("expected > start sequence but it was not received"); + return -1; + } + + tmp = atcmd_write(fd, msg, strlen(msg)); + tmp = atcmd_write_str(fd, CONTROL_Z_STR); + + tmp = atcmd_expect_line(fd, buf, sizeof(buf), "+CMGS: "); + if (tmp <= 0) { + log_debug("expected +CMGS: but it was not received"); + return -1; + } + msg_ref = atoi(buf + strlen("+CMGS: ")); + + tmp = atcmd_expect_line(fd, buf, sizeof(buf), "OK"); + if (tmp <= 0) { + log_debug("expected OK but it was not received"); + return -1; + } + + return msg_ref; +} + int atcmd_plus_cmss_write(int fd, int index, const char *addr, int addr_type) { char buf[ATCMD_LINE_SIZE]; @@ -785,6 +862,10 @@ int atcmd_plus_cpms_read(int fd, struct data_store *read_store, struct data_store *data_stores[] = {read_store, send_store, new_store}; struct data_store *store; + memset(read_store, 0, sizeof(*read_store)); + memset(send_store, 0, sizeof(*send_store)); + memset(new_store, 0, sizeof(*new_store)); + atcmd_writeline(fd, "AT+CPMS?"); tmp = atcmd_expect_line(fd, buf, sizeof(buf), "+CPMS: "); if (tmp <= 0) { @@ -804,7 +885,7 @@ int atcmd_plus_cpms_read(int fd, struct data_store *read_store, token = atcmd_value_tok(&save); if (!token) { - return -1; + break; } strncpy(store->name, token, STORE_NAME_LEN); @@ -906,8 +987,15 @@ int atcmd_plus_cpms_write(int fd, const char *read_name, char buf[ATCMD_LINE_SIZE]; int tmp; - atcmd_writeline(fd, "AT+CPMS=\"%s\",\"%s\",\"%s\"", - read_name, send_name, new_name); + atcmd_printf(fd, "AT+CPMS=\"%s\"", read_name); + if (send_name) { + atcmd_printf(fd, ",\"%s\"", send_name); + if (new_name) { + atcmd_printf(fd, ",\"%s\"", new_name); + } + } + atcmd_write_str(fd, ATCMD_EOL); + tmp = atcmd_expect_line(fd, buf, sizeof(buf), "OK"); if (tmp <= 0) { log_debug("expected OK but it was not received"); @@ -1158,9 +1246,9 @@ static int sms_atcmd_init(int fd) return -1; } - tmp = atcmd_plus_cmgf_write(fd, SMS_PDU_MODE); + tmp = atcmd_plus_cmgf_write(fd, Global.core.sms_mode); if (tmp < 0) { - return -1; + log_error("atcmd_plus_cmgf_write failed"); } memset(&read_store, 0, sizeof(read_store)); @@ -1175,25 +1263,28 @@ static int sms_atcmd_init(int fd) Global.core.msg_store_new) { if (!msg_store_choice(&read_store, Global.core.msg_store_read)) { - log_error("message storage location %s is not a choice", + log_error("read message storage location %s is not a choice", Global.core.msg_store_read); return -1; } - if (!msg_store_choice(&send_store, Global.core.msg_store_send)) { - log_error("message storage location %s is not a choice", + if (*Global.core.msg_store_send && !msg_store_choice(&send_store, Global.core.msg_store_send)) { + log_error("send message storage location %s is not a choice", Global.core.msg_store_send); return -1; } - if (!msg_store_choice(&new_store, Global.core.msg_store_new)) { - log_error("message storage location %s is not a choice", + if (*Global.core.msg_store_new && !msg_store_choice(&new_store, Global.core.msg_store_new)) { + log_error("new message storage location %s is not a choice", Global.core.msg_store_new); return -1; } - tmp = atcmd_plus_cpms_write(fd, Global.core.msg_store_read, - Global.core.msg_store_send, Global.core.msg_store_new); + tmp = atcmd_plus_cpms_write(fd, + Global.core.msg_store_read, + *Global.core.msg_store_send ? Global.core.msg_store_send : NULL, + *Global.core.msg_store_new ? Global.core.msg_store_new : NULL + ); if (tmp < 0) { - return -1; + log_error("atcmd_plus_cpms_write failed"); } } diff --git a/src/atcmd.h b/src/atcmd.h index de6eeee..6461250 100644 --- a/src/atcmd.h +++ b/src/atcmd.h @@ -62,7 +62,10 @@ int atcmd_v_write(int fd, int mode); int atcmd_q_write(int fd, int mode); int atcmd_plus_cmgf_write(int fd, int mode); int atcmd_plus_cmgw_write(int fd, const char *msg, size_t msg_len); +int atcmd_plus_cmgw_write_text(int fd, const char *addr, int addr_type, + const char *status, const char *msg, size_t msg_len); int atcmd_plus_cmgs_write(int fd, const char *msg, size_t msg_len); +int atcmd_plus_cmgs_write_text(int fd, const char *addr, const char *msg, size_t msg_len); int atcmd_plus_cmss_write(int fd, int index, const char *addr, int addr_type); int atcmd_plus_cmgd_write(int fd, int index); diff --git a/src/cmd_options.h b/src/cmd_options.h index fef1b16..7f5eb5c 100644 --- a/src/cmd_options.h +++ b/src/cmd_options.h @@ -21,10 +21,11 @@ enum cmd_opt_long_only { CMD_OPT_READ_TIMEOUT, CMD_OPT_ALPHABET, CMD_OPT_SMSC_ADDR, - CMD_OPT_CMGW_FIRST, + CMD_OPT_SEND_MODE, CMD_OPT_MSG_STORE_READ, CMD_OPT_MSG_STORE_SEND, CMD_OPT_MSG_STORE_NEW, + CMD_OPT_SMS_MODE, CMD_OPT_PHONEBOOK_STORE, CMD_OPT_SUBJECT, }; diff --git a/src/global.h b/src/global.h index fe8f5c2..5e2ffd8 100644 --- a/src/global.h +++ b/src/global.h @@ -30,6 +30,8 @@ struct global_core { char *msg_store_new; char *pb_store; + int sms_mode; + char *editor; char *edit_file; }; diff --git a/src/pdu.c b/src/pdu.c index 2ceb7ae..9221485 100644 --- a/src/pdu.c +++ b/src/pdu.c @@ -162,7 +162,7 @@ int pdu_format_vp(struct pdu_info *pdu, char *str, size_t len) } } -int pdu_addr_check(const char *addr_str) +int sms_addr_check(const char *addr_str) { if (addr_str[0] == '+') { addr_str++; @@ -188,7 +188,7 @@ int pdu_addr_check(const char *addr_str) #define NUM_ADDR "1234567890-." #define CMD_ADDR "1234567890*#+-." -int pdu_addr_type_infer(const char *str) +int sms_addr_type_infer(const char *str) { if (*str == '+' && strlen(str + 1) == strspn(str + 1, NUM_ADDR)) { log_debug("SMS_ADDR_GLOBAL"); @@ -205,7 +205,7 @@ int pdu_addr_type_infer(const char *str) } } -static int pdu_addr_clean_copy(struct pdu_addr *addr, const char *src) +static int sms_addr_clean_copy(struct sms_addr *addr, const char *src) { char *dest = addr->addr; int count = 0; @@ -238,15 +238,15 @@ static int pdu_addr_clean_copy(struct pdu_addr *addr, const char *src) return count; } -int pdu_addr_fill(struct pdu_addr *addr, const char *addr_str, int type) +int sms_addr_fill(struct sms_addr *addr, const char *addr_str, int type) { int tmp; memset(addr, 0 , sizeof(*addr)); - addr->type = pdu_addr_type_infer(addr_str); + addr->type = sms_addr_type_infer(addr_str); - tmp = pdu_addr_clean_copy(addr, addr_str); + tmp = sms_addr_clean_copy(addr, addr_str); if (tmp < 0) { return tmp; } @@ -300,7 +300,7 @@ done: pdu->user_data[total] = '\0'; pdu->user_data_len = total; - debug_buffer("message is: ", pdu->user_data, total); + debug_buffer("message is:", pdu->user_data, total); return total; } diff --git a/src/pdu.h b/src/pdu.h index 0305550..269b157 100644 --- a/src/pdu.h +++ b/src/pdu.h @@ -24,7 +24,7 @@ extern char *strptime(const char *s, const char *format, struct tm *tm); #define PDU_VPF_RELATIVE_2DAYS 0xA8 -struct pdu_addr { +struct sms_addr { char addr[PDU_ADDR_SIZE]; uint8_t type; uint8_t len; @@ -53,8 +53,8 @@ enum { struct pdu_info { int msg_len; - struct pdu_addr smsc_addr; - struct pdu_addr addr; + struct sms_addr smsc_addr; + struct sms_addr addr; union { uint8_t type; struct { @@ -105,8 +105,8 @@ int strpad(char *str, size_t len, unsigned char c); int pdu_format_timestamp(struct pdu_info *pdu, char *str, size_t len, const char *fmt); int pdu_format_vp(struct pdu_info *pdu, char *str, size_t len); -int pdu_addr_type_infer(const char *str); -int pdu_addr_fill(struct pdu_addr *addr, const char *addr_str, int type); +int sms_addr_type_infer(const char *str); +int sms_addr_fill(struct sms_addr *addr, const char *addr_str, int type); int pdu_user_data_read(int fd, struct pdu_info *pdu); #define shiftr(a, n) ((a) >> (n)) diff --git a/src/pdu_decode.c b/src/pdu_decode.c index 643fa15..4951ac7 100644 --- a/src/pdu_decode.c +++ b/src/pdu_decode.c @@ -82,7 +82,7 @@ int pdu_decode_timestamp(const char *pdu_str, struct tm *tm) return PDU_TIMESTAMP_LEN; } -int pdu_decode_addr(const char *pdu_str, struct pdu_addr *addr, int smsc) +int pdu_decode_addr(const char *pdu_str, struct sms_addr *addr, int smsc) { const char *begin = pdu_str; int addr_len; diff --git a/src/pdu_decode.h b/src/pdu_decode.h index 004c8ad..269bf88 100644 --- a/src/pdu_decode.h +++ b/src/pdu_decode.h @@ -4,7 +4,7 @@ #include "pdu.h" int pdu_decode_timestamp(const char *pdu_str, struct tm *tm); -int pdu_decode_addr(const char *pdu_str, struct pdu_addr *addr, int smsc); +int pdu_decode_addr(const char *pdu_str, struct sms_addr *addr, int smsc); int pdu_decode_user_data(const char *pdu_str, struct pdu_info *pdu); int pdu_decode(const char *pdu_str, struct pdu_info *pdu); diff --git a/src/pdu_encode.c b/src/pdu_encode.c index 30cb4a9..e3bee18 100644 --- a/src/pdu_encode.c +++ b/src/pdu_encode.c @@ -80,7 +80,7 @@ int pdu_encode_timestamp(char *pdu_str, size_t len, struct tm *tm) return PDU_TIMESTAMP_LEN; } -int pdu_encode_addr(char *pdu_str, size_t len, struct pdu_addr *addr, int smsc) +int pdu_encode_addr(char *pdu_str, size_t len, struct sms_addr *addr, int smsc) { char *begin = pdu_str; int addr_len; diff --git a/src/pdu_encode.h b/src/pdu_encode.h index 246ea3d..c47bade 100644 --- a/src/pdu_encode.h +++ b/src/pdu_encode.h @@ -4,7 +4,7 @@ #include "pdu.h" int pdu_encode_timestamp(char *pdu_str, size_t len, struct tm *tm); -int pdu_encode_addr(char *pdu_str, size_t len, struct pdu_addr *addr, int smsc); +int pdu_encode_addr(char *pdu_str, size_t len, struct sms_addr *addr, int smsc); int pdu_encode_user_data(char *pdu_str, size_t len, struct pdu_info *pdu); int pdu_encode(char *pdu_str, size_t len, struct pdu_info *pdu); diff --git a/src/pdu_encoder.c b/src/pdu_encoder.c index c2a046a..3df3016 100644 --- a/src/pdu_encoder.c +++ b/src/pdu_encoder.c @@ -148,11 +148,11 @@ int main(int argc, char *argv[]) pdu.data_coding.general.alphabet = alphabet; if (smsc_addr) { - pdu_addr_fill(&pdu.smsc_addr, smsc_addr, SMS_ADDR_UNSPEC); + sms_addr_fill(&pdu.smsc_addr, smsc_addr, SMS_ADDR_UNSPEC); } if (argc) { - pdu_addr_fill(&pdu.addr, *argv, SMS_ADDR_UNSPEC); + sms_addr_fill(&pdu.addr, *argv, SMS_ADDR_UNSPEC); argc++; argv--; } diff --git a/src/sms.config.example b/src/sms.config.example index 5081f17..c614d91 100644 --- a/src/sms.config.example +++ b/src/sms.config.example @@ -15,6 +15,7 @@ core: msg-store-send: ME msg-store-new: ME pb-store: ME + sms-mode: pdu editor: vi edit-file: "${HOME}/.smsmsg" diff --git a/src/sms_config.c b/src/sms_config.c index 2d44e18..08bac12 100644 --- a/src/sms_config.c +++ b/src/sms_config.c @@ -15,6 +15,7 @@ #endif #include "atcmd.h" +#include "sms_utils.h" #include "utils.h" #include "log.h" @@ -131,6 +132,14 @@ static int config_set_core_value(const char *key, const char *value) } else if (!strcmp("pb-store", key)) { free(Global.core.pb_store); Global.core.pb_store = strdup(value); + } else if (!strcmp("sms-mode", key)) { + if (!strcmp(value, "text")) { + Global.core.sms_mode = SMS_TEXT_MODE; + } else if (!strcmp(value, "pdu")) { + Global.core.sms_mode = SMS_PDU_MODE; + } else { + log_warning("invalid sms-mode: %s", value); + } } else if (!strcmp("editor", key)) { free(Global.core.editor); Global.core.editor = strdup(value); diff --git a/src/sms_list.c b/src/sms_list.c index 0ccec15..e6f29f1 100644 --- a/src/sms_list.c +++ b/src/sms_list.c @@ -42,6 +42,236 @@ #define CMGL_HEADER_START "+CMGL: " #define CMGR_HEADER_START "+CMGR: " +static int decode_timestamp_text_mode(const char *str, struct tm *tm) +{ + char *cp; + struct tm tm_now; + time_t now = time(NULL); + + localtime_r(&now, &tm_now); + + memset(tm, 0, sizeof(*tm)); + + cp = (char *) strptime(str, "%y/%m/%d,%H:%M:%S", tm); + if (!cp || *cp) { + log_error("timestamp could not be converted to tm"); + return -1; + } + + tm->tm_gmtoff = tm_now.tm_gmtoff; + + return 0; +} + +static int process_header_text_mode(struct msg_list_info *list_info, char *buf, size_t len) +{ + char *save = buf; + char *token; + + struct sms_msg *msg; + int index; + int status; + char *name; + char *timestamp = NULL; + int msg_len; + + token = atcmd_response_brk(&save); + if (!token) { + log_debug("response tokenizing failed at start"); + return -1; + } + + switch (list_info->cmd_type) { + case CMD_TYPE_CMGL: + token = atcmd_value_tok(&save); + if (!token) { + log_debug("response tokenizing failed at index"); + return -1; + } + index = atoi(token); + + break; + case CMD_TYPE_CMGR: + index = list_info->index; + break; + default: + return false; + } + + token = atcmd_value_tok(&save); + if (!token) { + log_debug("response tokenizing failed at msg-status"); + return -1; + } + status = msg_status_name_to_value(token); + + token = atcmd_value_tok(&save); + if (!token) { + log_debug("response tokenizing failed at name"); + return -1; + } + name = token; + + if (list_info->cmd_type == CMD_TYPE_CMGR) { + timestamp = atcmd_value_tok(&save); + if (!token) { + log_debug("response tokenizing failed at timestamp"); + return -1; + } + } + + token = atcmd_value_tok(&save); + if (!token) { + log_debug("response tokenizing failed at lang"); + return -1; + } + + token = atcmd_value_tok(&save); + if (!token) { + log_debug("response tokenizing failed at encode"); + return -1; + } + + if (list_info->cmd_type == CMD_TYPE_CMGR) { + token = atcmd_value_tok(&save); + if (!token) { + log_debug("response tokenizing failed at prio"); + return -1; + } + if (*save == '\"') { + token = atcmd_value_tok(&save); + if (!token) { + log_debug("response tokenizing failed at callback"); + return -1; + } + } + } + + token = atcmd_value_tok(&save); + if (!token) { + log_debug("response tokenizing failed at msg-len"); + return -1; + } + msg_len = atoi(token); + + switch (status) { + case SMS_MSG_REC_UNREAD: + list_info->nr_unread++; + break; + case SMS_MSG_REC_READ: + list_info->nr_read++; + break; + case SMS_MSG_STO_UNSENT: + list_info->nr_unsent++; + break; + case SMS_MSG_STO_SENT: + list_info->nr_sent++; + break; + default: + log_warning("msg-status unknown"); + list_info->nr_unknown++; + } + + msg = sms_msg_alloc(); + if (!msg) { + log_error("out of memory"); + return -1; + } + + memset(msg, 0, sizeof(*msg)); + + msg->index = index; + msg->status = status; + snprintf(msg->name, sizeof(msg->name), "%s", name); + msg->len = msg_len; + if (timestamp) { + decode_timestamp_text_mode(timestamp, &msg->pdu.timestamp); + } + + list_add_tail(&msg->list, &list_info->msg_list); + + list_info->nr_msgs++; + + return 0; +} + +static ssize_t readn(int fd, void *buf, size_t len) +{ + ssize_t cc; + ssize_t total; + + total = 0; + + while (len) { + cc = read(fd, buf, len); + if (cc <= 0) { + return cc; + } + + total += cc; + buf = buf + cc; + len -= cc; + } + + log_debug("read: \"%.*J\"", len, buf); + + return total; +} + +static int sms_list_text_mode(int fd, struct msg_list_info *list_info) +{ + char buf[ATCMD_LINE_SIZE]; + int tmp; + struct sms_msg *msg; + + while (1) { + tmp = atcmd_readline(fd, buf, sizeof(buf)); + if (tmp <= 0) { + return -1; + } + + list_info->nr_lines++; + + if (!strncmp(buf, CMGL_HEADER_START, strlen(CMGL_HEADER_START)) || + !strncmp(buf, CMGR_HEADER_START, strlen(CMGR_HEADER_START))) { + tmp = process_header_text_mode(list_info, buf, sizeof(buf)); + if (tmp < 0) { + log_debug("process_header_text_mode failed"); + return -1; + } + + if (list_empty(&list_info->msg_list)) { + log_debug("empty list"); + return -1; + } + + msg = list_entry(list_info->msg_list.prev, typeof(*msg), list); + if (msg->len <= 0) { + continue; + } + if (msg->len >= PDU_UD_SIZE) { + continue; + } + + list_info->nr_lines++; + + tmp = readn(fd, msg->pdu.user_data, msg->len); + if (tmp <= 0) { + log_debug("read message failed"); + return -1; + } + + msg->pdu.user_data_len = msg->len; + } else if (!strcmp(buf, "OK")) { + return 0; + } else if (*buf) { + log_debug("AT response error: %s", buf); + + return -1; + } + } +} + static int process_header(struct msg_list_info *list_info, char *buf, size_t len) { char *save = buf; @@ -221,8 +451,8 @@ static int print_list_yaml(struct msg_list_info *list_info) enum { LIST_STATE_BLANK, - LIST_STATE_OPEN, - LIST_STATE_PDU, + LIST_STATE_HEADER, + LIST_STATE_DATA, LIST_STATE_CLOSE, }; @@ -244,16 +474,16 @@ static int list_info_callback(char *buf, size_t len, void *data) return -1; } - list_info->state = LIST_STATE_OPEN; + list_info->state = LIST_STATE_HEADER; return 0; - case LIST_STATE_OPEN: - log_debug("state: LIST_STATE_OPEN"); + case LIST_STATE_HEADER: + log_debug("state: LIST_STATE_HEADER"); if (!strncmp(buf, CMGL_HEADER_START, strlen(CMGL_HEADER_START)) || !strncmp(buf, CMGR_HEADER_START, strlen(CMGR_HEADER_START))) { - list_info->state = LIST_STATE_PDU; + list_info->state = LIST_STATE_DATA; return process_header(list_info, buf, len); } else if (!strcmp(buf, "OK")) { @@ -269,8 +499,8 @@ static int list_info_callback(char *buf, size_t len, void *data) return 0; } - case LIST_STATE_PDU: - log_debug("state: LIST_STATE_PDU"); + case LIST_STATE_DATA: + log_debug("state: LIST_STATE_DATA"); if (list_empty(&list_info->msg_list)) { log_debug("empty list"); @@ -285,7 +515,7 @@ static int list_info_callback(char *buf, size_t len, void *data) } } - list_info->state = LIST_STATE_OPEN; + list_info->state = LIST_STATE_HEADER; return 0; @@ -324,7 +554,11 @@ int sms_list_get(int fd, struct msg_list_info *list_info) switch (list_info->cmd_type) { case CMD_TYPE_CMGL: - atcmd_writeline(fd, "AT+CMGL=%d", list_info->status); + if (Global.core.sms_mode == SMS_TEXT_MODE) { + atcmd_writeline(fd, "AT+CMGL=\"%s\"", msg_status_value_to_name(list_info->status)); + } else { + atcmd_writeline(fd, "AT+CMGL=%d", list_info->status); + } break; case CMD_TYPE_CMGR: @@ -335,12 +569,22 @@ int sms_list_get(int fd, struct msg_list_info *list_info) return -1; } - tmp = atcmd_response_foreach_line(fd, list_info_callback, list_info); - if (tmp < 0) { - log_error("listing failed"); - sms_list_free(list_info); + if (Global.core.sms_mode == SMS_TEXT_MODE) { + tmp = sms_list_text_mode(fd, list_info); + if (tmp < 0) { + log_error("listing failed"); + sms_list_free(list_info); - return tmp; + return tmp; + } + } else if (Global.core.sms_mode == SMS_PDU_MODE) { + tmp = atcmd_response_foreach_line(fd, list_info_callback, list_info); + if (tmp < 0) { + log_error("listing failed"); + sms_list_free(list_info); + + return tmp; + } } return 0; diff --git a/src/sms_main.c b/src/sms_main.c index 92c831f..0138487 100644 --- a/src/sms_main.c +++ b/src/sms_main.c @@ -59,6 +59,7 @@ static int global_init(void) Global.core.msg_store_send = strdup("ME"); Global.core.msg_store_new = strdup("ME"); Global.core.pb_store = strdup("ME"); + Global.core.sms_mode = SMS_PDU_MODE; Global.core.editor = strdup("vi"); Global.core.edit_file = strdup("${HOME}/.smsmsg"); @@ -218,6 +219,7 @@ static struct option long_options[] = { {"msg-store-send", 1, NULL, CMD_OPT_MSG_STORE_SEND}, {"msg-store-new", 1, NULL, CMD_OPT_MSG_STORE_NEW}, {"pb-store", 1, NULL, CMD_OPT_PHONEBOOK_STORE}, + {"sms-mode", 1, NULL, CMD_OPT_SMS_MODE}, {"interactive", 0, NULL, CMD_OPT_INTERACTIVE}, {"non-interactive", 0, NULL, CMD_OPT_NON_INTERACTIVE}, {"verbose", 0, NULL, CMD_OPT_VERBOSE}, @@ -278,7 +280,7 @@ int main(int argc, char *argv[]) Global.core.baud_rate = atoi(optarg); Global.core.baud_rate = value_to_baud(Global.core.baud_rate); if (Global.core.baud_rate == (speed_t) -1) { - sms_send_help(stderr); + usage(stderr); exit(1); } break; @@ -307,6 +309,17 @@ int main(int argc, char *argv[]) Global.core.pb_store = strdup(optarg); break; + case CMD_OPT_SMS_MODE: + if (!strcmp(optarg, "text")) { + Global.core.sms_mode = SMS_TEXT_MODE; + } else if (!strcmp(optarg, "pdu")) { + Global.core.sms_mode = SMS_PDU_MODE; + } else { + usage(stderr); + exit(1); + } + break; + case CMD_OPT_VERSION: print_version("sms"); exit(0); diff --git a/src/sms_send.c b/src/sms_send.c index 8ed7ebb..72b5a13 100644 --- a/src/sms_send.c +++ b/src/sms_send.c @@ -39,14 +39,19 @@ #include "pdu_encode.h" #include "phonebook.h" +enum { + SEND_MODE_CMGW_CMSS, + SEND_MODE_CMGS, +}; + struct send_options { char *file; int alphabet; const char *smsc_addr; - int cmgw_first; + int send_mode; }; -static int auto_fill_smsc(int fd, struct pdu_addr *addr) +static int auto_fill_smsc(int fd, struct sms_addr *addr) { char buf[ATCMD_LINE_SIZE]; char *save; @@ -97,17 +102,17 @@ static int auto_fill_smsc(int fd, struct pdu_addr *addr) return -1; } - return pdu_addr_fill(addr, addr_str, type); + return sms_addr_fill(addr, addr_str, type); } static int fill_addr(struct phonebook_list_info *list_info, - struct pdu_addr *addr, const char *addr_str) + struct sms_addr *addr, const char *addr_str) { struct phonebook_entry *entry; int type; int tmp; - type = pdu_addr_type_infer(addr_str); + type = sms_addr_type_infer(addr_str); if (type != SMS_ADDR_TEXT) { goto fill; } @@ -130,7 +135,7 @@ static int fill_addr(struct phonebook_list_info *list_info, fill: - tmp = pdu_addr_fill(addr, addr_str, SMS_ADDR_UNSPEC); + tmp = sms_addr_fill(addr, addr_str, SMS_ADDR_UNSPEC); if (tmp < 0) { log_debug("pdu fill failed with addr %s", addr_str); return -1; @@ -208,7 +213,7 @@ static int do_send(int fd, struct send_options *options, int argc, char **argv) pdu.data_coding.general.alphabet = options->alphabet; if (options->smsc_addr) { - tmp = pdu_addr_fill(&pdu.smsc_addr, options->smsc_addr, SMS_ADDR_UNSPEC); + tmp = sms_addr_fill(&pdu.smsc_addr, options->smsc_addr, SMS_ADDR_UNSPEC); if (tmp < 0) { return false; } @@ -224,18 +229,25 @@ static int do_send(int fd, struct send_options *options, int argc, char **argv) printf("preparing for send...\n"); } - if (options->cmgw_first) { - tmp = pdu_encode(buf, sizeof(buf), &pdu); - if (tmp < 0) { - log_error("pdu encode failed"); - return false; + if (options->send_mode == SEND_MODE_CMGW_CMSS) { + if (Global.core.sms_mode == SMS_PDU_MODE) { + tmp = pdu_encode(buf, sizeof(buf), &pdu); + if (tmp < 0) { + log_error("pdu encode failed"); + return false; + } } if (Global.core.verbose) { printf("writing message to memory\n"); } - mem_index = atcmd_plus_cmgw_write(fd, buf, pdu.msg_len); + if (Global.core.sms_mode == SMS_TEXT_MODE) { + mem_index = atcmd_plus_cmgw_write_text(fd, NULL, + SMS_ADDR_UNSPEC, NULL, pdu.user_data, pdu.user_data_len); + } else { + mem_index = atcmd_plus_cmgw_write(fd, buf, pdu.msg_len); + } if (mem_index < 0) { log_error("write message to memory failed"); return false; @@ -266,23 +278,30 @@ static int do_send(int fd, struct send_options *options, int argc, char **argv) continue; } - if (options->cmgw_first) { + if (options->send_mode == SEND_MODE_CMGW_CMSS) { tmp = atcmd_plus_cmss_write(fd, mem_index, - pdu.addr.addr, SMS_ADDR_UNSPEC); + pdu.addr.addr, SMS_ADDR_UNSPEC); if (tmp < 0) { printf("sending message to %s failed\n", argv[i]); failed++; continue; } } else { - tmp = pdu_encode(buf, sizeof(buf), &pdu); - if (tmp < 0) { - printf("sending message to %s failed\n", argv[i]); - failed++; - continue; + if (Global.core.sms_mode == SMS_PDU_MODE) { + tmp = pdu_encode(buf, sizeof(buf), &pdu); + if (tmp < 0) { + printf("sending message to %s failed\n", argv[i]); + failed++; + continue; + } } - tmp = atcmd_plus_cmgs_write(fd, buf, pdu.msg_len); + if (Global.core.sms_mode == SMS_TEXT_MODE) { + tmp = atcmd_plus_cmgs_write_text(fd, pdu.addr.addr, + pdu.user_data, pdu.user_data_len); + } else { + tmp = atcmd_plus_cmgs_write(fd, buf, pdu.msg_len); + } if (tmp < 0) { printf("sending message to %s failed\n", argv[i]); failed++; @@ -305,7 +324,7 @@ static struct option long_options[] = { {"alphabet", 1, NULL, CMD_OPT_ALPHABET}, {"file", 1, NULL, CMD_OPT_FILE}, {"smsc-addr", 1, NULL, CMD_OPT_SMSC_ADDR}, - {"cmgw-first", 0, NULL, CMD_OPT_CMGW_FIRST}, + {"send-mode", 1, NULL, CMD_OPT_SEND_MODE}, {NULL, 0, NULL, 0}, }; @@ -315,7 +334,7 @@ void sms_send_help(FILE *out) { fprintf(out, " --alphabet { seven-bit | eight-bit } |\n"); fprintf(out, " -f, --file |\n"); fprintf(out, " --smsc-addr |\n"); - fprintf(out, " --cmgw-first\n"); + fprintf(out, " --send-mode { cmgw-cmss | cmgs } \n"); fprintf(out, " }\n"); fprintf(out, "\n"); } @@ -330,9 +349,8 @@ int sms_send(int argc, char **argv) struct send_options options; options.alphabet = PDU_ALPHABET_DEFAULT; options.file = NULL; - options.cmgw_first = false; + options.send_mode = SEND_MODE_CMGS; options.smsc_addr = NULL; - options.cmgw_first = false; while ((i = getopt_long(argc, argv, short_options, long_options, &option_index)) >= 0) { switch (i) { @@ -344,6 +362,9 @@ int sms_send(int argc, char **argv) options.alphabet = PDU_ALPHABET_DEFAULT; } else if (!strcmp(optarg, "eight-bit")) { options.alphabet = PDU_ALPHABET_EIGHT; + } else { + sms_send_help(stderr); + return false; } break; @@ -355,8 +376,15 @@ int sms_send(int argc, char **argv) options.smsc_addr = optarg; break; - case CMD_OPT_CMGW_FIRST: - options.cmgw_first = true; + case CMD_OPT_SEND_MODE: + if (!strcmp(optarg, "cmgw-cmss")) { + options.send_mode = SEND_MODE_CMGW_CMSS; + } else if (!strcmp(optarg, "cmgs")) { + options.send_mode = SEND_MODE_CMGS; + } else { + sms_send_help(stderr); + return false; + } break; default: -- cgit v1.2.3