This commit was generated by cvs2svn to compensate for changes in r164,
[gnokii.git] / gnokii / gnokii.c
index 120a83f..b7f0850 100644 (file)
   WARNING: this code is the test tool. Well, our test tool is now
   really powerful and useful :-)
 
+  $Log$
+  Revision 1.1.1.12  2002/04/03 01:44:15  short
+  Implemented connection type "tcp" (GCT_TCP), use <hostname>:<port> as "port"
+
+  Revision 1.1.1.11  2002/04/03 00:08:17  short
+  Found in "gnokii-working" directory, some November-patches version
+
+  Revision 1.143  2001/09/14 13:30:07  pkot
+  Fixed bugs introduced during 0.3.3 merge
+
+  Revision 1.142  2001/09/14 13:02:03  pkot
+  Gnokii calendar changes from 0.3.3
+
+  Revision 1.141  2001/09/14 12:53:00  pkot
+  New preview logos.
+  Localization fixes.
+  Set valid operator on logos xgnokii screen.
+
+  Revision 1.140  2001/07/27 00:02:21  pkot
+  Generic AT support for the new structure (Manfred Jonsson)
+
+  Revision 1.139  2001/07/01 23:16:45  pkot
+  Fixed a typo in gnokii.c avoiding saving logo (Jan Havelka)
+
+  Revision 1.138  2001/06/28 00:28:45  pkot
+  Small docs updates (Pawel Kot)
+
+  Revision 1.137  2001/06/27 23:52:50  pkot
+  7110/6210 updates (Marian Jancar)
+
+  Revision 1.136  2001/06/10 23:49:49  pkot
+  Small fixes to hide compilation warnings and allow gnokii.c to compile
+
+  Revision 1.135  2001/06/10 11:42:26  machek
+  Cleanup: some formating, made Statemachine global, converted to new
+  structure w.r.t. SMS-es
+
+  Revision 1.134  2001/05/24 20:47:30  chris
+  More updating of 7110 code and some of xgnokii_lowlevel changed over.
+
+  Revision 1.133  2001/04/23 17:20:01  pkot
+  Added possibility for viewing logos (currently nol and ngg) on console (Bartek Klepacz)
+
+  Revision 1.132  2001/03/21 23:36:06  chris
+  Added the statemachine
+  This will break gnokii --identify and --monitor except for 6210/7110
+
+  Revision 1.131  2001/03/19 23:43:46  pkot
+  Solaris / BSD '#if defined' cleanup
+
+  Revision 1.130  2001/03/13 01:23:18  pkot
+  Windows updates (Manfred Jonsson)
+
+  Revision 1.129  2001/03/13 01:21:39  pkot
+  *BSD updates (Bert Driehuis)
+
+  Revision 1.128  2001/03/08 00:49:06  pkot
+  Fixed bug (introduced by me) in getmemory function. Now gnokii.c should compile
+
+  Revision 1.127  2001/03/08 00:18:13  pkot
+  Fixed writephonebook once again. Someone kick me please...
+
+  Revision 1.126  2001/03/07 21:46:12  pkot
+  Fixed writephonebook patch
+
+  Revision 1.125  2001/03/06 22:19:14  pkot
+  Cleanups and fixes in gnokii.c:
+   - reindenting
+   - fixed bug reported by Gabriele Zappi
+   - fixed small bugs introduced by Pavel Machek
+
+  Revision 1.124  2001/02/28 21:42:00  machek
+  Possibility to force overwrite in --getsms (-F). Possibility to get
+  multiple files (use --getsms -f xyzzy%d), cleanup.
+
+  Revision 1.123  2001/02/20 21:55:11  pkot
+  Small #include updates
+
+  Revision 1.122  2001/02/16 14:29:53  chris
+  Restructure of common/.  Fixed a problem in fbus-phonet.c
+  Lots of dprintfs for Marcin
+  Any size xpm can now be loaded (eg for 7110 startup logos)
+  nk7110 code detects 7110/6210 and alters startup logo size to suit
+  Moved Marcin's extended phonebook code into gnokii.c
+
+  Revision 1.121  2001/02/06 21:15:35  chris
+  Preliminary irda support for 7110 etc.  Not well tested!
+
+  Revision 1.120  2001/02/06 08:13:32  pkot
+  One more include in gnokii.c needed
+
+  Revision 1.119  2001/02/05 12:29:37  pkot
+  Changes needed to let unicode work
+
+  Revision 1.118  2001/02/01 15:17:33  pkot
+  Fixed --identify and added Manfred's manufacturer patch
+
+  Revision 1.117  2001/01/31 23:45:27  pkot
+  --identify should work ok now
+
+  Revision 1.116  2001/01/24 20:19:55  machek
+  Do not retry identification, if it is not implemented, it is bad idea.
+
+  Revision 1.115  2001/01/22 01:25:10  hugh
+  Tweaks for 3810 series, datacalls seem to be broken so need to do
+  some more debugging...
+
+  Revision 1.114  2001/01/17 02:54:55  chris
+  More 7110 work.  Use with care! (eg it is not possible to delete phonebook entries)
+  I can now edit my phonebook in xgnokii but it is 'work in progress'.
+
+  Revision 1.113  2001/01/15 17:00:49  pkot
+  Initial keypress sequence support. Disable compilation warning
+
+  Revision 1.112  2001/01/12 14:09:13  pkot
+  More cleanups. This time mainly in the code.
+
+  Revision 1.111  2001/01/10 16:32:18  pkot
+  Documentation updates.
+  FreeBSD fix for 3810 code.
+  Added possibility for deleting SMS just after reading it in gnokii.
+  2110 code updates.
+  Many cleanups.
+
+  Revision 1.110  2001/01/08 15:11:37  pkot
+  Documentation updates.
+  Fixed some bugs and removed FIXMEs.
+  We need to move some stuff from configure.in to aclocal.m4
+
+  Revision 1.109  2000/12/29 15:39:07  pkot
+  Reverted a change in fbus-3810.c which broke compling with --enable-debug.
+  Small fixes in gnokii.c
+
+  Revision 1.108  2000/12/19 16:18:16  pkot
+  configure script updates and added shared function for configfile reading
+
+  
 */
 
+#include "config.h"
 #include "misc.h"
 
 #include <stdio.h>
 #include <getopt.h>
 
 #endif
+
 #ifdef USE_NLS
 #include <locale.h>
 #endif
 
-#include "gsm-sms.h"
 #include "gsm-common.h"
 #include "gsm-api.h"
 #include "gsm-networks.h"
@@ -137,39 +275,38 @@ char *GetProfileVibrationString(int code)
        }
 }
 
-void short_version(void)
-{
-       fprintf(stderr, _("GNOKII Version %s\n"), VERSION);
-}
-
 /* This function shows the copyright and some informations usefull for
    debugging. */
-void version(void)
+
+int version(void)
 {
-       fprintf(stderr, _("Copyright (C) Hugh Blemings <hugh@blemings.org>, 1999, 2000\n"
+       fprintf(stdout, _("GNOKII Version %s\n"
+                         "Copyright (C) Hugh Blemings <hugh@blemings.org>, 1999, 2000\n"
                          "Copyright (C) Pavel Janík ml. <Pavel.Janik@suse.cz>, 1999, 2000\n"
                          "Copyright (C) Pavel Machek <pavel@ucw.cz>, 2001\n"
                          "Copyright (C) Pawe³ Kot <pkot@linuxnews.pl>, 2001\n"
                          "gnokii is free software, covered by the GNU General Public License, and you are\n"
                          "welcome to change it and/or distribute copies of it under certain conditions.\n"
                          "There is absolutely no warranty for gnokii.  See GPL for details.\n"
-                         "Built %s %s for %s on %s \n"), __TIME__, __DATE__, model, Port);
+                         "Built %s %s for %s on %s \n"), VERSION, __TIME__, __DATE__, model, Port);
+       return 0;
 }
 
 /* The function usage is only informative - it prints this program's usage and
    command-line options. */
