~ubuntu-branches/ubuntu/intrepid/gsmlib/intrepid

« back to all changes in this revision

Viewing changes to apps/gsmsmsstore.cc

  • Committer: Bazaar Package Importer
  • Author(s): Mikael Hedin
  • Date: 2002-01-24 12:59:07 UTC
  • Revision ID: james.westby@ubuntu.com-20020124125907-b7qkpokx5283jdpu
Tags: upstream-1.8
ImportĀ upstreamĀ versionĀ 1.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// *************************************************************************
 
2
// * GSM TA/ME library
 
3
// *
 
4
// * File:    gsmsmsstore.cc
 
5
// *
 
6
// * Purpose: SMS store management program
 
7
// *
 
8
// * Author:  Peter Hofmann (software@pxh.de)
 
9
// *
 
10
// * Created: 4.8.1999
 
11
// *************************************************************************
 
12
 
 
13
#ifdef HAVE_CONFIG_H
 
14
#include <gsm_config.h>
 
15
#endif
 
16
#include <gsmlib/gsm_nls.h>
 
17
#include <string>
 
18
#include <ctype.h>
 
19
#ifdef WIN32
 
20
#include <gsmlib/gsm_win32_serial.h>
 
21
#else
 
22
#include <gsmlib/gsm_unix_serial.h>
 
23
#include <unistd.h>
 
24
#endif
 
25
#if defined(HAVE_GETOPT_LONG) || defined(WIN32)
 
26
#include <getopt.h>
 
27
#endif
 
28
#include <stdio.h>
 
29
#include <stdlib.h>
 
30
#include <errno.h>
 
31
#include <gsmlib/gsm_me_ta.h>
 
32
#include <gsmlib/gsm_util.h>
 
33
#include <gsmlib/gsm_sorted_sms_store.h>
 
34
#include <iostream>
 
35
 
 
36
using namespace std;
 
37
using namespace gsmlib;
 
38
 
 
39
#ifdef HAVE_GETOPT_LONG
 
40
static struct option longOpts[] =
 
41
{
 
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}
 
59
};
 
60
#else
 
61
#define getopt_long(argc, argv, options, longopts, indexptr) \
 
62
  getopt(argc, argv, options)
 
63
#endif
 
64
 
 
65
bool verbose = false;           // true if --verbose option given
 
66
 
 
67
// type of operation to perform
 
68
 
 
69
enum Operation {CopyOp = 'c', BackupOp = 'k', DeleteOp = 'x',
 
70
                AddOp = 'a', ListOp = 'l', NoOp = 0};
 
71
 
 
72
// aux function, insert entry only if not already present in dest
 
73
 
 
74
void backup(SortedSMSStoreRef destStore, SMSStoreEntry &entry)
 
75
{
 
76
  // the following only works because we know that the default sort order
 
77
  // is by date
 
78
  assert(destStore->sortOrder() == ByDate);
 
79
 
 
80
  Timestamp date = entry.message()->serviceCentreTimestamp();
 
81
  pair<SortedSMSStore::iterator, SortedSMSStore::iterator> range =
 
82
    destStore->equal_range(date);
 
83
          
 
84
  for (SortedSMSStore::iterator j = range.first;
 
85
       j != range.second; ++j)
 
86
    if (entry == *j)
 
87
      // do nothing if the entry is already present in the destination
 
88
      return;
 
89
 
 
90
  if (verbose)
 
91
    cout << stringPrintf(_("inserting entry #%d from source into destination"),
 
92
                         entry.index()) << endl
 
93
         << entry.message()->toString();
 
94
  destStore->insert(entry);     // insert
 
95
}
 
96
 
 
97
// aux function, throw exception if operation != NoOp
 
98
 
 
99
void checkNoOp(Operation operation, int opt)
 
100
{
 
101
  if (operation != NoOp)
 
102
    throw GsmException(stringPrintf(_("incompatible options '%c' and '%c'"),
 
103
                                    (char)operation, (char)opt),
 
104
                       ParameterError);
 
105
}
 
106
 
 
107
// *** main program
 
108
 
 
109
int main(int argc, char *argv[])
 
