1
// *************************************************************************
4
// * File: gsmsmsstore.cc
6
// * Purpose: SMS store management program
8
// * Author: Peter Hofmann (software@pxh.de)
10
// * Created: 4.8.1999
11
// *************************************************************************
14
#include <gsm_config.h>
16
#include <gsmlib/gsm_nls.h>
20
#include <gsmlib/gsm_win32_serial.h>
22
#include <gsmlib/gsm_unix_serial.h>
25
#if defined(HAVE_GETOPT_LONG) || defined(WIN32)
31
#include <gsmlib/gsm_me_ta.h>
32
#include <gsmlib/gsm_util.h>
33
#include <gsmlib/gsm_sorted_sms_store.h>
37
using namespace gsmlib;
39
#ifdef HAVE_GETOPT_LONG
40
static struct option longOpts[] =
42
{"xonxoff", no_argument, (int*)NULL, 'X'},
43
{"init", required_argument, (int*)NULL, 'I'},
44
{"store", required_argument, (int*)NULL, 't'},
45
{"erase", no_argument, (int*)NULL, 'e'},
46
{"add", no_argument, (int*)NULL, 'a'},
47
{"list", no_argument, (int*)NULL, 'l'},
48
{"destination", required_argument, (int*)NULL, 'd'},
49
{"source", required_argument, (int*)NULL, 's'},
50
{"baudrate", required_argument, (int*)NULL, 'b'},
51
{"sca", required_argument, (int*)NULL, 'C'},
52
{"copy", no_argument, (int*)NULL, 'c'},
53
{"delete", no_argument, (int*)NULL, 'x'},
54
{"backup", no_argument, (int*)NULL, 'k'},
55
{"help", no_argument, (int*)NULL, 'h'},
56
{"version", no_argument, (int*)NULL, 'v'},
57
{"verbose", no_argument, (int*)NULL, 'V'},
58
{(char*)NULL, 0, (int*)NULL, 0}
61
#define getopt_long(argc, argv, options, longopts, indexptr) \
62
getopt(argc, argv, options)
65
bool verbose = false; // true if --verbose option given
67
// type of operation to perform
69
enum Operation {CopyOp = 'c', BackupOp = 'k', DeleteOp = 'x',
70
AddOp = 'a', ListOp = 'l', NoOp = 0};
72
// aux function, insert entry only if not already present in dest
74
void backup(SortedSMSStoreRef destStore, SMSStoreEntry &entry)
76
// the following only works because we know that the default sort order
78
assert(destStore->sortOrder() == ByDate);
80
Timestamp date = entry.message()->serviceCentreTimestamp();
81
pair<SortedSMSStore::iterator, SortedSMSStore::iterator> range =
82
destStore->equal_range(date);
84
for (SortedSMSStore::iterator j = range.first;
85
j != range.second; ++j)
87
// do nothing if the entry is already present in the destination
91
cout << stringPrintf(_("inserting entry #%d from source into destination"),
92
entry.index()) << endl
93
<< entry.message()->toString();
94
destStore->insert(entry); // insert
97
// aux function, throw exception if operation != NoOp
99
void checkNoOp(Operation operation, int opt)
101
if (operation != NoOp)
102
throw GsmException(stringPrintf(_("incompatible options '%c' and '%c'"),
103
(char)operation, (char)opt),
109
int main(int argc, char *argv[])
113
// handle command line options
118
char operation = NoOp;
119
SortedSMSStoreRef sourceStore, destStore;
120
bool useIndices = false; // use indices in delete, copy, backup op
121
string initString = DEFAULT_INIT_STRING;
122
bool swHandshake = false;
123
// service centre address (set on command line)
124
string serviceCentreAddress;
125
Ref<MeTa> sourceMeTa, destMeTa;
129
while((opt = getopt_long(argc, argv, "I:t:s:d:b:cxlakhvVXC:",
135
serviceCentreAddress = optarg;
150
destination = optarg;
159
checkNoOp((Operation)operation, opt);
163
checkNoOp((Operation)operation, opt);
164
operation = DeleteOp;
167
checkNoOp((Operation)operation, opt);
171
checkNoOp((Operation)operation, opt);
175
checkNoOp((Operation)operation, opt);
176
operation = BackupOp;
179
cerr << argv[0] << stringPrintf(_(": version %s [compiled %s]"),
180
VERSION, __DATE__) << endl;
184
cerr << argv[0] << _(": [-a][-b baudrate][-c][-C sca]"
185
"[-d device or file]\n"
186
" [-h][-I init string][-k][-l]"
187
"[-s device or file]"
188
"[-t SMS store name]\n [-v][-V][-x][-X]"
189
"{indices}|[phonenumber text]") << endl
191
<< _(" -a, --add add new SMS submit message\n"
192
" (phonenumber and text) to destination")
194
<< _(" -b, --baudrate baudrate to use for device "
197
<< _(" -c, --copy copy source entries to destination\n"
198
" (if indices are given, "
199
"copy only these entries)") << endl
200
<< _(" -C, --sca SMS service centre address") << endl
201
<< _(" -d, --destination sets the destination device to\n"
202
" connect to, or the file to write to")
204
<< _(" -h, --help prints this message") << endl
205
<< _(" -I, --init device AT init sequence") << endl
206
<< _(" -k, --backup backup new entries to destination\n"
207
" (if indices are given, "
208
"copy only these entries)") << endl
209
<< _(" -l, --list list source to stdout") << endl
210
<< _(" -s, --source sets the source device to connect to,\n"
211
" or the file to read") << endl
212
<< _(" -t, --store name of SMS store to use") << endl
213
<< _(" -v, --version prints version and exits") << endl
214
<< _(" -V, --verbose print detailed progress messages")
216
<< _(" -x, --delete delete entries denoted by indices")
218
<< _(" -X, --xonxoff switch on software handshake") << endl
223
throw GsmException(_("unknown option"), ParameterError);
227
// check if parameters are complete
228
if (operation == NoOp)
229
throw GsmException(_("no operation option given"), ParameterError);
230
if (operation == BackupOp || operation == CopyOp)
231
if (destination.length() == 0 || source.length() == 0)
232
throw GsmException(_("both source and destination required"),
234
if (operation == ListOp)
236
if (destination.length() != 0)
237
throw GsmException(_("destination must not be given"), ParameterError);
238
if (source.length() == 0)
239
throw GsmException(_("source required"), ParameterError);
241
if (operation == AddOp || operation == DeleteOp)
243
if (source.length() != 0)
244
throw GsmException(_("source must not be given"), ParameterError);
245
if (destination.length() == 0)
246
throw GsmException(_("destination required"), ParameterError);
248
if (operation == CopyOp || operation == DeleteOp || operation == BackupOp)
250
// check if all indices are numbers
251
for (int i = optind; i < argc; ++i)
252
for (char *pp = argv[i]; *pp != 0; ++pp)
254
throw GsmException(stringPrintf(_("expected number, got '%s'"),
255
argv[i]), ParameterError);
256
useIndices = optind != argc;
258
else if (operation == AddOp)
260
if (optind + 2 < argc)
261
throw GsmException(_("more than two parameters given"),
263
if (optind + 2 > argc)
264
throw GsmException(_("not enough parameters given"),
269
throw GsmException(_("unexpected parameters"), ParameterError);
271
// start accessing source store or file if required by operation
272
if (operation == CopyOp || operation == BackupOp || operation == ListOp)
274
sourceStore = new SortedSMSStore(true);
275
else if (isFile(source))
276
sourceStore = new SortedSMSStore(source);
280
throw GsmException(_("store name must be given"), ParameterError);
282
sourceMeTa = new MeTa(new
289
baudrate == "" ? DEFAULT_BAUD_RATE :
290
baudRateStrToSpeed(baudrate), initString,
292
sourceStore = new SortedSMSStore(sourceMeTa->getSMSStore(storeName));
295
// make sure destination file exists
296
if (destination != "")
300
ofstream f(destination.c_str(), ios::out | ios::app | ios::binary);
307
// start accessing destination destination store or file
308
if (operation == CopyOp || operation == BackupOp || operation == AddOp ||
309
operation == DeleteOp)
310
if (destination == "-")
311
destStore = new SortedSMSStore(false);
312
else if (isFile(destination))
313
destStore = new SortedSMSStore(destination);
317
throw GsmException(_("store name must be given"), ParameterError);
319
destMeTa = new MeTa(new
326
baudrate == "" ? DEFAULT_BAUD_RATE :
327
baudRateStrToSpeed(baudrate), initString,
329
destStore = new SortedSMSStore(destMeTa->getSMSStore(storeName));
332
// now do the actual work
337
sourceStore->setSortOrder(ByIndex); // needed in loop
340
for (int i = optind; i < argc; ++i)
342
SortedSMSStore::iterator j = sourceStore->find(atoi(argv[i]));
343
if (j == sourceStore->end())
344
throw GsmException(stringPrintf(_("no index '%s' in source"),
345
argv[i]), ParameterError);
346
backup(destStore, *j);
349
for (SortedSMSStore::iterator i = sourceStore->begin();
350
i != sourceStore->end(); ++i)
351
backup(destStore, *i);
357
if (! useIndices) // copy all entries
359
for (SortedSMSStore::iterator i = sourceStore->begin();
360
i != sourceStore->end(); ++i)
363
cout << stringPrintf(_("inserting entry #%d from source "
364
"into destination"), i->index()) << endl
365
<< i->message()->toString();
366
destStore->insert(*i);
369
else // copy indexed entries
371
sourceStore->setSortOrder(ByIndex); // needed in loop
373
for (int i = optind; i < argc; ++i)
375
SortedSMSStore::iterator j = sourceStore->find(atoi(argv[i]));
376
if (j == sourceStore->end())
377
throw GsmException(stringPrintf(_("no index '%s' in source"),
378
argv[i]), ParameterError);
380
cout << stringPrintf(_("inserting entry #%d from source into "
381
"destination"), j->index()) << endl
382
<< j->message()->toString();
383
destStore->insert(*j);
390
for (SortedSMSStore::iterator i = sourceStore->begin();
391
i != sourceStore->end(); ++i)
392
cout << stringPrintf(_("index #%d"), i->index()) << endl
393
<< i->message()->toString();
398
SMSMessageRef sms = new SMSSubmitMessage(argv[optind + 1], argv[optind]);
399
// set service centre address in new submit PDU if requested by user
400
if (serviceCentreAddress != "")
402
Address sca(serviceCentreAddress);
403
sms->setServiceCentreAddress(sca);
406
cout << _("inserting new entry into destination") << endl
408
destStore->insert(sms);
413
destStore->setSortOrder(ByIndex);
414
for (int i = optind; i < argc; ++i)
416
int index = atoi(argv[i]);
419
SortedSMSStore::iterator e = destStore->find(index);
420
if (e != destStore->end())
421
cout << stringPrintf(_("deleting entry #%d from destination"),
423
<< e->message()->toString();
425
if (destStore->erase(index) != 1)
426
throw GsmException(stringPrintf(_("no index '%s' in destination"),
427
argv[i]), ParameterError);
433
catch (GsmException &ge)
435
cerr << argv[0] << _("[ERROR]: ") << ge.what() << endl;