Not yet working stack checking (symbol STACKCHECK)
[gnokii.git] / gnokii / gnokii.c
1 /*
2
3   G N O K I I
4
5   A Linux/Unix toolset and driver for Nokia mobile phones.
6
7   Released under the terms of the GNU GPL, see file COPYING for more details.
8         
9   Mainline code for gnokii utility.  Handles command line parsing and
10   reading/writing phonebook entries and other stuff.
11
12 */
13
14 #include "config.h"
15
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <signal.h>
19 #include <string.h>
20 #include <ctype.h>
21 #include <time.h>
22 #include <sys/stat.h>
23
24 #ifdef UCLINUX
25 /* <getopt.h> or "getopt.h" would include insufficient getopt.h from uClinux */
26 #include "../getopt/getopt.h"
27 #endif /* UCLINUX */
28
29 #ifndef VC6
30   #if defined(__svr4__) || defined(__FreeBSD__)
31   #  include <strings.h>        /* for bzero */
32   #endif
33 #else
34   /* for VC6 make scripts save VERSION constant in mversion.h file */
35   #include "mversion.h"
36 #endif
37
38 #ifdef WIN32
39
40   #include <windows.h>
41
42   #include "misc_win32.h"
43   #include "getopt.h"
44
45   #define DEV_CONSOLE "CON:"
46
47 #else
48
49   #include <unistd.h>
50   #include <termios.h>
51   #include <fcntl.h>
52   #include <sys/types.h>
53   #include <sys/time.h>
54   #include <getopt.h>
55
56   #define DEV_CONSOLE "/dev/tty"
57 #endif
58
59 #include "misc.h"
60 #include "gsm-common.h"
61 #include "gsm-api.h"
62 #include "gsm-networks.h"
63 #ifndef UCLINUX
64 #include "gsm-ringtones.h"
65 #include "gsm-bitmaps.h"
66 #include "gsm-wap.h"
67 #include "gsm-sms.h"
68 #include "gsm-datetime.h"
69 #endif /* UCLINUX */
70 #include "gsm-phonebook.h"
71 #ifndef UCLINUX
72 #include "gsm-calendar.h"
73 #endif /* UCLINUX */
74 #include "gsm-coding.h"
75 #ifndef UCLINUX
76 #include "newmodules/n6110.h"
77 #endif
78 #include "files/cfgreader.h"
79 #ifndef UCLINUX
80 #include "files/gsm-filetypes.h"
81 #endif /* UCLINUX */
82 #include "gnokii.h"
83 #ifdef UCLINUX
84 #include "data/virtmodem.h"
85 #endif /* UCLINUX */
86
87 #ifdef USE_NLS
88   #include <locale.h>
89 #endif
90
91 static char *model;           /* Model from .gnokiirc file. */
92 static char *Port;            /* Port from .gnokiirc file */
93 static char *Initlength;      /* Init length from .gnokiirc file */
94 static char *Connection;      /* Connection type from .gnokiirc file */
95 #ifndef UCLINUX
96 char *SynchronizeTime; /* If we set date and time from computer to phone (from .gnokiirc file) */
97 #endif /* UCLINUX */
98 static char *BinDir;          /* Binaries directory from .gnokiirc file - not used here yet */
99
100 #ifndef UCLINUX
101 static GSM_SMSMessage SMS[4];
102 #endif /* UCLINUX */
103   
104 #ifndef UCLINUX
105
106 char *GetProfileCallAlertString(int code) {
107
108   switch (code) {
109     case PROFILE_CALLALERT_RINGING     : return "Ringing";
110     case PROFILE_CALLALERT_ASCENDING   : return "Ascending";
111     case PROFILE_CALLALERT_RINGONCE    : return "Ring once";
112     case PROFILE_CALLALERT_BEEPONCE    : return "Beep once";
113     case PROFILE_CALLALERT_CALLERGROUPS: return "Caller groups";
114     case PROFILE_CALLALERT_OFF         : return "Off";
115     default                            : return "Unknown";
116   }
117 }
118
119 char *GetProfileVolumeString(int code) {
120
121   switch (code) {
122     case PROFILE_VOLUME_LEVEL1 : return "Level 1";
123     case PROFILE_VOLUME_LEVEL2 : return "Level 2";
124     case PROFILE_VOLUME_LEVEL3 : return "Level 3";
125     case PROFILE_VOLUME_LEVEL4 : return "Level 4";
126     case PROFILE_VOLUME_LEVEL5 : return "Level 5";
127     default                    : return "Unknown";
128   }
129 }
130
131 char *GetProfileKeypadToneString(int code) {
132
133   switch (code) {
134     case PROFILE_KEYPAD_OFF    : return "Off";
135     case PROFILE_KEYPAD_LEVEL1 : return "Level 1";
136     case PROFILE_KEYPAD_LEVEL2 : return "Level 2";
137     case PROFILE_KEYPAD_LEVEL3 : return "Level 3";
138     default                    : return "Unknown";
139   }
140 }
141
142 char *GetProfileMessageToneString(int code) {
143
144   switch (code) {
145     case PROFILE_MESSAGE_NOTONE    : return "No tone";
146     case PROFILE_MESSAGE_STANDARD  : return "Standard";
147     case PROFILE_MESSAGE_SPECIAL   : return "Special";
148     case PROFILE_MESSAGE_BEEPONCE  : return "Beep once";
149     case PROFILE_MESSAGE_ASCENDING : return "Ascending";
150     default                        : return "Unknown";
151   }
152 }
153
154 char *GetProfileWarningToneString(int code) {
155
156   switch (code) {
157     case PROFILE_WARNING_OFF : return "Off";
158     case PROFILE_WARNING_ON  : return "On";
159     default                  : return "Unknown";
160   }
161 }
162
163 char *GetProfileOnOffString(int code) {
164
165   switch (code) {
166     case 0x00 : return "Off";
167     case 0x01 : return "On";
168     default   : return "Unknown";
169   }
170 }
171
172 static char *GetProfileVibrationString(int code)
173 {
174         switch (code) {
175         case PROFILE_VIBRATION_OFF:     return "Off";
176         case PROFILE_VIBRATION_ON:      return "On";
177         case PROFILE_VIBRATION_FIRST:   return "Vibrate first";
178         default:                        return "Unknown";
179         }
180 }
181
182 char BufferProfileGroups[90];
183
184 char *GetProfileCallerGroups(int code) 
185 {
186   static char az_group_name[5][MAX_BITMAP_TEXT_LENGTH];
187   static bool enteronce=false;
188   register int i;
189   GSM_Bitmap bitmap;
190
191   if( code == PROFILE_CALLERGROUPS_ALL )
192        return _("All calls alert");
193
194   if( !enteronce ) {
195     for(i=0;i<5;i++) az_group_name[i][0]='\0';
196     enteronce=true;
197   }
198
199   BufferProfileGroups[0]=0;
200     
201   for(i=0;i<5;i++)
202   {
203     int code2test;
204     char z_gtype[12];
205
206     code2test=(i==0) ? 1 : 2<<(i-1);
207
208     if( code & code2test )
209     {
210       if (!strcmp(az_group_name[i],"")) 
211       {
212         if (GetModelFeature (FN_CALLERGROUPS)!=0) {
213           bitmap.type=GSM_CallerLogo;
214           bitmap.number=i;
215           strcpy(z_gtype,_("unknown"));
216           if (GSM->GetBitmap(&bitmap)==GE_NONE)
217             strcpy( az_group_name[i], bitmap.text );
218         }
219         if ((!strcmp(az_group_name[i],""))) {
220             switch(i) {
221             case 0:strcpy(az_group_name[i],_("Family"));break;
222             case 1:strcpy(az_group_name[i],_("VIP"));break;
223             case 2:strcpy(az_group_name[i],_("Friends"));break;
224             case 3:strcpy(az_group_name[i],_("Colleagues"));break;
225             case 4:strcpy(az_group_name[i],_("Other"));break;
226             default:break;
227           }
228         }
229       }
230       strcpy(z_gtype,az_group_name[i]);
231
232       if( strlen(BufferProfileGroups) ) strcat(BufferProfileGroups,"+");
233       strcat(BufferProfileGroups, z_gtype);
234     }
235     
236   }
237
238   return BufferProfileGroups;
239 }
240
241 static char *print_error(GSM_Error e)
242 {
243
244 //      case GE_DEVICEOPENFAILED:         return "Couldn't open specified serial device.";
245 //      case GE_UNKNOWNMODEL:             return "Model specified isn't known/supported.";
246 //      case GE_NOLINK:                   return "Couldn't establish link with phone.";
247 //      case GE_TRYAGAIN:                 return "Try again.";
248 //      case GE_INVALIDSMSLOCATION:       return "Invalid SMS location.";
249 //      case GE_INVALIDPHBOOKLOCATION:    return "Invalid phonebook location.";
250 //      case GE_INVALIDMEMORYTYPE:        return "Invalid type of memory.";
251 //      case GE_INVALIDSPEEDDIALLOCATION: return "Invalid speed dial location.";
252 //      case GE_INVALIDCALNOTELOCATION:   return "Invalid calendar note location.";
253 //      case GE_INVALIDDATETIME:          return "Invalid date, time or alarm specification.";
254 //      case GE_EMPTYSMSLOCATION:         return "SMS location is empty.";
255 //      case GE_PHBOOKNAMETOOLONG:        return "Phonebook name is too long.";
256 //      case GE_PHBOOKNUMBERTOOLONG:      return "Phonebook number is too long.";
257 //      case GE_PHBOOKWRITEFAILED:        return "Phonebook write failed.";
258 //      case GE_SMSSENDOK:                return "SMS was send correctly.";
259 //      case GE_SMSSENDFAILED:            return "SMS send fail.";
260 //      case GE_SMSTOOLONG:               return "SMS message too long.";
261 //      case GE_NONEWCBRECEIVED:          return "Attempt to read CB when no new CB received";
262 //      case GE_INTERNALERROR:            return "Problem occured internal to model specific code.";
263 //      case GE_NOTSUPPORTED:             return "Function not supported by the phone";
264 //      case GE_BUSY:                     return "Command is still being executed.";
265 //      case GE_USERCANCELED:             return "User has cancelled the action.";   
266 //      case GE_UNKNOWN:                  return "Unknown error - well better than nothing!!";
267 //      case GE_MEMORYFULL:               return "Memory is full";
268 //      case GE_LINEBUSY:                 return "Outgoing call requested reported line busy";
269 //      case GE_NOCARRIER:                return "No Carrier error during data call setup ?";
270
271         switch (e) {
272         case GE_NONE:                     return "No error, done OK";
273         case GE_INVALIDSECURITYCODE:      return "Invalid Security code.";
274         case GE_NOTIMPLEMENTED:           return "Called command is not implemented for the used model. Please contact marcin-wiacek@topnet.pl, if you want to help in implementing it";
275         case GE_TIMEOUT:                  return "Command timed out.";
276         case GE_CANTOPENFILE:             return "Can't open file with bitmap/ringtone";
277         case GE_SUBFORMATNOTSUPPORTED:    return "Subformat of file not supported";
278         case GE_WRONGNUMBEROFCOLORS:      return "Wrong number of colors in specified bitmap file (only 2 colors files supported)";
279         case GE_WRONGCOLORS:              return "Wrong colors in bitmap file";
280         case GE_INVALIDIMAGESIZE:         return "Invalid size of bitmap (in file, sms etc.)";
281         case GE_INVALIDFILEFORMAT:        return "Invalid format of file";
282         case GE_TOOSHORT:                 return "File too short";
283         case GE_INSIDEBOOKMARKSMENU:      return "Inside WAP Bookmarks menu. Please leave it and try again";
284         case GE_INVALIDBOOKMARKLOCATION:  return "Invalid or empty WAP bookmark location";
285         case GE_INSIDESETTINGSMENU:       return "Inside WAP Settings menu. Please leave it and try again";
286         case GE_INVALIDSETTINGSLOCATION:  return "Invalid or empty WAP settings location";
287         default:                          return "Unknown error.";
288         }
289 }
290
291 GSM_Error GSM_ReadRingtoneFileOnConsole(char *FileName, GSM_Ringtone *ringtone)
292 {
293   GSM_Error error;
294   
295   error=GSM_ReadRingtoneFile(FileName, ringtone);
296   
297   switch (error) {
298     case GE_CANTOPENFILE:
299     case GE_SUBFORMATNOTSUPPORTED:
300       fprintf(stderr, _("File \"%s\"\nError: %s\n"),FileName,print_error(error));
301       break;
302     default:
303       break;
304   }
305   
306   return error;
307 }
308
309 GSM_Error GSM_SaveRingtoneFileOnConsole(char *FileName, GSM_Ringtone *ringtone)
310 {
311   int confirm,confirm2;
312   char ans[4];
313   struct stat buf;
314   GSM_Error error;
315
316   /* Ask before overwriting */
317   while (stat(FileName, &buf) == 0) {
318   
319     confirm=-1;
320     confirm2=-1;
321     
322     while (confirm < 0) {
323       fprintf(stderr, _("Saving ringtone. File \"%s\" exists. (O)verwrite, create (n)ew or (s)kip ? "),FileName);
324       GetLine(stdin, ans, 4);
325       if (!strcmp(ans, "O") || !strcmp(ans, "o")) confirm = 1;
326       if (!strcmp(ans, "N") || !strcmp(ans, "n")) confirm = 2;
327       if (!strcmp(ans, "S") || !strcmp(ans, "s")) return GE_USERCANCELED;
328     }  
329     if (confirm==1) break;
330     if (confirm==2) {
331       while (confirm2 < 0) {
332         fprintf(stderr, _("Enter name of new file: "));
333         GetLine(stdin, FileName, 50);
334         if (&FileName[0]==0) return GE_USERCANCELED;
335         confirm2=1;
336       }  
337     }
338   }
339   
340   error=GSM_SaveRingtoneFile(FileName,ringtone);
341   
342   switch (error) {
343     case GE_CANTOPENFILE:        fprintf(stderr, _("Failed to write file \"%s\"\n"),FileName);
344                                  break;
345     default:                     break;
346   }
347   
348   return error;
349 }
350
351 GSM_Error GSM_ReadBitmapFileOnConsole(char *FileName, GSM_Bitmap *bitmap)
352 {
353   GSM_Error error;
354   
355   error=GSM_ReadBitmapFile(FileName, bitmap);
356
357   switch (error) {
358     case GE_CANTOPENFILE:
359     case GE_WRONGNUMBEROFCOLORS:
360     case GE_WRONGCOLORS:        
361     case GE_INVALIDFILEFORMAT:  
362     case GE_SUBFORMATNOTSUPPORTED:
363     case GE_TOOSHORT:
364     case GE_INVALIDIMAGESIZE:
365       fprintf(stderr, _("File \"%s\"\nError: %s\n"),FileName,print_error(error));
366       break;
367     default: 
368       break;
369   }
370   
371   return error;
372 }
373
374 GSM_Error GSM_SaveBitmapFileOnConsole(char *FileName, GSM_Bitmap *bitmap)
375 {
376   int confirm,confirm2;
377   char ans[4];
378   struct stat buf;
379   GSM_Error error;
380
381   /* Ask before overwriting */
382   while (stat(FileName, &buf) == 0) {
383   
384     confirm=-1;
385     confirm2=-1;
386     
387     while (confirm < 0) {
388       fprintf(stderr, _("Saving logo. File \"%s\" exists. (O)verwrite, create (n)ew or (s)kip ? "),FileName);
389       GetLine(stdin, ans, 4);
390       if (!strcmp(ans, "O") || !strcmp(ans, "o")) confirm = 1;
391       if (!strcmp(ans, "N") || !strcmp(ans, "n")) confirm = 2;
392       if (!strcmp(ans, "S") || !strcmp(ans, "s")) return GE_USERCANCELED;
393     }  
394     if (confirm==1) break;
395     if (confirm==2) {
396       while (confirm2 < 0) {
397         fprintf(stderr, _("Enter name of new file: "));
398         GetLine(stdin, FileName, 50);
399         if (&FileName[0]==0) return GE_USERCANCELED;
400         confirm2=1;
401       }  
402     }
403   }
404   
405   error=GSM_SaveBitmapFile(FileName,bitmap);
406   
407   switch (error) {
408     case GE_CANTOPENFILE:        fprintf(stderr, _("Failed to write file \"%s\"\n"),FileName);
409                                  break;
410     default:                     break;
411   }
412   
413   return error;
414 }
415
416 /* mode == 0 -> overwrite
417  * mode == 1 -> ask
418  * mode == 2 -> append
419  */
420 int GSM_SaveTextFileOnConsole(char *FileName, char *text, int mode)
421 {
422   int confirm, confirm2;
423   char ans[4];
424   struct stat buf;
425   int error;
426
427   /* Ask before overwriting */
428   if (mode==1) {
429     while (stat(FileName, &buf) == 0 && mode==1) {
430       
431       confirm=-1;
432       confirm2=-1;
433       
434       while (confirm < 0) {
435         fprintf(stderr, _("File \"%s\" exists. (O)verwrite, (a)ppend, create (n)ew or (s)kip ? "),FileName);
436         GetLine(stdin, ans, 4);
437         if (!strcmp(ans, "O") || !strcmp(ans, "o")) {
438           mode = 0;
439           confirm = 1;
440         }
441         if (!strcmp(ans, "A") || !strcmp(ans, "a")) {
442           mode = 2;
443           confirm = 1;
444         }
445         if (!strcmp(ans, "N") || !strcmp(ans, "n")) confirm=2;
446         if (!strcmp(ans, "S") || !strcmp(ans, "s")) return -1;
447       }
448       
449       if (confirm==2) {
450         while (confirm2 < 0) {
451           fprintf(stderr, _("Enter name of new file: "));
452           GetLine(stdin, FileName, 50);
453           if (&FileName[0]==0) return -1;
454           mode=1;
455           confirm2=1;
456         }  
457       }
458       
459     }  
460   }
461   
462   error=GSM_SaveTextFile(FileName, text, mode);
463   
464   switch (error) {
465     case -1: fprintf(stderr, _("Failed to write file \"%s\"\n"),  FileName);
466              break;
467     default: break;
468   }
469
470   return error;
471 }
472
473 int GSM_SendMultiPartSMSOnConsole(GSM_MultiSMSMessage *MultiSMS, int argnum, int argc, char *argv[],
474                                   bool unicode, bool profile, bool scale) {
475
476   int w,i;
477   
478   struct option options[] = {
479              { "smscno",       required_argument, NULL, '1'},
480              { "smsc",         required_argument, NULL, '2'},
481              { "name",         required_argument, NULL, '3'},
482              { "unicode",      no_argument,       NULL, '4'},
483              { "profilestyle", no_argument,       NULL, '5'},
484              { "scale",        no_argument,       NULL, '6'},
485              { NULL,           0,                 NULL,  0 }
486   };
487
488   GSM_Error error;  
489
490   for (w=0;w<MultiSMS->number;w++) {
491
492     if (argnum!=0) {
493       optarg = NULL;
494   
495       /* We check optional parameters from ... */
496       optind = argnum;
497
498       while ((i = getopt_long(argc, argv, "v:ds", options, NULL)) != -1) {
499         switch (i) {
500
501           case '1': /* SMSC number */
502             MultiSMS->SMS[w].MessageCenter.No = 0;
503             strcpy(MultiSMS->SMS[w].MessageCenter.Number,optarg);
504             break;
505
506           case '2': /* SMSC number index in phone memory */
507             MultiSMS->SMS[w].MessageCenter.No = atoi(optarg);
508
509             if (MultiSMS->SMS[w].MessageCenter.No < 1 || MultiSMS->SMS[w].MessageCenter.No > 5) {
510               fprintf(stderr, _("Incorrect SMSC number with \"smscno\" option (can't be <1 and >5) !\n"));
511               GSM->Terminate();
512               return -1;
513             }
514             break;
515
516           case '3': /* Receiver/recipient */
517             strncpy(MultiSMS->SMS[w].Destination,optarg,11); break;
518
519           case '4': /* Unicode */
520             if (unicode) break;
521
522           case '5': /* Profile */
523             if (profile) break;
524
525           case '6': /* Scale */
526             if (scale) break;
527
528           case 'v': /* Set validaty of SMS */
529             MultiSMS->SMS[w].Validity = atoi(optarg);
530             break;
531
532           case 'd': /* delivery report */
533             MultiSMS->SMS[w].Type=GST_DR;
534             break;      
535
536           case 's': /* Set replying via the same SMSC */
537             MultiSMS->SMS[w].ReplyViaSameSMSC = true; break;
538
539         default:
540           fprintf(stderr,_("Unknown option number %i\n"),argc);
541           GSM->Terminate();    
542           return -1;
543
544         }
545       }
546     }
547
548     error=GSM->SendSMSMessage(&MultiSMS->SMS[w]);
549
550     if (error == GE_SMSSENDOK) {
551       fprintf(stdout, _("SMS %i/%i sent OK !\n"),w+1,MultiSMS->number);
552     } else {
553       fprintf(stdout, _("SMS %i/%i, sending failed (error=%d)\n"),w+1,MultiSMS->number, error);
554     }
555
556   }
557
558   GSM->Terminate();  
559
560   return 0;
561 }
562
563 static int GSM_SaveMultiPartSMSOnConsole(GSM_MultiSMSMessage *MultiSMS, int argnum, int argc, char *argv[],
564                                   bool inter, bool unicode, bool profile, bool scale) {
565
566   int w,i;
567   
568   GSM_SMSMessage SMSold;
569
570   struct option options[] = {
571              { "smscno",       required_argument, NULL, '1'},
572              { "smsc",         required_argument, NULL, '2'},
573              { "name",         required_argument, NULL, '3'},
574              { "unicode",      no_argument,       NULL, '4'},
575              { "profilestyle", no_argument,       NULL, '5'},
576              { "scale",        no_argument,       NULL, '6'},
577              { NULL,           0,                 NULL,  0 }
578   };
579
580   int interactive;
581   int confirm = -1;
582   char ans[8];
583
584   GSM_Error error;  
585
586   interactive = inter;
587
588   for (w=0;w<MultiSMS->number;w++) {
589
590     if (argnum!=0) {
591       optarg = NULL;
592   
593       /* We check optional parameters from ... */
594       optind = argnum;
595
596       while ((i = getopt_long(argc, argv, "risal:", options, NULL)) != -1) {
597         switch (i) {
598
599           case '1': /* SMSC number */
600             MultiSMS->SMS[w].MessageCenter.No = 0;
601             strcpy(MultiSMS->SMS[w].MessageCenter.Number,optarg);
602             break;
603
604           case '2': /* SMSC number index in phone memory */
605             MultiSMS->SMS[w].MessageCenter.No = atoi(optarg);
606
607             if (MultiSMS->SMS[w].MessageCenter.No < 1 || MultiSMS->SMS[w].MessageCenter.No > 5) {
608               fprintf(stderr, _("Incorrect SMSC number with \"smscno\" option (can't be <1 and >5) !\n"));
609               GSM->Terminate();
610               return -1;
611             }
612             break;
613
614           case '3': /* Receiver/recipient */
615             strncpy(MultiSMS->SMS[w].Destination,optarg,11); break;
616
617           case '4': /* Unicode */
618             if (unicode) break;
619
620           case '5': /* Profile */
621             if (profile) break;
622
623           case '6': /* Scale */
624             if (scale) break;
625
626           case 'r': /* mark as read */
627             MultiSMS->SMS[w].Status = GSS_SENTREAD; break;
628
629           case 'i': /* Save into Inbox */
630             MultiSMS->SMS[w].folder = GST_INBOX; break;
631           
632           case 's': /* Set replying via the same SMSC */
633             MultiSMS->SMS[w].ReplyViaSameSMSC = true; break;
634
635           case 'a': /* Ask before overwriting */
636             interactive=true;break;     
637         
638           case 'l': /* Specify location */
639             MultiSMS->SMS[0].Location = atoi(optarg); break;     
640
641         default:
642           fprintf(stderr,_("Unknown option number %i\n"),argc);
643           GSM->Terminate();    
644           return -1;
645         }
646       }
647     }
648
649     if (interactive && MultiSMS->SMS[0].Location!=0 && w==0) {
650       SMSold.Location=MultiSMS->SMS[0].Location;
651       error = GSM->GetSMSMessage(&SMSold);
652       switch (error) {
653         case GE_NONE:
654           fprintf(stderr, _("Message at specified location exists. "));
655           while (confirm < 0) {
656             fprintf(stderr, _("Overwrite? (yes/no) "));
657             GetLine(stdin, ans, 7);
658             if (!strcmp(ans, "yes")) confirm = 1;
659             if (!strcmp(ans, "no")) confirm = 0;
660           }  
661           if (!confirm) { GSM->Terminate(); return 0; }
662           else break;
663         case GE_INVALIDSMSLOCATION:
664           fprintf(stderr, _("Invalid location\n"));
665           GSM->Terminate();
666           return -1;
667         default:
668 /* FIXME: Remove this fprintf when the function is thoroughly tested */
669 #ifdef DEBUG
670             fprintf(stderr, _("Location %d empty. Saving\n"), SMS[w].Location);
671 #endif
672           break;
673       }
674     }
675
676     error=GSM->SaveSMSMessage(&MultiSMS->SMS[w]);
677
678     if (error == GE_NONE)
679       fprintf(stdout, _("SMS %i/%i saved at location %i !\n"),w+1,MultiSMS->number,MultiSMS->SMS[w].MessageNumber);
680     else
681       fprintf(stdout, _("SMS %i/%i saving failed (error=%d, location=%i)\n"), w+1, MultiSMS->number, error,MultiSMS->SMS[w].Location);
682   }
683
684   GSM->Terminate();  
685
686   return 0;
687 }
688
689 void GSM_PlayRingtoneOnConsole(GSM_Ringtone *ringtone)
690 {
691   int i;
692 #ifdef VC6
693   char mychar;
694 #endif
695
696   for (i=0;i<ringtone->NrNotes;i++) {
697 #ifdef VC6
698     if (_kbhit()) {
699       mychar=_getch();
700       break;
701     }
702 #endif
703     GSM_PlayOneNote (ringtone->notes[i]);
704   }
705   GSM->PlayTone(255*255,0);
706 }
707
708 #endif /* UCLINUX */
709
710 /* This function shows the copyright and some informations usefull for
711    debugging. */
712 static int version(void)
713 {
714
715   fprintf(stdout, _("GNOKII Version %s\n"
716 "Copyright (C) Hugh Blemings <hugh@linuxcare.com>, 1999, 2000\n"
717 "Copyright (C) Pavel Janík ml. <Pavel.Janik@linux.cz>, 1999, 2000\n"
718 "Built %s %s for %s on %s \n"), VERSION, __TIME__, __DATE__, model, Port);
719
720   return 0;
721 }
722
723 /* The function usage is only informative - it prints this program's usage and
724    command-line options. */
725
726 static int usage(void)
727 {
728
729   fprintf(stdout, _("   usage: gnokii [--help] [--version]\n"
730   ));
731 #ifndef UCLINUX
732 "          gnokii --monitor [-noloop|-nl]\n"
733   ));
734 #endif /* UCLINUX */
735
736 #ifndef UCLINUX
737   fprintf(stdout, _(
738 "          gnokii --getmemory memory_type [start [end]] [-short|-v30|-v21|-v]\n"
739   ));
740 #else /* UCLINUX */
741   fprintf(stdout, _(
742 "          gnokii --getmemory memory_type [start [end]] [-short]\n"
743   ));
744 #endif /* UCLINUX */
745
746   fprintf(stdout, _(
747 "          gnokii --writephonebook [-i]\n"
748   ));
749
750 #ifndef UCLINUX
751   fprintf(stdout, _(
752 "          gnokii --sendphonebookentry destination memory_type location\n"
753 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
754 "                 [-s] [-v n] [-d]\n"
755 "          gnokii --savephonebookentry memory_type location\n"
756 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
757 "                 [-r] [-i] [-s] [-a] [--name name]\n"
758 "          gnokii --getvoicemailbox\n"
759   ));
760 #endif /* UCLINUX */
761
762   fprintf(stdout, _(
763 "          gnokii --getspeeddial number\n"
764 "          gnokii --setspeeddial number memory_type location\n\n"
765   ));
766
767 #ifndef UCLINUX
768   fprintf(stdout, _(
769 "          gnokii --getsms memory_type start [end] [-f file]\n"
770 "          gnokii --getsmsstatus\n"
771 "          gnokii --getsmsfolders\n"
772 "          gnokii --deletesms memory_type start [end]\n"
773 "          gnokii --sendsms destination [--smsc message_center_number |\n"
774 "                 --smscno message_center_index] [--long n] [-s] [-C n]\n"
775 "                 [--enablevoice|--disablevoice|--enablefax|--disablefax|\n"
776 "                  --enableemail|--disableemail|--void][--unicode][-v n][-d]\n"
777 "          gnokii --savesms destination|\"\" [--smsc \n"
778 "                 message_center_number] [--smscno message_center_index]\n"
779 "                 [--long n] [-r] [-i] [-s][-C n][-a][-l][F n][--smsname name]\n"
780 "                 [--enablevoice|--disablevoice|--enablefax|--disablefax|\n"
781 "                  --enableemail|--disableemail|--void|--hang|--bug][--unicode]\n"
782 "          gnokii --receivesms\n"
783 "          gnokii --getsmsc message_center_number\n"
784 "          gnokii --renamesmsc number new_name\n\n"
785
786 "          gnokii --setdatetime [YYYY [MM [DD [HH [MM]]]]]\n"
787 "          gnokii --getdatetime\n"
788 "          gnokii --setalarm HH MM\n"
789 "          gnokii --getalarm\n\n"
790
791 "          gnokii --getcalendarnote { start end [-v30|-v10] | --short|-s }\n"
792 "          gnokii --writecalendarnote vcardfile number\n"
793 "          gnokii --deletecalendarnote index\n"
794 "          gnokii --sendcalendarnote destination vcardfile number\n"
795 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
796 "                 [-s] [-v n] [-d]\n"
797 "          gnokii --savecalendarnote vcardfile number\n"
798 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
799 "                 [-r] [-i] [-s] [-a] [--name name]\n\n"
800
801 "          gnokii --netmonitor {reset|off|field|devel|next|nr}\n"
802 "          gnokii --nm_collect screen1|-d [screen2|-d]...\n"
803 "          gnokii --netmonitordata [-S file] [-I file] [-h] [-n n] [-ts n][-tm n]\n"
804 "                 [-fs str] [-ls str] FLD1:FLD2:FLDn:... \n"
805 "                 (see files netmonitordata_????_??? for details)\n\n"
806
807 "          gnokii --bitmapconvert source destination\n"
808 "          gnokii --bitmapconvert source destination op|7110op [network code]\n"
809 "          gnokii --bitmapconvert source destination caller [caller group number]\n"
810 "          gnokii --bitmapconvert source destination\n"
811 "                   startup|7110startup|6210startup\n"
812 "          gnokii --bitmapconvert source destination picture\n"
813 "          gnokii --showbitmap logofile\n"
814 "          gnokii --sendlogo op destination logofile network_code\n"
815 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
816 "                 [-s] [-v n] [-d]\n"
817 "          gnokii --sendlogo picture destination logofile text\n"
818 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
819 "                 [-s] [-v n] [-d] [--unicode]\n"
820 "          gnokii --sendlogo screensaver destination logofile\n"
821 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
822 "                 [-s] [-v n] [-d]\n"
823 "          gnokii --sendlogo caller destination logofile\n"
824 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
825 "                 [-s] [-v n] [-d]\n"
826 "          gnokii --savelogo op logofile network_code\n"
827 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
828 "                 [-r] [-i] [-s] [-a] [-l] [--name name]\n"
829 "          gnokii --savelogo picture logofile text\n"
830 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
831 "                 [-r] [-i] [-s] [-a] [-l] [--name name] [--unicode]\n"
832 "          gnokii --savelogo screensaver logofile\n"
833 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
834 "                 [-r] [-i] [-s] [-a] [-l] [--name name]\n"
835 "          gnokii --savelogo caller logofile\n"
836 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
837 "                 [-r] [-i] [-s] [-a] [-l] [--name name]\n"
838 "          gnokii --setlogo op|7110op [logofile] [network code]\n"
839 "          gnokii --setlogo startup|7110startup|6210startup [logofile]\n"
840 "          gnokii --setlogo startup 1|2|3\n"
841 "          gnokii --setlogo caller [logofile] [caller group number] [group name]\n"
842 "          gnokii --setlogo picture [logofile] [number] [text] [sender]\n"
843 "          gnokii --setlogo {dealer|text} [text]\n"
844 "          gnokii --getlogo op|7110op [logofile] [network code]\n"
845 "          gnokii --getlogo startup|7110startup|6210startup [logofile]\n"
846 "          gnokii --getlogo caller [logofile][caller group number]\n"
847 "          gnokii --getlogo picture [logofile][number]\n"
848 "          gnokii --getlogo {dealer|text}\n\n"
849
850 "          gnokii --sendringtone destination ringtonefile\n"
851 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
852 "                 [-s] [-v n] [-d] [--scale] [--profilestyle]\n"
853 "          gnokii --saveringtone ringtonefile\n"
854 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
855 "                 [-r] [-i] [-s] [-a] [--name name] [--scale] [--profilestyle]\n"
856 "          gnokii --setringtone ringtonefile [location]\n"
857 "          gnokii --getringtone ringtonefile [location]\n"
858 "          gnokii --ringtoneconvert source destination\n"
859 "          gnokii --binringtoneconvert source destination\n"
860 "          gnokii --playringtone ringtonefile\n"
861 "          gnokii --composer ringtonefile\n"
862 "          gnokii --allringtones\n\n"
863
864 "          gnokii --getprofile [number]\n"
865 "          gnokii --setprofile number feature value\n"
866 "          gnokii --sendprofile destination profile_name ringtonefile\n"
867 "                 picturefile [--smsc message_center_number]\n"
868 "                 [--smscno message_center_index] [-s] [-v n] [-d] [--scale]\n\n"
869   ));
870 #endif /* UCLINUX */
871
872   fprintf(stdout, _(
873 "          gnokii --reset [soft|hard]\n"
874   ));
875
876 #ifndef UCLINUX
877   fprintf(stdout, _(
878 "          gnokii --dialvoice number\n"
879   ));
880 #endif /* UCLINUX */
881
882   fprintf(stdout, _(
883 "          gnokii --cancelcall\n"
884   ));
885
886 #ifndef UCLINUX
887   fprintf(stdout, _(
888 "          gnokii --displayoutput\n"
889 "          gnokii --presskeysequence sequence\n"
890 "          gnokii --backupsettings file\n"
891 "          gnokii --restoresettings file\n"
892 "          gnokii --getphoneprofile\n"
893 "          gnokii --setphoneprofile feature value\n"
894 "          gnokii --getoperatorname\n"
895 "          gnokii --setoperatorname code name\n"
896 "          gnokii --senddtmf string\n"
897 "          gnokii --divert register|enable|query|disable|erasure\n"
898 "                 all|busy|noans|outofreach all|voice|fax|data\n"
899 "                 [number timeout]\n\n"
900
901 "          gnokii --phonetests\n"
902 "          gnokii --simlock\n"
903 "          gnokii --getdisplaystatus\n"
904   ));
905 #endif /* UCLINUX */
906
907   fprintf(stdout, _(
908 "          gnokii --identify\n\n"
909   ));
910
911 #ifndef UCLINUX
912   fprintf(stdout, _(
913 "          gnokii --getwapbookmark location\n"
914 "          gnokii --setwapbookmark title url [location]\n"
915 "          gnokii --sendwapbookmark location destination\n"
916 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
917 "                 [-s] [-v n] [-d]\n"
918 "          gnokii --savewapbookmark location\n"
919 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
920 "                 [-r] [-i] [-s] [-a] [-l] [--name name]\n"
921 "          gnokii --getwapsettings location\n"
922 "          gnokii --savewapsettings location\n"
923 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
924 "                 [-r] [-i] [-s] [-a] [-l] [--name name]\n"
925 "          gnokii --sendwapsettings location destination\n"
926 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
927 "                 [-s] [-v n] [-d]\n"
928   ));
929
930 #ifdef SECURITY
931   fprintf(stdout, _(
932 "\n          gnokii --entersecuritycode PIN|PIN2|PUK|PUK2\n"
933 "          gnokii --getsecuritycodestatus\n"
934 "          gnokii --getsecuritycode PIN|PIN2|PUK|PUK2|SecurityCode\n"
935 "          gnokii --geteeprom\n"
936 "          gnokii --resetphonesettings\n"
937   ));
938 #endif
939
940 #ifdef DEBUG
941   fprintf(stdout, _(
942 "          gnokii --sniff [port]\n"
943 "          gnokii --decodefile file\n"
944   ));
945 #endif
946
947 #endif /* UCLINUX */
948
949 #ifdef UCLINUX
950   fprintf(stdout, _(
951 "          gnokii --gnokiid [--debug]\n"
952   ));
953 #endif
954
955   return 0;
956 }
957
958 /* fbusinit is the generic function which waits for the FBUS link. The limit
959    is 10 seconds. After 10 seconds we quit. */
960
961 static void fbusinit(void (*rlp_handler)(RLP_F96Frame *frame))
962 {
963
964   int count=0;
965   GSM_Error error;
966
967 #ifndef WIN32
968   if (strcmp(GetMygnokiiVersion(),VERSION)!=0)
969     fprintf(stderr,_("WARNING: version of installed libmygnokii.so (%s) is different to version of gnokii (%s)\n"),GetMygnokiiVersion(),VERSION);
970 #endif
971
972   /* Initialise the code for the GSM interface. */     
973   error = GSM_Initialise(model, Port, Initlength, GetConnectionTypeFromString(Connection), rlp_handler, ""/*SynchronizeTime*/);
974
975   if (error != GE_NONE) {
976     fprintf(stderr, _("GSM/FBUS init failed! (Unknown model ?). Quitting.\n"));
977     exit(-1);
978   }
979
980   /* First (and important!) wait for GSM link to be active. We allow 10
981      seconds... */
982   while (count++ < 200 && *GSM_LinkOK == false)
983     usleep(50000);
984
985   if (*GSM_LinkOK == false) {
986     fprintf (stderr, _("Hmmm... GSM_LinkOK never went true. Quitting.\n"));
987     exit(-1);
988   }  
989 }
990
991 /* This function checks that the argument count for a given options is withing
992    an allowed range. */
993
994 static int checkargs(int opt, struct gnokii_arg_len gals[], int argc)
995 {
996
997   int i;
998
999   /* Walk through the whole array with options requiring arguments. */
1000
1001   for(i = 0;!(gals[i].gal_min == 0 && gals[i].gal_max == 0); i++) {
1002
1003     /* Current option. */
1004
1005     if(gals[i].gal_opt == opt) {
1006
1007       /* Argument count checking. */
1008
1009       if(gals[i].gal_flags == GAL_XOR) {
1010         if(gals[i].gal_min == argc || gals[i].gal_max == argc) return 0;
1011       }
1012       else {
1013         if(gals[i].gal_min <= argc && gals[i].gal_max >= argc) return 0;
1014       }
1015
1016       return 1;
1017
1018     }
1019
1020   }
1021
1022   /* We do not have options without arguments in the array, so check them. */
1023
1024   if (argc==0) return 0;
1025           else return 1;
1026 }
1027
1028 static int gnokiid(int argc, char *argv[]);
1029
1030 /* Main function - handles command line arguments, passes them to separate
1031    functions accordingly. */
1032
1033 int main(int argc, char *argv[])
1034 {
1035
1036   int c, i, rc = -1;
1037   int nargc = argc-2;
1038   char **nargv;
1039
1040   /* Every option should be in this array. */
1041
1042   static struct option long_options[] =
1043   {
1044
1045     { "help",               no_argument,       NULL, OPT_HELP             },// Display usage.
1046     { "version",            no_argument,       NULL, OPT_VERSION          },// Display version and build information.
1047 #ifndef UCLINUX
1048     { "getsmsfolders",      no_argument,       NULL, OPT_GETSMSFOLDERS    },// Gets SMS folders
1049     { "getsmsstatus",       no_argument,       NULL, OPT_GETSMSSTATUS     },// Get SMS Folder Status
1050 #endif /* UCLINUX */
1051     { "identify",           no_argument,       NULL, OPT_IDENTIFY         },// Identify
1052 #ifndef UCLINUX
1053     { "pmon",               no_argument,       NULL, OPT_PMON             },// For development purposes: run in passive monitoring mode
1054     { "foogle",             no_argument,       NULL, OPT_FOOGLE           },// For development purposes: insert you function calls here
1055     { "getdatetime",        no_argument,       NULL, OPT_GETDATETIME      },// Get date and time mode    
1056     { "getalarm",           no_argument,       NULL, OPT_GETALARM         },// Get alarm    
1057 #endif /* UCLINUX */
1058     { "cancelcall",         no_argument,       NULL, OPT_CANCELCALL       },// Cancel Call    
1059 #ifndef UCLINUX
1060     { "getdisplaystatus",   no_argument,       NULL, OPT_GETDISPLAYSTATUS },// Get display status mode    
1061     { "allringtones",       no_argument,       NULL, OPT_ALLRINGTONES     },/* Displays names of available ringtones */    
1062     { "displayoutput",      no_argument,       NULL, OPT_DISPLAYOUTPUT    },/* Show texts from phone's display */
1063     { "getphoneprofile",    no_argument,       NULL, OPT_GETPHONEPROFILE  },/* Get/Set phone profile settings */
1064     { "getoperatorname",    no_argument,       NULL, OPT_GETOPERATORNAME  },/* Get downloaded operator name */    
1065     { "getvoicemailbox",    no_argument,       NULL, OPT_GETVOICEMAILBOX  },/* Gets voice mailbox number */    
1066     { "phonetests",         no_argument,       NULL, OPT_PHONETESTS       },
1067     { "simlockinfo",        no_argument,       NULL, OPT_SIMLOCKINFO      },    
1068     { "receivesms",         no_argument,       NULL, OPT_RECEIVESMS       },    
1069     { "setoperatorname",    optional_argument, NULL, OPT_SETOPERATORNAME  },/* Set downloaded operator name */    
1070     { "setdatetime",        optional_argument, NULL, OPT_SETDATETIME      },// Set date and time    
1071 #endif /* UCLINUX */
1072     { "writephonebook",     optional_argument, NULL, OPT_WRITEPHONEBOOK   },// Write phonebook (memory) mode
1073     { "reset",              optional_argument, NULL, OPT_RESET            },// Resets the phone
1074 #ifndef UCLINUX
1075     { "monitor",            optional_argument, NULL, OPT_MONITOR          },// Monitor mode
1076     { "setlogo",            optional_argument, NULL, OPT_SETLOGO          },// Set logo
1077     { "getprofile",         optional_argument, NULL, OPT_GETPROFILE       },// Show profile
1078     { "setalarm",           required_argument, NULL, OPT_SETALARM         },// Set alarm
1079     { "dialvoice",          required_argument, NULL, OPT_DIALVOICE        },// Voice call mode
1080     { "getcalendarnote",    required_argument, NULL, OPT_GETCALENDARNOTE  },// Get calendar note mode    
1081     { "writecalendarnote",  required_argument, NULL, OPT_WRITECALENDARNOTE},// Write calendar note mode
1082     { "sendcalendarnote",   required_argument, NULL, OPT_SENDCALENDARNOTE },
1083     { "savecalendarnote",   required_argument, NULL, OPT_SAVECALENDARNOTE },
1084     { "sendphonebookentry", required_argument, NULL, OPT_SENDPHONEBOOKENTRY},
1085     { "savephonebookentry", required_argument, NULL, OPT_SAVEPHONEBOOKENTRY},
1086     { "deletecalendarnote", required_argument, NULL, OPT_DELCALENDARNOTE  },// Delete calendar note mode    
1087 #endif /* UCLINUX */
1088     { "getmemory",          required_argument, NULL, OPT_GETMEMORY        },// Get memory mode
1089     { "getspeeddial",       required_argument, NULL, OPT_GETSPEEDDIAL     },// Get speed dial mode
1090     { "setspeeddial",       required_argument, NULL, OPT_SETSPEEDDIAL     },// Set speed dial mode
1091 #ifndef UCLINUX
1092     { "getsms",             required_argument, NULL, OPT_GETSMS           },// Get SMS message mode
1093     { "deletesms",          required_argument, NULL, OPT_DELETESMS        },// Delete SMS message mode
1094     { "sendsms",            required_argument, NULL, OPT_SENDSMS          },// Send SMS message mode
1095     { "savesms",            required_argument, NULL, OPT_SAVESMS          },// Save SMS message mode
1096     { "sendlogo",           required_argument, NULL, OPT_SENDLOGO         },// Send logo as SMS message mode
1097     { "savelogo",           required_argument, NULL, OPT_SAVELOGO         },// Save logo on SIM
1098     { "sendringtone",       required_argument, NULL, OPT_SENDRINGTONE     },// Send ringtone as SMS message
1099     { "saveringtone",       required_argument, NULL, OPT_SAVERINGTONE     },// Saves ringtone on SIM
1100     { "setringtone",        required_argument, NULL, OPT_SETRINGTONE      },// Set ringtone    
1101     { "getringtone",        required_argument, NULL, OPT_GETRINGTONE      },// Get bin/normal ringtone    
1102     { "presskeysequence",   required_argument, NULL, OPT_PRESSKEYSEQUENCE },/* Presses keys in phone's display */
1103     { "getsmsc",            required_argument, NULL, OPT_GETSMSC          },// Get SMS center number mode
1104     { "renamesmsc",         required_argument, NULL, OPT_RENAMESMSC       },// Rename SMSC
1105     { "netmonitor",         required_argument, NULL, OPT_NETMONITOR       },// NetMonitor mode
1106     { "senddtmf",           required_argument, NULL, OPT_SENDDTMF         },// Send DTMF sequence
1107     { "getlogo",            required_argument, NULL, OPT_GETLOGO          },// Get logo
1108     { "setprofile",         required_argument, NULL, OPT_SETPROFILE       },// Set profile feature
1109     { "sendprofile",        required_argument, NULL, OPT_SENDPROFILE      },// Send profile via SMS
1110     { "setphoneprofile",    required_argument, NULL, OPT_SETPHONEPROFILE  },/* Get/Set phone profile settings */
1111     { "restoresettings",    required_argument, NULL, OPT_RESTORESETTINGS  },//Restore various settings from one file
1112     { "backupsettings",     required_argument, NULL, OPT_BACKUPSETTINGS   },//Backup various settings to one file
1113     { "playringtone",       required_argument, NULL, OPT_PLAYRINGTONE     },/* Plays ringtones */    
1114     { "composer",           required_argument, NULL, OPT_COMPOSER         },/* Shows ringtone like in Nokia Composer */    
1115     { "ringtoneconvert",    required_argument, NULL, OPT_RINGTONECONVERT  },/* Convert ringtone files */    
1116     { "binringtoneconvert", required_argument, NULL, OPT_BINRINGTONECONVERT},/* Convert binary ringtone files */    
1117     { "bitmapconvert",      required_argument, NULL, OPT_BITMAPCONVERT    },/* Convert bitmap files */    
1118     { "showbitmap",         required_argument, NULL, OPT_SHOWBITMAP       },    
1119     { "nm_collect",         required_argument, NULL, OPT_NM_COLLECT       },// NetMonitor periodical data collection mode (newbiee)
1120     { "netmonitordata",     required_argument, NULL, OPT_NETMONITORDATA   },// NetMonitor periodical data collection mode (advanced)
1121     { "getwapbookmark",     required_argument, NULL, OPT_GETWAPBOOKMARK   },    
1122     { "setwapbookmark",     required_argument, NULL, OPT_SETWAPBOOKMARK   },    
1123     { "savewapbookmark",    required_argument, NULL, OPT_SAVEWAPBOOKMARK  },    
1124     { "savewapsettings",    required_argument, NULL, OPT_SAVEWAPSETTINGS  },    
1125     { "sendwapsettings",    required_argument, NULL, OPT_SENDWAPSETTINGS  },    
1126     { "sendwapbookmark",    required_argument, NULL, OPT_SENDWAPBOOKMARK  },    
1127     { "getwapsettings",     required_argument, NULL, OPT_GETWAPSETTINGS   },    
1128     { "divert",             required_argument, NULL, OPT_DIVERT           },
1129
1130 #ifdef SECURITY
1131     { "entersecuritycode",  required_argument, NULL, OPT_ENTERSECURITYCODE    },// Enter Security Code mode
1132     { "getsecuritycode",    required_argument, NULL, OPT_GETSECURITYCODE      },// Get Security Code
1133   { "getsecuritycodestatus",no_argument,       NULL, OPT_GETSECURITYCODESTATUS},// Get Security Code status
1134     { "geteeprom",          no_argument,       NULL, OPT_GETEEPROM            },// Gets EEPROM
1135     { "resetphonesettings", no_argument,       NULL, OPT_RESETPHONESETTINGS   },// Reset phone settings
1136     { "setsimlock",         no_argument,       NULL, OPT_SETSIMLOCK           },// Sets simlock
1137 #endif
1138
1139 #ifdef DEBUG
1140     { "sniff",              optional_argument, NULL, OPT_SNIFFER    },// Will show datas from port
1141     { "decodefile",         required_argument, NULL, OPT_DECODEFILE },//decode input file
1142 #endif
1143 #endif /* UCLINUX */
1144
1145 #ifdef UCLINUX
1146     { "gnokiid",            optional_argument, NULL, OPT_GNOKIID          },// gnokiid mode
1147 #endif /* UCLINUX */
1148
1149     { 0, 0, 0, 0},
1150   };
1151
1152   /* Every command which requires arguments should have an appropriate entry
1153      in this array. */
1154         
1155   struct gnokii_arg_len gals[] =
1156   {
1157
1158 #ifndef UCLINUX
1159     { OPT_MONITOR,           0, 1, 0 },
1160
1161 #ifdef SECURITY
1162     { OPT_ENTERSECURITYCODE, 1, 1, 0 },
1163     { OPT_GETSECURITYCODE,   1, 1, 0 },
1164 #endif
1165
1166 #ifdef DEBUG
1167     { OPT_SNIFFER,           0, 1, 0 },
1168     { OPT_DECODEFILE,        1, 1, 0 },
1169 #endif
1170
1171     { OPT_SETDATETIME,       0, 5, 0 },
1172     { OPT_BACKUPSETTINGS,    1, 1, 0 },
1173     { OPT_RESTORESETTINGS,   1, 1, 0 },
1174     { OPT_SETALARM,          2, 2, 0 },
1175     { OPT_DIALVOICE,         1, 1, 0 },
1176     { OPT_GETCALENDARNOTE,   1, 3, 0 },
1177     { OPT_WRITECALENDARNOTE, 2, 2, 0 },
1178     { OPT_SAVECALENDARNOTE,  2, 9, 0 },
1179     { OPT_SENDCALENDARNOTE,  3, 9, 0 },
1180     { OPT_SAVEPHONEBOOKENTRY,2, 9, 0 },
1181     { OPT_SENDPHONEBOOKENTRY,3, 9, 0 },
1182     { OPT_DELCALENDARNOTE,   1, 1, 0 },
1183 #endif /* UCLINUX */
1184     { OPT_GETMEMORY,         2, 4, 0 },
1185     { OPT_GETSPEEDDIAL,      1, 1, 0 },
1186     { OPT_SETSPEEDDIAL,      3, 3, 0 },
1187 #ifndef UCLINUX
1188     { OPT_GETSMS,            2, 5, 0 },
1189     { OPT_DELETESMS,         2, 3, 0 },
1190     { OPT_SENDSMS,           1,10, 0 },
1191     { OPT_SAVESMS,           1,11, 0 },
1192     { OPT_SENDLOGO,          3, 9, 0 },
1193     { OPT_SAVELOGO,          2,10, 0 },
1194     { OPT_SENDRINGTONE,      2, 7, 0 },
1195     { OPT_SAVERINGTONE,      1, 9, 0 },
1196     { OPT_GETSMSC,           1, 1, 0 },
1197     { OPT_RENAMESMSC,        2, 2, 0 },
1198     { OPT_NETMONITOR,        1, 1, 0 },
1199     { OPT_SENDDTMF,          1, 1, 0 },
1200     { OPT_SETLOGO,           1, 5, 0 },
1201     { OPT_GETLOGO,           1, 4, 0 },
1202     { OPT_SETRINGTONE,       1, 3, 0 },
1203     { OPT_GETRINGTONE,       1, 2, 0 },
1204     { OPT_PRESSKEYSEQUENCE,  1, 1, 0 },
1205 #endif /* UCLINUX */
1206     { OPT_RESET,             0, 1, 0 },
1207 #ifndef UCLINUX
1208     { OPT_GETPROFILE,        0, 1, 0 },
1209     { OPT_SETPROFILE,        3, 3, 0 },
1210     { OPT_SENDPROFILE,       4,10, 0 },
1211 #endif /* UCLINUX */
1212     { OPT_WRITEPHONEBOOK,    0, 1, 0 },
1213 #ifndef UCLINUX
1214     { OPT_PLAYRINGTONE,      1, 1, 0 },
1215     { OPT_COMPOSER,          1, 1, 0 },
1216     { OPT_RINGTONECONVERT,   2, 2, 0 },
1217     { OPT_BINRINGTONECONVERT,2, 2, 0 },
1218     { OPT_BITMAPCONVERT,     2, 4, 0 },
1219     { OPT_SHOWBITMAP,        1, 1, 0 },
1220     { OPT_SETOPERATORNAME,   0, 2, 0 },    
1221     { OPT_SETPHONEPROFILE,   2, 2, 0 },        
1222     { OPT_NM_COLLECT,        1, MAX_NM_COLLECT, 0 },
1223     { OPT_NETMONITORDATA,    0,99, 0 },
1224     { OPT_GETWAPBOOKMARK,    1, 1, 0 },
1225     { OPT_SETWAPBOOKMARK,    2, 3, 0 },
1226     { OPT_SAVEWAPBOOKMARK,   1, 9, 0 },
1227     { OPT_SENDWAPBOOKMARK,   2, 9, 0 },
1228     { OPT_GETWAPSETTINGS,    1, 1, 0 },
1229     { OPT_SAVEWAPSETTINGS,   1, 9, 0 },
1230     { OPT_SENDWAPSETTINGS,   2, 9, 0 },
1231     { OPT_DIVERT,            3, 5, 0 },    
1232 #endif /* UCLINUX */
1233
1234 #ifdef UCLINUX
1235     { OPT_GNOKIID,           0, 1, 0 },
1236 #endif /* UCLINUX */
1237
1238     { 0, 0, 0, 0 },
1239   };
1240
1241   LIVE;
1242
1243   opterr = 0;
1244
1245   /* For GNU gettext */
1246
1247 #ifdef USE_NLS
1248 #ifndef VC6
1249   textdomain("gnokii");
1250   setlocale(LC_ALL, "pl_PL"); //here is string for Polish localisation
1251 #else
1252   setlocale(LC_ALL, ".852"); //Polish codepage for console, not "real" WIN CP
1253 #endif
1254
1255 #endif
1256
1257     /* Read config file */
1258     if (CFG_ReadConfig(&model, &Port, &Initlength, &Connection, &BinDir, false) < 0) {
1259         exit(-1);
1260     }
1261
1262   /* Handle command line arguments. */
1263
1264   c = getopt_long(argc, argv, "", long_options, NULL);
1265
1266   if (c == -1) {
1267
1268     /* No argument given - we should display usage. */
1269     usage();
1270     exit(-1);
1271   }
1272
1273   /* We have to build an array of the arguments which will be passed to the
1274      functions.  Please note that every text after the --command will be
1275      passed as arguments.  A syntax like gnokii --cmd1 args --cmd2 args will
1276      not work as expected; instead args --cmd2 args is passed as a
1277      parameter. */
1278
1279   if((nargv = malloc(sizeof(char *) * argc)) != NULL) {
1280
1281     for(i = 2; i < argc; i++)
1282       nargv[i-2] = argv[i];
1283         
1284     if(checkargs(c, gals, nargc)) {
1285
1286       free(nargv);
1287
1288       /* Wrong number of arguments - we should display usage. */
1289       usage();
1290       exit(-1);
1291     }
1292
1293 #ifndef VC6
1294 #if defined(__svr4__)
1295     /* have to ignore SIGALARM */
1296     sigignore(SIGALRM);
1297 #endif
1298 #endif
1299
1300     switch(c) {
1301
1302     // First, error conditions  
1303     case '?':
1304       fprintf(stderr, _("Use '%s --help' for usage informations.\n"), argv[0]);
1305       break;
1306         
1307     // Then, options with no arguments
1308     case OPT_HELP:                  rc = usage();                   break;
1309     case OPT_VERSION:               rc = version();                 break;
1310 #ifndef UCLINUX
1311     case OPT_MONITOR:               rc = monitormode(nargc, nargv); break;
1312     case OPT_GETSMSFOLDERS:         rc = getsmsfolders();           break;
1313     case OPT_GETDATETIME:           rc = getdatetime();             break;
1314     case OPT_GETALARM:              rc = getalarm();                break;
1315     case OPT_GETDISPLAYSTATUS:      rc = getdisplaystatus();        break;
1316     case OPT_PMON:                  rc = pmon();                    break;
1317 #endif /* UCLINUX */
1318     case OPT_WRITEPHONEBOOK:        rc = writephonebook(nargc, nargv);break;
1319
1320 #ifndef UCLINUX
1321 #ifdef SECURITY
1322     case OPT_ENTERSECURITYCODE:     rc = entersecuritycode(optarg); break;
1323     case OPT_GETSECURITYCODESTATUS: rc = getsecuritycodestatus();   break;
1324     case OPT_GETSECURITYCODE:       rc = getsecuritycode(optarg);   break;
1325     case OPT_GETEEPROM:             rc = geteeprom();               break;
1326     case OPT_RESETPHONESETTINGS:    rc = resetphonesettings();      break;
1327     case OPT_SETSIMLOCK:            rc = setsimlock();              break;
1328 #endif
1329
1330 #ifdef DEBUG
1331     case OPT_SNIFFER:               rc = sniff(nargc, nargv);       break;
1332     case OPT_DECODEFILE:            rc = decodefile(nargc, nargv);  break;
1333 #endif                                  
1334         
1335     // Now, options with arguments
1336     case OPT_SETDATETIME:           rc = setdatetime(nargc, nargv); break;
1337     case OPT_SETALARM:              rc = setalarm(nargv);           break;
1338     case OPT_DIALVOICE:             rc = dialvoice(optarg);         break;
1339 #endif /* UCLINUX */
1340     case OPT_CANCELCALL:            rc = cancelcall();              break;
1341 #ifndef UCLINUX
1342     case OPT_GETCALENDARNOTE:       rc = getcalendarnote(nargc, nargv);break;
1343     case OPT_DELCALENDARNOTE:       rc = deletecalendarnote(optarg);break;
1344     case OPT_SAVECALENDARNOTE:      rc = savecalendarnote(nargc, nargv);break;
1345     case OPT_SENDCALENDARNOTE:      rc = sendcalendarnote(nargc, nargv);break;
1346     case OPT_SAVEPHONEBOOKENTRY:    rc = savephonebookentry(nargc, nargv);break;
1347     case OPT_SENDPHONEBOOKENTRY:    rc = sendphonebookentry(nargc, nargv);break;
1348     case OPT_WRITECALENDARNOTE:     rc = writecalendarnote(nargv);  break;
1349 #endif /* UCLINUX */
1350     case OPT_GETMEMORY:             rc = getmemory(nargc, nargv);   break;
1351     case OPT_GETSPEEDDIAL:          rc = getspeeddial(optarg);      break;
1352     case OPT_SETSPEEDDIAL:          rc = setspeeddial(nargv);       break;
1353 #ifndef UCLINUX
1354     case OPT_GETSMS:                rc = getsms(argc, argv);        break;
1355     case OPT_GETSMSSTATUS:          rc = getsmsstatus(argc, argv);  break;
1356     case OPT_DELETESMS:             rc = deletesms(nargc, nargv);   break;
1357     case OPT_SENDSMS:               rc = sendsms(nargc, nargv);     break;
1358     case OPT_SAVESMS:               rc = savesms(nargc, nargv);     break;
1359     case OPT_DIVERT:                rc = divert(nargc, nargv);      break;
1360     case OPT_SENDLOGO:              rc = sendlogo(nargc, nargv);    break;
1361     case OPT_SAVELOGO:              rc = savelogo(nargc, nargv);    break;
1362     case OPT_GETSMSC:               rc = getsmsc(optarg);           break;
1363     case OPT_RENAMESMSC:            rc = renamesmsc(nargc,nargv);   break;
1364     case OPT_NETMONITOR:            rc = netmonitor(optarg);        break;
1365 #endif /* UCLINUX */
1366     case OPT_IDENTIFY:              rc = identify();                break;
1367 #ifndef UCLINUX
1368     case OPT_SETLOGO:               rc = setlogo(nargc, nargv);     break;
1369     case OPT_GETLOGO:               rc = getlogo(nargc, nargv);     break;
1370     case OPT_RECEIVESMS:            rc = receivesms(nargc, nargv);  break;
1371     case OPT_SETRINGTONE:           rc = setringtone(nargc, nargv); break;
1372     case OPT_GETRINGTONE:           rc = getringtone(nargc, nargv); break;
1373     case OPT_PRESSKEYSEQUENCE:      rc = presskeysequence(nargv);   break;
1374     case OPT_SENDRINGTONE:          rc = sendringtone(nargc, nargv);break;
1375     case OPT_SAVERINGTONE:          rc = saveringtone(nargc, nargv);break;
1376     case OPT_GETPROFILE:            rc = getprofile(nargc, nargv);  break;
1377     case OPT_SETPROFILE:            rc = setprofile(nargc, nargv);  break;
1378     case OPT_SENDPROFILE:           rc = sendprofile(nargc, nargv); break;
1379     case OPT_DISPLAYOUTPUT:         rc = displayoutput();           break;
1380     case OPT_RESTORESETTINGS:       rc = restoresettings(nargv);    break;
1381     case OPT_BACKUPSETTINGS:        rc = backupsettings(nargv);     break;
1382     case OPT_RINGTONECONVERT:       rc = ringtoneconvert(nargc, nargv);break;
1383     case OPT_BINRINGTONECONVERT:    rc = binringtoneconvert(nargc, nargv);break;
1384     case OPT_BITMAPCONVERT:         rc = bitmapconvert(nargc, nargv);break;
1385     case OPT_SHOWBITMAP:            rc = showbitmap(nargc, nargv);  break;
1386     case OPT_PLAYRINGTONE:          rc = playringtone(nargc, nargv);break;
1387     case OPT_COMPOSER:              rc = composer(nargc, nargv);    break;
1388     case OPT_FOOGLE:                rc = foogle(nargv);             break;
1389     case OPT_PHONETESTS:            rc = phonetests();              break;
1390     case OPT_SIMLOCKINFO:           rc = simlockinfo();             break;
1391     case OPT_SENDDTMF:              rc = senddtmf(optarg);          break;
1392 #endif /* UCLINUX */
1393     case OPT_RESET:                 rc = reset(nargc,nargv);        break;
1394 #ifndef UCLINUX
1395     case OPT_GETOPERATORNAME:       rc = getoperatorname();         break;
1396     case OPT_SETOPERATORNAME:       rc = setoperatorname(nargc,nargv);break;
1397     case OPT_GETWAPBOOKMARK:        rc = getwapbookmark(nargc,nargv);break;
1398     case OPT_SETWAPBOOKMARK:        rc = setwapbookmark(nargc,nargv);break;
1399     case OPT_SAVEWAPBOOKMARK:       rc = savewapbookmark(nargc,nargv);break;
1400     case OPT_SENDWAPBOOKMARK:       rc = sendwapbookmark(nargc,nargv);break;
1401     case OPT_GETWAPSETTINGS:        rc = getwapsettings(nargc,nargv);break;
1402     case OPT_SAVEWAPSETTINGS:       rc = savewapsettings(nargc,nargv);break;
1403     case OPT_SENDWAPSETTINGS:       rc = sendwapsettings(nargc,nargv);break;
1404     case OPT_ALLRINGTONES:          rc = allringtones();            break;
1405     case OPT_GETPHONEPROFILE:       rc = getphoneprofile();         break;
1406     case OPT_SETPHONEPROFILE:       rc = setphoneprofile(nargc,nargv);break;
1407     case OPT_GETVOICEMAILBOX:       rc = getvoicemailbox();         break;
1408     case OPT_NM_COLLECT:            rc = nm_collect(nargc, nargv);  break;
1409     case OPT_NETMONITORDATA:        rc = netmonitordata(nargc, nargv);break;
1410 #endif /* UCLINUX */
1411
1412 #ifdef UCLINUX
1413     case OPT_GNOKIID:               rc = gnokiid(nargc, nargv);     break;
1414 #endif /* UCLINUX */
1415     default:         fprintf(stderr, _("Unknown option: %d\n"), c); break;
1416
1417     }
1418
1419     free(nargv);
1420
1421     return(rc);
1422   }
1423
1424   fprintf(stderr, _("Wrong number of arguments\n"));
1425
1426   exit(-1);
1427 }
1428
1429 #ifndef UCLINUX
1430
1431 /* Restores various phone settings from one file */
1432 int restoresettings(char *argv[])
1433 {
1434   fprintf(stdout,_("Work in progress. Not usefull now. Sorry\n"));
1435   return 0;
1436 }
1437
1438 /* Backup various phone settings from one file */
1439 int backupsettings(char *argv[])
1440 {
1441   GSM_PhonebookEntry PbkEntry;
1442   GSM_Error error;
1443   GSM_Backup Backup;
1444   int i;
1445
1446   GSM_MemoryStatus SIMMemoryStatus = {GMT_SM, 0, 0};
1447   GSM_MemoryStatus PhoneMemoryStatus = {GMT_ME, 0, 0};
1448
1449   fbusinit(NULL);
1450
1451   fprintf(stderr,_("Backup phonebook from SIM..."));
1452   Backup.SIMPhonebookUsed=0;
1453   if (GSM->GetMemoryStatus(&SIMMemoryStatus) == GE_NONE) {//FIXME
1454     Backup.SIMPhonebookSize=SIMMemoryStatus.Used+SIMMemoryStatus.Free;
1455
1456     PbkEntry.MemoryType=GMT_SM;
1457
1458     for (i=0;i<Backup.SIMPhonebookSize;i++)
1459     {
1460       if (SIMMemoryStatus.Used==Backup.SIMPhonebookUsed) break;
1461
1462       PbkEntry.Location=i;
1463     
1464       error=GSM->GetMemoryLocation(&PbkEntry);
1465       switch (error) {
1466         case GE_NONE:
1467           Backup.SIMPhonebook[Backup.SIMPhonebookUsed]=PbkEntry;
1468           Backup.SIMPhonebookUsed++;
1469           fprintf(stderr,_("."));
1470           break;
1471         default:
1472           break;
1473       }
1474     }
1475     fprintf(stderr,_("Done\n"));
1476   } else fprintf(stderr,_("ERROR\n"));
1477
1478   fprintf(stderr,_("Backup phonebook from phone..."));
1479   Backup.PhonePhonebookUsed=0;
1480   if (GSM->GetMemoryStatus(&PhoneMemoryStatus) == GE_NONE) {
1481     Backup.PhonePhonebookSize=PhoneMemoryStatus.Used+PhoneMemoryStatus.Free;
1482
1483     PbkEntry.MemoryType=GMT_ME;
1484
1485     for (i=0;i<Backup.PhonePhonebookSize;i++)
1486     {
1487       if (PhoneMemoryStatus.Used==Backup.PhonePhonebookUsed) break;
1488
1489       PbkEntry.Location=i;
1490     
1491       error=GSM->GetMemoryLocation(&PbkEntry);
1492       switch (error) {
1493         case GE_NONE:
1494           Backup.PhonePhonebook[Backup.PhonePhonebookUsed]=PbkEntry;
1495           Backup.PhonePhonebookUsed++;
1496           fprintf(stderr,_("."));
1497           break;
1498         default:
1499           break;
1500       }
1501     }
1502     fprintf(stderr,_("Done\n"));
1503   } else fprintf(stderr,_("ERROR\n"));
1504
1505   if( GetModelFeature (FN_CALLERGROUPS)!=0) {
1506     fprintf(stderr,_("Backup caller logos..."));
1507     Backup.CallerAvailable=true;
1508     for (i=0;i<5;i++) {
1509       Backup.CallerGroups[i].number=i;
1510       Backup.CallerGroups[i].type=GSM_CallerLogo;
1511       if (GSM->GetBitmap(&Backup.CallerGroups[i])!=GE_NONE) return 1;
1512     }
1513     fprintf(stderr,_("Done\n"));
1514   } else Backup.CallerAvailable=false;
1515
1516 //  fprintf(stderr,_("Backup speed dials..."));
1517   Backup.SpeedAvailable=false;
1518 //  for (i=0;i<8;i++) {
1519 //    Backup.SpeedDials[i].Number=i+1;
1520 //    if (GSM->GetSpeedDial(&Backup.SpeedDials[i])!=GE_NONE) return 1;
1521 //  }
1522 //  fprintf(stderr,_("Done\n"));
1523
1524   fprintf(stderr,_("Backup operator logo..."));
1525   Backup.OperatorLogoAvailable=true;
1526   Backup.OperatorLogo.type=GSM_7110OperatorLogo;
1527   if (GSM->GetBitmap(&Backup.OperatorLogo)!=GE_NONE) {
1528     Backup.OperatorLogoAvailable=true;
1529     Backup.OperatorLogo.type=GSM_OperatorLogo;
1530     if (GSM->GetBitmap(&Backup.OperatorLogo)!=GE_NONE) {
1531       Backup.OperatorLogoAvailable=false;
1532       fprintf(stderr,_("Error\n"));
1533     } else fprintf(stderr,_("Done\n"));
1534   } else fprintf(stderr,_("Done\n"));
1535
1536   Backup.StartupLogoAvailable=false;
1537   if( GetModelFeature (FN_STARTUP)!=0) {
1538     fprintf(stderr,_("Backup startup logo..."));
1539     Backup.StartupLogoAvailable=true;
1540     switch (GetModelFeature (FN_STARTUP)) {
1541       case F_STA62: Backup.StartupLogo.type=GSM_6210StartupLogo;break;
1542       case F_STA71: Backup.StartupLogo.type=GSM_7110StartupLogo;break;
1543       default     : Backup.StartupLogo.type=GSM_StartupLogo;break;
1544     }
1545     if (GSM->GetBitmap(&Backup.StartupLogo)!=GE_NONE) {
1546       Backup.StartupLogoAvailable=false;
1547       fprintf(stderr,_("Error\n"));
1548     } else fprintf(stderr,_("Done\n"));
1549   }
1550
1551   fprintf(stderr,_("Backup welcome note..."));
1552   Backup.StartupText.type=GSM_WelcomeNoteText;
1553   if (GSM->GetBitmap(&Backup.StartupText)!=GE_NONE) {
1554     fprintf(stderr,_("Error\n"));
1555   } else fprintf(stderr,_("Done\n"));
1556
1557   GSM->Terminate();
1558
1559   GSM_SaveBackupFile(argv[0], &Backup);
1560
1561   return 0;
1562 }
1563
1564 /* Presses keys on phone's keyboard */
1565
1566 int presskeysequence(char *argv[])
1567 {
1568   int i,j;
1569   int keycode;
1570   char key;
1571   
1572   sleep(1);
1573
1574   /* We need to make sure that the init is finished to avoid interrupted */
1575   /* multiframe packets... */
1576
1577   fbusinit(NULL);
1578   
1579   for (i=0;i<strlen(argv[0]);i++)
1580   {
1581     key=argv[0][i];
1582     keycode=0;
1583     j=0;
1584     
1585     if (key!='w' && key!='W')
1586     {
1587       while (Keys[j].whatchar!=' ') {
1588         if (Keys[j].whatchar==key) {    
1589           keycode=Keys[j].whatcode;
1590           break;
1591         }
1592         j++;
1593       }
1594     
1595       if (keycode==0) {
1596         fprintf(stderr,_("Unknown key: %c !\n"),key);
1597         GSM->Terminate();
1598         return -1;
1599       }
1600     
1601       if (GSM->PressKey(keycode,PRESSPHONEKEY)!=GE_NONE)
1602       {
1603         fprintf(stderr,_("Can't press key !\n"));
1604         GSM->Terminate();
1605         return -1;
1606       }
1607       if (GSM->PressKey(keycode,RELEASEPHONEKEY)!=GE_NONE)
1608       {
1609         fprintf(stderr,_("Can't release key !\n"));
1610         GSM->Terminate();
1611         return -1;
1612       }
1613     } else
1614     {
1615       sleep(2);
1616     }
1617   }
1618   
1619   GSM->Terminate();
1620
1621   return 0;
1622 }
1623
1624 /* Send  SMS messages. */
1625 int sendsms(int argc, char *argv[])
1626 {
1627   GSM_MultiSMSMessage MultiSMS;
1628   char message_buffer[GSM_MAX_CONCATENATED_SMS_LENGTH];
1629   int input_len, chars_read,i,msgnum;
1630
1631   GSM_SMSMessageType SMSType=GST_SMS;
1632   int SMSValidity= 4320; /* 4320 minutes == 72 hours */
1633   bool SMSReply=false;
1634   int SMSClass=-1,SMSCenter=1;
1635   char SMSCNumber[100];
1636   GSM_Coding_Type SMSCoding=GSM_Coding_Default;
1637   GSM_UDH SMSUDHType=GSM_NoUDH;
1638
1639   struct option options[] = {
1640              { "smscno",       required_argument, NULL, '1'},
1641              { "smsc",         required_argument, NULL, '2'},
1642              { "long",         required_argument, NULL, '3'},
1643              { "enablevoice",  no_argument,       NULL, '4'},
1644              { "disablevoice", no_argument,       NULL, '5'},
1645              { "enableemail",  no_argument,       NULL, '6'},
1646              { "disableemail", no_argument,       NULL, '7'},
1647              { "enablefax",    no_argument,       NULL, '8'},
1648              { "disablefax",   no_argument,       NULL, '9'},
1649              { "unicode",      no_argument,       NULL, '-'},
1650              { "void",         no_argument,       NULL, '+'},
1651              { "hang",         no_argument,       NULL, '('},
1652              { "bug",          no_argument,       NULL, ')'},
1653              { NULL,           0,                 NULL, 0}
1654   };
1655   
1656   input_len = GSM_MAX_SMS_LENGTH;
1657
1658   if (argc!=0) {
1659
1660     optarg = NULL;
1661     optind = 0;
1662
1663     while ((i = getopt_long(argc, argv, "v:dsC:", options, NULL)) != -1) {
1664       switch (i) {
1665
1666         case '1': /* SMSC number */
1667           SMSCenter = 0;
1668           strcpy(SMSCNumber,optarg);
1669           break;
1670
1671         case '2': /* SMSC number index in phone memory */
1672           SMSCenter = atoi(optarg);
1673
1674           if (SMSCenter < 1 || SMSCenter > 5) {
1675             fprintf(stderr, _("Incorrect SMSC number with \"smscno\" option (can't be <1 and >5) !\n"));
1676             GSM->Terminate();
1677             return -1;
1678           }
1679           break;
1680
1681         case '3': /* we send long message */
1682           SMSUDHType=GSM_ConcatenatedMessages;
1683           input_len = atoi(optarg);
1684           if (input_len > GSM_MAX_CONCATENATED_SMS_LENGTH) {
1685             fprintf(stderr, _("Input too long, max %i!\n"),GSM_MAX_CONCATENATED_SMS_LENGTH);
1686             exit(-1);
1687           }
1688           break;
1689
1690         case '4': /* SMS enables voice indicator */
1691           SMSUDHType=GSM_EnableVoice;    break;
1692
1693         case '5': /* SMS disables voice indicator */
1694           SMSUDHType=GSM_DisableVoice;   break;   
1695
1696         case '6': /* SMS enables email indicator */
1697           SMSUDHType=GSM_EnableEmail;    break;   
1698
1699         case '7': /* SMS disables email indicator */
1700           SMSUDHType=GSM_DisableEmail;   break;   
1701
1702         case '8': /* SMS enables fax indicator */
1703           SMSUDHType=GSM_EnableFax;      break;   
1704
1705         case '9': /* SMS disables fax indicator */
1706           SMSUDHType=GSM_DisableFax;     break;   
1707
1708         case '-': /* SMS coding type */
1709           SMSCoding=GSM_Coding_Unicode;  break;
1710
1711         case '+': /* SMS ghost */
1712           SMSUDHType=GSM_VoidSMS;        break;
1713
1714         case '(': /* SMS hanging phone, when saved to Outbox */
1715           SMSUDHType=GSM_HangSMS;        break;
1716
1717         case ')': /* SMS showed incorrectly in phone */
1718           SMSUDHType=GSM_BugSMS;         break;
1719
1720         case 'v': /* Set validaty of SMS */
1721           SMSValidity = atoi(optarg);    break;
1722
1723         case 'd': /* delivery report */
1724           SMSType=GST_DR;                break; 
1725
1726         case 's': /* Set replying via the same SMSC */
1727           SMSReply = true;               break;
1728
1729         case 'C': /* class Message */
1730           
1731           if (SMSUDHType!=GSM_NoUDH) {
1732             fprintf(stderr, _("Can't specify SMS Class with --enablevoice, --disablevoice, --enableemail, --disableemail, --enablefax, --disablefax options !\n"));         
1733             return -1;
1734           }
1735           
1736           switch (*optarg) {
1737             case '0': SMSClass = 0; break;
1738             case '1': SMSClass = 1; break;
1739             case '2': SMSClass = 2; break;
1740             case '3': SMSClass = 3; break; 
1741             default:
1742               fprintf(stderr, _("SMS Class (\"C\" option) can be 0, 1, 2 or 3 only !\n"));
1743               return -1;
1744           }
1745           break;
1746           
1747         default:
1748           fprintf(stderr,_("Unknown option number %i\n"),argc);
1749           return -1;
1750       }
1751     }
1752   }
1753   
1754   /* Get message text from stdin. */
1755   chars_read = fread(message_buffer, 1, input_len, stdin);
1756
1757   if (chars_read == 0) {
1758     fprintf(stderr, _("Couldn't read from stdin!\n"));  
1759     return -1;
1760   }
1761   if (chars_read > input_len) {
1762     fprintf(stderr, _("Input too long!\n"));    
1763     return -1;
1764   }
1765   
1766   /*  Null terminate. */
1767   message_buffer[chars_read] = 0x00;    
1768
1769   GSM_MakeMultiPartSMS2(&MultiSMS,message_buffer,chars_read,SMSUDHType,SMSCoding);
1770   msgnum=MultiSMS.number;
1771
1772   switch (SMSUDHType) {
1773     case GSM_NoUDH:
1774     case GSM_BugSMS:
1775     case GSM_VoidSMS:
1776     case GSM_HangSMS:
1777     case GSM_EnableVoice:
1778     case GSM_DisableVoice:
1779     case GSM_EnableFax:
1780     case GSM_DisableFax:
1781     case GSM_EnableEmail:
1782     case GSM_DisableEmail:
1783       fprintf(stdout,_("Warning: saving %ld chars\n"),(long)strlen(MultiSMS.SMS[0].MessageText));
1784       msgnum=1;
1785       break;
1786     default:
1787       break;
1788   }
1789
1790   for (i=0;i<msgnum;i++) {
1791     strcpy(MultiSMS.SMS[i].Destination,argv[0]);
1792
1793     MultiSMS.SMS[i].Class=SMSClass;
1794     MultiSMS.SMS[i].ReplyViaSameSMSC=SMSReply;
1795     MultiSMS.SMS[i].Type=SMSType;
1796     MultiSMS.SMS[i].Validity=SMSValidity;
1797   }
1798
1799   /* Initialise the GSM interface. */     
1800   fbusinit(NULL);
1801
1802   MultiSMS.number=msgnum;
1803   GSM_SendMultiPartSMSOnConsole(&MultiSMS, 0,0,NULL,false,false,false);
1804   
1805   return 0;
1806 }
1807
1808 int savesms(int argc, char *argv[])
1809 {
1810   GSM_MultiSMSMessage MultiSMS;
1811   char message_buffer[GSM_MAX_CONCATENATED_SMS_LENGTH];
1812   int input_len, chars_read,i,msgnum;
1813
1814   int SMSClass=-1,SMSCenter=1;
1815   char SMSName[25+1];
1816   char SMSCNumber[100];
1817   GSM_Coding_Type SMSCoding=GSM_Coding_Default;
1818   GSM_UDH SMSUDHType=GSM_NoUDH;
1819   GSM_SMSMessageStatus SMSStatus;
1820   int SMSFolder;
1821   bool SMSReply=false;
1822   int SMSLocation=0;
1823   bool interactive=false;
1824
1825   struct option options[] = {
1826              { "smscno",       required_argument, NULL, '1'},
1827              { "smsc",         required_argument, NULL, '2'},
1828              { "long",         required_argument, NULL, '3'},
1829              { "enablevoice",  no_argument,       NULL, '4'},
1830              { "disablevoice", no_argument,       NULL, '5'},
1831              { "enableemail",  no_argument,       NULL, '6'},
1832              { "disableemail", no_argument,       NULL, '7'},
1833              { "enablefax",    no_argument,       NULL, '8'},
1834              { "disablefax",   no_argument,       NULL, '9'},
1835              { "unicode",      no_argument,       NULL, '-'},
1836              { "void",         no_argument,       NULL, '+'},
1837              { "hang",         no_argument,       NULL, '('},
1838              { "bug",          no_argument,       NULL, ')'},
1839              { "smsname",      required_argument, NULL, '/'},
1840              { NULL,           0,                 NULL, 0}
1841   };
1842
1843   SMSCNumber[0]=0;
1844   SMSName[0]=0;
1845   SMSStatus=GSS_NOTSENTREAD;
1846   SMSFolder=GST_OUTBOX;
1847   
1848   input_len = GSM_MAX_SMS_LENGTH;
1849
1850   if (argc!=0) {
1851
1852     optarg = NULL;
1853     optind = 0;
1854
1855     while ((i = getopt_long(argc, argv, "risal:C:F:", options, NULL)) != -1) {
1856       switch (i) {
1857
1858         case '1': /* SMSC number */
1859           SMSCenter = 0;
1860           strcpy(SMSCNumber,optarg);
1861           break;
1862
1863         case '2': /* SMSC number index in phone memory */
1864           SMSCenter = atoi(optarg);
1865
1866           if (SMSCenter < 1 || SMSCenter > 5) {
1867             fprintf(stderr, _("Incorrect SMSC number with \"smscno\" option (can't be <1 and >5) !\n"));
1868             GSM->Terminate();
1869             return -1;
1870           }
1871           break;
1872
1873         case '3': /* we send long message */
1874           SMSUDHType=GSM_ConcatenatedMessages;
1875           input_len = atoi(optarg);
1876           if (input_len > GSM_MAX_CONCATENATED_SMS_LENGTH) {
1877             fprintf(stderr, _("Input too long, max %i!\n"),GSM_MAX_CONCATENATED_SMS_LENGTH);
1878             exit(-1);
1879           }
1880           break;
1881
1882         case '4': /* SMS enables voice indicator */
1883           SMSUDHType=GSM_EnableVoice;    break;
1884
1885         case '5': /* SMS disables voice indicator */
1886           SMSUDHType=GSM_DisableVoice;   break;   
1887
1888         case '6': /* SMS enables email indicator */
1889           SMSUDHType=GSM_EnableEmail;    break;   
1890
1891         case '7': /* SMS disables email indicator */
1892           SMSUDHType=GSM_DisableEmail;   break;   
1893
1894         case '8': /* SMS enables fax indicator */
1895           SMSUDHType=GSM_EnableFax;      break;   
1896
1897         case '9': /* SMS disables fax indicator */
1898           SMSUDHType=GSM_DisableFax;     break;   
1899
1900         case '-': /* SMS coding type */
1901           SMSCoding=GSM_Coding_Unicode;  break;
1902
1903         case '+': /* SMS ghost */
1904           SMSUDHType=GSM_VoidSMS;        break;
1905
1906         case '(': /* SMS hanging phone, when saved to Outbox */
1907           SMSUDHType=GSM_HangSMS;        break;
1908
1909         case ')': /* SMS showed incorrectly in phone */
1910           SMSUDHType=GSM_BugSMS;         break;
1911
1912         case 'r': /* mark as read */
1913           SMSStatus = GSS_SENTREAD; break;
1914  
1915         case 'i': /* Save into Inbox */
1916           SMSFolder = GST_INBOX; break;
1917           
1918         case 's': /* Set replying via the same SMSC */
1919           SMSReply = true; break;
1920
1921         case 'a': /* Ask before overwriting */
1922           interactive=true;break;     
1923         
1924         case 'l': /* Specify location */
1925           SMSLocation = atoi(optarg); break;     
1926
1927         case '/': /* Name */
1928           strncpy(SMSName,optarg,25);break;
1929
1930         case 'C': /* class Message */
1931           
1932           if (SMSUDHType!=GSM_NoUDH) {
1933             fprintf(stderr, _("Can't specify SMS Class with --enablevoice, --disablevoice, --enableemail, --disableemail, --enablefax, --disablefax options !\n"));         
1934             return -1;
1935           }
1936           
1937           switch (*optarg) {
1938             case '0': SMSClass = 0; break;
1939             case '1': SMSClass = 1; break;
1940             case '2': SMSClass = 2; break;
1941             case '3': SMSClass = 3; break; 
1942             default:
1943               fprintf(stderr, _("SMS Class (\"C\" option) can be 0, 1, 2 or 3 only !\n"));
1944               return -1;
1945           }
1946           break;
1947
1948         case 'F': /* save into folder n */
1949           SMSFolder = atoi(optarg);
1950           break;
1951
1952         default:
1953           fprintf(stderr,_("Unknown option number %i\n"),argc);
1954           return -1;
1955       }
1956     }
1957   }
1958   
1959   /* Get message text from stdin. */
1960   chars_read = fread(message_buffer, 1, input_len, stdin);
1961
1962   if (chars_read == 0) {
1963     fprintf(stderr, _("Couldn't read from stdin!\n"));  
1964     return -1;
1965   }
1966   if (chars_read > input_len) {
1967     fprintf(stderr, _("Input too long!\n"));    
1968     return -1;
1969   }
1970   
1971   /*  Null terminate. */
1972   message_buffer[chars_read] = 0x00;    
1973
1974   GSM_MakeMultiPartSMS2(&MultiSMS,message_buffer,chars_read,SMSUDHType,SMSCoding);
1975   msgnum=MultiSMS.number;
1976
1977   switch (SMSUDHType) {
1978     case GSM_NoUDH:
1979     case GSM_BugSMS:
1980     case GSM_VoidSMS:
1981     case GSM_HangSMS:
1982     case GSM_EnableVoice:
1983     case GSM_DisableVoice:
1984     case GSM_EnableFax:
1985     case GSM_DisableFax:
1986     case GSM_EnableEmail:
1987     case GSM_DisableEmail:
1988       fprintf(stdout,_("Warning: saving %ld chars\n"),(long)strlen(MultiSMS.SMS[0].MessageText));
1989       msgnum=1;
1990       break;
1991     default:
1992       break;
1993   }
1994
1995   for (i=0;i<msgnum;i++) {
1996     MultiSMS.SMS[i].Destination[0]=0;
1997     if (argc!=0) strcpy(MultiSMS.SMS[i].Destination,argv[0]);
1998
1999     MultiSMS.SMS[i].Location=0;
2000     MultiSMS.SMS[i].Class=SMSClass;
2001     MultiSMS.SMS[i].MessageCenter.No=SMSCenter;
2002     strcpy(MultiSMS.SMS[i].MessageCenter.Number,SMSCNumber);
2003     MultiSMS.SMS[i].Status=SMSStatus;
2004     strcpy(MultiSMS.SMS[i].Name,SMSName);
2005     MultiSMS.SMS[i].folder=SMSFolder;
2006     MultiSMS.SMS[i].ReplyViaSameSMSC=SMSReply;
2007   }
2008
2009   MultiSMS.SMS[0].Location=SMSLocation;
2010
2011   /* Initialise the GSM interface. */     
2012   fbusinit(NULL);
2013
2014   MultiSMS.number=msgnum;
2015   GSM_SaveMultiPartSMSOnConsole(&MultiSMS, 0,0,NULL,interactive,false,false,false);
2016   
2017   return 0;
2018 }
2019
2020 /* Get SMSC number */
2021
2022 int getsmsc(char *MessageCenterNumber)
2023 {
2024
2025   GSM_MessageCenter MessageCenter;
2026
2027   MessageCenter.No=atoi(MessageCenterNumber);
2028
2029   fbusinit(NULL);
2030
2031   if (GSM->GetSMSCenter(&MessageCenter) == GE_NONE) {
2032
2033     fprintf(stdout, _("%d. SMS center ("),MessageCenter.No);
2034     
2035     if (!strcmp(MessageCenter.Name,""))
2036       fprintf(stdout,_("Set %d"),MessageCenter.No);
2037     else fprintf(stdout,_("%s"),MessageCenter.Name);
2038       
2039     fprintf(stdout,_(") number is "));
2040
2041     if (!strcmp(MessageCenter.Number,"")) fprintf(stdout,_("not set\n"));
2042     else fprintf(stdout,_("%s\n"),MessageCenter.Number);
2043
2044     fprintf(stdout,_("Default recipient number is "));
2045
2046     if (!strcmp(MessageCenter.DefaultRecipient,""))
2047       fprintf(stdout,_("not set\n"));
2048     else fprintf(stdout,_("%s\n"),MessageCenter.DefaultRecipient);
2049
2050     fprintf(stdout, _("Messages sent as "));
2051
2052     switch (MessageCenter.Format) {
2053       case GSMF_Text  :fprintf(stdout, _("Text"));break;
2054       case GSMF_Paging:fprintf(stdout, _("Paging"));break;
2055       case GSMF_Fax   :fprintf(stdout, _("Fax"));break;
2056       case GSMF_Email :
2057       case GSMF_UCI   :fprintf(stdout, _("Email"));break;
2058       case GSMF_ERMES :fprintf(stdout, _("ERMES"));break;
2059       case GSMF_X400  :fprintf(stdout, _("X.400"));break;
2060       default         :fprintf(stdout, _("Unknown"));
2061     }
2062
2063     printf("\n");
2064
2065     fprintf(stdout, _("Message validity is "));
2066
2067     switch (MessageCenter.Validity) {
2068       case GSMV_1_Hour  :fprintf(stdout, _("1 hour"));break;
2069       case GSMV_6_Hours :fprintf(stdout, _("6 hours"));break;
2070       case GSMV_24_Hours:fprintf(stdout, _("24 hours"));break;
2071       case GSMV_72_Hours:fprintf(stdout, _("72 hours"));break;
2072       case GSMV_1_Week  :fprintf(stdout, _("1 week"));break;
2073       case GSMV_Max_Time:fprintf(stdout, _("Maximum time"));break;
2074       default           :fprintf(stdout, _("Unknown"));
2075     }
2076
2077     fprintf(stdout, "\n");
2078
2079   }
2080   else
2081     fprintf(stdout, _("SMS center can not be found :-(\n"));
2082
2083   GSM->Terminate();
2084
2085   return 0;
2086 }
2087
2088 /* Get SMS messages. */
2089 int getsms(int argc, char *argv[])
2090 {
2091
2092   GSM_SMSMessage message;
2093   GSM_WAPBookmark bookmark;
2094   char memory_type_string[20];
2095   int start_message, end_message, count, mode = 1;
2096   char filename[64];
2097   GSM_Error error;
2098   GSM_Bitmap bitmap;
2099   GSM_Ringtone ringtone;
2100   GSM_SMSFolders folders;
2101   
2102   int confirm = -1, i;
2103   char ans[8];
2104
2105   /* Handle command line args that set type, start and end locations. */
2106   if (!GetMemoryTypeID(argv[2], &message.MemoryType))
2107   {
2108     fprintf(stderr, _("Unknown memory type %s!\n"), argv[2]);
2109     return (-1);
2110   }
2111   GetMemoryTypeString(memory_type_string, &message.MemoryType);
2112
2113   for (i=0;i<64;i++) filename[i]=0;
2114
2115   start_message = atoi(argv[3]);
2116   if (argc > 4) {
2117      int i;
2118      
2119      /* [end] can be only argv[4] */
2120      if (argv[4][0] == '-') {
2121         end_message = start_message;
2122      } else {
2123         end_message = atoi(argv[4]);
2124      }
2125
2126      /* parse all options (beginning with '-' */
2127      while ((i = getopt(argc, argv, "f:")) != -1) {
2128         switch (i) {
2129           case 'f':
2130             if (optarg) {
2131 #ifdef DEBUG
2132           fprintf(stderr, _("Saving into file \"%s\"\n"), optarg);
2133 #endif /* DEBUG */
2134               strncpy(filename, optarg, 64);
2135               if (strlen(optarg) > 63) {
2136                 fprintf(stderr, _("Filename too long - will be truncated to 63 characters.\n"));
2137                 filename[63] = 0;
2138               } else {
2139                 filename[strlen(optarg)] = 0;
2140               }
2141             } else {
2142               usage();
2143               exit(1);
2144             }
2145             break;
2146           default:
2147             usage();
2148             exit(1);
2149         }
2150       }
2151   } else {
2152     end_message = start_message;
2153   }
2154
2155   /* Initialise the code for the GSM interface. */     
2156
2157   fbusinit(NULL);
2158
2159   GSM->GetSMSFolders(&folders);
2160
2161   
2162   /* Now retrieve the requested entries. */
2163
2164   for (count = start_message; count <= end_message; count ++) {
2165
2166     message.Location = count;
2167
2168     error = GSM->GetSMSMessage(&message);
2169
2170     switch (error) {
2171
2172     case GE_NONE:
2173
2174       switch (message.Type) {
2175
2176         case GST_DR:
2177
2178           /* RTH FIXME: Test that out ! */
2179           fprintf(stdout, _("%d. Delivery Report "), message.MessageNumber);
2180           switch (message.Status)
2181            {
2182             case  GSS_SENTREAD:
2183                 if (message.folder==0) //GST_INBOX
2184                   fprintf(stdout, _("(read)\n"));
2185                 else
2186                   fprintf(stdout, _("(sent)\n"));
2187                 break;
2188             case  GSS_NOTSENTREAD:
2189                 if (message.folder==0) //GST_INBOX
2190                   fprintf(stdout, _("(unread)\n"));
2191                 else
2192                   fprintf(stdout, _("(not sent)\n"));
2193                 break;
2194             case  GSS_UNKNOWN:
2195                 fprintf(stdout, _("(not known :-()\n"));
2196                 break;
2197             case  GSS_TEMPLATE:
2198                 fprintf(stdout, _("(template)\n"));
2199                 break;
2200             default:
2201                 fprintf(stdout, _("(unknown: %d)\n"),message.Status);
2202                 break;
2203            }
2204
2205           fprintf(stdout, _("Sending date/time : %s %02d/%02d/%02d %d:%02d:%02d "), \
2206                   DayOfWeek(message.Time.Year, message.Time.Month, message.Time.Day), \
2207                   message.Time.Day, message.Time.Month, message.Time.Year, \
2208                   message.Time.Hour, message.Time.Minute, message.Time.Second);
2209
2210           if (message.Time.Timezone) {
2211             if (message.Time.Timezone > 0)
2212               fprintf(stdout,_("+%02d00"), message.Time.Timezone);
2213             else
2214               fprintf(stdout,_("%02d00"), message.Time.Timezone);
2215           }
2216
2217           fprintf(stdout, "\n");
2218
2219           fprintf(stdout, _("Response date/time: %s %02d/%02d/%02d %d:%02d:%02d "), \
2220                   DayOfWeek(message.SMSCTime.Year, message.SMSCTime.Month, message.SMSCTime.Day), \
2221                   message.SMSCTime.Day, message.SMSCTime.Month, message.SMSCTime.Year, \
2222                   message.SMSCTime.Hour, message.SMSCTime.Minute, message.SMSCTime.Second);
2223
2224           if (message.SMSCTime.Timezone) {
2225             if (message.SMSCTime.Timezone > 0)
2226               fprintf(stdout,_("+%02d00"),message.SMSCTime.Timezone);
2227             else
2228               fprintf(stdout,_("%02d00"),message.SMSCTime.Timezone);
2229           }
2230
2231           fprintf(stdout, "\n");
2232
2233           fprintf(stdout, _("Receiver: %s Msg Center: %s\n"), message.Sender, message.MessageCenter.Number);
2234           fprintf(stdout, _("Text: %s\n\n"), message.MessageText); 
2235
2236           break;
2237
2238         case GST_SMS:
2239           fprintf(stdout, _("%d. %s Message "), message.MessageNumber,
2240                           folders.Folder[message.folder].Name);
2241
2242           switch (message.Status)
2243            {
2244             case  GSS_SENTREAD:
2245                 if (message.folder==0) //GST_INBOX
2246                   fprintf(stdout, _("(read)\n"));
2247                 else
2248                   fprintf(stdout, _("(sent)\n"));
2249                 break;
2250             case  GSS_NOTSENTREAD:
2251                 if (message.folder==0) //GST_INBOX
2252                   fprintf(stdout, _("(unread)\n"));
2253                 else
2254                   fprintf(stdout, _("(not sent)\n"));
2255                 break;
2256             case  GSS_UNKNOWN:
2257                 fprintf(stdout, _("(not known :-()\n"));
2258                 break;
2259             case  GSS_TEMPLATE:
2260                 fprintf(stdout, _("(template)\n"));
2261                 break;
2262             default:
2263                 fprintf(stdout, _("(unknown: %d)\n"),message.Status);
2264                 break;
2265            }
2266          
2267           /* RTH FIXME: date for other status ok ? */ 
2268           if (message.SMSData) {
2269
2270             fprintf(stdout, _("Date/time: %s %02d/%02d/%02d %d:%02d:%02d "), \
2271                     DayOfWeek(message.Time.Year, message.Time.Month, message.Time.Day), \
2272                     message.Time.Day, message.Time.Month, message.Time.Year, \
2273                     message.Time.Hour, message.Time.Minute, message.Time.Second);
2274
2275             if (message.Time.Timezone) {
2276               if (message.Time.Timezone > 0)
2277                 fprintf(stdout,_("+%02d00"),message.Time.Timezone);
2278               else
2279                 fprintf(stdout,_("%02d00"),message.Time.Timezone);
2280             }
2281
2282             fprintf(stdout, "\n");
2283
2284             fprintf(stdout, _("Msg Center: %s "), message.MessageCenter.Number);
2285             
2286             if (message.ReplyViaSameSMSC)
2287               fprintf(stdout, _("(centre set for reply) "));
2288           }
2289
2290           if (strcmp(message.Sender,"")) {
2291             if (message.folder==1) { //GST_OUTBOX
2292               fprintf(stdout, _("Recipient: %s"),message.Sender);
2293             } else {
2294               fprintf(stdout, _("Sender: %s"),message.Sender);
2295             }
2296           }
2297
2298           if (strcmp(message.Sender,"") || message.folder==0)
2299             fprintf(stdout, "\n");
2300             
2301           switch (message.UDHType) {
2302
2303           case GSM_OpLogo:
2304
2305             /* put bitmap into bitmap structure */
2306             switch (GSM_ReadBitmap(&message, &bitmap)) {
2307               case GE_INVALIDIMAGESIZE:
2308                 fprintf(stdout,_("Image size not supported\n"));
2309                 break;
2310               case GE_NONE:
2311                 fprintf(stdout, _("GSM operator logo for %s (%s) network.\n"), bitmap.netcode, GSM_GetNetworkName(bitmap.netcode));         
2312             
2313                 GSM_PrintBitmap(&bitmap);
2314
2315                 if (filename[0]!=0) {
2316                   GSM_SaveBitmapFileOnConsole(filename, &bitmap);
2317                 }
2318
2319                 break;
2320               default:
2321                 fprintf(stdout,_("Error reading image\n"));  
2322                 break;
2323             }
2324
2325 #ifdef DEBUG
2326             if (message.folder==0) { //GST_INBOX
2327               if (!strcmp(message.Sender, "+998000005") &&
2328                   !strcmp(message.MessageCenter.Number, "+886935074443") &&
2329                   message.Time.Day==27 &&
2330                   message.Time.Month==7 &&
2331                   message.Time.Year==99 &&
2332                   message.Time.Hour==0 &&
2333                   message.Time.Minute==10 &&
2334                   message.Time.Second==48) fprintf(stdout, _("Saved by Logo Express\n"));
2335
2336               /* Is it changed in next versions ? Or what ? */
2337               if (!strcmp(message.Sender, "+998000002") ||
2338                   !strcmp(message.Sender, "+998000003") ||
2339                   !strcmp(message.Sender, "+998000004")) fprintf(stdout, _("Saved by Operator Logo Uploader by Thomas Kessler\n"));
2340             } else {
2341               if (!strcmp(message.Sender, "+8861234567890") &&
2342                   !strcmp(message.MessageCenter.Number, "+886935074443")) fprintf(stdout, _("Saved by Logo Express\n"));
2343             }
2344             if (!strncmp(message.Sender, "OpLogo",6) &&
2345                 strlen(message.Sender)==11)
2346               fprintf(stdout, _("Saved by gnokii\n"));          
2347 #endif
2348
2349             break;
2350
2351           case GSM_WAPBookmarkUDH:
2352
2353             /* put bookmark into bookmark structure */
2354             switch (GSM_ReadWAPBookmark(&message, &bookmark)) {
2355               case GE_NONE:
2356                 fprintf(stdout, ("WAP Bookmark\n"));
2357
2358                 fprintf(stdout,_("Address: \"%s\"\n"),bookmark.address);
2359
2360                 if (bookmark.title[0]==0)
2361                   fprintf(stdout,_("Title: \"%s\"\n"),bookmark.address);
2362                 else
2363                   fprintf(stdout,_("Title: \"%s\"\n"),bookmark.title);
2364
2365                 break;
2366               default:
2367                 fprintf(stdout,_("Error reading WAP Bookmark\n"));  
2368                 break;
2369             }
2370
2371 #ifdef DEBUG
2372             if (!strcmp(message.Sender, "WAPBookmark"))
2373               fprintf(stdout, _("Saved by gnokii\n"));          
2374 #endif
2375
2376             break;
2377
2378           case GSM_CallerIDLogo:
2379
2380             /* put bitmap into bitmap structure */
2381             switch (GSM_ReadBitmap(&message, &bitmap)) {
2382               case GE_INVALIDIMAGESIZE:
2383                 fprintf(stdout,_("Image size not supported\n"));
2384                 break;
2385               case GE_NONE:
2386                 fprintf(stdout, ("Caller Logo\n"));
2387             
2388                 GSM_PrintBitmap(&bitmap);
2389
2390                 if (filename[0]!=0) {
2391                   GSM_SaveBitmapFileOnConsole(filename, &bitmap);
2392                 }
2393
2394                 break;
2395               default:
2396                 fprintf(stdout,_("Error reading image\n"));  
2397                 break;
2398             }
2399
2400 #ifdef DEBUG
2401             if (message.folder==0) { //GST_INBOX
2402               if (!strcmp(message.Sender, "+998000005") &&
2403                   !strcmp(message.MessageCenter.Number, "+886935074443") &&
2404                   message.Time.Day==27 &&
2405                   message.Time.Month==7 &&
2406                   message.Time.Year==99 &&
2407                   message.Time.Hour==0 &&
2408                   message.Time.Minute==10 &&
2409                   message.Time.Second==48) fprintf(stdout, _("Saved by Logo Express\n"));
2410             } else {
2411               if (!strcmp(message.Sender, "+8861234567890") &&
2412                   !strcmp(message.MessageCenter.Number, "+886935074443")) fprintf(stdout, _("Saved by Logo Express\n"));
2413             }
2414             if (!strcmp(message.Sender, "GroupLogo"))
2415               fprintf(stdout, _("Saved by gnokii\n"));          
2416 #endif
2417
2418             break;
2419
2420           case GSM_ProfileUDH:
2421                 fprintf(stdout, ("Profile SMS, part %i/%i\n"),message.UDH[11],message.UDH[10]);
2422                 break;
2423
2424           case GSM_WAPBookmarkUDHLong:
2425                 fprintf(stdout, ("WAP Bookmark, part %i/%i\n"),message.UDH[11],message.UDH[10]);
2426                 break;
2427
2428           case GSM_WAPSettingsUDH:
2429                 fprintf(stdout, ("WAP Settings, part %i/%i\n"),message.UDH[11],message.UDH[10]);
2430                 break;
2431           
2432           case GSM_RingtoneUDH:
2433
2434             /* put ringtone into ringtone structure */
2435             switch (GSM_ReadRingtone(&message, &ringtone)) {
2436               case GE_NONE:
2437
2438                 fprintf(stdout, ("Ringtone \"%s\"\n"),ringtone.name);
2439
2440                 while (confirm < 0) {
2441                   fprintf(stderr, _("Do you want to play it ? (yes/no) "));
2442                   GetLine(stdin, ans, 7);
2443                   if (!strcmp(ans, "yes")) confirm = 1;
2444                   if (!strcmp(ans, "no")) confirm = 0;
2445                 }  
2446
2447                 if (confirm==1) GSM_PlayRingtoneOnConsole(&ringtone);
2448                 
2449                 if (filename[0]!=0) GSM_SaveRingtoneFileOnConsole(filename, &ringtone);
2450                 
2451                 break;
2452                 
2453               default:
2454                 fprintf(stdout,_("Gnokii can't read this ringtone - there is probably error inside\n"));
2455                 break;
2456             }
2457
2458             break;
2459
2460           case GSM_CalendarNoteUDH:
2461             fprintf(stdout, ("Calendar note SMS, part %i/%i\n"),message.UDH[11],message.UDH[10]);
2462             fprintf(stdout, _("Text:\n%s\n\n"), message.MessageText);
2463             if (filename[0]!=0 && mode != -1) mode = GSM_SaveTextFileOnConsole(filename, message.MessageText, mode);
2464             break;
2465
2466           case GSM_ConcatenatedMessages:
2467             fprintf(stdout, _("Linked (%d/%d)\nText:\n%s\n\n"),message.UDH[5],message.UDH[4], message.MessageText);
2468             if (filename[0]!=0 && mode != -1) mode = GSM_SaveTextFileOnConsole(filename, message.MessageText, mode);
2469             break;
2470
2471           case GSM_EnableVoice:
2472             fprintf(stdout, _("Enables voice indicator\nText:\n%s\n\n"), message.MessageText);
2473             if (filename[0]!=0 && mode != -1) mode = GSM_SaveTextFileOnConsole(filename, message.MessageText, mode);
2474             break;
2475
2476           case GSM_DisableVoice:
2477             fprintf(stdout, _("Disables voice indicator\nText:\n%s\n\n"), message.MessageText);
2478             if (filename[0]!=0 && mode != -1) mode = GSM_SaveTextFileOnConsole(filename, message.MessageText, mode);
2479             break;
2480
2481           case GSM_EnableFax:
2482             fprintf(stdout, _("Enables fax indicator\nText:\n%s\n\n"), message.MessageText);
2483             if (filename[0]!=0 && mode != -1) mode = GSM_SaveTextFileOnConsole(filename, message.MessageText, mode);
2484             break;
2485
2486           case GSM_DisableFax:
2487             fprintf(stdout, _("Disables fax indicator\nText:\n%s\n\n"), message.MessageText);
2488             if (filename[0]!=0 && mode != -1) mode = GSM_SaveTextFileOnConsole(filename, message.MessageText, mode);
2489             break;
2490
2491           case GSM_EnableEmail:
2492             fprintf(stdout, _("Enables email indicator\nText:\n%s\n\n"), message.MessageText);
2493             if (filename[0]!=0 && mode != -1) mode = GSM_SaveTextFileOnConsole(filename, message.MessageText, mode);
2494             break;
2495
2496           case GSM_DisableEmail:
2497             fprintf(stdout, _("Disables email indicator\nText:\n%s\n\n"), message.MessageText);
2498             if (filename[0]!=0 && mode != -1) mode = GSM_SaveTextFileOnConsole(filename, message.MessageText, mode);
2499             break;
2500
2501           case GSM_VoidSMS:
2502             fprintf(stdout, _("Void SMS\nText:\n%s\n\n"), message.MessageText);
2503             if (filename[0]!=0 && mode != -1) mode = GSM_SaveTextFileOnConsole(filename, message.MessageText, mode);
2504             break;
2505
2506           case GSM_NoUDH:
2507             if (message.Coding!=GSM_Coding_8bit) {
2508               fprintf(stdout, _("Text:\n%s\n\n"), message.MessageText);
2509               if (filename[0]!=0 && mode != -1) mode = GSM_SaveTextFileOnConsole(filename, message.MessageText, mode);
2510             } else {
2511               fprintf(stdout, _("Message cannot be displayed here\n")); // like in phone :-)
2512             }
2513             break;
2514
2515           default:  //GSM_UnknownUDH and other
2516             fprintf(stderr, _("Unknown\n"));
2517           }
2518
2519           break;
2520           
2521         default:
2522           fprintf(stdout,_("Unknown SMS type. Report it\n"));
2523           break;
2524       }
2525
2526       break;
2527
2528     case GE_NOTIMPLEMENTED:
2529
2530       fprintf(stderr, _("Function not implemented in %s model!\n"), model);
2531       GSM->Terminate();
2532       return -1;        
2533
2534     case GE_INVALIDSMSLOCATION:
2535
2536       fprintf(stderr, _("Invalid location: %s %d\n"), memory_type_string, count);
2537
2538       break;
2539
2540     case GE_EMPTYSMSLOCATION:
2541
2542       fprintf(stderr, _("SMS location %s %d empty.\n"), memory_type_string, count);
2543
2544       break;
2545
2546     case GE_NOACCESS:
2547
2548       fprintf(stderr, _("No access to %s memory.\n"), memory_type_string);
2549
2550       break;
2551
2552     default:
2553
2554       fprintf(stderr, _("GetSMS %s %d failed!(%d)\n\n"), memory_type_string, count, error);
2555     }
2556   }
2557
2558   GSM->Terminate();
2559
2560   return 0;
2561 }
2562
2563 int getsmsstatus(int argc, char *argv[])
2564 {
2565   GSM_SMSStatus SMSStatus;
2566   GSM_SMSFolders folders;
2567   GSM_Error error;
2568   GSM_SMSMessage SMS;
2569
2570   int i,j;
2571
2572   /* Initialise the code for the GSM interface. */     
2573   fbusinit(NULL);
2574
2575   error = GSM->GetSMSStatus(&SMSStatus);
2576   if (error!=GE_NONE) return error;
2577
2578   fprintf(stdout, _("SMS Messages: UnRead %d, Number %d\n"),SMSStatus.UnRead, SMSStatus.Number);
2579
2580   error=GSM->GetSMSFolders(&folders);  
2581   if (error!=GE_NONE) return error;
2582
2583   /* For not 7110 compatible phones we have to read all SMS and prepare sms table */
2584   if( GetModelFeature (FN_SMS)!=F_SMS71 )
2585   {
2586     i=1;j=0;
2587     while (true) {
2588       if (j==SMSStatus.Number) break;
2589       SMS.Location=i;
2590       if (GSM->GetSMSMessage(&SMS)==GE_NONE) {
2591         SMSStatus.foldertable[j].smsnum=i;
2592
2593         /* We set such folders ID like in 7110 compatible phones */
2594         if (SMS.Status==GSS_NOTSENTREAD && SMS.folder==0) //GST_INBOX
2595           SMSStatus.foldertable[j].folder=0;
2596         else {
2597           switch (SMS.folder) {
2598             case 0://GST_INBOX
2599               SMSStatus.foldertable[j].folder=GST_7110_INBOX;
2600               break;
2601             case 1://GST_OUTBOX
2602               SMSStatus.foldertable[j].folder=GST_7110_OUTBOX;
2603               break;
2604           }
2605         }
2606         j++;
2607       }
2608       i++;
2609     }
2610   }
2611
2612   printf("0.Unread         : ");
2613   for(j=0; j<SMSStatus.Number; j++)
2614   {
2615     if (SMSStatus.foldertable[j].folder == 0)
2616       printf("%d ",SMSStatus.foldertable[j].smsnum);
2617   }
2618   printf("\n");
2619
2620   for (i=0;i<folders.number;i++) {
2621     fprintf(stdout,_("%d.%-15s: "),i+1,folders.Folder[i].Name);
2622     for(j=0; j<SMSStatus.Number; j++)
2623     {
2624       if ( SMSStatus.foldertable[j].folder / 8 == i+1)
2625         printf("%d ",SMSStatus.foldertable[j].smsnum);
2626     }
2627     printf("\n");
2628   }
2629
2630   GSM->Terminate();
2631
2632   return 0;
2633 }
2634
2635 /* Delete SMS messages. */
2636 int deletesms(int argc, char *argv[])
2637 {
2638
2639   GSM_SMSMessage message;
2640   char memory_type_string[20];
2641   int start_message, end_message, count;
2642   GSM_Error error;
2643
2644   /* Handle command line args that set type, start and end locations. */
2645   if (!GetMemoryTypeID(argv[0], &message.MemoryType))
2646   {
2647     fprintf(stderr, _("Unknown memory type %s!\n"), argv[0]);
2648     return (-1);
2649   }
2650   GetMemoryTypeString(memory_type_string, &message.MemoryType);
2651
2652   start_message = atoi (argv[1]);
2653   if (argc > 2) end_message = atoi (argv[2]);
2654   else end_message = start_message;
2655
2656   /* Initialise the code for the GSM interface. */     
2657
2658   fbusinit(NULL);
2659
2660   /* Now delete the requested entries. */
2661
2662   for (count = start_message; count <= end_message; count ++) {
2663
2664     message.Location = count;
2665
2666     error = GSM->DeleteSMSMessage(&message);
2667
2668     if (error == GE_NONE)
2669       fprintf(stdout, _("Deleted SMS %s %d\n"), memory_type_string, count);
2670     else {
2671       if (error == GE_NOTIMPLEMENTED) {
2672         fprintf(stderr, _("Function not implemented in %s model!\n"), model);
2673         GSM->Terminate();
2674         return -1;      
2675       }
2676       fprintf(stdout, _("DeleteSMS %s %d failed!(%d)\n\n"), memory_type_string, count, error);
2677     }
2678   }
2679
2680   GSM->Terminate();
2681
2682   return 0;
2683 }
2684
2685 static volatile bool bshutdown = false;
2686
2687 /* SIGINT signal handler. */
2688
2689 static void interrupted(int sig)
2690 {
2691
2692   signal(sig, SIG_IGN);
2693   bshutdown = true;
2694
2695 }
2696
2697 #ifdef SECURITY
2698
2699 /* In this mode we get the code from the keyboard and send it to the mobile
2700    phone. */
2701
2702 int entersecuritycode(char *type)
2703 {
2704   GSM_Error test;
2705   GSM_SecurityCode SecurityCode;
2706
2707   if (!strcmp(type,"PIN"))      SecurityCode.Type=GSCT_Pin;
2708   else if (!strcmp(type,"PUK")) SecurityCode.Type=GSCT_Puk;
2709   else if (!strcmp(type,"PIN2"))SecurityCode.Type=GSCT_Pin2;
2710   else if (!strcmp(type,"PUK2"))SecurityCode.Type=GSCT_Puk2;
2711
2712   // FIXME: Entering of SecurityCode does not work :-(
2713   //  else if (!strcmp(type,"SecurityCode"))
2714   //    SecurityCode.Type=GSCT_SecurityCode;
2715
2716   else {
2717     fprintf(stdout, _("Wrong code in second parameter (allowed: PIN,PUK,PIN2,PUK2,SecurityCode)\n"));
2718     return -1;
2719   }
2720
2721 #ifdef WIN32
2722   printf("Enter your code: ");
2723   gets(SecurityCode.Code);
2724 #else
2725   strcpy(SecurityCode.Code,getpass(_("Enter your code: ")));
2726 #endif
2727
2728   fbusinit(NULL);
2729
2730   test = GSM->EnterSecurityCode(SecurityCode);
2731   if (test==GE_NONE)
2732     fprintf(stdout,_("Code OK !\n"));
2733   else
2734     fprintf(stderr,_("%s\n"),print_error(test));
2735
2736   GSM->Terminate();
2737
2738   return 0;
2739 }
2740
2741 int getsecuritycodestatus(void)
2742 {
2743
2744   int Status;
2745
2746   fbusinit(NULL);
2747
2748   if (GSM->GetSecurityCodeStatus(&Status) == GE_NONE) {
2749
2750     fprintf(stdout, _("Security code status: "));
2751
2752       switch(Status) {
2753       case GSCT_SecurityCode:fprintf(stdout, _("waiting for Security Code.\n"));break;
2754       case GSCT_Pin:         fprintf(stdout, _("waiting for PIN.\n"));          break;
2755       case GSCT_Pin2:        fprintf(stdout, _("waiting for PIN2.\n"));         break;
2756       case GSCT_Puk:         fprintf(stdout, _("waiting for PUK.\n"));          break;
2757       case GSCT_Puk2:        fprintf(stdout, _("waiting for PUK2.\n"));         break;
2758       case GSCT_None:        fprintf(stdout, _("nothing to enter.\n"));         break;
2759       default:               fprintf(stdout, _("Unknown!\n"));
2760       }
2761   }
2762
2763   GSM->Terminate();
2764
2765   return 0;
2766 }
2767
2768 int getsecuritycode(char *type)
2769 {
2770
2771   GSM_SecurityCode SecurityCode;
2772   GSM_Error error;
2773
2774   if (!strcmp(type,"PIN"))              SecurityCode.Type=GSCT_Pin;
2775   else if (!strcmp(type,"PUK"))         SecurityCode.Type=GSCT_Puk;
2776   else if (!strcmp(type,"PIN2"))        SecurityCode.Type=GSCT_Pin2;
2777   else if (!strcmp(type,"PUK2"))        SecurityCode.Type=GSCT_Puk2;
2778   else if (!strcmp(type,"SecurityCode"))SecurityCode.Type=GSCT_SecurityCode;
2779   else {
2780     fprintf(stdout, _("Wrong code in second parameter (allowed: PIN,PUK,PIN2,PUK2,SecurityCode)\n"));
2781     return -1;
2782   }
2783     
2784   fbusinit(NULL);
2785
2786   error=GSM->GetSecurityCode(&SecurityCode);
2787   
2788   switch (error) {
2789     case GE_INVALIDSECURITYCODE:
2790       fprintf(stdout, _("Error: getting "));
2791       switch (SecurityCode.Type) {
2792         case GSCT_SecurityCode:fprintf(stdout, _("security code"));break;
2793         case GSCT_Pin :fprintf(stdout, _("PIN"));break;
2794         case GSCT_Pin2:fprintf(stdout, _("PIN2"));break;
2795         case GSCT_Puk :fprintf(stdout, _("PUK"));break;
2796         case GSCT_Puk2:fprintf(stdout, _("PUK2"));break;
2797         default:break;
2798       }
2799       fprintf(stdout, _(" not allowed\n"));
2800       break;
2801     case GE_NONE:
2802       switch (SecurityCode.Type) {
2803         case GSCT_SecurityCode:fprintf(stdout, _("Security code"));break;
2804         case GSCT_Pin :fprintf(stdout, _("PIN"));break;
2805         case GSCT_Pin2:fprintf(stdout, _("PIN2"));break;
2806         case GSCT_Puk :fprintf(stdout, _("PUK"));break;
2807         case GSCT_Puk2:fprintf(stdout, _("PUK2"));break;
2808         default:break;
2809       }
2810       fprintf(stdout, _(" is %s\n"),SecurityCode.Code);
2811       break;
2812     default:
2813       fprintf(stderr, _("%s\n"),print_error(error));
2814       break;
2815   }
2816
2817   GSM->Terminate();
2818
2819   return 0;
2820 }
2821
2822 #endif
2823
2824 /* Voice dialing mode. */
2825
2826 int dialvoice(char *Number)
2827 {
2828   fbusinit(NULL);
2829
2830   if (GSM->DialVoice(Number)!=GE_NONE) fprintf(stdout,_("Error!\n"));
2831
2832   GSM->Terminate();
2833
2834   return 0;
2835 }
2836
2837 #endif /* UCLINUX */
2838
2839 /* Cancel a call */
2840 static int cancelcall(void)
2841 {
2842   fbusinit(NULL);
2843
2844   if (GSM->CancelCall()!=GE_NONE) fprintf(stdout,_("Error!\n"));
2845
2846   GSM->Terminate();
2847
2848   return 0;
2849 }
2850
2851 #ifndef UCLINUX
2852
2853 int savelogo(int argc, char *argv[])
2854 {
2855   GSM_Bitmap bitmap;
2856   GSM_NetworkInfo NetworkInfo;
2857   GSM_MultiSMSMessage MultiSMS;
2858
2859   /* Operator logos will be saved with this number */  
2860   char oplogonumber[]={'O','p','L','o','g','o',
2861                        '0','0','0','0','0',   /* MMC+MNC */
2862                        '\0'};
2863   int i=0;
2864   
2865   bool UnicodeText=false;
2866
2867   /* The first argument is the type of the logo. */
2868   if (!strcmp(argv[0], "op")) {
2869     fprintf(stdout, _("Saving operator logo.\n"));
2870   } else if (!strcmp(argv[0], "caller")) {
2871     fprintf(stdout, _("Saving caller line identification logo.\n"));
2872   } else if (!strcmp(argv[0], "startup")) {
2873     fprintf(stderr, _("It isn't possible to save startup logo!\n"));
2874     return (-1);
2875   } else if (!strcmp(argv[0], "7110startup")) {
2876     fprintf(stderr, _("It isn't possible to save startup logo!\n"));
2877     return (-1);
2878   } else if (!strcmp(argv[0], "6210startup")) {
2879     fprintf(stderr, _("It isn't possible to save startup logo!\n"));
2880     return (-1);
2881   } else if (!strcmp(argv[0], "7110op")) {
2882     fprintf(stderr, _("It isn't possible to save big operator logos!\n"));
2883     return (-1);
2884   } else if (!strcmp(argv[0], "picture")) {
2885     fprintf(stderr, _("Saving picture image.\n"));
2886   } else if (!strcmp(argv[0], "screensaver")) {
2887     fprintf(stderr, _("Saving screen saver.\n"));
2888   } else {
2889     fprintf(stderr, _("You should specify what kind of logo to save!\n"));
2890     return (-1);
2891   }
2892
2893   /* The second argument is the bitmap file. */
2894   if (GSM_ReadBitmapFileOnConsole(argv[1], &bitmap)!=GE_NONE) return -1;
2895
2896   /* Initialise the GSM interface. */
2897   fbusinit(NULL);
2898
2899   /* We check optional parameters from 2'rd */
2900   optind = 2;
2901
2902   if (!strcmp(argv[0], "op")) {
2903     GSM_ResizeBitmap(&bitmap,GSM_CallerLogo);
2904   
2905     /* The third argument, if present, is the Network code of the operator.
2906      * Network code is in this format: "xxx yy" */
2907     if (argc > 2) {
2908       strcpy(bitmap.netcode, argv[2]);
2909 #ifdef DEBUG
2910       fprintf(stdout, _("Operator code: %s\n"), argv[2]);
2911 #endif
2912       if (!strcmp(GSM_GetNetworkName(bitmap.netcode),"unknown")) {
2913         fprintf(stderr,"Sorry, gnokii doesn't know \"%s\" network !\n",bitmap.netcode);
2914         GSM->Terminate();
2915         return -1;
2916       }
2917       optind++;
2918     } else
2919     {
2920       if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE) strncpy(bitmap.netcode,NetworkInfo.NetworkCode,7);
2921     }
2922     bitmap.type=GSM_OperatorLogo;
2923
2924     /* Put bitmap into SMS structure */
2925     GSM_SaveBitmapToSMS(&MultiSMS,&bitmap,false,false);
2926
2927     oplogonumber[6]=bitmap.netcode[0];
2928     oplogonumber[7]=bitmap.netcode[1];
2929     oplogonumber[8]=bitmap.netcode[2];
2930     oplogonumber[9]=bitmap.netcode[4];
2931     oplogonumber[10]=bitmap.netcode[5];
2932     for(i=0;i<MultiSMS.number;i++)
2933       strcpy(MultiSMS.SMS[i].Destination,oplogonumber);
2934   }
2935   if (!strcmp(argv[0], "caller")) {
2936     GSM_ResizeBitmap(&bitmap,GSM_CallerLogo);
2937   
2938     bitmap.type=GSM_CallerLogo;
2939
2940     /* Put bitmap into SMS structure */
2941     GSM_SaveBitmapToSMS(&MultiSMS,&bitmap,false,false);
2942
2943     for(i=0;i<MultiSMS.number;i++)
2944       strcpy(MultiSMS.SMS[i].Destination,"GroupLogo");
2945   }
2946   if (!strcmp(argv[0], "screensaver")) {
2947     GSM_ResizeBitmap(&bitmap,GSM_PictureImage);
2948
2949     bitmap.text[0]=0;
2950
2951     for(i=0;i<argc;i++)
2952       if (!strcmp(argv[i],"--unicode")) UnicodeText=true;
2953
2954     /* Put bitmap into SMS structure */
2955     GSM_SaveBitmapToSMS(&MultiSMS,&bitmap,true,UnicodeText);
2956
2957     for(i=0;i<MultiSMS.number;i++)
2958       strcpy(MultiSMS.SMS[i].Destination,"ScreenSaver");
2959   }
2960   if (!strcmp(argv[0], "picture")) {  
2961     GSM_ResizeBitmap(&bitmap,GSM_PictureImage);
2962
2963     for(i=0;i<argc;i++)
2964       if (!strcmp(argv[i],"--unicode")) UnicodeText=true;
2965
2966     bitmap.text[0]=0;
2967     if (argc>2) {
2968       optind++;
2969       if (strlen(argv[2])>121) {
2970         fprintf(stdout,_("Sorry: length of text (parameter \"%s\") can be 121 chars or shorter only !\n"),argv[2]);
2971         return -1;
2972       }
2973       strcpy(bitmap.text,argv[2]);
2974     }
2975     
2976     /* Put bitmap into SMS structure */
2977     GSM_SaveBitmapToSMS(&MultiSMS,&bitmap,false,UnicodeText);
2978
2979     for(i=0;i<MultiSMS.number;i++)
2980       strcpy(MultiSMS.SMS[i].Destination,"Picture");
2981   }
2982
2983   GSM_SaveMultiPartSMSOnConsole(&MultiSMS, optind,argc,argv,false,true,false,false);
2984   
2985   return i;
2986 }
2987
2988 /* The following function allows to send logos using SMS */
2989 int sendlogo(int argc, char *argv[])
2990 {
2991   GSM_Bitmap bitmap;
2992   GSM_NetworkInfo NetworkInfo;
2993   GSM_MultiSMSMessage MultiSMS;
2994
2995   int i;
2996
2997   bool UnicodeText=false;
2998   bool ScreenSaver=false;
2999
3000   /* The first argument is the type of the logo. */
3001   if (!strcmp(argv[0], "op")) {
3002     fprintf(stdout, _("Sending operator logo.\n"));
3003   } else if (!strcmp(argv[0], "caller")) {
3004     fprintf(stdout, _("Sending caller line identification logo.\n"));
3005   } else if (!strcmp(argv[0], "picture")) {
3006     fprintf(stdout, _("Sending picture image.\n"));
3007   } else if (!strcmp(argv[0], "screensaver")) {
3008     fprintf(stdout, _("Sending screen saver.\n"));
3009   } else if (!strcmp(argv[0], "startup")) {
3010     fprintf(stderr, _("It isn't possible to send startup logo!\n"));
3011     return (-1);
3012   } else if (!strcmp(argv[0], "7110startup")) {
3013     fprintf(stderr, _("It isn't possible to send startup logo!\n"));
3014     return (-1);
3015   } else if (!strcmp(argv[0], "6210startup")) {
3016     fprintf(stderr, _("It isn't possible to send startup logo!\n"));
3017     return (-1);
3018   } else if (!strcmp(argv[0], "7110op")) {
3019     fprintf(stderr, _("It isn't possible to send big operator logos!\n"));
3020     return (-1);
3021   } else {
3022     fprintf(stderr, _("You should specify what kind of logo to send!\n"));
3023     return (-1);
3024   }
3025
3026   /* The third argument is the bitmap file. */
3027   if (GSM_ReadBitmapFileOnConsole(argv[2], &bitmap)!=GE_NONE) return -1;
3028
3029   /* Initialise the GSM interface. */
3030   fbusinit(NULL);
3031
3032   optind = 3;
3033
3034   if (!strcmp(argv[0], "op")) {
3035     GSM_ResizeBitmap(&bitmap,GSM_CallerLogo);
3036   
3037     /* The third argument, if present, is the Network code of the operator.
3038      * Network code is in this format: "xxx yy" */
3039     if (argc > 3) {
3040       strcpy(bitmap.netcode, argv[3]);
3041 #ifdef DEBUG
3042       fprintf(stdout, _("Operator code: %s\n"), argv[3]);
3043 #endif
3044       if (!strcmp(GSM_GetNetworkName(bitmap.netcode),"unknown")) {
3045         fprintf(stderr,"Sorry, gnokii doesn't know \"%s\" network !\n",bitmap.netcode);
3046         GSM->Terminate();
3047         return -1;
3048       }
3049       optind++;
3050     } else
3051     {
3052       if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE) strncpy(bitmap.netcode,NetworkInfo.NetworkCode,7);
3053     }
3054     bitmap.type=GSM_OperatorLogo;
3055   }
3056   if (!strcmp(argv[0], "caller")) {
3057     GSM_ResizeBitmap(&bitmap,GSM_CallerLogo);
3058   
3059     bitmap.type=GSM_CallerLogo;
3060   }
3061   if (!strcmp(argv[0], "screensaver")) {
3062     GSM_ResizeBitmap(&bitmap,GSM_PictureImage);
3063
3064     bitmap.text[0]=0;
3065
3066     for(i=0;i<argc;i++)
3067       if (!strcmp(argv[i],"--unicode")) UnicodeText=true;
3068     
3069     ScreenSaver=true;
3070   }
3071   if (!strcmp(argv[0], "picture")) {  
3072     GSM_ResizeBitmap(&bitmap,GSM_PictureImage);
3073
3074     for(i=0;i<argc;i++)
3075       if (!strcmp(argv[i],"--unicode")) UnicodeText=true;
3076
3077     bitmap.text[0]=0;
3078     if (argc>3) {
3079       optind++;
3080       if (strlen(argv[3])>121) {
3081         fprintf(stdout,_("Sorry: length of text (parameter \"%s\") can be 121 chars or shorter only !\n"),argv[3]);
3082         return -1;
3083       }
3084       strcpy(bitmap.text,argv[3]);
3085     }
3086   }
3087
3088   /* Put bitmap into SMS structure */
3089   GSM_SaveBitmapToSMS(&MultiSMS,&bitmap,ScreenSaver,UnicodeText);
3090
3091   /* The second argument is the destination, ie the phone number of recipient. */
3092   for(i=0;i<MultiSMS.number;i++)
3093     strcpy(MultiSMS.SMS[i].Destination,argv[1]);
3094
3095   GSM_SendMultiPartSMSOnConsole(&MultiSMS, optind,argc,argv,true,false,false);
3096
3097   return i;
3098 }
3099
3100 /* Getting logos. */
3101
3102 int getlogo(int argc, char *argv[])
3103 {
3104   GSM_Bitmap bitmap;
3105   GSM_Error error;
3106   int num;
3107
3108   bitmap.type=GSM_None;
3109
3110   if (!strcmp(argv[0],"7110op"))
3111     bitmap.type=GSM_7110OperatorLogo;
3112     
3113   if (!strcmp(argv[0],"op"))
3114     bitmap.type=GSM_OperatorLogo;
3115     
3116   if (!strcmp(argv[0],"caller")) {
3117     /* There is caller group number missing in argument list. */
3118     if (argc==3) {     
3119       num=argv[2][0]-'0';
3120       if ((num<1)||(num>9)) num=1;
3121       bitmap.number=num;
3122     } else
3123     {
3124       bitmap.number=1;
3125     }
3126     bitmap.number--;
3127     bitmap.type=GSM_CallerLogo;
3128   }
3129
3130   if (!strcmp(argv[0],"picture")) {
3131     /* There is a number missing in argument list. */
3132     if (argc==3) {     
3133       if (strlen(argv[2])==2) {
3134         num=(argv[2][0]-'0')*10+(argv[2][1]-'0');
3135       } else {
3136         num=argv[2][0]-'0';
3137       }
3138       if (num<1) num=1;
3139       bitmap.number=num;
3140     } else
3141     {
3142       bitmap.number=1;
3143     }
3144     bitmap.number--;
3145     bitmap.type=GSM_PictureImage;
3146   }    
3147
3148   if (!strcmp(argv[0],"startup"))
3149     bitmap.type=GSM_StartupLogo;
3150
3151   if (!strcmp(argv[0],"7110startup"))
3152     bitmap.type=GSM_7110StartupLogo;
3153
3154   if (!strcmp(argv[0],"6210startup"))
3155     bitmap.type=GSM_6210StartupLogo;
3156     
3157   if (!strcmp(argv[0],"dealer"))
3158     bitmap.type=GSM_DealerNoteText;  
3159     
3160   if (!strcmp(argv[0],"text"))
3161     bitmap.type=GSM_WelcomeNoteText;  
3162
3163   if (bitmap.type!=GSM_None) {
3164   
3165     fbusinit(NULL);
3166     
3167     fprintf(stdout, _("Getting Logo\n"));
3168         
3169     error=GSM->GetBitmap(&bitmap);
3170
3171     GSM->Terminate();
3172     
3173     switch (error)
3174     {
3175       case GE_NONE:
3176         if (bitmap.type==GSM_DealerNoteText) fprintf(stdout, _("Dealer welcome note "));
3177         if (bitmap.type==GSM_WelcomeNoteText) fprintf(stdout, _("Welcome note "));      
3178         if (bitmap.type==GSM_DealerNoteText || bitmap.type==GSM_WelcomeNoteText)
3179         {
3180           if (bitmap.text[0]!=0)
3181           {
3182             fprintf(stdout, _("currently set to \"%s\"\n"), bitmap.text);
3183           } else {
3184             fprintf(stdout, _("currently empty\n"));
3185           }
3186         } else
3187         {
3188           if (bitmap.width!=0)
3189           {
3190             if (bitmap.type==GSM_OperatorLogo || bitmap.type==GSM_7110OperatorLogo)
3191             {
3192               fprintf(stdout,"Operator logo for %s (%s) network got succesfully\n",bitmap.netcode,GSM_GetNetworkName(bitmap.netcode));
3193             }
3194             if (bitmap.type==GSM_StartupLogo || bitmap.type==GSM_7110StartupLogo || bitmap.type==GSM_6210StartupLogo)
3195             {
3196               fprintf(stdout,"Startup logo got successfully\n");
3197             }
3198             if (bitmap.type==GSM_CallerLogo)
3199             {
3200               fprintf(stdout,"Caller logo got successfully\n");
3201             }
3202             if (bitmap.type==GSM_PictureImage)
3203             {
3204               fprintf(stdout,"Picture Image got successfully");
3205               if (strcmp(bitmap.text,""))
3206                 fprintf(stdout,_(", text \"%s\""),bitmap.text);         
3207               if (strcmp(bitmap.Sender,""))
3208                 fprintf(stdout,_(", sender \"%s\""),bitmap.Sender);             
3209               fprintf(stdout,"\n");
3210             }
3211             if (argc>1)
3212             {
3213               if (GSM_SaveBitmapFileOnConsole(argv[1], &bitmap)!=GE_NONE) return(-1);
3214             }
3215           } else
3216           {
3217             fprintf(stdout,"Your phone doesn't have logo uploaded !\n");
3218             return -1;
3219           }
3220         }
3221         break;
3222       case GE_NOTIMPLEMENTED:
3223         fprintf(stderr, _("Function not implemented !\n"));
3224         return -1;
3225       case GE_NOTSUPPORTED:
3226         fprintf(stderr, _("This kind of logo is not supported !\n"));
3227         return -1;
3228       default:
3229         fprintf(stderr, _("Error getting logo (wrong location ?) !\n"));
3230         return -1;
3231     }
3232   } else
3233   {
3234     fprintf(stderr, _("What kind of logo do you want to get ?\n"));
3235     return -1;
3236   }
3237
3238   return 0;
3239 }
3240
3241 /* Setting logos. */
3242
3243 int setlogo(int argc, char *argv[])
3244 {
3245
3246   GSM_Bitmap bitmap,oldbit;
3247   GSM_NetworkInfo NetworkInfo;
3248   GSM_Error error;
3249   char model[64];
3250   int num;
3251   
3252   bool ok=true;
3253   
3254   int i;
3255   
3256   fbusinit(NULL);
3257   
3258   if (!strcmp(argv[0],"text") || !strcmp(argv[0],"dealer"))
3259   {
3260     if (!strcmp(argv[0],"text")) bitmap.type=GSM_WelcomeNoteText;
3261                             else bitmap.type=GSM_DealerNoteText;
3262     bitmap.text[0]=0x00;
3263     if (argc>1) strncpy(bitmap.text,argv[1],255);
3264   } else
3265   {
3266     if (!strcmp(argv[0],"op") || !strcmp(argv[0],"startup") || !strcmp(argv[0],"caller") ||
3267         !strcmp(argv[0],"7110op") || !strcmp(argv[0],"6210startup") || !strcmp(argv[0],"7110startup") ||
3268         !strcmp(argv[0],"picture"))
3269     {
3270       if (argc>1)
3271       {
3272         if (!strcmp(argv[0],"startup"))
3273         {
3274           bitmap.type=GSM_StartupLogo;
3275           bitmap.width=84;
3276           bitmap.height=48;
3277           bitmap.size=bitmap.width*bitmap.height/8;
3278           num=argv[1][0]-'0';
3279           if (num>=1 && num<=3) {
3280             bitmap.number=num;
3281           } else {
3282             if (GSM_ReadBitmapFileOnConsole(argv[1], &bitmap)!=GE_NONE) {
3283               GSM->Terminate();
3284               return(-1);
3285             }
3286             bitmap.number=0;
3287             GSM_ResizeBitmap(&bitmap,GSM_StartupLogo);
3288           }
3289         } else {
3290           if (GSM_ReadBitmapFileOnConsole(argv[1], &bitmap)!=GE_NONE) {
3291             GSM->Terminate();
3292             return(-1);
3293           }
3294         }
3295         if (!strcmp(argv[0],"op"))
3296         {
3297           if (bitmap.type!=GSM_OperatorLogo || argc<3)
3298           {
3299             if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE) strncpy(bitmap.netcode,NetworkInfo.NetworkCode,7);
3300           }
3301           GSM_ResizeBitmap(&bitmap,GSM_OperatorLogo);
3302           if (argc==3)
3303           {
3304             strncpy(bitmap.netcode,argv[2],7);
3305             if (!strcmp(GSM_GetNetworkName(bitmap.netcode),"unknown"))
3306             {
3307               fprintf(stderr,"Sorry, gnokii doesn't know \"%s\" network !\n",bitmap.netcode);
3308               return -1;
3309             }
3310           }
3311         }
3312         if (!strcmp(argv[0],"7110op"))
3313         {
3314           if (bitmap.type!=GSM_7110OperatorLogo || argc<3)
3315           {
3316             if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE) strncpy(bitmap.netcode,NetworkInfo.NetworkCode,7);
3317           }
3318           GSM_ResizeBitmap(&bitmap,GSM_7110OperatorLogo);
3319           if (argc==3)
3320           {
3321             strncpy(bitmap.netcode,argv[2],7);
3322             if (!strcmp(GSM_GetNetworkName(bitmap.netcode),"unknown"))
3323             {
3324               fprintf(stderr,"Sorry, gnokii doesn't know \"%s\" network !\n",bitmap.netcode);
3325               return -1;
3326             }
3327           }
3328         }
3329         if (!strcmp(argv[0],"picture"))
3330         {
3331           GSM_ResizeBitmap(&bitmap,GSM_PictureImage);
3332           bitmap.number=1;
3333           if (argc>2)
3334           {
3335             if (strlen(argv[2])==2) {
3336               num=(argv[2][0]-'0')*10+(argv[2][1]-'0');
3337             } else {
3338               num=argv[2][0]-'0';
3339             }
3340             if (num<1) num=1;   
3341             bitmap.number=num;
3342           }
3343           bitmap.number--;
3344           bitmap.text[0]=0;
3345           if (argc>3)
3346             strncpy(bitmap.text,argv[3],121);
3347           strcpy(bitmap.Sender,"\0");
3348           if (argc>4)
3349             strncpy(bitmap.Sender,argv[4],GSM_MAX_SENDER_LENGTH);
3350         }
3351         if (!strcmp(argv[0],"7110startup"))
3352         {
3353           GSM_ResizeBitmap(&bitmap,GSM_7110StartupLogo);
3354         }
3355         if (!strcmp(argv[0],"6210startup"))
3356         {
3357           GSM_ResizeBitmap(&bitmap,GSM_6210StartupLogo);
3358         }
3359         if (!strcmp(argv[0],"caller"))
3360         {
3361           GSM_ResizeBitmap(&bitmap,GSM_CallerLogo);
3362           if (argc>2)
3363           {
3364             num=argv[2][0]-'0';
3365             if ((num<0)||(num>9)) num=0;
3366             bitmap.number=num;
3367           } else
3368           {
3369             bitmap.number=0;
3370           }
3371           oldbit.type=GSM_CallerLogo;
3372           oldbit.number=bitmap.number;
3373           if (GSM->GetBitmap(&oldbit)==GE_NONE)
3374           {
3375             /* We have to get the old name and ringtone!! */
3376             bitmap.ringtone=oldbit.ringtone;
3377             strncpy(bitmap.text,oldbit.text,255);
3378           }
3379           if (argc>3) strncpy(bitmap.text,argv[3],255);   
3380         }
3381         fprintf(stdout, _("Setting Logo.\n"));
3382       } else
3383       {
3384         /* FIX ME: is it possible to permanently remove op logo ? */
3385         if (!strcmp(argv[0],"op"))
3386         {
3387           bitmap.type=GSM_OperatorLogo;
3388           strncpy(bitmap.netcode,"000 00",7);
3389           bitmap.width=72;
3390           bitmap.height=14;
3391           bitmap.size=bitmap.width*bitmap.height/8;
3392           GSM_ClearBitmap(&bitmap);
3393         }
3394         if (!strcmp(argv[0],"7110op"))
3395         {
3396           bitmap.type=GSM_7110OperatorLogo;
3397           strncpy(bitmap.netcode,"000 00",7);
3398           bitmap.width=78;
3399           bitmap.height=21;
3400           bitmap.size=(bitmap.width*bitmap.height + 7)/8;
3401           GSM_ClearBitmap(&bitmap);
3402         }
3403         /* FIX ME: how to remove startup and group logos ? */
3404         fprintf(stdout, _("Removing Logo.\n"));
3405       }  
3406     } else
3407     {
3408       fprintf(stderr, _("What kind of logo do you want to set ?\n"));
3409       GSM->Terminate();
3410       return -1;
3411     }
3412   }
3413     
3414   while (GSM->GetModel(model)  != GE_NONE)
3415     sleep(1);
3416   
3417   /* For Nokia 6110/6130/6150 we use different method of uploading.
3418      Phone will display menu, when received it */
3419   if (!strcmp(model,"NSE-3") || !strcmp(model,"NSK-3") || !strcmp(model,"NSM-1"))
3420   {
3421     if (!strcmp(argv[0],"caller") && argc<3)
3422       bitmap.number=255;
3423     if (!strcmp(argv[0],"op") && argc<3)
3424       bitmap.number=255;
3425   }
3426
3427   error=GSM->SetBitmap(&bitmap);
3428   
3429   switch (error)
3430   {
3431     case GE_NONE: oldbit.type=bitmap.type;
3432                   oldbit.number=bitmap.number;
3433                   if (GSM->GetBitmap(&oldbit)==GE_NONE) {
3434                     if (bitmap.type==GSM_WelcomeNoteText ||
3435                         bitmap.type==GSM_DealerNoteText) {
3436                       if (strcmp(bitmap.text,oldbit.text)) {
3437                         fprintf(stderr, _("Error setting"));
3438                         if (bitmap.type==GSM_DealerNoteText) fprintf(stderr, _(" dealer"));
3439                         fprintf(stderr, _(" welcome note - "));
3440
3441                         /* I know, it looks horrible, but... */
3442                         /* I set it to the short string - if it won't be set */
3443                         /* it means, PIN is required. If it will be correct, previous */
3444                         /* (user) text was too long */
3445
3446                         /* Without it, I could have such thing: */
3447                         /* user set text to very short string (for example, "Marcin") */
3448                         /* then enable phone without PIN and try to set it to the very long (too long for phone) */
3449                         /* string (which start with "Marcin"). If we compare them as only length different, we could think, */
3450                         /* that phone accepts strings 6 chars length only (length of "Marcin") */
3451                         /* When we make it correct, we don't have this mistake */
3452                         
3453                         strcpy(oldbit.text,"!\0");
3454                         GSM->SetBitmap(&oldbit);
3455                         GSM->GetBitmap(&oldbit);
3456                         if (oldbit.text[0]!='!') {
3457                           fprintf(stderr, _("SIM card and PIN is required\n"));
3458                         } else {
3459                           GSM->SetBitmap(&bitmap);
3460                           GSM->GetBitmap(&oldbit);
3461                           fprintf(stderr, _("too long, truncated to \"%s\" (length %ld)\n"),oldbit.text,(long)strlen(oldbit.text));
3462                         }
3463                         ok=false;
3464                       }
3465                     } else {
3466                       if (bitmap.type==GSM_StartupLogo) {
3467                         for (i=0;i<oldbit.size;i++) {
3468                           if (oldbit.bitmap[i]!=bitmap.bitmap[i]) {
3469                             fprintf(stderr, _("Error setting startup logo - SIM card and PIN is required\n"));
3470                             ok=false;
3471                             break;
3472                           }
3473                         }
3474                       }
3475                     }
3476                   }
3477                   if (ok) fprintf(stdout, _("Done.\n"));
3478                   break;
3479     case GE_NOTIMPLEMENTED:fprintf(stderr, _("Function not implemented.\n"));
3480                            break;
3481     case GE_NOTSUPPORTED:fprintf(stderr, _("This kind of logo is not supported.\n"));
3482                            break;
3483     default:fprintf(stderr, _("Error (wrong location ?) !\n"));
3484             break;
3485   }
3486   
3487   GSM->Terminate();
3488
3489   return 0;
3490 }
3491
3492 /* Calendar notes receiving. */
3493
3494 int getcalendarnote(int argc, char *argv[])
3495 {
3496   GSM_CalendarNote CalendarNote;
3497   GSM_NotesInfo NotesInfo;
3498   GSM_Error error;
3499   int i;
3500   int vCalVer=0;
3501   bool vInfo=false;
3502   int start, stop;
3503   bool was_note=false;
3504   char z_text[MAX_CALENDAR_TEXT_LENGTH+11];
3505
3506   /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */
3507   char model[64];
3508
3509   struct tm *now;
3510   time_t nowh;
3511   GSM_DateTime Date;
3512
3513   nowh=time(NULL);
3514   now=localtime(&nowh);
3515   
3516   Date.Year = now->tm_year;
3517
3518   /* I have 100 (for 2000) Year now :-) */
3519   if (Date.Year>99 && Date.Year<1900) {
3520     Date.Year=Date.Year+1900;
3521   }
3522
3523   start=atoi(argv[0]);  
3524   stop=start;
3525   
3526   switch (argc) {
3527     case 2:
3528       if (!strcmp(argv[argc-1],"-v10")) {
3529         vCalVer=10;
3530       } else {
3531         if (!strcmp(argv[argc-1],"-v30")) {
3532           vCalVer=30;
3533         } else {
3534           stop=atoi(argv[1]);
3535         }
3536       }
3537       break;
3538     case 3:
3539       stop=atoi(argv[1]);
3540       if (!strcmp(argv[argc-1],"-v10")) {
3541         vCalVer=10;
3542       } else {
3543         if (!strcmp(argv[argc-1],"-v30")) {
3544           vCalVer=30;
3545         } else {      
3546           usage();
3547           return -1;
3548         }
3549       }
3550       break;
3551   }
3552
3553   fbusinit(NULL);
3554
3555   while (GSM->GetModel(model)  != GE_NONE)
3556     sleep(1);
3557
3558   if (!strcmp(argv[0],"-s") || !strcmp(argv[0],"--short")) 
3559     vInfo=true;
3560   else if (!isdigit(argv[0][0])) {
3561     usage();
3562     return -1;
3563   }
3564     
3565   error=GSM->GetCalendarNotesInfo(&NotesInfo);
3566   if ( error == GE_NONE ) {
3567      if( NotesInfo.HowMany == 0 ) {
3568          fprintf(stderr, _("Sorry! No Calendar Notes present on phone.\n"));
3569          start=0; stop=(-1); /* This for skipping next 'for' loop ;-> */
3570       }
3571 #ifdef DEBUG
3572       fprintf(stdout, _(" CALENDAR NOTES INFO \n"));
3573       fprintf(stdout, _("---------------------\n"));
3574       fprintf(stdout, _("How Many Locations :%d\n"), NotesInfo.HowMany);
3575
3576       /* For 6210 (NPE-3) and 7110 (NSE-5), Locations have a different behaviour */
3577       if ( GetModelFeature (FN_CALENDAR)==F_CAL71 ) {
3578         fprintf(stdout, _("Locations are :\n"));
3579         for(i=0;i<NotesInfo.HowMany;i++)
3580             fprintf(stdout, _("%4d) %4d\n"), i+1, NotesInfo.Location[i]);
3581       }
3582 #endif
3583   } else {
3584       /* For 6210 (NPE-3) and 7110 (NSE-5), Locations have a different behaviour */
3585       if ( GetModelFeature (FN_CALENDAR)==F_CAL71 ) {
3586         fprintf(stderr, _("Can't read Notes Infos from phone.\n"));
3587         start=0; stop=(-1); /* This for skipping next 'for' loop ;-> */
3588       }
3589   }
3590
3591   if (GetModelFeature (FN_CALENDAR)!=F_CAL71) {
3592     error=GE_NONE;
3593     NotesInfo.HowMany=200;
3594     for (i=0;i<200;i++) {
3595       NotesInfo.Location[i]=i+1;
3596     }
3597   }
3598   
3599   if( vInfo && stop!=(-1) && error==GE_NONE )
3600   {
3601     /* Info datas (for 7110 and comp.) */
3602     fprintf(stdout, _(" CALENDAR NOTES SUMMARY INFORMATION \n"));
3603     fprintf(stdout, _(" ==================================\n"));
3604     if (GetModelFeature (FN_CALENDAR)==F_CAL71) {
3605       fprintf(stdout, _("Calendar notes present on phone: %d\n"), NotesInfo.HowMany);
3606       fprintf(stdout, _("Locations are :\n"));
3607     }
3608     fprintf(stdout,  "----------------------------------------------------------------------------\n");
3609     fprintf(stdout,_(" Loc Phys Type    Summary description              Dt start    Alarm  Recurs\n") );
3610     fprintf(stdout,  "----------------------------------------------------------------------------\n");
3611
3612     for(i=0;i<NotesInfo.HowMany;i++)
3613     {
3614       /* very short format ... */
3615       /*
3616       fprintf(stdout, _("%4d) %4d\n"), i, NotesInfo.Location[i]);
3617       */
3618       CalendarNote.Location=i+1;
3619       CalendarNote.ReadNotesInfo=false;
3620
3621       if (GSM->GetCalendarNote(&CalendarNote) == GE_NONE) {
3622         char z_type[11];
3623         char z_recur[15];
3624         switch (CalendarNote.Type) {
3625            case GCN_REMINDER:strcpy(z_type, "REMIND");  break;
3626            case GCN_CALL:    strcpy(z_type, "CALL");    break;
3627            case GCN_MEETING: strcpy(z_type, "MEETING"); break;
3628            case GCN_BIRTHDAY:strcpy(z_type, "BDAY");    break;
3629            default:          strcpy(z_type, "UNKNOWN"); break;
3630           }
3631
3632         if( CalendarNote.Recurrance ) {
3633           sprintf( z_recur,"%d ", CalendarNote.Recurrance/24 );
3634           strcat( z_recur, CalendarNote.Recurrance == 1 ? "day" : "days" );
3635         }
3636         else
3637           strcpy( z_recur, "No" );
3638
3639         strcpy(z_text,"");
3640         
3641         if( CalendarNote.Type == GCN_CALL )
3642           sprintf(z_text, "\"%s\"", CalendarNote.Phone );
3643           
3644         if (CalendarNote.Text[0]!=0)
3645           sprintf(z_text, "\"%s\"", CalendarNote.Text );
3646           
3647         if(CalendarNote.Type == GCN_BIRTHDAY) {
3648           int i_age;
3649           i_age = Date.Year - CalendarNote.Time.Year;
3650           sprintf(z_text, "\"%s (%d %s)\"", CalendarNote.Text,
3651              i_age, (i_age==1)?"year":"years");
3652           strcpy( z_recur, "-" );
3653           if (GetModelFeature (FN_CALENDAR)==F_CAL71)
3654             fprintf(stdout,
3655                 _("%4d %4d %-7.7s %-32.32s %04d-%02d-%02d  %s %s\n"), 
3656               i+1,NotesInfo.Location[i], z_type, z_text,
3657               CalendarNote.Time.Year, 
3658               CalendarNote.Time.Month, 
3659               CalendarNote.Time.Day,
3660               (CalendarNote.AlarmType==0x00) ? "Tone  " : "Silent",
3661               " " );
3662           else
3663             fprintf(stdout,
3664                 _("%4d %4d %-7.7s %-32.32s %04d-%02d-%02d  %s %s\n"), 
3665               i+1,NotesInfo.Location[i], z_type, z_text,
3666               CalendarNote.Time.Year, 
3667               CalendarNote.Time.Month, 
3668               CalendarNote.Time.Day,
3669               (CalendarNote.Alarm.Year) ? "Yes" : "No ",
3670               " " );
3671         } else
3672           if (GetModelFeature (FN_CALENDAR)==F_CAL71)
3673             fprintf(stdout,
3674                 _("%4d %4d %-7.7s %-32.32s %04d-%02d-%02d  %s    %s\n"), 
3675               i+1,NotesInfo.Location[i], z_type, z_text,
3676               CalendarNote.Time.Year, 
3677               CalendarNote.Time.Month, 
3678               CalendarNote.Time.Day,
3679               (CalendarNote.Alarm.Year) ? "Yes" : "No ",
3680               z_recur );
3681            else
3682             fprintf(stdout,
3683                 _("%4d %4d %-7.7s %-32.32s %04d-%02d-%02d  %s\n"), 
3684               i+1,NotesInfo.Location[i], z_type, z_text,
3685               CalendarNote.Time.Year, 
3686               CalendarNote.Time.Month, 
3687               CalendarNote.Time.Day,
3688               (CalendarNote.Alarm.Year) ? "Yes" : "No ");
3689       } else {
3690         if (GetModelFeature (FN_CALENDAR)!=F_CAL71) break;
3691       }
3692     }
3693   }
3694   else
3695   for (i=start;i<=stop;i++) {
3696     if (error==GE_NONE) {
3697         if( i>NotesInfo.HowMany ) {
3698             fprintf(stderr, _("Only %d Calendar Notes present on phone!\n"),NotesInfo.HowMany);
3699             break;
3700         }
3701         if( i==0 ) {
3702             fprintf(stderr, _("Calendar Notes location can't be zero... skipping.\n"));
3703             continue;
3704         }
3705     }
3706     
3707     CalendarNote.Location=i;
3708     CalendarNote.ReadNotesInfo=false;
3709
3710     if (GSM->GetCalendarNote(&CalendarNote) == GE_NONE) {
3711
3712       if (vCalVer!=0) {
3713         if (!was_note) {
3714           fprintf(stdout, GSM_GetVCALENDARStart(vCalVer));
3715           was_note=true;
3716         }
3717
3718        &