110
{
 
111
  try
 
112
  {
 
113
    // handle command line options
 
114
    string destination;
 
115
    string source;
 
116
    string baudrate;
 
117
    string storeName;
 
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;
 
126
 
 
127
    int opt;
 
128
    int dummy;
 
129
    while((opt = getopt_long(argc, argv, "I:t:s:d:b:cxlakhvVXC:",
 
130
                             longOpts, &dummy))
 
131
          != -1)
 
132
      switch (opt)
 
133
      {
 
134
      case 'C':
 
135
        serviceCentreAddress = optarg;
 
136
        break;
 
137
      case 'X':
 
138
        swHandshake = true;
 
139
        break;
 
140
      case 'I':
 
141
        initString = optarg;
 
142
        break;
 
143
      case 'V':
 
144
        verbose = true;
 
145
        break;
 
146
      case 't':
 
147
        storeName = optarg;
 
148
        break;
 
149
      case 'd':
 
150
        destination = optarg;
 
151
        break;
 
152
      case 's':
 
153
        source = optarg;
 
154
        break;
 
155
      case 'b':
 
156
        baudrate = optarg;
 
157
        break;
 
158
      case 'c':
 
159
        checkNoOp((Operation)operation, opt);
 
160
        operation = CopyOp;
 
161
        break;
 
162
      case 'x':
 
163
        checkNoOp((Operation)operation, opt);
 
164
        operation = DeleteOp;
 
165
        break;
 
166
      case 'l':
 
167
        checkNoOp((Operation)operation, opt);
 
168
        operation = ListOp;
 
169
        break;
 
170
      case 'a':
 
171
        checkNoOp((Operation)operation, opt);
 
172
        operation = AddOp;
 
173
        break;
 
174
      case 'k':
 
175
        checkNoOp((Operation)operation, opt);
 
176
        operation = BackupOp;
 
177
        break;
 
178
      case 'v':
 
179
        cerr << argv[0] << stringPrintf(_(": version %s [compiled %s]"),
 
180
                                        VERSION, __DATE__) << endl;
 
181
        exit(0);
 
182
        break;
 
183
      case 'h':
 
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
 
190
             << endl
 
191
             << _("  -a, --add         add new SMS submit message\n"
 
192
                  "                    (phonenumber and text) to destination")
 
193
             << endl
 
194
             << _("  -b, --baudrate    baudrate to use for device "
 
195
                  "(default: 38400)")
 
196
             << endl
 
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")
 
203
             << endl
 
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")
 
215
             << endl
 
216
             << _("  -x, --delete      delete entries denoted by indices")
 
217
             << endl
 
218
             << _("  -X, --xonxoff     switch on software handshake") << endl
 
219
             << endl;
 
220
        exit(0);
 
221
        break;
 
222
      case '?':
 
223
        throw GsmException(_("unknown option"), ParameterError);
 
224
        break;
 
225
      }
 
226
 
 
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"),
 
233
                           ParameterError);
 
234
    if (operation == ListOp)
 
235
    {
 
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);
 
240
    }
 
241
    if (operation == AddOp || operation == DeleteOp)
 
242
    {
 
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);
 
247
    }
 
248
    if (operation == CopyOp || operation == DeleteOp || operation == BackupOp)
 
249
    {
 
250
      // check if all indices are numbers
 
251
      for (int i = optind; i < argc; ++i)
 
252
        for (char *pp = argv[i]; *pp != 0; ++pp)
 
253
          if (! isdigit(*pp))
 
254
            throw GsmException(stringPrintf(_("expected number, got '%s'"),
 
255
                                            argv[i]), ParameterError);
 
256
      useIndices = optind != argc;
 
257
    }
 
258
    else if (operation == AddOp)
 
259
    {
 
260
      if (optind + 2 < argc)
 
261
        throw GsmException(_("more than two parameters given"),
 
262
                           ParameterError);
 
263
      if (optind + 2 > argc)
 
264
        throw GsmException(_("not enough parameters given"),
 
265
                           ParameterError);
 
266
    }
 
267
    else
 
268
      if (optind != argc)
 
269
        throw GsmException(_("unexpected parameters"), ParameterError);
 
270
    
 
271
    // start accessing source store or file if required by operation
 
272
    if (operation == CopyOp || operation == BackupOp || operation == ListOp)
 
273
      if (source == "-")
 
274
        sourceStore = new SortedSMSStore(true);
 
275
      else if (isFile(source))
 
276
        sourceStore = new SortedSMSStore(source);
 
277
      else
 
278
      {
 
279
        if (storeName == "")
 
280
          throw GsmException(_("store name must be given"), ParameterError);
 
281
        
 
282
        sourceMeTa = new MeTa(new
 
283
#ifdef WIN32
 
284
                              Win32SerialPort
 
285
#else
 
286
                              UnixSerialPort
 
287
#endif
 
288
                              (source,
 
289
                               baudrate == "" ? DEFAULT_BAUD_RATE :
 
290
                               baudRateStrToSpeed(baudrate), initString,
 
291
                               swHandshake));
 
292
        sourceStore = new SortedSMSStore(sourceMeTa->getSMSStore(storeName));
 
293
      }
 