+
 int usage(void)
 {
-       fprintf(stderr, _("   usage: gnokii [--help|--monitor|--version]\n"
+       fprintf(stdout, _("   usage: gnokii [--help|--monitor|--version]\n"
                          "          gnokii --getmemory memory_type start [end]\n"
                          "          gnokii --writephonebook [-i]\n"
                          "          gnokii --getspeeddial number\n"
                          "          gnokii --setspeeddial number memory_type location\n"
                          "          gnokii --getsms memory_type start [end] [-f file] [-F file] [-d]\n"
                          "          gnokii --deletesms memory_type start [end]\n"
-                         "          gnokii --sendsms destination [--smsc message_center_number |\n"
-                         "                 --smscno message_center_index] [-r] [-C n] [-v n]\n"
-                         "                 [--long n]\n"
+                         "          gnokii --sendsms destination [-r] [-C n] [-v n]\n"
+                         "                 [--longtext|--longudh] [--udh] [-8]\n"
+                         "                 [--smsc message_center_number | --smscno message_center_index]\n"
                          "          gnokii --savesms [-m] [-l n] [-i]\n"
                          "          gnokii --getsmsc message_center_number\n"
                          "          gnokii --setdatetime [YYYY [MM [DD [HH [MM]]]]]\n"
@@ -185,7 +322,9 @@ int usage(void)
                          "          gnokii --identify\n"
                          "          gnokii --senddtmf string\n"
                          "          gnokii --sendlogo {caller|op} destination logofile [network code]\n"
+                         "                 [--smsc message_center_number | --smscno message_center_index]\n"
                          "          gnokii --sendringtone destination rtttlfile\n"
+                         "                 [--smsc message_center_number | --smscno message_center_index]\n"
                          "          gnokii --setlogo op [logofile] [network code]\n"
                          "          gnokii --setlogo startup [logofile]\n"
                          "          gnokii --setlogo caller [logofile] [caller group number] [group name]\n"
@@ -200,14 +339,9 @@ int usage(void)
                          "          gnokii --getprofile [number]\n"
                          "          gnokii --displayoutput\n"
                          "          gnokii --keysequence\n"
-                         "          gnokii --divert {--op|-o} {register|enable|query|disable|erasure}\n"
-                         "                 {--type|-t} {all|busy|noans|outofreach|notavail}\n"
-                         "                 {--call|-c} {all|voice|fax|data}\n"
-                         "                 [{--timeout|-m} time_in_seconds]\n"
-                         "                 [{--number|-n} number]\n"
-                       ));
+               ));
 #ifdef SECURITY
-       fprintf(stderr, _(
+       fprintf(stdout, _(
                "          gnokii --entersecuritycode PIN|PIN2|PUK|PUK2\n"
                "          gnokii --getsecuritycodestatus\n"
                ));
@@ -223,15 +357,15 @@ static GSM_Data data;
 
 void fbusinit(void (*rlp_handler)(RLP_F96Frame *frame))
 {
-       int count = 0;
+       int count=0;
        GSM_Error error;
-       GSM_ConnectionType connection = GCT_Serial;
+       GSM_ConnectionType connection=GCT_Serial;
 
        GSM_DataClear(&data);
 
-       if (!strcasecmp(Connection, "dau9p"))    connection = GCT_DAU9P; /* Use only with 6210/7110 for faster connection with such cable */
-       if (!strcasecmp(Connection, "infrared")) connection = GCT_Infrared;
-       if (!strcasecmp(Connection, "irda"))     connection = GCT_Irda;
+       if (!strcmp(Connection, "infrared")) connection=GCT_Infrared;
+       if (!strcmp(Connection, "irda"))     connection=GCT_Irda;
+       if (!strcmp(Connection, "tcp"))      connection=GCT_TCP;
 
        /* Initialise the code for the GSM interface. */     
 
@@ -296,18 +430,18 @@ int main(int argc, char *argv[])
        static struct option long_options[] =
        {
                /* FIXME: these comments are nice, but they would be more usefull as docs for the user */
-               /* Display usage. */
+               // Display usage.
                { "help",               no_argument,       NULL, OPT_HELP },
 
-               /* Display version and build information. */
+               // Display version and build information.
                { "version",            no_argument,       NULL, OPT_VERSION },
 
-               /* Monitor mode */
+               // Monitor mode
                { "monitor",            no_argument,       NULL, OPT_MONITOR },
 
 #ifdef SECURITY
 
-               /* Enter Security Code mode */
+               // Enter Security Code mode
                { "entersecuritycode",  required_argument, NULL, OPT_ENTERSECURITYCODE },
 
                // Get Security Code status
@@ -363,7 +497,7 @@ int main(int argc, char *argv[])
                // Send SMS message mode
                { "sendsms",            required_argument, NULL, OPT_SENDSMS },
 
-               // Ssve SMS message mode
+               // Save SMS message mode
                { "savesms",            optional_argument, NULL, OPT_SAVESMS },
 
                // Send logo as SMS message mode
@@ -410,10 +544,7 @@ int main(int argc, char *argv[])
 
                // Simulate pressing the keys
                { "keysequence",        no_argument,       NULL, OPT_KEYPRESS },
-
-               /* Divert calls */
-               { "divert",             required_argument, NULL, OPT_DIVERT },
-
+    
                // For development purposes: insert you function calls here
                { "foogle",             no_argument,       NULL, OPT_FOOGLE },
 
@@ -442,8 +573,8 @@ int main(int argc, char *argv[])
                { OPT_DELETESMS,         2, 3, 0 },
                { OPT_SENDSMS,           1, 10, 0 },
                { OPT_SAVESMS,           0, 6, 0 },
-               { OPT_SENDLOGO,          3, 4, GAL_XOR },
-               { OPT_SENDRINGTONE,      2, 2, 0 },
+               { OPT_SENDLOGO,          3, 6, 0 },
+               { OPT_SENDRINGTONE,      2, 6, 0 },
                { OPT_GETSMSC,           1, 1, 0 },
                { OPT_GETWELCOMENOTE,    1, 1, 0 },
                { OPT_SETWELCOMENOTE,    1, 1, 0 },
@@ -456,7 +587,6 @@ int main(int argc, char *argv[])
                { OPT_RESET,             0, 1, 0 },
                { OPT_GETPROFILE,        0, 1, 0 },
                { OPT_WRITEPHONEBOOK,    0, 1, 0 },
-               { OPT_DIVERT,            6, 10, 0 },
 
                { 0, 0, 0, 0 },
        };
@@ -474,26 +604,22 @@ int main(int argc, char *argv[])
                exit(-1);
        }
 
-       /* Introduce yourself */
-       short_version();
-
        /* Handle command line arguments. */
        c = getopt_long(argc, argv, "", long_options, NULL);
        if (c == -1)            /* No argument given - we should display usage. */
                usage();
 
        switch(c) {
-       /* First, error conditions */
+       // First, error conditions
        case '?':
        case ':':
                fprintf(stderr, _("Use '%s --help' for usage informations.\n"), argv[0]);
                exit(0);
-       /* Then, options with no arguments */
+       // Then, options with no arguments
        case OPT_HELP:
                usage();
        case OPT_VERSION:
-               version();
-               exit(0);
+               return version();
        }
        
        /* We have to build an array of the arguments which will be passed to the
@@ -545,7 +671,7 @@ int main(int argc, char *argv[])
                case OPT_WRITEPHONEBOOK:
                        rc = writephonebook(nargc, nargv);
                        break;
-               /* Now, options with arguments */
+               // Now, options with arguments
                case OPT_SETDATETIME:
                        rc = setdatetime(nargc, nargv);
                        break;
@@ -610,7 +736,7 @@ int main(int argc, char *argv[])
                        rc = setringtone(nargc, nargv);
                        break;
                case OPT_SENDRINGTONE:
-                       rc = sendringtone(nargc, nargv);
+                       rc = sendringtone(argc, argv);
                        break;
                case OPT_GETPROFILE:
                        rc = getprofile(nargc, nargv);
@@ -621,20 +747,17 @@ int main(int argc, char *argv[])
                case OPT_KEYPRESS:
                        rc = presskeysequence();
                        break;
+#ifndef WIN32
+               case OPT_FOOGLE:
+                       rc = foogle(nargv);
+                       break;
+#endif
                case OPT_SENDDTMF:
                        rc = senddtmf(optarg);
                        break;
                case OPT_RESET:
                        rc = reset(optarg);
                        break;
-               case OPT_DIVERT:
-                       rc = divert(argc, argv);
-                       break;
-#ifndef WIN32
-               case OPT_FOOGLE:
-                       rc = foogle(nargv);
-                       break;
-#endif
                default:
                        fprintf(stderr, _("Unknown option: %d\n"), c);
                        break;
@@ -647,23 +770,80 @@ int main(int argc, char *argv[])
        exit(-1);
 }
 
+#define SMSC_SHORTCHAR_SMSC   (0xF0)
+#define SMSC_SHORTCHAR_SMSCNO (0xF1)
+#define SMSC_OPTIONS \
+               { "smsc",     required_argument, NULL, SMSC_SHORTCHAR_SMSC}, \
+               { "smscno",   required_argument, NULL, SMSC_SHORTCHAR_SMSCNO}
+
+/* RETURNS: Whether the options was found as ours (=>rerun getopt_long())
+ */
+static bool smsc_options_parse(int option,GSM_SMSMessage *SMS)
+{
+       switch (option) {
+
+       case SMSC_SHORTCHAR_SMSC: /* SMSC number */
+               SMS->MessageCenter.No = 0;
+               strcpy(SMS->MessageCenter.Number,optarg);
+               break;
+
+       case SMSC_SHORTCHAR_SMSCNO: /* SMSC number index in phone memory */
+               SMS->MessageCenter.No = atoi(optarg);
+
+               if (SMS->MessageCenter.No < 1 || SMS->MessageCenter.No > 5)
+                       usage();
+               break;
+
+       default:
+               return(false);          /* option not recognized */
+       }
+
+       return(true);   /* option was successfuly processed */
+}
+
+/* RETURNS: Success
+ */
+bool sendsms_deconcatenated(GSM_SMSMessage *sms,char *buf,size_t buflen,bool useudh)
+{
+       GSM_Deconcatenate_state SMS_Deconcatenate_state;
+       GSM_Error error;
+
+       SMS_Deconcatenate_state.first=true;
+       while (SMS_Deconcatenate(&SMS_Deconcatenate_state,sms,buf,buflen,useudh)) {
+               /* Send the message. */
+               error = GSM->SendSMSMessage(sms);
+
+               if (error == GE_SMSSENDOK) {
+                       fprintf(stdout, _("Send succeeded!\n"));
+               } else {
+                       fprintf(stdout, _("SMS Send failed (error=%d)\n"), error);
+                       return(false);
+               }
+               /* Here the sleep have no meaning.
+                * If it is required by some backend phone driver, it should be done THERE!
+                */
+               /* sleep(10); */
+       }
+       return(true);
+}
+
 /* Send  SMS messages. */
 int sendsms(int argc, char *argv[])
 {
        GSM_SMSMessage SMS;
-       GSM_Error error;
-       //      char UDH[GSM_MAX_USER_DATA_HEADER_LENGTH];
        /* The maximum length of an uncompressed concatenated short message is
           255 * 153 = 39015 default alphabet characters */
-       char message_buffer[255 * GSM_MAX_SMS_LENGTH];
+       char message_buffer[GSM_MAX_CONCATENATED_SMS_LENGTH];
        int input_len, chars_read;
-       int i; /*, offset, nr_msg, aux;*/
+       int i;
+       bool useudh = false;
 
        struct option options[] = {
-               { "smsc",    required_argument, NULL, '1'},
-               { "smscno",  required_argument, NULL, '2'},
-               { "long",         required_argument, NULL, '3'},
-               { NULL,      0,                 NULL, 0}
+               SMSC_OPTIONS,
+               { "longtext", no_argument,       NULL, '3'},
+               { "longudh",  no_argument,       NULL, '4'},
+               { "udh",      no_argument,       NULL, '5'},
+               { NULL,       0,                 NULL, 0}
        };
 
        input_len = GSM_MAX_SMS_LENGTH;
@@ -678,72 +858,60 @@ int sendsms(int argc, char *argv[])
           - unset user data header indicator
        */
 
-       memset(&SMS, 0, sizeof(GSM_SMSMessage));
-       
-       SMS.Type = SMS_Submit;
-       SMS.DCS.Type = SMS_GeneralDataCoding;
-       SMS.DCS.u.General.Compressed = false;
-       SMS.DCS.u.General.Alphabet = SMS_DefaultAlphabet;
-       SMS.DCS.u.General.Class = 0;
+       SMS.Type = GST_MO;
+       SMS.Class = -1;
+       SMS.Compression = false;
+       SMS.EightBit = false;
        SMS.MessageCenter.No = 1;
-       SMS.Validity.VPF = SMS_RelativeFormat;
-       SMS.Validity.u.Relative = 4320; /* 4320 minutes == 72 hours */
-       SMS.UDH_No = 0;
-       SMS.Report = false;
+       SMS.Validity = 4320; /* 4320 minutes == 72 hours */
+       SMS.UDHPresent = false;
 
-       strcpy(SMS.RemoteNumber.number, argv[0]);
-       if (SMS.RemoteNumber.number[0] == '+') SMS.RemoteNumber.type = SMS_International;
-       else SMS.RemoteNumber.type = SMS_Unknown;
+       strcpy(SMS.Destination, argv[0]);
 
        optarg = NULL;
        optind = 0;
 
        while ((i = getopt_long(argc, argv, "r8cC:v:", options, NULL)) != -1) {
-               switch (i) {       // -8 is for 8-bit data, -c for compression. both are not yet implemented.
-               case '1': /* SMSC number */
-                       SMS.MessageCenter.No = 0;
-                       strcpy(SMS.MessageCenter.Number, optarg);
-                       if (SMS.MessageCenter.Number[0] == '+') SMS.MessageCenter.Type = SMS_International;
-                       else SMS.MessageCenter.Type = SMS_Unknown;
+               if (smsc_options_parse(i,&SMS))
+                       continue;
+               switch (i) {       // -c for compression. not yet implemented.
+               case '3': /* we send long message in text format */
+                       input_len = GSM_MAX_CONCATENATED_SMS_LENGTH;
+                       useudh = false;
                        break;
-               case '2': /* SMSC number index in phone memory */
-                       SMS.MessageCenter.No = atoi(optarg);
-
-                       if (SMS.MessageCenter.No < 1 || SMS.MessageCenter.No > 5)
-                               usage();
-                       data.MessageCenter = &SMS.MessageCenter;
-                       error = SM_Functions(GOP_GetSMSCenter, &data, &State);
-                       break;
-               case '3': /* we send long message */
-                       input_len = atoi(optarg);
-                       if (input_len > 255 * GSM_MAX_SMS_LENGTH) {
-                               fprintf(stderr, _("Input too long!\n"));        
-                               exit(-1);
-                       }
+               case '4': /* we send long message in UDH format */
+                       input_len = GSM_MAX_CONCATENATED_SMS_LENGTH;
+                       useudh = true;
+                       break;
+               case '5': /* UDH indication requested */
+                       SMS.UDHPresent = true;
                        break;
                case 'r': /* request for delivery report */
-                       SMS.Report = true;
+                       SMS.Type = GST_DR;
                        break;
                case 'C': /* class Message */
                        switch (*optarg) {
                        case '0':
-                               SMS.DCS.u.General.Class = 1;
+                               SMS.Class = 0;
                                break;
                        case '1':
-                               SMS.DCS.u.General.Class = 2;
+                               SMS.Class = 1;
                                break;
                        case '2':
-                               SMS.DCS.u.General.Class = 3;
+                               SMS.Class = 2;
                                break;
                        case '3':
-                               SMS.DCS.u.General.Class = 4;
+                               SMS.Class = 3;
                                break;
                        default:
                                usage();
                        }
                        break;
+               case '8': /* 8-bit data */
+                       SMS.EightBit = true;
+                       break;
                case 'v':
-                       SMS.Validity.u.Relative = atoi(optarg);
+                       SMS.Validity = atoi(optarg);
                        break;
                default:
                        usage(); /* Would be better to have an sendsms_usage() here. */
@@ -761,21 +929,24 @@ int sendsms(int argc, char *argv[])
                return -1;
        }
 
+       if (SMS.UDHPresent) {
+u8 UDHlen = 1 + message_buffer[0];     /* designifify */
+
+               if (chars_read < UDHlen || sizeof(SMS.UDH) < UDHlen) {
+                       fprintf(stderr, _("Input too short to satisfy UDH!\n"));
+                       return -1;
+               }
+               memcpy(SMS.UDH, message_buffer, UDHlen);
+               chars_read-=UDHlen;
+               memmove(message_buffer, message_buffer + UDHlen, chars_read);
+       }
+
        /*  Null terminate. */
        message_buffer[chars_read] = 0x00;      
-       strncpy(SMS.MessageText, message_buffer, chars_read);
-       data.SMSMessage = &SMS;
 
-       /* Send the message. */
-       error = SM_Functions(GOP_SendSMS, &data, &State);
-
-       if (error == GE_SMSSENDOK) {
-               fprintf(stdout, _("Send succeeded!\n"));
-       } else {
-               fprintf(stdout, _("SMS Send failed (error=%d)\n"), error);
-       }
+       sendsms_deconcatenated(&SMS,message_buffer,chars_read,useudh);
 
-       if (GSM && GSM->Terminate) GSM->Terminate();
+       GSM->Terminate();
 
        return 0;
 }
@@ -786,24 +957,24 @@ int savesms(int argc, char *argv[])
        GSM_Error error;
        /* The maximum length of an uncompressed concatenated short message is
           255 * 153 = 39015 default alphabet characters */
-       char message_buffer[255 * GSM_MAX_SMS_LENGTH];
+       char message_buffer[GSM_MAX_CONCATENATED_SMS_LENGTH];
        int input_len, chars_read;
        int i, confirm = -1;
        int interactive = 0;
        char ans[8];
 
        /* Defaults */
-       SMS.Type = SMS_Deliver;
-       SMS.DCS.Type = SMS_GeneralDataCoding;
-       SMS.DCS.u.General.Compressed = false;
-       SMS.DCS.u.General.Alphabet = SMS_DefaultAlphabet;
-       SMS.DCS.u.General.Class = 0;
+       SMS.Type = GST_MO;
+       SMS.Destination[0] = '\0';
+       SMS.Class = -1;
+       SMS.Compression = false;
+       SMS.EightBit = false;
        SMS.MessageCenter.No = 1;
-       SMS.Validity.VPF = SMS_RelativeFormat;
-       SMS.Validity.u.Relative = 4320; /* 4320 minutes == 72 hours */
-       SMS.UDH_No = 0;
-       SMS.Status = SMS_Unsent;
-       SMS.Number = 0;
+       SMS.Validity = 4320; /* 4320 minutes == 72 hours */
+       SMS.UDHPresent = false;
+       SMS.Status = GSS_NOTSENTREAD;
+       SMS.Location = 0;
+       SMS.MemoryType = GMT_SM;
 
        input_len = GSM_MAX_SMS_LENGTH;
 
@@ -811,10 +982,10 @@ int savesms(int argc, char *argv[])
        while ((i = getopt(argc, argv, "ml:in:s:c:")) != -1) {
                switch (i) {
                case 'm': /* mark the message as sent */
-                       SMS.Status = SMS_Sent;
+                       SMS.Status = GSS_SENTREAD;
                        break;
                case 'l': /* Specify the location */
-                       SMS.Number = atoi(optarg);
+                       SMS.Location = atoi(optarg);
                        break;
                case 'i': /* Ask before overwriting */
                        interactive = 1;
@@ -834,7 +1005,7 @@ int savesms(int argc, char *argv[])
        if (interactive) {
                GSM_SMSMessage aux;
 
-               aux.Number = SMS.Number;
+               aux.Location = SMS.Location;
                data.SMSMessage = &aux;
                error = SM_Functions(GOP_GetSMS, &data, &State);
                switch (error) {
@@ -843,20 +1014,20 @@ int savesms(int argc, char *argv[])
                        while (confirm < 0) {
                                fprintf(stderr, _("Overwrite? (yes/no) "));
                                GetLine(stdin, ans, 7);
-                               if (!strcmp(ans, _("yes"))) confirm = 1;
-                               else if (!strcmp(ans, _("no"))) confirm = 0;
+                               if (!strcmp(ans, "yes")) confirm = 1;
+                               else if (!strcmp(ans, "no")) confirm = 0;
                        }  
-                       if (!confirm) {
-                               if (GSM && GSM->Terminate) GSM->Terminate();
-                               return 0;
-                       }
+                       if (!confirm) { GSM->Terminate(); return 0; }
                        else break;
                case GE_INVALIDSMSLOCATION:
                        fprintf(stderr, _("Invalid location\n"));
-                       if (GSM && GSM->Terminate) GSM->Terminate();
+                       GSM->Terminate();
                        return -1;
                default:
-                       dprintf("Location %d empty. Saving\n", SMS.Number);
+/* FIXME: Remove this fprintf when the function is thoroughly tested */
+#ifdef DEBUG
+                       fprintf(stderr, _("Location %d empty. Saving\n"), SMS.Location);
+#endif
                        break;
                }
        }
@@ -876,6 +1047,7 @@ int savesms(int argc, char *argv[])
 
        strncpy (SMS.MessageText, message_buffer, chars_read);
        SMS.MessageText[chars_read] = 0;
+       SMS.MessageTextLength=chars_read;
 
        error = GSM->SaveSMSMessage(&SMS);
 
@@ -885,7 +1057,7 @@ int savesms(int argc, char *argv[])
                fprintf(stdout, _("Saving failed (error=%d)\n"), error);
        }
        sleep(10);
-       if (GSM && GSM->Terminate) GSM->Terminate();
+       GSM->Terminate();
 
        return 0;
 }
@@ -893,12 +1065,12 @@ int savesms(int argc, char *argv[])
 /* Get SMSC number */
 int getsmsc(char *MessageCenterNumber)
 {
-       SMS_MessageCenter       MessageCenter;
+       GSM_MessageCenter       MessageCenter;
        GSM_Data                data;
        GSM_Error               error;
        
        memset(&MessageCenter, 0, sizeof(MessageCenter));
-       MessageCenter.No = atoi(MessageCenterNumber);
+       MessageCenter.No=atoi(MessageCenterNumber);
        
        if (GSM && GSM->GetSMSCenter && GSM->Terminate) {
                error = GSM->GetSMSCenter(&MessageCenter);
@@ -916,25 +1088,25 @@ int getsmsc(char *MessageCenterNumber)
                fprintf(stdout, _("Messages sent as "));
                
                switch (MessageCenter.Format) {
-               case SMS_Text:
+               case GSMF_Text:
                        fprintf(stdout, _("Text"));
                        break;
-               case SMS_VoiceMail:
-                       fprintf(stdout, _("VoiceMail"));
+               case GSMF_Paging:
+                       fprintf(stdout, _("Paging"));
                        break;
-               case SMS_Fax:
+               case GSMF_Fax:
                        fprintf(stdout, _("Fax"));
                        break;
-               case SMS_Email:
-//             case GSMF_UCI:
+               case GSMF_Email:
+               case GSMF_UCI:
                        fprintf(stdout, _("Email"));
                        break;
-/*             case GSMF_ERMES:
+               case GSMF_ERMES:
                        fprintf(stdout, _("ERMES"));
                        break;
                case GSMF_X400:
                        fprintf(stdout, _("X.400"));
-                       break; */
+                       break;
                default:
                        fprintf(stdout, _("Unknown"));
                        break;
@@ -944,22 +1116,22 @@ int getsmsc(char *MessageCenterNumber)
                fprintf(stdout, _("Message validity is "));
                
                switch (MessageCenter.Validity) {
-               case SMS_V1H:
+               case GSMV_1_Hour:
                        fprintf(stdout, _("1 hour"));
                        break;
-               case SMS_V6H:
+               case GSMV_6_Hours:
                        fprintf(stdout, _("6 hours"));
                        break;
-               case SMS_V24H:
+               case GSMV_24_Hours:
                        fprintf(stdout, _("24 hours"));
                        break;
-               case SMS_V72H:
+               case GSMV_72_Hours:
                        fprintf(stdout, _("72 hours"));
                        break;
-               case SMS_V1W:
+               case GSMV_1_Week:
                        fprintf(stdout, _("1 week"));
                        break;
-               case SMS_VMax:
+               case GSMV_Max_Time:
                        fprintf(stdout, _("Maximum time"));
                        break;
                default:
@@ -985,8 +1157,6 @@ int getsmsc(char *MessageCenterNumber)
 int getsms(int argc, char *argv[])
 {
        int del = 0;
-       SMS_Folder folder;
-       SMS_FolderList folderlist;
        GSM_SMSMessage message;
        char *memory_type_string;
        int start_message, end_message, count, mode = 1;
@@ -1025,7 +1195,7 @@ int getsms(int argc, char *argv[])
                                mode = 0;
                        case 'f':
                                if (optarg) {
-                                       fprintf(stderr, _("Saving into %s\n"), optarg);
+                                       dprintf(_("Saving into %s\n"), optarg);
                                        strncpy(filename, optarg, 64);
                                        if (strlen(optarg) > 63) {
                                                fprintf(stderr, _("Filename too long - will be truncated to 63 characters.\n"));
@@ -1040,37 +1210,32 @@ int getsms(int argc, char *argv[])
                        }
                }
        }
-       data.SMSFolderList = &folderlist;
-       folder.FolderID = 0;
-       data.SMSFolder = &folder;
+
        /* Now retrieve the requested entries. */
        for (count = start_message; count <= end_message; count ++) {
-               int offset = 0;
 
-               message.Number = count;
+               message.Location = count;
                data.SMSMessage = &message;
-               dprintf("MemoryType (gnokii.c) : %i\n", data.SMSMessage->MemoryType);
                error = SM_Functions(GOP_GetSMS, &data, &State);
 
                switch (error) {
                case GE_NONE:
                        switch (message.Type) {
-                       case SMS_Text:
-                               fprintf(stdout, _("%d. MO Message "), message.Number);
+                       case GST_MO:
+                               fprintf(stdout, _("%d. Outbox Message "), message.MessageNumber);
                                if (message.Status)
                                        fprintf(stdout, _("(sent)\n"));
-                               fprintf(stdout, _("%d. MO Message "), message.Number);
-                               if (message.Status)
+                               else
                                        fprintf(stdout, _("(not sent)\n"));
                                fprintf(stdout, _("Text: %s\n\n"), message.MessageText); 
                                break;
-                       case SMS_Delivery_Report:
-                               fprintf(stdout, _("%d. Delivery Report "), message.Number);
+                       case GST_DR:
+                               fprintf(stdout, _("%d. Delivery Report "), message.MessageNumber);
                                if (message.Status)
                                        fprintf(stdout, _("(read)\n"));
                                else
                                        fprintf(stdout, _("(not read)\n"));
-                               fprintf(stdout, _("Sending date/time: %02d/%02d/%04d %02d:%02d:%02d "), \
+                               fprintf(stdout, _("Sending date/time: %d/%d/%d %d:%02d:%02d "), \
                                        message.Time.Day, message.Time.Month, message.Time.Year, \
                                        message.Time.Hour, message.Time.Minute, message.Time.Second);
                                if (message.Time.Timezone) {
@@ -1080,7 +1245,7 @@ int getsms(int argc, char *argv[])
                                                fprintf(stdout,_("%02d00"), message.Time.Timezone);
                                }
                                fprintf(stdout, "\n");
-                               fprintf(stdout, _("Response date/time: %02d/%02d/%04d %02d:%02d:%02d "), \
+                               fprintf(stdout, _("Response date/time: %d/%d/%d %d:%02d:%02d "), \
                                        message.SMSCTime.Day, message.SMSCTime.Month, message.SMSCTime.Year, \
                                        message.SMSCTime.Hour, message.SMSCTime.Minute, message.SMSCTime.Second);
                                if (message.SMSCTime.Timezone) {
@@ -1090,16 +1255,16 @@ int getsms(int argc, char *argv[])
                                                fprintf(stdout,_("%02d00"),message.SMSCTime.Timezone);
                                }
                                fprintf(stdout, "\n");
-                               fprintf(stdout, _("Receiver: %s Msg Center: %s\n"), message.RemoteNumber.number, message.MessageCenter.Number);
+                               fprintf(stdout, _("Receiver: %s Msg Center: %s\n"), message.Sender, message.MessageCenter.Number);
                                fprintf(stdout, _("Text: %s\n\n"), message.MessageText); 
                                break;
                        default:
-                               fprintf(stdout, _("%d. Inbox Message "), message.Number);
+                               fprintf(stdout, _("%d. Inbox Message "), message.MessageNumber);
                                if (message.Status)
                                        fprintf(stdout, _("(read)\n"));
                                else
                                        fprintf(stdout, _("(not read)\n"));
-                               fprintf(stdout, _("Date/time: %02d/%02d/%04d %02d:%02d:%02d "), \
+                               fprintf(stdout, _("Date/time: %d/%d/%d %d:%02d:%02d "), \
                                        message.Time.Day, message.Time.Month, message.Time.Year, \
                                        message.Time.Hour, message.Time.Minute, message.Time.Second);
                                if (message.Time.Timezone) {
@@ -1109,39 +1274,36 @@ int getsms(int argc, char *argv[])
                                                fprintf(stdout,_("%02d00"),message.Time.Timezone);
                                }
                                fprintf(stdout, "\n");
-                               fprintf(stdout, _("Sender: %s Msg Center: %s\n"), message.RemoteNumber.number, message.MessageCenter.Number);
-                               switch (message.UDH[0].Type) {
-                               case SMS_OpLogo:
+                               fprintf(stdout, _("Sender: %s Msg Center: %s\n"), message.Sender, message.MessageCenter.Number);
+                               switch (SMS_DetectUDH(&message)) {
+                               case GSM_OpLogo:
                                        fprintf(stdout, _("GSM operator logo for %s (%s) network.\n"), bitmap.netcode, GSM_GetNetworkName(bitmap.netcode));
-                                       if (!strcmp(message.RemoteNumber.number, "+998000005") && !strcmp(message.MessageCenter.Number, "+886935074443")) fprintf(stdout, _("Saved by Logo Express\n"));
-                                       if (!strcmp(message.RemoteNumber.number, "+998000002") || !strcmp(message.RemoteNumber.number, "+998000003")) fprintf(stdout, _("Saved by Operator Logo Uploader by Thomas Kessler\n"));
-                                       offset = 3;
-                               case SMS_CallerIDLogo:
+                                       if (!strcmp(message.Sender, "+998000005") && !strcmp(message.MessageCenter.Number, "+886935074443")) dprintf(_("Saved by Logo Express\n"));
+                                       if (!strcmp(message.Sender, "+998000002") || !strcmp(message.Sender, "+998000003")) dprintf(_("Saved by Operator Logo Uploader by Thomas Kessler\n"));
+                               case GSM_CallerIDLogo:
                                        fprintf(stdout, ("Logo:\n"));
                                        /* put bitmap into bitmap structure */
-                                       GSM_ReadSMSBitmap(message.UDH[0].Type, message.MessageText+2+offset, message.MessageText, &bitmap);
+                                       GSM_ReadSMSBitmap(&message, &bitmap);
                                        GSM_PrintBitmap(&bitmap);
                                        if (*filename) {
                                                error = GE_NONE;
                                                if ((stat(filename, &buf) == 0)) {
                                                        fprintf(stdout, _("File %s exists.\n"), filename);
-                                                       fprintf(stdout, _("Overwrite? (yes/no) "));
+                                                       fprintf(stderr, _("Overwrite? (yes/no) "));
                                                        GetLine(stdin, ans, 4);
-                                                       if (!strcmp(ans, _("yes"))) {
+                                                       if (!strcmp(ans, "yes")) {
                                                                error = GSM_SaveBitmapFile(filename, &bitmap);
                                                        }
                                                } else error = GSM_SaveBitmapFile(filename, &bitmap);          
-                                               if (error != GE_NONE) fprintf(stderr, _("Couldn't save logofile %s!\n"), filename);
+                                               if (error!=GE_NONE) fprintf(stderr, _("Couldn't save logofile %s!\n"), filename);
                                        }
                                        break;
-                               case SMS_Ringtone:
-                                       fprintf(stdout, _("Ringtone\n"));
+                               case GSM_RingtoneUDH:
+                                       fprintf(stdout, ("Ringtone\n"));
                                        break;
-                               case SMS_ConcatenatedMessages:
-                                       fprintf(stdout, _("Linked (%d/%d):\n"),
-                                               message.UDH[0].u.ConcatenatedShortMessage.CurrentNumber,
-                                               message.UDH[0].u.ConcatenatedShortMessage.MaximumNumber);
-                               case SMS_NoUDH:
+                               case GSM_ConcatenatedMessages:
+                                       fprintf(stdout, _("Linked (%d/%d):\n"),message.UDH[5],message.UDH[4]);
+                               case GSM_NoUDH:
                                        fprintf(stdout, _("Text:\n%s\n\n"), message.MessageText);
                                        if ((mode != -1) && *filename) {
                                                char buf[1024];
@@ -1149,9 +1311,6 @@ int getsms(int argc, char *argv[])
                                                mode = GSM_SaveTextFile(buf, message.MessageText, mode);
                                        }
                                        break;
-                               case SMS_BusinessCard:
-                                       fprintf(stdout, _("Business Card:\n%s"), message.MessageText);
-                                       break;
                                default:
                                        fprintf(stderr, _("Unknown\n"));
                                        break;
@@ -1177,7 +1336,7 @@ int getsms(int argc, char *argv[])
                        fprintf(stderr, _("SMS location %s %d empty.\n"), memory_type_string, count);
                        break;
                default:
-                       fprintf(stdout, _("GetSMS %s %d failed!(%s)\n\n"), memory_type_string, count, print_error(error));
+                       fprintf(stdout, _("GetSMS %s %d failed!(%d)\n\n"), memory_type_string, count, error);
                        break;
                }
        }
@@ -1209,7 +1368,7 @@ int deletesms(int argc, char *argv[])
        /* Now delete the requested entries. */
        for (count = start_message; count <= end_message; count ++) {
 
-               message.Number = count;
+               message.Location = count;
                data.SMSMessage = &message;
                error = SM_Functions(GOP_DeleteSMS, &data, &State);
 
@@ -1218,14 +1377,14 @@ int deletesms(int argc, char *argv[])
                else {
                        if (error == GE_NOTIMPLEMENTED) {
                                fprintf(stderr, _("Function not implemented in %s model!\n"), model);
-                               if (GSM && GSM->Terminate) GSM->Terminate();
+                               GSM->Terminate();
                                return -1;      
                        }
                        fprintf(stdout, _("DeleteSMS %s %d failed!(%d)\n\n"), memory_type_string, count, error);
                }
        }
 
-       if (GSM && GSM->Terminate) GSM->Terminate();
+       GSM->Terminate();
 
        return 0;
 }
@@ -1248,18 +1407,17 @@ int entersecuritycode(char *type)
        GSM_Error test;
        GSM_SecurityCode SecurityCode;
 
-       if (!strcmp(type, "PIN"))
-               SecurityCode.Type = GSCT_Pin;
-       else if (!strcmp(type, "PUK"))
-               SecurityCode.Type = GSCT_Puk;
-       else if (!strcmp(type, "PIN2"))
-               SecurityCode.Type = GSCT_Pin2;
-       else if (!strcmp(type, "PUK2"))
-               SecurityCode.Type = GSCT_Puk2;
-       /* FIXME: Entering of SecurityCode does not work :-(
-       else if (!strcmp(type, "SecurityCode"))
-               SecurityCode.Type = GSCT_SecurityCode;
-       */
+       if (!strcmp(type,"PIN"))
+               SecurityCode.Type=GSCT_Pin;
+       else if (!strcmp(type,"PUK"))
+               SecurityCode.Type=GSCT_Puk;
+       else if (!strcmp(type,"PIN2"))
+               SecurityCode.Type=GSCT_Pin2;
+       else if (!strcmp(type,"PUK2"))
+               SecurityCode.Type=GSCT_Puk2;
+       // FIXME: Entering of SecurityCode does not work :-(
+       //  else if (!strcmp(type,"SecurityCode"))
+       //    SecurityCode.Type=GSCT_SecurityCode;
        else
                usage();
 
@@ -1267,10 +1425,10 @@ int entersecuritycode(char *type)
        printf("Enter your code: ");
        gets(SecurityCode.Code);
 #else
-       strcpy(SecurityCode.Code, getpass(_("Enter your code: ")));
+       strcpy(SecurityCode.Code,getpass(_("Enter your code: ")));
 #endif
 
-       if (GSM && GSM->EnterSecurityCode) test = GSM->EnterSecurityCode(SecurityCode);
+       test = GSM->EnterSecurityCode(SecurityCode);
        if (test == GE_INVALIDSECURITYCODE)
                fprintf(stdout, _("Error: invalid code.\n"));
        else if (test == GE_NONE)
@@ -1280,7 +1438,7 @@ int entersecuritycode(char *type)
        else
                fprintf(stdout, _("Other error.\n"));
 
-       if (GSM && GSM->Terminate) GSM->Terminate();
+       GSM->Terminate();
 
        return 0;
 }
@@ -1289,7 +1447,7 @@ int getsecuritycodestatus(void)
 {
        int Status;
 
-       if (GSM && GSM->GetSecurityCodeStatus && GSM->GetSecurityCodeStatus(&Status) == GE_NONE) {
+       if (GSM->GetSecurityCodeStatus(&Status) == GE_NONE) {
 
                fprintf(stdout, _("Security code status: "));
 
@@ -1318,7 +1476,7 @@ int getsecuritycodestatus(void)
                }
        }
 
-       if (GSM && GSM->Terminate) GSM->Terminate();
+       GSM->Terminate();
 
        return 0;
 }
@@ -1329,9 +1487,9 @@ int getsecuritycodestatus(void)
 /* Voice dialing mode. */
 int dialvoice(char *Number)
 {
-       if (GSM && GSM->DialVoice) GSM->DialVoice(Number);
+       GSM->DialVoice(Number);
 
-       if (GSM && GSM->Terminate) GSM->Terminate();
+       GSM->Terminate();
 
        return 0;
 }
@@ -1341,19 +1499,15 @@ int sendlogo(int argc, char *argv[])
 {
        GSM_SMSMessage SMS;
        GSM_Bitmap bitmap;
-       GSM_Error error;
 
-       char UserDataHeader[7] = {      0x06, /* UDH Length */
-                                       0x05, /* IEI: application port addressing scheme, 16 bit address */
-                                       0x04, /* IEI length */
-                                       0x15, /* destination address: high byte */
-                                       0x00, /* destination address: low byte */
-                                       0x00, /* originator address */
-                                       0x00};
+       char Data[sizeof(bitmap.bitmap) +64/*headers safety*/];
 
-       char Data[7] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+       int current=0, i;
 
-       int current=0;
+       struct option options[] = {
+               SMSC_OPTIONS,
+               { NULL,       0,                 NULL, 0}
+       };
 
        /* Default settings for SMS message:
           - no delivery report
@@ -1364,23 +1518,36 @@ int sendlogo(int argc, char *argv[])
           - validity 3 days
           - set UserDataHeaderIndicator
        */
-       SMS.Type = SMS_Submit;
-       SMS.DCS.Type = SMS_GeneralDataCoding;
-       SMS.DCS.u.General.Compressed = false;
-       SMS.DCS.u.General.Alphabet = SMS_8bit;
-       SMS.DCS.u.General.Class = 2;
+
+       SMS.Type = GST_MO;
+       SMS.Class = 1;
+       SMS.Compression = false;
+       SMS.EightBit = true;
        SMS.MessageCenter.No = 1;
-       SMS.Validity.VPF = SMS_RelativeFormat;
-       SMS.Validity.u.Relative = 4320; /* 4320 minutes == 72 hours */
+       SMS.Validity = 4320; /* 4320 minutes == 72 hours */
+
+       optarg = NULL;
+       optind = 0;
+       while ((i = getopt_long(argc, argv, "", options, NULL)) != -1) {
+               if (smsc_options_parse(i,&SMS))
+                       continue;
+               switch (i) {
+               default:
+                       usage(); /* Would be better to have an sendsms_usage() here. */
+               }
+       }
+
+/*
+       if (argc!=3 && argc!=4)
+               usage();
+*/
 
        /* The first argument is the type of the logo. */
        if (!strcmp(argv[0], "op")) {
-               SMS.UDH[0].Type = SMS_OpLogo;
-               UserDataHeader[4] = 0x82; /* NBS port 0x1582 */
+               SMS_SetupUDH(&SMS,GSM_OpLogo);          /* error ignored */
                fprintf(stdout, _("Sending operator logo.\n"));
-       } else if (!strcmp(argv[0], "caller")) {
-               SMS.UDH[0].Type = SMS_CallerIDLogo;
-               UserDataHeader[4] = 0x83; /* NBS port 0x1583 */
+       } else if (!strcmp(argv[0], "caller")) {        /* error ignored */
+               SMS_SetupUDH(&SMS,GSM_CallerIDLogo);
                fprintf(stdout, _("Sending caller line identification logo.\n"));
        } else {
                fprintf(stderr, _("You should specify what kind of logo to send!\n"));
@@ -1388,7 +1555,7 @@ int sendlogo(int argc, char *argv[])
        }
 
        /* The second argument is the destination, ie the phone number of recipient. */
-       SMS.MemoryType = atoi(argv[1]);
+       strcpy(SMS.Destination,argv[1]);
 
        /* The third argument is the bitmap file. */
        GSM_ReadBitmapFile(argv[2], &bitmap);
@@ -1413,23 +1580,17 @@ int sendlogo(int argc, char *argv[])
        }
 
        /* Set the logo size */
-       current++;
+       Data[current++] = 0x00;         /* RFU by Nokia */
        Data[current++] = bitmap.width;
        Data[current++] = bitmap.height;
 
-       Data[current++] = 0x01;
-
-       memcpy(SMS.MessageText, UserDataHeader, 7);
-       memcpy(SMS.MessageText, Data, current);
-       memcpy(SMS.MessageText+current, bitmap.bitmap, bitmap.size);
+       Data[current++] = 0x01;         /* depth=number of grayscales */
 
+       memcpy(Data+current,bitmap.bitmap,bitmap.size);
+       current+=bitmap.size;
+       
        /* Send the message. */
-       error = GSM->SendSMSMessage(&SMS,current+bitmap.size);
-
-       if (error == GE_SMSSENDOK)
-               fprintf(stdout, _("Send succeeded!\n"));
-       else
-               fprintf(stdout, _("SMS Send failed (error=%d)\n"), error);
+       sendsms_deconcatenated(&SMS,Data,current,true/*useudh*/);
 
        GSM->Terminate();
        return 0;
@@ -1449,9 +1610,9 @@ GSM_Error SaveBitmapFileOnConsole(char *FileName, GSM_Bitmap *bitmap)
                while (!confirm) {
                        fprintf(stderr, _("Saving logo. File \"%s\" exists. (O)verwrite, create (n)ew or (s)kip ? "), FileName);
                        GetLine(stdin, ans, 4);
-                       if (!strcmp(ans, _("O")) || !strcmp(ans, _("o"))) confirm = 1;
-                       if (!strcmp(ans, _("N")) || !strcmp(ans, _("n"))) confirm = 2;
-                       if (!strcmp(ans, _("S")) || !strcmp(ans, _("s"))) return GE_USERCANCELED;
+                       if (!strcmp(ans, "O") || !strcmp(ans, "o")) confirm = 1;
+                       if (!strcmp(ans, "N") || !strcmp(ans, "n")) confirm = 2;
+                       if (!strcmp(ans, "S") || !strcmp(ans, "s")) return GE_USERCANCELED;
                }  
                if (confirm == 1) break;
                if (confirm == 2) {
@@ -1640,13 +1801,13 @@ int setlogo(int argc, char *argv[])
                if (!strcmp(argv[0], "op") || !strcmp(argv[0], "startup") || !strcmp(argv[0], "caller")) {
                        if (argc > 1) {
                                if (ReadBitmapFileOnConsole(argv[1], &bitmap) != GE_NONE) {
-                                       if (GSM && GSM->Terminate) GSM->Terminate();
+                                       GSM->Terminate();
                                        return(-1);
                                }
 
                                if (!strcmp(argv[0], "op")) {
                                        if (bitmap.type != GSM_OperatorLogo || argc < 3) {
-                                               if (GSM && GSM->GetNetworkInfo && GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE) strncpy(bitmap.netcode, NetworkInfo.NetworkCode, 7);
+                                               if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE) strncpy(bitmap.netcode, NetworkInfo.NetworkCode, 7);
                                        }
                                        GSM_ResizeBitmap(&bitmap, GSM_OperatorLogo, GSM_Info);
                                        if (argc == 3) {
@@ -1670,7 +1831,7 @@ int setlogo(int argc, char *argv[])
                                        }
                                        oldbit.type = GSM_CallerLogo;
                                        oldbit.number = bitmap.number;
-                                       if (GSM && GSM->GetBitmap && GSM->GetBitmap(&oldbit) == GE_NONE) {
+                                       if (GSM->GetBitmap(&oldbit) == GE_NONE) {
                                                /* We have to get the old name and ringtone!! */
                                                bitmap.ringtone = oldbit.ringtone;
                                                strncpy(bitmap.text, oldbit.text, 255);
@@ -1694,18 +1855,18 @@ int setlogo(int argc, char *argv[])
                        }  
                } else {
                        fprintf(stderr, _("What kind of logo do you want to set ?\n"));
-                       if (GSM && GSM->Terminate) GSM->Terminate();
+                       GSM->Terminate();
                        return -1;
                }
        }
     
-       if (GSM && GSM->SetBitmap) error = GSM->SetBitmap(&bitmap);
+       error=GSM->SetBitmap(&bitmap);
   
        switch (error) {
        case GE_NONE:
                oldbit.type = bitmap.type;
                oldbit.number = bitmap.number;
-               if (GSM && GSM->GetBitmap && GSM->GetBitmap(&oldbit) == GE_NONE) {
+               if (GSM->GetBitmap(&oldbit) == GE_NONE) {
                        if (bitmap.type == GSM_WelcomeNoteText ||
                            bitmap.type == GSM_DealerNoteText) {
                                if (strcmp(bitmap.text, oldbit.text)) {
@@ -1726,13 +1887,13 @@ int setlogo(int argc, char *argv[])
                                        /* When we make it correct, we don't have this mistake */
                        
                                        strcpy(oldbit.text, "!\0");
-                                       if (GSM && GSM->SetBitmap) GSM->SetBitmap(&oldbit);
-                                       if (GSM && GSM->GetBitmap) GSM->GetBitmap(&oldbit);
+                                       GSM->SetBitmap(&oldbit);
+                                       GSM->GetBitmap(&oldbit);
                                        if (oldbit.text[0]!='!') {
                                                fprintf(stderr, _("SIM card and PIN is required\n"));
                                        } else {
-                                               if (GSM && GSM->SetBitmap) GSM->SetBitmap(&bitmap);
-                                               if (GSM && GSM->GetBitmap) GSM->GetBitmap(&oldbit);
+                                               GSM->SetBitmap(&bitmap);
+                                               GSM->GetBitmap(&oldbit);
                                                fprintf(stderr, _("too long, truncated to \"%s\" (length %i)\n"),oldbit.text,strlen(oldbit.text));
                                        }
                                        ok = false;
@@ -1762,7 +1923,7 @@ int setlogo(int argc, char *argv[])
                break;
        }
   
-       if (GSM && GSM->Terminate) GSM->Terminate();
+       GSM->Terminate();
 
        return 0;
 }
@@ -1911,7 +2072,7 @@ int getcalendarnote(int argc, char *argv[])
                }
        }
        
-       if (GSM && GSM->Terminate) GSM->Terminate();
+       GSM->Terminate();
        return error;
 }
 
@@ -1926,12 +2087,12 @@ int writecalendarnote(char *argv[])
        }
 
         /* Error 22=Calendar full ;-) */
-       if (GSM && GSM->WriteCalendarNote && GSM->WriteCalendarNote(&CalendarNote) == GE_NONE)
+       if ((GSM->WriteCalendarNote(&CalendarNote)) == GE_NONE)
                fprintf(stdout, _("Succesfully written!\n"));
        else
                fprintf(stdout, _("Failed to write calendar note!\n"));
 
-       if (GSM && GSM->Terminate) GSM->Terminate();
+       GSM->Terminate();
 
        return 0;
 }
@@ -1949,7 +2110,7 @@ int deletecalendarnote(int argc, char *argv[])
 
                CalendarNote.Location = i;
 
-               if (GSM && GSM->DeleteCalendarNote && GSM->DeleteCalendarNote(&CalendarNote) == GE_NONE) {
+               if (GSM->DeleteCalendarNote(&CalendarNote) == GE_NONE) {
                        fprintf(stdout, _("   Calendar note deleted.\n"));
                } else {
                        fprintf(stderr, _("The calendar note can not be deleted\n"));
@@ -1957,7 +2118,7 @@ int deletecalendarnote(int argc, char *argv[])
 
        }
 
-       if (GSM && GSM->Terminate) GSM->Terminate();
+       GSM->Terminate();
 
        return 0;
 }
@@ -2000,16 +2161,15 @@ int setdatetime(int argc, char *argv[])
        }
 
        /* FIXME: Error checking should be here. */
-       if (GSM && GSM->SetDateTime) GSM->SetDateTime(&Date);
+       GSM->SetDateTime(&Date);
 
-       if (GSM && GSM->Terminate) GSM->Terminate();
+       GSM->Terminate();
 
        return 0;
 }
 
 /* In this mode we receive the date and time from mobile phone. */
-int getdatetime(void)
-{
+int getdatetime(void) {
        GSM_Data        data;
        GSM_DateTime    date_time;
        GSM_Error       error;
@@ -2048,9 +2208,9 @@ int setalarm(char *argv[])
        Date.Hour = atoi(argv[0]);
        Date.Minute = atoi(argv[1]);
 
-       if (GSM && GSM->SetAlarm) GSM->SetAlarm(1, &Date);
+       GSM->SetAlarm(1, &Date);
 
-       if (GSM && GSM->Terminate) GSM->Terminate();
+       GSM->Terminate();
 
        return 0;
 }
@@ -2131,55 +2291,55 @@ int monitormode(void)
        /* Loop here indefinitely - allows you to see messages from GSM code in
           response to unknown messages etc. The loops ends after pressing the
           Ctrl+C. */
-       data.RFUnits = &rf_units;
-       data.RFLevel = &rflevel;
-       data.BatteryUnits = &batt_units;
-       data.BatteryLevel = &batterylevel;
+       data.RFUnits=&rf_units;
+       data.RFLevel=&rflevel;
+       data.BatteryUnits=&batt_units;
+       data.BatteryLevel=&batterylevel;
 
        while (!bshutdown) {
-               if (SM_Functions(GOP_GetRFLevel, &data, sm) == GE_NONE)
+               if (SM_Functions(GOP_GetRFLevel,&data,sm) == GE_NONE)
                        fprintf(stdout, _("RFLevel: %d\n"), (int)rflevel);
 
-               if (SM_Functions(GOP_GetBatteryLevel, &data, sm) == GE_NONE)
+               if (SM_Functions(GOP_GetBatteryLevel,&data,sm) == GE_NONE)
                        fprintf(stdout, _("Battery: %d\n"), (int)batterylevel);
 
 //             if (GSM->GetPowerSource(&powersource) == GE_NONE)
 //                     fprintf(stdout, _("Power Source: %s\n"), (powersource==GPS_ACDC)?_("AC/DC"):_("battery"));
 
-               data.MemoryStatus = &SIMMemoryStatus;
-               if (SM_Functions(GOP_GetMemoryStatus, &data, sm) == GE_NONE)
+               data.MemoryStatus=&SIMMemoryStatus;
+               if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
                        fprintf(stdout, _("SIM: Used %d, Free %d\n"), SIMMemoryStatus.Used, SIMMemoryStatus.Free);
 
-               data.MemoryStatus = &PhoneMemoryStatus;
-               if (SM_Functions(GOP_GetMemoryStatus, &data, sm) == GE_NONE)
+               data.MemoryStatus=&PhoneMemoryStatus;
+               if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
                        fprintf(stdout, _("Phone: Used %d, Free %d\n"), PhoneMemoryStatus.Used, PhoneMemoryStatus.Free);
 
-               data.MemoryStatus = &DC_MemoryStatus;
-               if (SM_Functions(GOP_GetMemoryStatus, &data, sm) == GE_NONE)
+               data.MemoryStatus=&DC_MemoryStatus;
+               if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
                        fprintf(stdout, _("DC: Used %d, Free %d\n"), DC_MemoryStatus.Used, DC_MemoryStatus.Free);
 
-               data.MemoryStatus = &EN_MemoryStatus;
-               if (SM_Functions(GOP_GetMemoryStatus, &data, sm) == GE_NONE)
+               data.MemoryStatus=&EN_MemoryStatus;
+               if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
                        fprintf(stdout, _("EN: Used %d, Free %d\n"), EN_MemoryStatus.Used, EN_MemoryStatus.Free);
 
-               data.MemoryStatus = &FD_MemoryStatus;
-               if (SM_Functions(GOP_GetMemoryStatus, &data, sm) == GE_NONE)
+               data.MemoryStatus=&FD_MemoryStatus;
+               if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
                        fprintf(stdout, _("FD: Used %d, Free %d\n"), FD_MemoryStatus.Used, FD_MemoryStatus.Free);
 
-               data.MemoryStatus = &LD_MemoryStatus;
-               if (SM_Functions(GOP_GetMemoryStatus, &data, sm) == GE_NONE)
+               data.MemoryStatus=&LD_MemoryStatus;
+               if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
                        fprintf(stdout, _("LD: Used %d, Free %d\n"), LD_MemoryStatus.Used, LD_MemoryStatus.Free);
 
-               data.MemoryStatus = &MC_MemoryStatus;
-               if (SM_Functions(GOP_GetMemoryStatus, &data, sm) == GE_NONE)
+               data.MemoryStatus=&MC_MemoryStatus;
+               if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
                        fprintf(stdout, _("MC: Used %d, Free %d\n"), MC_MemoryStatus.Used, MC_MemoryStatus.Free);
 
-               data.MemoryStatus = &ON_MemoryStatus;
-               if (SM_Functions(GOP_GetMemoryStatus, &data, sm) == GE_NONE)
+               data.MemoryStatus=&ON_MemoryStatus;
+               if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
                        fprintf(stdout, _("ON: Used %d, Free %d\n"), ON_MemoryStatus.Used, ON_MemoryStatus.Free);
 
-               data.MemoryStatus = &RC_MemoryStatus;
-               if (SM_Functions(GOP_GetMemoryStatus, &data, sm) == GE_NONE)
+               data.MemoryStatus=&RC_MemoryStatus;
+               if (SM_Functions(GOP_GetMemoryStatus,&data,sm) == GE_NONE)
                        fprintf(stdout, _("RC: Used %d, Free %d\n"), RC_MemoryStatus.Used, RC_MemoryStatus.Free);
 
 //             if (GSM->GetSMSStatus(&SMSStatus) == GE_NONE)
@@ -2197,7 +2357,9 @@ int monitormode(void)
                sleep(1);
        }
 
-       fprintf(stderr, _("Leaving monitor mode...\n"));
+       fprintf (stderr, _("Leaving monitor mode...\n"));
+
+       //GSM->Terminate();
 
        return 0;
 }
@@ -2216,7 +2378,7 @@ static GSM_Error PrettyOutputFn(char *Display, char *Indicators)
 }
 
 #if 0
-/* Uncomment it if used */
+// Uncomment it if used
 static GSM_Error OutputFn(char *Display, char *Indicators)
 {
        if (Display)
@@ -2269,7 +2431,7 @@ int displayoutput(void)
                        memset(&buf[0], 0, 102);
                        while (read(0, buf, 100) > 0) {
                                fprintf(stderr, "handling keys (%d).\n", strlen(buf));
-                               if (GSM && GSM->HandleString && GSM->HandleString(buf) != GE_NONE)
+                               if (GSM->HandleString(buf) != GE_NONE)
                                        fprintf(stdout, _("Key press simulation failed.\n"));
                                memset(buf, 0, 102);
                        }
@@ -2286,7 +2448,7 @@ int displayoutput(void)
        } else
                fprintf (stderr, _("Error!\n"));
 
-       if (GSM && GSM->Terminate) GSM->Terminate();
+       GSM->Terminate();
        return 0;
 }
 
@@ -2302,18 +2464,18 @@ int getprofile(int argc, char *argv[])
        char model[64];
 
        profile.Number = 0;
-       if (GSM && GSM->GetProfile) error = GSM->GetProfile(&profile);
+       error = GSM->GetProfile(&profile);
 
        if (error == GE_NONE) {
   
-               while (GSM && GSM->GetModel && GSM->GetModel(model) != GE_NONE)
+               while (GSM->GetModel(model) != GE_NONE)
                        sleep(1);
 
                max_profiles = 7; /* This is correct for 6110 (at least my). How do we get
                                     the number of profiles? */
 
-               /* For N5110 */
-               /* FIXME: It should be set to 3 for N5130 and 3210 too */
+               /*For N5110*/
+               /*FIX ME: It should be set to 3 for N5130 and 3210 too*/
                if (!strcmp(model, "NSE-1"))
                        max_profiles = 3;
 
@@ -2324,13 +2486,13 @@ int getprofile(int argc, char *argv[])
 
                        if (profile.Number < 0) {
                                fprintf(stderr, _("Profile number must be value from 1 to %d!\n"), max_profiles);
-                               if (GSM && GSM->Terminate) GSM->Terminate();
+                               GSM->Terminate();
                                return -1;
                        }
 
                        if (profile.Number >= max_profiles) {
                                fprintf(stderr, _("This phone supports only %d profiles!\n"), max_profiles);
-                               if (GSM && GSM->Terminate) GSM->Terminate();
+                               GSM->Terminate();
                                return -1;
                        }
                } else {
@@ -2343,7 +2505,7 @@ int getprofile(int argc, char *argv[])
                        profile.Number = i;
 
                        if (profile.Number != 0)
-                               if (GSM && GSM->GetProfile) GSM->GetProfile(&profile);
+                               GSM->GetProfile(&profile);
 
                        fprintf(stdout, "%d. \"%s\"\n", profile.Number + 1, profile.Name);
                        if (profile.DefaultName == -1) fprintf(stdout, _(" (name defined)\n"));
@@ -2383,16 +2545,16 @@ int getprofile(int argc, char *argv[])
        } else {
                if (error == GE_NOTIMPLEMENTED) {
                        fprintf(stderr, _("Function not implemented in %s model!\n"), model);
-                       if (GSM && GSM->Terminate) GSM->Terminate();
+                       GSM->Terminate();
                        return -1;
                } else {
                        fprintf(stderr, _("Unspecified error\n"));
-                       if (GSM && GSM->Terminate) GSM->Terminate();
+                       GSM->Terminate();
                        return -1;
                }
        }
 
-       if (GSM && GSM->Terminate) GSM->Terminate();
+       GSM->Terminate();
        return 0;
 }
 
@@ -2425,8 +2587,8 @@ int getmemory(int argc, char *argv[])
 
                entry.Location = count;
 
-               data.PhonebookEntry = &entry;
-               error = SM_Functions(GOP_ReadPhonebook, &data, sm);
+               data.PhonebookEntry=&entry;
+               error=SM_Functions(GOP_ReadPhonebook,&data,sm);
 
                if (error == GE_NONE) {
                        fprintf(stdout, "%s;%s;%s;%d;%d\n", entry.Name, entry.Number, memory_type_string, entry.Location, entry.Group);
@@ -2570,7 +2732,7 @@ int writephonebook(int argc, char *args[])
                        GSM_PhonebookEntry aux;
 
                        aux.Location = entry.Location;
-                       if (GSM && GSM->GetMemoryLocation) error = GSM->GetMemoryLocation(&aux);
+                       error = GSM->GetMemoryLocation(&aux);
                        
                        if (error == GE_NONE) {
                                if (!aux.Empty) {
@@ -2588,13 +2750,13 @@ int writephonebook(int argc, char *args[])
                                }
                        } else {
                                fprintf(stderr, _("Unknown error (%d)\n"), error);
-                               if (GSM && GSM->Terminate) GSM->Terminate();
+                               GSM->Terminate();
                                return 0;
                        }
                }
 
                /* Do write and report success/failure. */
-               if (GSM && GSM->WritePhonebookLocation) error = GSM->WritePhonebookLocation(&entry);
+               error = GSM->WritePhonebookLocation(&entry);
 
                if (error == GE_NONE)
                        fprintf (stdout, _("Write Succeeded: memory type: %s, loc: %d, name: %s, number: %s\n"), memory_type_string, entry.Location, entry.Name, entry.Number);
@@ -2603,7 +2765,7 @@ int writephonebook(int argc, char *args[])
 
        }
 
-       if (GSM && GSM->Terminate) GSM->Terminate();
+       GSM->Terminate();
        return 0;
 }
 
@@ -2664,11 +2826,11 @@ int setspeeddial(char *argv[])
        entry.Number = atoi(argv[0]);
        entry.Location = atoi(argv[2]);
 
-       if (GSM && GSM->SetSpeedDial && GSM->SetSpeedDial(&entry) == GE_NONE) {
+       if (GSM->SetSpeedDial(&entry) == GE_NONE) {
                fprintf(stdout, _("Succesfully written!\n"));
        }
 
-       if (GSM && GSM->Terminate) GSM->Terminate();
+       GSM->Terminate();
        return 0;
 }
 
@@ -2677,7 +2839,7 @@ int getdisplaystatus(void)
 { 
        int Status;
 
-       if (GSM && GSM->GetDisplayStatus) GSM->GetDisplayStatus(&Status);
+       GSM->GetDisplayStatus(&Status);
 
        fprintf(stdout, _("Call in progress: %s\n"), Status & (1<<DS_Call_In_Progress)?_("on"):_("off"));
        fprintf(stdout, _("Unknown: %s\n"),          Status & (1<<DS_Unknown)?_("on"):_("off"));
@@ -2688,7 +2850,7 @@ int getdisplaystatus(void)
        fprintf(stdout, _("Keyboard lock: %s\n"),    Status & (1<<DS_Keyboard_Lock)?_("on"):_("off"));
        fprintf(stdout, _("SMS storage full: %s\n"), Status & (1<<DS_SMS_Storage_Full)?_("on"):_("off"));
 
-       if (GSM && GSM->Terminate) GSM->Terminate();
+       GSM->Terminate();
        return 0;
 }
 
@@ -2709,12 +2871,12 @@ int netmonitor(char *Mode)
                mode = 0x00;
 
        memset(&Screen, 0, 50);
-       if (GSM && GSM->NetMonitor) GSM->NetMonitor(mode, Screen);
+       GSM->NetMonitor(mode, Screen);
 
        if (Screen)
                fprintf(stdout, "%s\n", Screen);
 
-       if (GSM && GSM->Terminate) GSM->Terminate();
+       GSM->Terminate();
        return 0;
 }
 
@@ -2724,10 +2886,10 @@ int identify(void)
        char imei[64], model[64], rev[64], manufacturer[64];
        GSM_Statemachine *sm = &State;
 
-       data.Manufacturer = manufacturer;
-       data.Model = model;
-       data.Revision = rev;
-       data.Imei = imei;
+       data.Manufacturer=manufacturer;
+       data.Model=model;
+       data.Revision=rev;
+       data.Imei=imei;
 
        /* Retrying is bad idea: what if function is simply not implemented?
           Anyway let's wait 2 seconds for the right packet from the phone. */
@@ -2745,13 +2907,15 @@ int identify(void)
        fprintf(stdout, _("Model:    %s\n"), model);
        fprintf(stdout, _("Revision: %s\n"), rev);
 
+       //GSM->Terminate();
+
        return 0;
 }
 
 int senddtmf(char *String)
 {
-       if (GSM && GSM->SendDTMF) GSM->SendDTMF(String);
-       if (GSM && GSM->Terminate) GSM->Terminate();
+       GSM->SendDTMF(String);
+       GSM->Terminate();
        return 0;
 }
 
@@ -2772,8 +2936,8 @@ int reset( char *type)
                        }
        }
 
-       if (GSM && GSM->Reset) GSM->Reset(_type);
-       if (GSM && GSM->Terminate) GSM->Terminate();
+       GSM->Reset(_type);
+       GSM->Terminate();
 
        return 0;
 }
@@ -2783,6 +2947,7 @@ int reset( char *type)
    tool. */
 int pmon(void)
 { 
+
        GSM_Error error;
        GSM_ConnectionType connection=GCT_Serial;
        GSM_Statemachine sm;
@@ -2804,22 +2969,69 @@ int pmon(void)
 
 int sendringtone(int argc, char *argv[])
 {
+       GSM_SMSMessage SMS;
        GSM_Ringtone ringtone;
-       GSM_Error error;
+       int i;
+       int size = GSM_MAX_RINGTONE_PACKAGE_LENGTH;
+       char Package[GSM_MAX_RINGTONE_PACKAGE_LENGTH];
 
-       if (GSM_ReadRingtoneFile(argv[0], &ringtone)) {
+       struct option options[] = {
+               SMSC_OPTIONS,
+               { NULL,       0,                 NULL, 0}
+       };
+
+       /* Default settings for SMS message:
+          - no delivery report
+          - Class Message 1
+          - no compression
+          - 8 bit data
+          - SMSC no. 1
+          - validity 3 days
+          - set UserDataHeaderIndicator
+       */
+
+       SMS.Type = GST_MO;
+       SMS.Class = 1;
+       SMS.Compression = false;
+       SMS.EightBit = true;
+       SMS.MessageCenter.No = 1;
+       SMS.Validity = 4320; /* 4320 minutes == 72 hours */
+
+       SMS_SetupUDH(&SMS,GSM_RingtoneUDH);             /* error ignored */
+
+       optarg = NULL;
+       optind = 0;
+       argv[1]=argv[0];
+       argv++;
+       argc--;
+       while ((i = getopt_long(argc, argv, "", options, NULL)) != -1) {
+               if (smsc_options_parse(i,&SMS))
+                       continue;
+               switch (i) {
+               default:
+                       usage(); /* Would be better to have an sendsms_usage() here. */
+               }
+       }
+       argc-=optind;
+       argv+=optind;
+
+       if (argc!=2)
+               usage();
+
+       if (GSM_ReadRingtoneFile(argv[1], &ringtone)) {
                fprintf(stdout, _("Failed to load ringtone.\n"));
                return(-1);
        }  
+       if (strlen(argv[0])+1 > sizeof(SMS.Destination)) {
+               fprintf(stdout, _("Destination number \"%s\" length too long!\n"), argv[0]);
+               return(-1);
+       }
+       strcpy(SMS.Destination, argv[0]);
+       GSM_PackRingtone(&ringtone, Package, &size);
 
-       if (GSM && GSM->SendRingtone) error = GSM->SendRingtone(&ringtone,argv[1]);
-
-       if (error == GE_NONE) 
-               fprintf(stdout, _("Send succeeded!\n"));
-       else
-               fprintf(stdout, _("SMS Send failed (error=%d)\n"), error);
+       sendsms_deconcatenated(&SMS,Package,size,true/*useudh*/);
 
-       if (GSM && GSM->Terminate) GSM->Terminate();
+       GSM->Terminate();
        return 0;
 }
 
@@ -2834,14 +3046,14 @@ int setringtone(int argc, char *argv[])
                return(-1);
        }  
 
-       if (GSM && GSM->SetRingtone) error = GSM->SetRingtone(&ringtone);
+       error = GSM->SetRingtone(&ringtone);
 
        if (error == GE_NONE) 
                fprintf(stdout, _("Send succeeded!\n"));
        else
                fprintf(stdout, _("Send failed\n"));
 
-       if (GSM && GSM->Terminate) GSM->Terminate();
+       GSM->Terminate();
        return 0;
 }
 
@@ -2854,124 +3066,23 @@ int presskeysequence(void)
        memset(&buf[0], 0, 102);
        while (read(0, buf, 100) > 0) {
                fprintf(stderr, "handling keys (%d).\n", strlen(buf));
-               if (GSM && GSM->HandleString && GSM->HandleString(buf) != GE_NONE)
+               if (GSM->HandleString(buf) != GE_NONE)
                        fprintf(stdout, _("Key press simulation failed.\n"));
                memset(buf, 0, 102);
        }
 
-       if (GSM && GSM->Terminate) GSM->Terminate();
-       return 0;
-}
-
-/* Options for --divert:
-   --op, -o [register|enable|query|disable|erasure]  REQ
-   --type, -t [all|busy|noans|outofreach|notavail]   REQ
-   --call, -c [all|voice|fax|data]                   REQ
-   --timeout, m time_in_seconds                      OPT
-   --number, -n number                               OPT
- */
-int divert(int argc, char **argv)
-{
-       int opt;
-       GSM_CallDivert cd;
-       GSM_Statemachine *sm = &State;
-       GSM_Data data;
-       GSM_Error error;
-       struct option options[] = {
-               { "op",      required_argument, NULL, 'o'},
-               { "type",    required_argument, NULL, 't'},
-               { "call",    required_argument, NULL, 'c'},
-               { "number",  required_argument, NULL, 'n'},
-               { "timeout", required_argument, NULL, 'm'},
-               { NULL,      0,                 NULL, 0}
-       };
-
-       optarg = NULL;
-       optind = 0;
-
-       /* Skip --divert */
-       argc--; argv++;
-
-       memset(&cd, 0, sizeof(GSM_CallDivert));
-
-       while ((opt = getopt_long(argc, argv, "o:t:n:c:m:", options, NULL)) != -1) {
-               switch (opt) {
-               case 'o':
-                       if (!strcmp("register", optarg)) {
-                               cd.Operation = GSM_CDV_Register;
-                       } else if (!strcmp("enable", optarg)) {
-                               cd.Operation = GSM_CDV_Enable;
-                       } else if (!strcmp("disable", optarg)) {
-                               cd.Operation = GSM_CDV_Disable;
-                       } else if (!strcmp("erasure", optarg)) {
-                               cd.Operation = GSM_CDV_Erasure;
-                       } else if (!strcmp("query", optarg)) {
-                               cd.Operation = GSM_CDV_Query;
-                       } else {
-                               usage();
-                               exit(-1);
-                       }
-                       break;
-               case 't':
-                       if (!strcmp("all", optarg)) {
-                               cd.DType = GSM_CDV_AllTypes;
-                       } else if (!strcmp("busy", optarg)) {
-                               cd.DType = GSM_CDV_Busy;
-                       } else if (!strcmp("noans", optarg)) {
-                               cd.DType = GSM_CDV_NoAnswer;
-                       } else if (!strcmp("outofreach", optarg)) {
-                               cd.DType = GSM_CDV_OutOfReach;
-                       } else if (!strcmp("notavail", optarg)) {
-                               cd.DType = GSM_CDV_NotAvailable;
-                       } else {
-                               usage();
-                               exit(-1);
-                       }
-                       break;
-               case 'c':
-                       if (!strcmp("all", optarg)) {
-                               cd.CType = GSM_CDV_AllCalls;
-                       } else if (!strcmp("voice", optarg)) {
-                               cd.CType = GSM_CDV_VoiceCalls;
-                       } else if (!strcmp("fax", optarg)) {
-                               cd.CType = GSM_CDV_FaxCalls;
-                       } else if (!strcmp("data", optarg)) {
-                               cd.CType = GSM_CDV_DataCalls;
-                       } else {
-                               usage();
-                               exit(-1);
-                       }
-                       break;
-               case 'm':
-                       cd.Timeout = atoi(optarg);
-                       break;
-               case 'n':
-                       strcpy(cd.Number.number, optarg);
-                       if (cd.Number.number[0] == '+') cd.Number.type = SMS_International;
-                       else cd.Number.type = SMS_Unknown;
-                       break;
-               default:
-                       usage();
-                       exit(-1);
-               }
-       }
-       data.CallDivert = &cd;
-       error = SM_Functions(GOP_CallDivert, &data, sm);
-
-       if (error == GE_NONE) {
-               fprintf(stderr, "Divert succeeded.\n");
-       } else {
-               fprintf(stderr, "%s\n", print_error(error));
-       }
+       GSM->Terminate();
        return 0;
 }
-
 /* This is a "convenience" function to allow quick test of new API stuff which
    doesn't warrant a "proper" command line function. */
 #ifndef WIN32
 int foogle(char *argv[])
 {
-       /* Fill in what you would like to test here... */
+       /* Initialise the code for the GSM interface. */     
+       fbusinit(NULL);
+       // Fill in what you would like to test here...
        return 0;
 }
 #endif