294
      
 
295
    // make sure destination file exists
 
296
    if (destination != "")
 
297
    {
 
298
      try
 
299
      {
 
300
        ofstream f(destination.c_str(), ios::out | ios::app | ios::binary);
 
301
      }
 
302
      catch (exception)
 
303
      {
 
304
      }
 
305
    }
 
306
 
 
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);
 
314
      else
 
315
      {
 
316
        if (storeName == "")
 
317
          throw GsmException(_("store name must be given"), ParameterError);
 
318
        
 
319
        destMeTa = new MeTa(new
 
320
#ifdef WIN32
 
321
                            Win32SerialPort
 
322
#else
 
323
                            UnixSerialPort
 
324
#endif
 
325
                            (destination,
 
326
                             baudrate == "" ? DEFAULT_BAUD_RATE :
 
327
                             baudRateStrToSpeed(baudrate), initString,
 
328
                             swHandshake));
 
329
        destStore = new SortedSMSStore(destMeTa->getSMSStore(storeName));      
 
330
      }
 
331
 
 
332
    // now do the actual work
 
333
    switch (operation)
 
334
    {
 
335
    case BackupOp:
 
336
    {
 
337
      sourceStore->setSortOrder(ByIndex); // needed in loop
 
338
 
 
339
      if (useIndices)
 
340
        for (int i = optind; i < argc; ++i)
 
341
        {
 
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);
 
347
        }
 
348
      else
 
349
        for (SortedSMSStore::iterator i = sourceStore->begin();
 
350
             i != sourceStore->end(); ++i)
 
351
          backup(destStore, *i);
 
352
      break;
 
353
    }
 
354
    case CopyOp:
 
355
    {                        
 
356
      destStore->clear();
 
357
      if (! useIndices)         // copy all entries
 
358
      {
 
359
        for (SortedSMSStore::iterator i = sourceStore->begin();
 
360
             i != sourceStore->end(); ++i)
 
361
        {
 
362
          if (verbose)
 
363
            cout << stringPrintf(_("inserting entry #%d from source "
 
364
                                   "into destination"), i->index()) << endl
 
365
                 << i->message()->toString();
 
366
          destStore->insert(*i);
 
367
        }
 
368
      }
 
369
      else                      // copy indexed entries
 
370
      {
 
371
        sourceStore->setSortOrder(ByIndex); // needed in loop
 
372
 
 
373
        for (int i = optind; i < argc; ++i)
 
374
        {
 
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);
 
379
          if (verbose)
 
380
            cout << stringPrintf(_("inserting entry #%d from source into "
 
381
                                   "destination"), j->index()) << endl
 
382
                 << j->message()->toString();
 
383
          destStore->insert(*j);
 
384
        }
 
385
      }
 
386
      break;
 
387
    }
 
388
    case ListOp:
 
389
    {
 
390
      for (SortedSMSStore::iterator i = sourceStore->begin();
 
391
           i != sourceStore->end(); ++i)
 
392
        cout << stringPrintf(_("index #%d"), i->index()) << endl
 
393
             << i->message()->toString();
 
394
      break;
 
395
    }
 
396
    case AddOp:
 
397
    {
 
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 != "")
 
401
      {
 
402
        Address sca(serviceCentreAddress);
 
403
        sms->setServiceCentreAddress(sca);
 
404
      }
 
405
      if (verbose)
 
406
        cout << _("inserting new entry into destination") << endl
 
407
             << sms->toString();
 
408
      destStore->insert(sms);
 
409
      break;
 
410
    }
 
411
    case DeleteOp:
 
412
    {
 
413
      destStore->setSortOrder(ByIndex);
 
414
      for (int i = optind; i < argc; ++i)
 
415
      {
 
416
        int index = atoi(argv[i]);
 
417
        if (verbose)
 
418
        {
 
419
          SortedSMSStore::iterator e = destStore->find(index);
 
420
          if (e != destStore->end())
 
421
            cout << stringPrintf(_("deleting entry #%d from destination"),
 
422
                                 index) << endl
 
423
                 << e->message()->toString();
 
424
        }
 
425
        if (destStore->erase(index) != 1)
 
426
          throw GsmException(stringPrintf(_("no index '%s' in destination"),
 
427
                                          argv[i]), ParameterError);
 
428
      }
 
429
      break;
 
430
    }
 
431
    }
 
432
  }
 
433
  catch (GsmException &ge)
 
434
  {
 
435
    cerr << argv[0] << _("[ERROR]: ") << ge.what() << endl;
 
436
    return 1;
 
437
  }
 
438
  return 0;
 
439
}