http://marcin-wiacek.fkn.pl/english/zips/mygnokii.tar.gz
[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 <stdio.h>
15 #include <stdlib.h>
16 #include <signal.h>
17 #include <string.h>
18 #include <ctype.h>
19 #include <time.h>
20 #include <sys/stat.h>
21
22 #ifndef VC6
23   #if defined(__svr4__) || defined(__FreeBSD__)
24   #  include <strings.h>        /* for bzero */
25   #endif
26 #else
27   /* for VC6 make scripts save VERSION constant in mversion.h file */
28   #include "mversion.h"
29 #endif
30
31 #ifdef WIN32
32
33   #include <windows.h>
34
35   #include "misc_win32.h"
36   #include "getopt.h"
37
38   #define DEV_CONSOLE "CON:"
39
40 #else
41
42   #include <unistd.h>
43   #include <termios.h>
44   #include <fcntl.h>
45   #include <sys/types.h>
46   #include <sys/time.h>
47   #include <getopt.h>
48
49   #define DEV_CONSOLE "/dev/tty"
50 #endif
51
52 #include "misc.h"
53 #include "gsm-common.h"
54 #include "gsm-api.h"
55 #include "gsm-networks.h"
56 #include "gsm-ringtones.h"
57 #include "gsm-bitmaps.h"
58 #include "gsm-wap.h"
59 #include "gsm-sms.h"
60 #include "gsm-datetime.h"
61 #include "gsm-phonebook.h"
62 #include "gsm-calendar.h"
63 #include "gsm-coding.h"
64 #include "newmodules/n6110.h"
65 #include "files/cfgreader.h"
66 #include "files/gsm-filetypes.h"
67 #include "gnokii.h"
68
69 #ifdef USE_NLS
70   #include <locale.h>
71 #endif
72
73 char *model;           /* Model from .gnokiirc file. */
74 char *Port;            /* Port from .gnokiirc file */
75 char *Initlength;      /* Init length from .gnokiirc file */
76 char *Connection;      /* Connection type from .gnokiirc file */
77 char *SynchronizeTime; /* If we set date and time from computer to phone (from .gnokiirc file) */
78 char *BinDir;          /* Binaries directory from .gnokiirc file - not used here yet */
79
80 GSM_SMSMessage SMS[4];
81   
82 char *GetProfileCallAlertString(int code) {
83
84   switch (code) {
85     case PROFILE_CALLALERT_RINGING     : return "Ringing";
86     case PROFILE_CALLALERT_ASCENDING   : return "Ascending";
87     case PROFILE_CALLALERT_RINGONCE    : return "Ring once";
88     case PROFILE_CALLALERT_BEEPONCE    : return "Beep once";
89     case PROFILE_CALLALERT_CALLERGROUPS: return "Caller groups";
90     case PROFILE_CALLALERT_OFF         : return "Off";
91     default                            : return "Unknown";
92   }
93 }
94
95 char *GetProfileVolumeString(int code) {
96
97   switch (code) {
98     case PROFILE_VOLUME_LEVEL1 : return "Level 1";
99     case PROFILE_VOLUME_LEVEL2 : return "Level 2";
100     case PROFILE_VOLUME_LEVEL3 : return "Level 3";
101     case PROFILE_VOLUME_LEVEL4 : return "Level 4";
102     case PROFILE_VOLUME_LEVEL5 : return "Level 5";
103     default                    : return "Unknown";
104   }
105 }
106
107 char *GetProfileKeypadToneString(int code) {
108
109   switch (code) {
110     case PROFILE_KEYPAD_OFF    : return "Off";
111     case PROFILE_KEYPAD_LEVEL1 : return "Level 1";
112     case PROFILE_KEYPAD_LEVEL2 : return "Level 2";
113     case PROFILE_KEYPAD_LEVEL3 : return "Level 3";
114     default                    : return "Unknown";
115   }
116 }
117
118 char *GetProfileMessageToneString(int code) {
119
120   switch (code) {
121     case PROFILE_MESSAGE_NOTONE    : return "No tone";
122     case PROFILE_MESSAGE_STANDARD  : return "Standard";
123     case PROFILE_MESSAGE_SPECIAL   : return "Special";
124     case PROFILE_MESSAGE_BEEPONCE  : return "Beep once";
125     case PROFILE_MESSAGE_ASCENDING : return "Ascending";
126     default                        : return "Unknown";
127   }
128 }
129
130 char *GetProfileWarningToneString(int code) {
131
132   switch (code) {
133     case PROFILE_WARNING_OFF : return "Off";
134     case PROFILE_WARNING_ON  : return "On";
135     default                  : return "Unknown";
136   }
137 }
138
139 char *GetProfileOnOffString(int code) {
140
141   switch (code) {
142     case 0x00 : return "Off";
143     case 0x01 : return "On";
144     default   : return "Unknown";
145   }
146 }
147
148 static char *GetProfileVibrationString(int code)
149 {
150         switch (code) {
151         case PROFILE_VIBRATION_OFF:     return "Off";
152         case PROFILE_VIBRATION_ON:      return "On";
153         case PROFILE_VIBRATION_FIRST:   return "Vibrate first";
154         default:                        return "Unknown";
155         }
156 }
157
158 char BufferProfileGroups[90];
159
160 char *GetProfileCallerGroups(int code) 
161 {
162   static char az_group_name[5][MAX_BITMAP_TEXT_LENGTH];
163   static bool enteronce=false;
164   register int i;
165   GSM_Bitmap bitmap;
166
167   if( code == PROFILE_CALLERGROUPS_ALL )
168        return _("All calls alert");
169
170   if( !enteronce ) {
171     for(i=0;i<5;i++) az_group_name[i][0]='\0';
172     enteronce=true;
173   }
174
175   BufferProfileGroups[0]=0;
176     
177   for(i=0;i<5;i++)
178   {
179     int code2test;
180     char z_gtype[12];
181
182     code2test=(i==0) ? 1 : 2<<(i-1);
183
184     if( code & code2test )
185     {
186       if (!strcmp(az_group_name[i],"")) 
187       {
188         if (GetModelFeature (FN_CALLERGROUPS)!=0) {
189           bitmap.type=GSM_CallerLogo;
190           bitmap.number=i;
191           strcpy(z_gtype,_("unknown"));
192           if (GSM->GetBitmap(&bitmap)==GE_NONE)
193             strcpy( az_group_name[i], bitmap.text );
194         }
195         if ((!strcmp(az_group_name[i],""))) {
196             switch(i) {
197             case 0:strcpy(az_group_name[i],_("Family"));break;
198             case 1:strcpy(az_group_name[i],_("VIP"));break;
199             case 2:strcpy(az_group_name[i],_("Friends"));break;
200             case 3:strcpy(az_group_name[i],_("Colleagues"));break;
201             case 4:strcpy(az_group_name[i],_("Other"));break;
202             default:break;
203           }
204         }
205       }
206       strcpy(z_gtype,az_group_name[i]);
207
208       if( strlen(BufferProfileGroups) ) strcat(BufferProfileGroups,"+");
209       strcat(BufferProfileGroups, z_gtype);
210     }
211     
212   }
213
214   return BufferProfileGroups;
215 }
216
217 char *print_error(GSM_Error e)
218 {
219
220 //      case GE_DEVICEOPENFAILED:         return "Couldn't open specified serial device.";
221 //      case GE_UNKNOWNMODEL:             return "Model specified isn't known/supported.";
222 //      case GE_NOLINK:                   return "Couldn't establish link with phone.";
223 //      case GE_TRYAGAIN:                 return "Try again.";
224 //      case GE_INVALIDSMSLOCATION:       return "Invalid SMS location.";
225 //      case GE_INVALIDPHBOOKLOCATION:    return "Invalid phonebook location.";
226 //      case GE_INVALIDMEMORYTYPE:        return "Invalid type of memory.";
227 //      case GE_INVALIDSPEEDDIALLOCATION: return "Invalid speed dial location.";
228 //      case GE_INVALIDCALNOTELOCATION:   return "Invalid calendar note location.";
229 //      case GE_INVALIDDATETIME:          return "Invalid date, time or alarm specification.";
230 //      case GE_EMPTYSMSLOCATION:         return "SMS location is empty.";
231 //      case GE_PHBOOKNAMETOOLONG:        return "Phonebook name is too long.";
232 //      case GE_PHBOOKNUMBERTOOLONG:      return "Phonebook number is too long.";
233 //      case GE_PHBOOKWRITEFAILED:        return "Phonebook write failed.";
234 //      case GE_SMSSENDOK:                return "SMS was send correctly.";
235 //      case GE_SMSSENDFAILED:            return "SMS send fail.";
236 //      case GE_SMSTOOLONG:               return "SMS message too long.";
237 //      case GE_NONEWCBRECEIVED:          return "Attempt to read CB when no new CB received";
238 //      case GE_INTERNALERROR:            return "Problem occured internal to model specific code.";
239 //      case GE_NOTSUPPORTED:             return "Function not supported by the phone";
240 //      case GE_BUSY:                     return "Command is still being executed.";
241 //      case GE_USERCANCELED:             return "User has cancelled the action.";   
242 //      case GE_UNKNOWN:                  return "Unknown error - well better than nothing!!";
243 //      case GE_MEMORYFULL:               return "Memory is full";
244 //      case GE_LINEBUSY:                 return "Outgoing call requested reported line busy";
245 //      case GE_NOCARRIER:                return "No Carrier error during data call setup ?";
246
247         switch (e) {
248         case GE_NONE:                     return "No error, done OK";
249         case GE_INVALIDSECURITYCODE:      return "Invalid Security code.";
250         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";
251         case GE_TIMEOUT:                  return "Command timed out.";
252         case GE_CANTOPENFILE:             return "Can't open file with bitmap/ringtone";
253         case GE_SUBFORMATNOTSUPPORTED:    return "Subformat of file not supported";
254         case GE_WRONGNUMBEROFCOLORS:      return "Wrong number of colors in specified bitmap file (only 2 colors files supported)";
255         case GE_WRONGCOLORS:              return "Wrong colors in bitmap file";
256         case GE_INVALIDIMAGESIZE:         return "Invalid size of bitmap (in file, sms etc.)";
257         case GE_INVALIDFILEFORMAT:        return "Invalid format of file";
258         case GE_TOOSHORT:                 return "File too short";
259         case GE_INSIDEBOOKMARKSMENU:      return "Inside WAP Bookmarks menu. Please leave it and try again";
260         case GE_INVALIDBOOKMARKLOCATION:  return "Invalid or empty WAP bookmark location";
261         case GE_INSIDESETTINGSMENU:       return "Inside WAP Settings menu. Please leave it and try again";
262         case GE_INVALIDSETTINGSLOCATION:  return "Invalid or empty WAP settings location";
263         default:                          return "Unknown error.";
264         }
265 }
266
267
268 GSM_Error GSM_ReadRingtoneFileOnConsole(char *FileName, GSM_Ringtone *ringtone)
269 {
270   GSM_Error error;
271   
272   error=GSM_ReadRingtoneFile(FileName, ringtone);
273   
274   switch (error) {
275     case GE_CANTOPENFILE:
276     case GE_SUBFORMATNOTSUPPORTED:
277       fprintf(stderr, _("File \"%s\"\nError: %s\n"),FileName,print_error(error));
278       break;
279     default:
280       break;
281   }
282   
283   return error;
284 }
285
286 GSM_Error GSM_SaveRingtoneFileOnConsole(char *FileName, GSM_Ringtone *ringtone)
287 {
288   int confirm,confirm2;
289   char ans[4];
290   struct stat buf;
291   GSM_Error error;
292
293   /* Ask before overwriting */
294   while (stat(FileName, &buf) == 0) {
295   
296     confirm=-1;
297     confirm2=-1;
298     
299     while (confirm < 0) {
300       fprintf(stderr, _("Saving ringtone. File \"%s\" exists. (O)verwrite, create (n)ew or (s)kip ? "),FileName);
301       GetLine(stdin, ans, 4);
302       if (!strcmp(ans, "O") || !strcmp(ans, "o")) confirm = 1;
303       if (!strcmp(ans, "N") || !strcmp(ans, "n")) confirm = 2;
304       if (!strcmp(ans, "S") || !strcmp(ans, "s")) return GE_USERCANCELED;
305     }  
306     if (confirm==1) break;
307     if (confirm==2) {
308       while (confirm2 < 0) {
309         fprintf(stderr, _("Enter name of new file: "));
310         GetLine(stdin, FileName, 50);
311         if (&FileName[0]==0) return GE_USERCANCELED;
312         confirm2=1;
313       }  
314     }
315   }
316   
317   error=GSM_SaveRingtoneFile(FileName,ringtone);
318   
319   switch (error) {
320     case GE_CANTOPENFILE:        fprintf(stderr, _("Failed to write file \"%s\"\n"),FileName);
321                                  break;
322     default:                     break;
323   }
324   
325   return error;
326 }
327
328 GSM_Error GSM_ReadBitmapFileOnConsole(char *FileName, GSM_Bitmap *bitmap)
329 {
330   GSM_Error error;
331   
332   error=GSM_ReadBitmapFile(FileName, bitmap);
333
334   switch (error) {
335     case GE_CANTOPENFILE:
336     case GE_WRONGNUMBEROFCOLORS:
337     case GE_WRONGCOLORS:        
338     case GE_INVALIDFILEFORMAT:  
339     case GE_SUBFORMATNOTSUPPORTED:
340     case GE_TOOSHORT:
341     case GE_INVALIDIMAGESIZE:
342       fprintf(stderr, _("File \"%s\"\nError: %s\n"),FileName,print_error(error));
343       break;
344     default: 
345       break;
346   }
347   
348   return error;
349 }
350
351 GSM_Error GSM_SaveBitmapFileOnConsole(char *FileName, GSM_Bitmap *bitmap)
352 {
353   int confirm,confirm2;
354   char ans[4];
355   struct stat buf;
356   GSM_Error error;
357
358   /* Ask before overwriting */
359   while (stat(FileName, &buf) == 0) {
360   
361     confirm=-1;
362     confirm2=-1;
363     
364     while (confirm < 0) {
365       fprintf(stderr, _("Saving logo. File \"%s\" exists. (O)verwrite, create (n)ew or (s)kip ? "),FileName);
366       GetLine(stdin, ans, 4);
367       if (!strcmp(ans, "O") || !strcmp(ans, "o")) confirm = 1;
368       if (!strcmp(ans, "N") || !strcmp(ans, "n")) confirm = 2;
369       if (!strcmp(ans, "S") || !strcmp(ans, "s")) return GE_USERCANCELED;
370     }  
371     if (confirm==1) break;
372     if (confirm==2) {
373       while (confirm2 < 0) {
374         fprintf(stderr, _("Enter name of new file: "));
375         GetLine(stdin, FileName, 50);
376         if (&FileName[0]==0) return GE_USERCANCELED;
377         confirm2=1;
378       }  
379     }
380   }
381   
382   error=GSM_SaveBitmapFile(FileName,bitmap);
383   
384   switch (error) {
385     case GE_CANTOPENFILE:        fprintf(stderr, _("Failed to write file \"%s\"\n"),FileName);
386                                  break;
387     default:                     break;
388   }
389   
390   return error;
391 }
392
393 /* mode == 0 -> overwrite
394  * mode == 1 -> ask
395  * mode == 2 -> append
396  */
397 int GSM_SaveTextFileOnConsole(char *FileName, char *text, int mode)
398 {
399   int confirm, confirm2;
400   char ans[4];
401   struct stat buf;
402   int error;
403
404   /* Ask before overwriting */
405   if (mode==1) {
406     while (stat(FileName, &buf) == 0 && mode==1) {
407       
408       confirm=-1;
409       confirm2=-1;
410       
411       while (confirm < 0) {
412         fprintf(stderr, _("File \"%s\" exists. (O)verwrite, (a)ppend, create (n)ew or (s)kip ? "),FileName);
413         GetLine(stdin, ans, 4);
414         if (!strcmp(ans, "O") || !strcmp(ans, "o")) {
415           mode = 0;
416           confirm = 1;
417         }
418         if (!strcmp(ans, "A") || !strcmp(ans, "a")) {
419           mode = 2;
420           confirm = 1;
421         }
422         if (!strcmp(ans, "N") || !strcmp(ans, "n")) confirm=2;
423         if (!strcmp(ans, "S") || !strcmp(ans, "s")) return -1;
424       }
425       
426       if (confirm==2) {
427         while (confirm2 < 0) {
428           fprintf(stderr, _("Enter name of new file: "));
429           GetLine(stdin, FileName, 50);
430           if (&FileName[0]==0) return -1;
431           mode=1;
432           confirm2=1;
433         }  
434       }
435       
436     }  
437   }
438   
439   error=GSM_SaveTextFile(FileName, text, mode);
440   
441   switch (error) {
442     case -1: fprintf(stderr, _("Failed to write file \"%s\"\n"),  FileName);
443              break;
444     default: break;
445   }
446
447   return error;
448 }
449
450 int GSM_SendMultiPartSMSOnConsole(GSM_MultiSMSMessage *MultiSMS, int argnum, int argc, char *argv[],
451                                   bool unicode, bool profile, bool scale) {
452
453   int w,i;
454   
455   struct option options[] = {
456              { "smscno",       required_argument, NULL, '1'},
457              { "smsc",         required_argument, NULL, '2'},
458              { "name",         required_argument, NULL, '3'},
459              { "unicode",      no_argument,       NULL, '4'},
460              { "profilestyle", no_argument,       NULL, '5'},
461              { "scale",        no_argument,       NULL, '6'},
462              { NULL,           0,                 NULL,  0 }
463   };
464
465   GSM_Error error;  
466
467   for (w=0;w<MultiSMS->number;w++) {
468
469     if (argnum!=0) {
470       optarg = NULL;
471   
472       /* We check optional parameters from ... */
473       optind = argnum;
474
475       while ((i = getopt_long(argc, argv, "v:ds", options, NULL)) != -1) {
476         switch (i) {
477
478           case '1': /* SMSC number */
479             MultiSMS->SMS[w].MessageCenter.No = 0;
480             strcpy(MultiSMS->SMS[w].MessageCenter.Number,optarg);
481             break;
482
483           case '2': /* SMSC number index in phone memory */
484             MultiSMS->SMS[w].MessageCenter.No = atoi(optarg);
485
486             if (MultiSMS->SMS[w].MessageCenter.No < 1 || MultiSMS->SMS[w].MessageCenter.No > 5) {
487               fprintf(stderr, _("Incorrect SMSC number with \"smscno\" option (can't be <1 and >5) !\n"));
488               GSM->Terminate();
489               return -1;
490             }
491             break;
492
493           case '3': /* Receiver/recipient */
494             strncpy(MultiSMS->SMS[w].Destination,optarg,11); break;
495
496           case '4': /* Unicode */
497             if (unicode) break;
498
499           case '5': /* Profile */
500             if (profile) break;
501
502           case '6': /* Scale */
503             if (scale) break;
504
505           case 'v': /* Set validaty of SMS */
506             MultiSMS->SMS[w].Validity = atoi(optarg);
507             break;
508
509           case 'd': /* delivery report */
510             MultiSMS->SMS[w].Type=GST_DR;
511             break;      
512
513           case 's': /* Set replying via the same SMSC */
514             MultiSMS->SMS[w].ReplyViaSameSMSC = true; break;
515
516         default:
517           fprintf(stderr,_("Unknown option number %i\n"),argc);
518           GSM->Terminate();    
519           return -1;
520
521         }
522       }
523     }
524
525     error=GSM->SendSMSMessage(&MultiSMS->SMS[w]);
526
527     if (error == GE_SMSSENDOK) {
528       fprintf(stdout, _("SMS %i/%i sent OK !\n"),w+1,MultiSMS->number);
529     } else {
530       fprintf(stdout, _("SMS %i/%i, sending failed (error=%d)\n"),w+1,MultiSMS->number, error);
531     }
532
533   }
534
535   GSM->Terminate();  
536
537   return 0;
538 }
539
540 int GSM_SaveMultiPartSMSOnConsole(GSM_MultiSMSMessage *MultiSMS, int argnum, int argc, char *argv[],
541                                   bool inter, bool unicode, bool profile, bool scale) {
542
543   int w,i;
544   
545   GSM_SMSMessage SMSold;
546
547   struct option options[] = {
548              { "smscno",       required_argument, NULL, '1'},
549              { "smsc",         required_argument, NULL, '2'},
550              { "name",         required_argument, NULL, '3'},
551              { "unicode",      no_argument,       NULL, '4'},
552              { "profilestyle", no_argument,       NULL, '5'},
553              { "scale",        no_argument,       NULL, '6'},
554              { NULL,           0,                 NULL,  0 }
555   };
556
557   int interactive;
558   int confirm = -1;
559   char ans[8];
560
561   GSM_Error error;  
562
563   interactive = inter;
564
565   for (w=0;w<MultiSMS->number;w++) {
566
567     if (argnum!=0) {
568       optarg = NULL;
569   
570       /* We check optional parameters from ... */
571       optind = argnum;
572
573       while ((i = getopt_long(argc, argv, "risal:", options, NULL)) != -1) {
574         switch (i) {
575
576           case '1': /* SMSC number */
577             MultiSMS->SMS[w].MessageCenter.No = 0;
578             strcpy(MultiSMS->SMS[w].MessageCenter.Number,optarg);
579             break;
580
581           case '2': /* SMSC number index in phone memory */
582             MultiSMS->SMS[w].MessageCenter.No = atoi(optarg);
583
584             if (MultiSMS->SMS[w].MessageCenter.No < 1 || MultiSMS->SMS[w].MessageCenter.No > 5) {
585               fprintf(stderr, _("Incorrect SMSC number with \"smscno\" option (can't be <1 and >5) !\n"));
586               GSM->Terminate();
587               return -1;
588             }
589             break;
590
591           case '3': /* Receiver/recipient */
592             strncpy(MultiSMS->SMS[w].Destination,optarg,11); break;
593
594           case '4': /* Unicode */
595             if (unicode) break;
596
597           case '5': /* Profile */
598             if (profile) break;
599
600           case '6': /* Scale */
601             if (scale) break;
602
603           case 'r': /* mark as read */
604             MultiSMS->SMS[w].Status = GSS_SENTREAD; break;
605
606           case 'i': /* Save into Inbox */
607             MultiSMS->SMS[w].folder = GST_INBOX; break;
608           
609           case 's': /* Set replying via the same SMSC */
610             MultiSMS->SMS[w].ReplyViaSameSMSC = true; break;
611
612           case 'a': /* Ask before overwriting */
613             interactive=true;break;     
614         
615           case 'l': /* Specify location */
616             MultiSMS->SMS[0].Location = atoi(optarg); break;     
617
618         default:
619           fprintf(stderr,_("Unknown option number %i\n"),argc);
620           GSM->Terminate();    
621           return -1;
622         }
623       }
624     }
625
626     if (interactive && MultiSMS->SMS[0].Location!=0 && w==0) {
627       SMSold.Location=MultiSMS->SMS[0].Location;
628       error = GSM->GetSMSMessage(&SMSold);
629       switch (error) {
630         case GE_NONE:
631           fprintf(stderr, _("Message at specified location exists. "));
632           while (confirm < 0) {
633             fprintf(stderr, _("Overwrite? (yes/no) "));
634             GetLine(stdin, ans, 7);
635             if (!strcmp(ans, "yes")) confirm = 1;
636             if (!strcmp(ans, "no")) confirm = 0;
637           }  
638           if (!confirm) { GSM->Terminate(); return 0; }
639           else break;
640         case GE_INVALIDSMSLOCATION:
641           fprintf(stderr, _("Invalid location\n"));
642           GSM->Terminate();
643           return -1;
644         default:
645 /* FIXME: Remove this fprintf when the function is thoroughly tested */
646 #ifdef DEBUG
647             fprintf(stderr, _("Location %d empty. Saving\n"), SMS[w].Location);
648 #endif
649           break;
650       }
651     }
652
653     error=GSM->SaveSMSMessage(&MultiSMS->SMS[w]);
654
655     if (error == GE_NONE)
656       fprintf(stdout, _("SMS %i/%i saved at location %i !\n"),w+1,MultiSMS->number,MultiSMS->SMS[w].MessageNumber);
657     else
658       fprintf(stdout, _("SMS %i/%i saving failed (error=%d, location=%i)\n"), w+1, MultiSMS->number, error,MultiSMS->SMS[w].Location);
659   }
660
661   GSM->Terminate();  
662
663   return 0;
664 }
665
666 void GSM_PlayRingtoneOnConsole(GSM_Ringtone *ringtone)
667 {
668   int i;
669 #ifdef VC6
670   char mychar;
671 #endif
672
673   for (i=0;i<ringtone->NrNotes;i++) {
674 #ifdef VC6
675     if (_kbhit()) {
676       mychar=_getch();
677       break;
678     }
679 #endif
680     GSM_PlayOneNote (ringtone->notes[i]);
681   }
682   GSM->PlayTone(255*255,0);
683 }
684
685 /* This function shows the copyright and some informations usefull for
686    debugging. */
687 int version(void)
688 {
689
690   fprintf(stdout, _("GNOKII Version %s\n"
691 "Copyright (C) Hugh Blemings <hugh@linuxcare.com>, 1999, 2000\n"
692 "Copyright (C) Pavel Janík ml. <Pavel.Janik@linux.cz>, 1999, 2000\n"
693 "Built %s %s for %s on %s \n"), VERSION, __TIME__, __DATE__, model, Port);
694
695   return 0;
696 }
697
698 /* The function usage is only informative - it prints this program's usage and
699    command-line options. */
700
701 int usage(void)
702 {
703
704   fprintf(stdout, _("   usage: gnokii [--help|--monitor [-noloop|-nl]|--version]\n"
705 "          gnokii --getmemory memory_type [start [end]] [-short|-v30|-v21|-v]\n"
706 "          gnokii --writephonebook [-i]\n"
707 "          gnokii --sendphonebookentry destination memory_type location\n"
708 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
709 "                 [-s] [-v n] [-d]\n"
710 "          gnokii --savephonebookentry memory_type location\n"
711 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
712 "                 [-r] [-i] [-s] [-a] [--name name]\n"
713 "          gnokii --getvoicemailbox\n"
714 "          gnokii --getspeeddial number\n"
715 "          gnokii --setspeeddial number memory_type location\n\n"
716
717 "          gnokii --getsms memory_type start [end] [-f file]\n"
718 "          gnokii --getsmsstatus\n"
719 "          gnokii --getsmsfolders\n"
720 "          gnokii --deletesms memory_type start [end]\n"
721 "          gnokii --sendsms destination [--smsc message_center_number |\n"
722 "                 --smscno message_center_index] [--long n] [-s] [-C n]\n"
723 "                 [--enablevoice|--disablevoice|--enablefax|--disablefax|\n"
724 "                  --enableemail|--disableemail|--void][--unicode][-v n][-d]\n"
725 "          gnokii --savesms destination|\"\" [--smsc \n"
726 "                 message_center_number] [--smscno message_center_index]\n"
727 "                 [--long n] [-r] [-i] [-s][-C n][-a][-l][F n][--smsname name]\n"
728 "                 [--enablevoice|--disablevoice|--enablefax|--disablefax|\n"
729 "                  --enableemail|--disableemail|--void|--hang|--bug][--unicode]\n"
730 "          gnokii --receivesms\n"
731 "          gnokii --getsmsc message_center_number\n"
732 "          gnokii --renamesmsc number new_name\n\n"
733
734 "          gnokii --setdatetime [YYYY [MM [DD [HH [MM]]]]]\n"
735 "          gnokii --getdatetime\n"
736 "          gnokii --setalarm HH MM\n"
737 "          gnokii --getalarm\n\n"
738
739 "          gnokii --getcalendarnote { start end [-v30|-v10] | --short|-s }\n"
740 "          gnokii --writecalendarnote vcardfile number\n"
741 "          gnokii --deletecalendarnote index\n"
742 "          gnokii --sendcalendarnote destination vcardfile number\n"
743 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
744 "                 [-s] [-v n] [-d]\n"
745 "          gnokii --savecalendarnote vcardfile number\n"
746 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
747 "                 [-r] [-i] [-s] [-a] [--name name]\n\n"
748
749 "          gnokii --netmonitor {reset|off|field|devel|next|nr}\n"
750 "          gnokii --nm_collect screen1|-d [screen2|-d]...\n"
751 "          gnokii --netmonitordata [-S file] [-I file] [-h] [-n n] [-ts n][-tm n]\n"
752 "                 [-fs str] [-ls str] FLD1:FLD2:FLDn:... \n"
753 "                 (see files netmonitordata_????_??? for details)\n\n"
754
755 "          gnokii --bitmapconvert source destination\n"
756 "          gnokii --bitmapconvert source destination op|7110op [network code]\n"
757 "          gnokii --bitmapconvert source destination caller [caller group number]\n"
758 "          gnokii --bitmapconvert source destination\n"
759 "                   startup|7110startup|6210startup\n"
760 "          gnokii --bitmapconvert source destination picture\n"
761 "          gnokii --showbitmap logofile\n"
762 "          gnokii --sendlogo op destination logofile network_code\n"
763 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
764 "                 [-s] [-v n] [-d]\n"
765 "          gnokii --sendlogo picture destination logofile text\n"
766 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
767 "                 [-s] [-v n] [-d] [--unicode]\n"
768 "          gnokii --sendlogo screensaver destination logofile\n"
769 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
770 "                 [-s] [-v n] [-d]\n"
771 "          gnokii --sendlogo caller destination logofile\n"
772 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
773 "                 [-s] [-v n] [-d]\n"
774 "          gnokii --savelogo op logofile network_code\n"
775 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
776 "                 [-r] [-i] [-s] [-a] [-l] [--name name]\n"
777 "          gnokii --savelogo picture logofile text\n"
778 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
779 "                 [-r] [-i] [-s] [-a] [-l] [--name name] [--unicode]\n"
780 "          gnokii --savelogo screensaver logofile\n"
781 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
782 "                 [-r] [-i] [-s] [-a] [-l] [--name name]\n"
783 "          gnokii --savelogo caller logofile\n"
784 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
785 "                 [-r] [-i] [-s] [-a] [-l] [--name name]\n"
786 "          gnokii --setlogo op|7110op [logofile] [network code]\n"
787 "          gnokii --setlogo startup|7110startup|6210startup [logofile]\n"
788 "          gnokii --setlogo startup 1|2|3\n"
789 "          gnokii --setlogo caller [logofile] [caller group number] [group name]\n"
790 "          gnokii --setlogo picture [logofile] [number] [text] [sender]\n"
791 "          gnokii --setlogo {dealer|text} [text]\n"
792 "          gnokii --getlogo op|7110op [logofile] [network code]\n"
793 "          gnokii --getlogo startup|7110startup|6210startup [logofile]\n"
794 "          gnokii --getlogo caller [logofile][caller group number]\n"
795 "          gnokii --getlogo picture [logofile][number]\n"
796 "          gnokii --getlogo {dealer|text}\n\n"
797
798 "          gnokii --sendringtone destination ringtonefile\n"
799 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
800 "                 [-s] [-v n] [-d] [--scale] [--profilestyle]\n"
801 "          gnokii --saveringtone ringtonefile\n"
802 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
803 "                 [-r] [-i] [-s] [-a] [--name name] [--scale] [--profilestyle]\n"
804 "          gnokii --setringtone ringtonefile [location]\n"
805 "          gnokii --getringtone ringtonefile [location]\n"
806 "          gnokii --ringtoneconvert source destination\n"
807 "          gnokii --binringtoneconvert source destination\n"
808 "          gnokii --playringtone ringtonefile\n"
809 "          gnokii --composer ringtonefile\n"
810 "          gnokii --allringtones\n\n"
811
812 "          gnokii --getprofile [number]\n"
813 "          gnokii --setprofile number feature value\n"
814 "          gnokii --sendprofile destination profile_name ringtonefile\n"
815 "                 picturefile [--smsc message_center_number]\n"
816 "                 [--smscno message_center_index] [-s] [-v n] [-d] [--scale]\n\n"
817
818 "          gnokii --reset [soft|hard]\n"
819 "          gnokii --dialvoice number\n"
820 "          gnokii --cancelcall\n"
821 "          gnokii --displayoutput\n"
822 "          gnokii --presskeysequence sequence\n"
823 "          gnokii --backupsettings file\n"
824 "          gnokii --restoresettings file\n"
825 "          gnokii --getphoneprofile\n"
826 "          gnokii --setphoneprofile feature value\n"
827 "          gnokii --getoperatorname\n"
828 "          gnokii --setoperatorname code name\n"
829 "          gnokii --senddtmf string\n"
830 "          gnokii --divert register|enable|query|disable|erasure\n"
831 "                 all|busy|noans|outofreach all|voice|fax|data\n"
832 "                 [number timeout]\n\n"
833
834 "          gnokii --phonetests\n"
835 "          gnokii --simlock\n"
836 "          gnokii --getdisplaystatus\n"
837 "          gnokii --identify\n\n"
838
839 "          gnokii --getwapbookmark location\n"
840 "          gnokii --setwapbookmark title url [location]\n"
841 "          gnokii --sendwapbookmark location destination\n"
842 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
843 "                 [-s] [-v n] [-d]\n"
844 "          gnokii --savewapbookmark location\n"
845 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
846 "                 [-r] [-i] [-s] [-a] [-l] [--name name]\n"
847 "          gnokii --getwapsettings location\n"
848 "          gnokii --savewapsettings location\n"
849 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
850 "                 [-r] [-i] [-s] [-a] [-l] [--name name]\n"
851 "          gnokii --sendwapsettings location destination\n"
852 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
853 "                 [-s] [-v n] [-d]\n"
854   ));
855
856 #ifdef SECURITY
857   fprintf(stdout, _(
858 "\n          gnokii --entersecuritycode PIN|PIN2|PUK|PUK2\n"
859 "          gnokii --getsecuritycodestatus\n"
860 "          gnokii --getsecuritycode PIN|PIN2|PUK|PUK2|SecurityCode\n"
861 "          gnokii --geteeprom\n"
862 "          gnokii --resetphonesettings\n"
863   ));
864 #endif
865
866 #ifdef DEBUG
867   fprintf(stdout, _(
868 "          gnokii --sniff [port]\n"
869 "          gnokii --decodefile file\n"
870   ));
871 #endif
872
873   return 0;
874 }
875
876 /* fbusinit is the generic function which waits for the FBUS link. The limit
877    is 10 seconds. After 10 seconds we quit. */
878
879 void fbusinit(void (*rlp_handler)(RLP_F96Frame *frame))
880 {
881
882   int count=0;
883   GSM_Error error;
884
885 #ifndef WIN32
886   if (strcmp(GetMygnokiiVersion(),VERSION)!=0)
887     fprintf(stderr,_("WARNING: version of installed libmygnokii.so (%s) is different to version of gnokii (%s)\n"),GetMygnokiiVersion(),VERSION);
888 #endif
889
890   /* Initialise the code for the GSM interface. */     
891   error = GSM_Initialise(model, Port, Initlength, GetConnectionTypeFromString(Connection), rlp_handler, SynchronizeTime);
892
893   if (error != GE_NONE) {
894     fprintf(stderr, _("GSM/FBUS init failed! (Unknown model ?). Quitting.\n"));
895     exit(-1);
896   }
897
898   /* First (and important!) wait for GSM link to be active. We allow 10
899      seconds... */
900   while (count++ < 200 && *GSM_LinkOK == false)
901     usleep(50000);
902
903   if (*GSM_LinkOK == false) {
904     fprintf (stderr, _("Hmmm... GSM_LinkOK never went true. Quitting.\n"));
905     exit(-1);
906   }  
907 }
908
909 /* This function checks that the argument count for a given options is withing
910    an allowed range. */
911
912 int checkargs(int opt, struct gnokii_arg_len gals[], int argc)
913 {
914
915   int i;
916
917   /* Walk through the whole array with options requiring arguments. */
918
919   for(i = 0;!(gals[i].gal_min == 0 && gals[i].gal_max == 0); i++) {
920
921     /* Current option. */
922
923     if(gals[i].gal_opt == opt) {
924
925       /* Argument count checking. */
926
927       if(gals[i].gal_flags == GAL_XOR) {
928         if(gals[i].gal_min == argc || gals[i].gal_max == argc) return 0;
929       }
930       else {
931         if(gals[i].gal_min <= argc && gals[i].gal_max >= argc) return 0;
932       }
933
934       return 1;
935
936     }
937
938   }
939
940   /* We do not have options without arguments in the array, so check them. */
941
942   if (argc==0) return 0;
943           else return 1;
944 }
945
946 /* Main function - handles command line arguments, passes them to separate
947    functions accordingly. */
948
949 int main(int argc, char *argv[])
950 {
951
952   int c, i, rc = -1;
953   int nargc = argc-2;
954   char **nargv;
955
956   /* Every option should be in this array. */
957
958   static struct option long_options[] =
959   {
960
961     { "help",               no_argument,       NULL, OPT_HELP             },// Display usage.
962     { "version",            no_argument,       NULL, OPT_VERSION          },// Display version and build information.
963     { "getsmsfolders",      no_argument,       NULL, OPT_GETSMSFOLDERS    },// Gets SMS folders
964     { "getsmsstatus",       no_argument,       NULL, OPT_GETSMSSTATUS     },// Get SMS Folder Status
965     { "identify",           no_argument,       NULL, OPT_IDENTIFY         },// Identify
966     { "pmon",               no_argument,       NULL, OPT_PMON             },// For development purposes: run in passive monitoring mode
967     { "foogle",             no_argument,       NULL, OPT_FOOGLE           },// For development purposes: insert you function calls here
968     { "getdatetime",        no_argument,       NULL, OPT_GETDATETIME      },// Get date and time mode    
969     { "getalarm",           no_argument,       NULL, OPT_GETALARM         },// Get alarm    
970     { "cancelcall",         no_argument,       NULL, OPT_CANCELCALL       },// Cancel Call    
971     { "getdisplaystatus",   no_argument,       NULL, OPT_GETDISPLAYSTATUS },// Get display status mode    
972     { "allringtones",       no_argument,       NULL, OPT_ALLRINGTONES     },/* Displays names of available ringtones */    
973     { "displayoutput",      no_argument,       NULL, OPT_DISPLAYOUTPUT    },/* Show texts from phone's display */
974     { "getphoneprofile",    no_argument,       NULL, OPT_GETPHONEPROFILE  },/* Get/Set phone profile settings */
975     { "getoperatorname",    no_argument,       NULL, OPT_GETOPERATORNAME  },/* Get downloaded operator name */    
976     { "getvoicemailbox",    no_argument,       NULL, OPT_GETVOICEMAILBOX  },/* Gets voice mailbox number */    
977     { "phonetests",         no_argument,       NULL, OPT_PHONETESTS       },
978     { "simlockinfo",        no_argument,       NULL, OPT_SIMLOCKINFO      },    
979     { "receivesms",         no_argument,       NULL, OPT_RECEIVESMS       },    
980     { "setoperatorname",    optional_argument, NULL, OPT_SETOPERATORNAME  },/* Set downloaded operator name */    
981     { "setdatetime",        optional_argument, NULL, OPT_SETDATETIME      },// Set date and time    
982     { "writephonebook",     optional_argument, NULL, OPT_WRITEPHONEBOOK   },// Write phonebook (memory) mode
983     { "reset",              optional_argument, NULL, OPT_RESET            },// Resets the phone
984     { "monitor",            optional_argument, NULL, OPT_MONITOR          },// Monitor mode
985     { "setlogo",            optional_argument, NULL, OPT_SETLOGO          },// Set logo
986     { "getprofile",         optional_argument, NULL, OPT_GETPROFILE       },// Show profile
987     { "setalarm",           required_argument, NULL, OPT_SETALARM         },// Set alarm
988     { "dialvoice",          required_argument, NULL, OPT_DIALVOICE        },// Voice call mode
989     { "getcalendarnote",    required_argument, NULL, OPT_GETCALENDARNOTE  },// Get calendar note mode    
990     { "writecalendarnote",  required_argument, NULL, OPT_WRITECALENDARNOTE},// Write calendar note mode
991     { "sendcalendarnote",   required_argument, NULL, OPT_SENDCALENDARNOTE },
992     { "savecalendarnote",   required_argument, NULL, OPT_SAVECALENDARNOTE },
993     { "sendphonebookentry", required_argument, NULL, OPT_SENDPHONEBOOKENTRY},
994     { "savephonebookentry", required_argument, NULL, OPT_SAVEPHONEBOOKENTRY},
995     { "deletecalendarnote", required_argument, NULL, OPT_DELCALENDARNOTE  },// Delete calendar note mode    
996     { "getmemory",          required_argument, NULL, OPT_GETMEMORY        },// Get memory mode
997     { "getspeeddial",       required_argument, NULL, OPT_GETSPEEDDIAL     },// Get speed dial mode
998     { "setspeeddial",       required_argument, NULL, OPT_SETSPEEDDIAL     },// Set speed dial mode
999     { "getsms",             required_argument, NULL, OPT_GETSMS           },// Get SMS message mode
1000     { "deletesms",          required_argument, NULL, OPT_DELETESMS        },// Delete SMS message mode
1001     { "sendsms",            required_argument, NULL, OPT_SENDSMS          },// Send SMS message mode
1002     { "savesms",            required_argument, NULL, OPT_SAVESMS          },// Save SMS message mode
1003     { "sendlogo",           required_argument, NULL, OPT_SENDLOGO         },// Send logo as SMS message mode
1004     { "savelogo",           required_argument, NULL, OPT_SAVELOGO         },// Save logo on SIM
1005     { "sendringtone",       required_argument, NULL, OPT_SENDRINGTONE     },// Send ringtone as SMS message
1006     { "saveringtone",       required_argument, NULL, OPT_SAVERINGTONE     },// Saves ringtone on SIM
1007     { "setringtone",        required_argument, NULL, OPT_SETRINGTONE      },// Set ringtone    
1008     { "getringtone",        required_argument, NULL, OPT_GETRINGTONE      },// Get bin/normal ringtone    
1009     { "presskeysequence",   required_argument, NULL, OPT_PRESSKEYSEQUENCE },/* Presses keys in phone's display */
1010     { "getsmsc",            required_argument, NULL, OPT_GETSMSC          },// Get SMS center number mode
1011     { "renamesmsc",         required_argument, NULL, OPT_RENAMESMSC       },// Rename SMSC
1012     { "netmonitor",         required_argument, NULL, OPT_NETMONITOR       },// NetMonitor mode
1013     { "senddtmf",           required_argument, NULL, OPT_SENDDTMF         },// Send DTMF sequence
1014     { "getlogo",            required_argument, NULL, OPT_GETLOGO          },// Get logo
1015     { "setprofile",         required_argument, NULL, OPT_SETPROFILE       },// Set profile feature
1016     { "sendprofile",        required_argument, NULL, OPT_SENDPROFILE      },// Send profile via SMS
1017     { "setphoneprofile",    required_argument, NULL, OPT_SETPHONEPROFILE  },/* Get/Set phone profile settings */
1018     { "restoresettings",    required_argument, NULL, OPT_RESTORESETTINGS  },//Restore various settings from one file
1019     { "backupsettings",     required_argument, NULL, OPT_BACKUPSETTINGS   },//Backup various settings to one file
1020     { "playringtone",       required_argument, NULL, OPT_PLAYRINGTONE     },/* Plays ringtones */    
1021     { "composer",           required_argument, NULL, OPT_COMPOSER         },/* Shows ringtone like in Nokia Composer */    
1022     { "ringtoneconvert",    required_argument, NULL, OPT_RINGTONECONVERT  },/* Convert ringtone files */    
1023     { "binringtoneconvert", required_argument, NULL, OPT_BINRINGTONECONVERT},/* Convert binary ringtone files */    
1024     { "bitmapconvert",      required_argument, NULL, OPT_BITMAPCONVERT    },/* Convert bitmap files */    
1025     { "showbitmap",         required_argument, NULL, OPT_SHOWBITMAP       },    
1026     { "nm_collect",         required_argument, NULL, OPT_NM_COLLECT       },// NetMonitor periodical data collection mode (newbiee)
1027     { "netmonitordata",     required_argument, NULL, OPT_NETMONITORDATA   },// NetMonitor periodical data collection mode (advanced)
1028     { "getwapbookmark",     required_argument, NULL, OPT_GETWAPBOOKMARK   },    
1029     { "setwapbookmark",     required_argument, NULL, OPT_SETWAPBOOKMARK   },    
1030     { "savewapbookmark",    required_argument, NULL, OPT_SAVEWAPBOOKMARK  },    
1031     { "savewapsettings",    required_argument, NULL, OPT_SAVEWAPSETTINGS  },    
1032     { "sendwapsettings",    required_argument, NULL, OPT_SENDWAPSETTINGS  },    
1033     { "sendwapbookmark",    required_argument, NULL, OPT_SENDWAPBOOKMARK  },    
1034     { "getwapsettings",     required_argument, NULL, OPT_GETWAPSETTINGS   },    
1035     { "divert",             required_argument, NULL, OPT_DIVERT           },
1036
1037 #ifdef SECURITY
1038     { "entersecuritycode",  required_argument, NULL, OPT_ENTERSECURITYCODE    },// Enter Security Code mode
1039     { "getsecuritycode",    required_argument, NULL, OPT_GETSECURITYCODE      },// Get Security Code
1040   { "getsecuritycodestatus",no_argument,       NULL, OPT_GETSECURITYCODESTATUS},// Get Security Code status
1041     { "geteeprom",          no_argument,       NULL, OPT_GETEEPROM            },// Gets EEPROM
1042     { "resetphonesettings", no_argument,       NULL, OPT_RESETPHONESETTINGS   },// Reset phone settings
1043     { "setsimlock",         no_argument,       NULL, OPT_SETSIMLOCK           },// Sets simlock
1044 #endif
1045
1046 #ifdef DEBUG
1047     { "sniff",              optional_argument, NULL, OPT_SNIFFER    },// Will show datas from port
1048     { "decodefile",         required_argument, NULL, OPT_DECODEFILE },//decode input file
1049 #endif
1050
1051     { 0, 0, 0, 0},
1052   };
1053
1054   /* Every command which requires arguments should have an appropriate entry
1055      in this array. */
1056         
1057   struct gnokii_arg_len gals[] =
1058   {
1059
1060     { OPT_MONITOR,           0, 1, 0 },
1061
1062 #ifdef SECURITY
1063     { OPT_ENTERSECURITYCODE, 1, 1, 0 },
1064     { OPT_GETSECURITYCODE,   1, 1, 0 },
1065 #endif
1066
1067 #ifdef DEBUG
1068     { OPT_SNIFFER,           0, 1, 0 },
1069     { OPT_DECODEFILE,        1, 1, 0 },
1070 #endif
1071
1072     { OPT_SETDATETIME,       0, 5, 0 },
1073     { OPT_BACKUPSETTINGS,    1, 1, 0 },
1074     { OPT_RESTORESETTINGS,   1, 1, 0 },
1075     { OPT_SETALARM,          2, 2, 0 },
1076     { OPT_DIALVOICE,         1, 1, 0 },
1077     { OPT_GETCALENDARNOTE,   1, 3, 0 },
1078     { OPT_WRITECALENDARNOTE, 2, 2, 0 },
1079     { OPT_SAVECALENDARNOTE,  2, 9, 0 },
1080     { OPT_SENDCALENDARNOTE,  3, 9, 0 },
1081     { OPT_SAVEPHONEBOOKENTRY,2, 9, 0 },
1082     { OPT_SENDPHONEBOOKENTRY,3, 9, 0 },
1083     { OPT_DELCALENDARNOTE,   1, 1, 0 },
1084     { OPT_GETMEMORY,         2, 4, 0 },
1085     { OPT_GETSPEEDDIAL,      1, 1, 0 },
1086     { OPT_SETSPEEDDIAL,      3, 3, 0 },
1087     { OPT_GETSMS,            2, 5, 0 },
1088     { OPT_DELETESMS,         2, 3, 0 },
1089     { OPT_SENDSMS,           1,10, 0 },
1090     { OPT_SAVESMS,           1,11, 0 },
1091     { OPT_SENDLOGO,          3, 9, 0 },
1092     { OPT_SAVELOGO,          2,10, 0 },
1093     { OPT_SENDRINGTONE,      2, 7, 0 },
1094     { OPT_SAVERINGTONE,      1, 9, 0 },
1095     { OPT_GETSMSC,           1, 1, 0 },
1096     { OPT_RENAMESMSC,        2, 2, 0 },
1097     { OPT_NETMONITOR,        1, 1, 0 },
1098     { OPT_SENDDTMF,          1, 1, 0 },
1099     { OPT_SETLOGO,           1, 5, 0 },
1100     { OPT_GETLOGO,           1, 4, 0 },
1101     { OPT_SETRINGTONE,       1, 3, 0 },
1102     { OPT_GETRINGTONE,       1, 2, 0 },
1103     { OPT_PRESSKEYSEQUENCE,  1, 1, 0 },
1104     { OPT_RESET,             0, 1, 0 },
1105     { OPT_GETPROFILE,        0, 1, 0 },
1106     { OPT_SETPROFILE,        3, 3, 0 },
1107     { OPT_SENDPROFILE,       4,10, 0 },
1108     { OPT_WRITEPHONEBOOK,    0, 1, 0 },
1109     { OPT_PLAYRINGTONE,      1, 1, 0 },
1110     { OPT_COMPOSER,          1, 1, 0 },
1111     { OPT_RINGTONECONVERT,   2, 2, 0 },
1112     { OPT_BINRINGTONECONVERT,2, 2, 0 },
1113     { OPT_BITMAPCONVERT,     2, 4, 0 },
1114     { OPT_SHOWBITMAP,        1, 1, 0 },
1115     { OPT_SETOPERATORNAME,   0, 2, 0 },    
1116     { OPT_SETPHONEPROFILE,   2, 2, 0 },        
1117     { OPT_NM_COLLECT,        1, MAX_NM_COLLECT, 0 },
1118     { OPT_NETMONITORDATA,    0,99, 0 },
1119     { OPT_GETWAPBOOKMARK,    1, 1, 0 },
1120     { OPT_SETWAPBOOKMARK,    2, 3, 0 },
1121     { OPT_SAVEWAPBOOKMARK,   1, 9, 0 },
1122     { OPT_SENDWAPBOOKMARK,   2, 9, 0 },
1123     { OPT_GETWAPSETTINGS,    1, 1, 0 },
1124     { OPT_SAVEWAPSETTINGS,   1, 9, 0 },
1125     { OPT_SENDWAPSETTINGS,   2, 9, 0 },
1126     { OPT_DIVERT,            3, 5, 0 },    
1127
1128     { 0, 0, 0, 0 },
1129   };
1130
1131   opterr = 0;
1132
1133   /* For GNU gettext */
1134
1135 #ifdef USE_NLS
1136 #ifndef VC6
1137   textdomain("gnokii");
1138   setlocale(LC_ALL, "pl_PL"); //here is string for Polish localisation
1139 #else
1140   setlocale(LC_ALL, ".852"); //Polish codepage for console, not "real" WIN CP
1141 #endif
1142
1143 #endif
1144
1145     /* Read config file */
1146     if (CFG_ReadConfig(&model, &Port, &Initlength, &Connection, &BinDir, &SynchronizeTime,false) < 0) {
1147         exit(-1);
1148     }
1149
1150   /* Handle command line arguments. */
1151
1152   c = getopt_long(argc, argv, "", long_options, NULL);
1153
1154   if (c == -1) {
1155
1156     /* No argument given - we should display usage. */
1157     usage();
1158     exit(-1);
1159   }
1160
1161   /* We have to build an array of the arguments which will be passed to the
1162      functions.  Please note that every text after the --command will be
1163      passed as arguments.  A syntax like gnokii --cmd1 args --cmd2 args will
1164      not work as expected; instead args --cmd2 args is passed as a
1165      parameter. */
1166
1167   if((nargv = malloc(sizeof(char *) * argc)) != NULL) {
1168
1169     for(i = 2; i < argc; i++)
1170       nargv[i-2] = argv[i];
1171         
1172     if(checkargs(c, gals, nargc)) {
1173
1174       free(nargv);
1175
1176       /* Wrong number of arguments - we should display usage. */
1177       usage();
1178       exit(-1);
1179     }
1180
1181 #ifndef VC6
1182 #if defined(__svr4__)
1183     /* have to ignore SIGALARM */
1184     sigignore(SIGALRM);
1185 #endif
1186 #endif
1187
1188     switch(c) {
1189
1190     // First, error conditions  
1191     case '?':
1192       fprintf(stderr, _("Use '%s --help' for usage informations.\n"), argv[0]);
1193       break;
1194         
1195     // Then, options with no arguments
1196     case OPT_HELP:                  rc = usage();                   break;
1197     case OPT_VERSION:               rc = version();                 break;
1198     case OPT_MONITOR:               rc = monitormode(nargc, nargv); break;
1199     case OPT_GETSMSFOLDERS:         rc = getsmsfolders();           break;
1200     case OPT_GETDATETIME:           rc = getdatetime();             break;
1201     case OPT_GETALARM:              rc = getalarm();                break;
1202     case OPT_GETDISPLAYSTATUS:      rc = getdisplaystatus();        break;
1203     case OPT_PMON:                  rc = pmon();                    break;
1204     case OPT_WRITEPHONEBOOK:        rc = writephonebook(nargc, nargv);break;
1205
1206 #ifdef SECURITY
1207     case OPT_ENTERSECURITYCODE:     rc = entersecuritycode(optarg); break;
1208     case OPT_GETSECURITYCODESTATUS: rc = getsecuritycodestatus();   break;
1209     case OPT_GETSECURITYCODE:       rc = getsecuritycode(optarg);   break;
1210     case OPT_GETEEPROM:             rc = geteeprom();               break;
1211     case OPT_RESETPHONESETTINGS:    rc = resetphonesettings();      break;
1212     case OPT_SETSIMLOCK:            rc = setsimlock();              break;
1213 #endif
1214
1215 #ifdef DEBUG
1216     case OPT_SNIFFER:               rc = sniff(nargc, nargv);       break;
1217     case OPT_DECODEFILE:            rc = decodefile(nargc, nargv);  break;
1218 #endif                                  
1219         
1220     // Now, options with arguments
1221     case OPT_SETDATETIME:           rc = setdatetime(nargc, nargv); break;
1222     case OPT_SETALARM:              rc = setalarm(nargv);           break;
1223     case OPT_DIALVOICE:             rc = dialvoice(optarg);         break;
1224     case OPT_CANCELCALL:            rc = cancelcall();              break;
1225     case OPT_GETCALENDARNOTE:       rc = getcalendarnote(nargc, nargv);break;
1226     case OPT_DELCALENDARNOTE:       rc = deletecalendarnote(optarg);break;
1227     case OPT_SAVECALENDARNOTE:      rc = savecalendarnote(nargc, nargv);break;
1228     case OPT_SENDCALENDARNOTE:      rc = sendcalendarnote(nargc, nargv);break;
1229     case OPT_SAVEPHONEBOOKENTRY:    rc = savephonebookentry(nargc, nargv);break;
1230     case OPT_SENDPHONEBOOKENTRY:    rc = sendphonebookentry(nargc, nargv);break;
1231     case OPT_WRITECALENDARNOTE:     rc = writecalendarnote(nargv);  break;
1232     case OPT_GETMEMORY:             rc = getmemory(nargc, nargv);   break;
1233     case OPT_GETSPEEDDIAL:          rc = getspeeddial(optarg);      break;
1234     case OPT_SETSPEEDDIAL:          rc = setspeeddial(nargv);       break;
1235     case OPT_GETSMS:                rc = getsms(argc, argv);        break;
1236     case OPT_GETSMSSTATUS:          rc = getsmsstatus(argc, argv);  break;
1237     case OPT_DELETESMS:             rc = deletesms(nargc, nargv);   break;
1238     case OPT_SENDSMS:               rc = sendsms(nargc, nargv);     break;
1239     case OPT_SAVESMS:               rc = savesms(nargc, nargv);     break;
1240     case OPT_DIVERT:                rc = divert(nargc, nargv);      break;
1241     case OPT_SENDLOGO:              rc = sendlogo(nargc, nargv);    break;
1242     case OPT_SAVELOGO:              rc = savelogo(nargc, nargv);    break;
1243     case OPT_GETSMSC:               rc = getsmsc(optarg);           break;
1244     case OPT_RENAMESMSC:            rc = renamesmsc(nargc,nargv);   break;
1245     case OPT_NETMONITOR:            rc = netmonitor(optarg);        break;
1246     case OPT_IDENTIFY:              rc = identify();                break;
1247     case OPT_SETLOGO:               rc = setlogo(nargc, nargv);     break;
1248     case OPT_GETLOGO:               rc = getlogo(nargc, nargv);     break;
1249     case OPT_RECEIVESMS:            rc = receivesms(nargc, nargv);  break;
1250     case OPT_SETRINGTONE:           rc = setringtone(nargc, nargv); break;
1251     case OPT_GETRINGTONE:           rc = getringtone(nargc, nargv); break;
1252     case OPT_PRESSKEYSEQUENCE:      rc = presskeysequence(nargv);   break;
1253     case OPT_SENDRINGTONE:          rc = sendringtone(nargc, nargv);break;
1254     case OPT_SAVERINGTONE:          rc = saveringtone(nargc, nargv);break;
1255     case OPT_GETPROFILE:            rc = getprofile(nargc, nargv);  break;
1256     case OPT_SETPROFILE:            rc = setprofile(nargc, nargv);  break;
1257     case OPT_SENDPROFILE:           rc = sendprofile(nargc, nargv); break;
1258     case OPT_DISPLAYOUTPUT:         rc = displayoutput();           break;
1259     case OPT_RESTORESETTINGS:       rc = restoresettings(nargv);    break;
1260     case OPT_BACKUPSETTINGS:        rc = backupsettings(nargv);     break;
1261     case OPT_RINGTONECONVERT:       rc = ringtoneconvert(nargc, nargv);break;
1262     case OPT_BINRINGTONECONVERT:    rc = binringtoneconvert(nargc, nargv);break;
1263     case OPT_BITMAPCONVERT:         rc = bitmapconvert(nargc, nargv);break;
1264     case OPT_SHOWBITMAP:            rc = showbitmap(nargc, nargv);  break;
1265     case OPT_PLAYRINGTONE:          rc = playringtone(nargc, nargv);break;
1266     case OPT_COMPOSER:              rc = composer(nargc, nargv);    break;
1267     case OPT_FOOGLE:                rc = foogle(nargv);             break;
1268     case OPT_PHONETESTS:            rc = phonetests();              break;
1269     case OPT_SIMLOCKINFO:           rc = simlockinfo();             break;
1270     case OPT_SENDDTMF:              rc = senddtmf(optarg);          break;
1271     case OPT_RESET:                 rc = reset(nargc,nargv);        break;
1272     case OPT_GETOPERATORNAME:       rc = getoperatorname();         break;
1273     case OPT_SETOPERATORNAME:       rc = setoperatorname(nargc,nargv);break;
1274     case OPT_GETWAPBOOKMARK:        rc = getwapbookmark(nargc,nargv);break;
1275     case OPT_SETWAPBOOKMARK:        rc = setwapbookmark(nargc,nargv);break;
1276     case OPT_SAVEWAPBOOKMARK:       rc = savewapbookmark(nargc,nargv);break;
1277     case OPT_SENDWAPBOOKMARK:       rc = sendwapbookmark(nargc,nargv);break;
1278     case OPT_GETWAPSETTINGS:        rc = getwapsettings(nargc,nargv);break;
1279     case OPT_SAVEWAPSETTINGS:       rc = savewapsettings(nargc,nargv);break;
1280     case OPT_SENDWAPSETTINGS:       rc = sendwapsettings(nargc,nargv);break;
1281     case OPT_ALLRINGTONES:          rc = allringtones();            break;
1282     case OPT_GETPHONEPROFILE:       rc = getphoneprofile();         break;
1283     case OPT_SETPHONEPROFILE:       rc = setphoneprofile(nargc,nargv);break;
1284     case OPT_GETVOICEMAILBOX:       rc = getvoicemailbox();         break;
1285     case OPT_NM_COLLECT:            rc = nm_collect(nargc, nargv);  break;
1286     case OPT_NETMONITORDATA:        rc = netmonitordata(nargc, nargv);break;
1287
1288     default:         fprintf(stderr, _("Unknown option: %d\n"), c); break;
1289
1290     }
1291
1292     free(nargv);
1293
1294     return(rc);
1295   }
1296
1297   fprintf(stderr, _("Wrong number of arguments\n"));
1298
1299   exit(-1);
1300 }
1301
1302 /* Restores various phone settings from one file */
1303 int restoresettings(char *argv[])
1304 {
1305   fprintf(stdout,_("Work in progress. Not usefull now. Sorry\n"));
1306   return 0;
1307 }
1308
1309 /* Backup various phone settings from one file */
1310 int backupsettings(char *argv[])
1311 {
1312   GSM_PhonebookEntry PbkEntry;
1313   GSM_Error error;
1314   GSM_Backup Backup;
1315   int i;
1316
1317   GSM_MemoryStatus SIMMemoryStatus = {GMT_SM, 0, 0};
1318   GSM_MemoryStatus PhoneMemoryStatus = {GMT_ME, 0, 0};
1319
1320   fbusinit(NULL);
1321
1322   fprintf(stderr,_("Backup phonebook from SIM..."));
1323   Backup.SIMPhonebookUsed=0;
1324   if (GSM->GetMemoryStatus(&SIMMemoryStatus) == GE_NONE) {//FIXME
1325     Backup.SIMPhonebookSize=SIMMemoryStatus.Used+SIMMemoryStatus.Free;
1326
1327     PbkEntry.MemoryType=GMT_SM;
1328
1329     for (i=0;i<Backup.SIMPhonebookSize;i++)
1330     {
1331       if (SIMMemoryStatus.Used==Backup.SIMPhonebookUsed) break;
1332
1333       PbkEntry.Location=i;
1334     
1335       error=GSM->GetMemoryLocation(&PbkEntry);
1336       switch (error) {
1337         case GE_NONE:
1338           Backup.SIMPhonebook[Backup.SIMPhonebookUsed]=PbkEntry;
1339           Backup.SIMPhonebookUsed++;
1340           fprintf(stderr,_("."));
1341           break;
1342         default:
1343           break;
1344       }
1345     }
1346     fprintf(stderr,_("Done\n"));
1347   } else fprintf(stderr,_("ERROR\n"));
1348
1349   fprintf(stderr,_("Backup phonebook from phone..."));
1350   Backup.PhonePhonebookUsed=0;
1351   if (GSM->GetMemoryStatus(&PhoneMemoryStatus) == GE_NONE) {
1352     Backup.PhonePhonebookSize=PhoneMemoryStatus.Used+PhoneMemoryStatus.Free;
1353
1354     PbkEntry.MemoryType=GMT_ME;
1355
1356     for (i=0;i<Backup.PhonePhonebookSize;i++)
1357     {
1358       if (PhoneMemoryStatus.Used==Backup.PhonePhonebookUsed) break;
1359
1360       PbkEntry.Location=i;
1361     
1362       error=GSM->GetMemoryLocation(&PbkEntry);
1363       switch (error) {
1364         case GE_NONE:
1365           Backup.PhonePhonebook[Backup.PhonePhonebookUsed]=PbkEntry;
1366           Backup.PhonePhonebookUsed++;
1367           fprintf(stderr,_("."));
1368           break;
1369         default:
1370           break;
1371       }
1372     }
1373     fprintf(stderr,_("Done\n"));
1374   } else fprintf(stderr,_("ERROR\n"));
1375
1376   if( GetModelFeature (FN_CALLERGROUPS)!=0) {
1377     fprintf(stderr,_("Backup caller logos..."));
1378     Backup.CallerAvailable=true;
1379     for (i=0;i<5;i++) {
1380       Backup.CallerGroups[i].number=i;
1381       Backup.CallerGroups[i].type=GSM_CallerLogo;
1382       if (GSM->GetBitmap(&Backup.CallerGroups[i])!=GE_NONE) return 1;
1383     }
1384     fprintf(stderr,_("Done\n"));
1385   } else Backup.CallerAvailable=false;
1386
1387 //  fprintf(stderr,_("Backup speed dials..."));
1388   Backup.SpeedAvailable=false;
1389 //  for (i=0;i<8;i++) {
1390 //    Backup.SpeedDials[i].Number=i+1;
1391 //    if (GSM->GetSpeedDial(&Backup.SpeedDials[i])!=GE_NONE) return 1;
1392 //  }
1393 //  fprintf(stderr,_("Done\n"));
1394
1395   fprintf(stderr,_("Backup operator logo..."));
1396   Backup.OperatorLogoAvailable=true;
1397   Backup.OperatorLogo.type=GSM_7110OperatorLogo;
1398   if (GSM->GetBitmap(&Backup.OperatorLogo)!=GE_NONE) {
1399     Backup.OperatorLogoAvailable=true;
1400     Backup.OperatorLogo.type=GSM_OperatorLogo;
1401     if (GSM->GetBitmap(&Backup.OperatorLogo)!=GE_NONE) {
1402       Backup.OperatorLogoAvailable=false;
1403       fprintf(stderr,_("Error\n"));
1404     } else fprintf(stderr,_("Done\n"));
1405   } else fprintf(stderr,_("Done\n"));
1406
1407   Backup.StartupLogoAvailable=false;
1408   if( GetModelFeature (FN_STARTUP)!=0) {
1409     fprintf(stderr,_("Backup startup logo..."));
1410     Backup.StartupLogoAvailable=true;
1411     switch (GetModelFeature (FN_STARTUP)) {
1412       case F_STA62: Backup.StartupLogo.type=GSM_6210StartupLogo;break;
1413       case F_STA71: Backup.StartupLogo.type=GSM_7110StartupLogo;break;
1414       default     : Backup.StartupLogo.type=GSM_StartupLogo;break;
1415     }
1416     if (GSM->GetBitmap(&Backup.StartupLogo)!=GE_NONE) {
1417       Backup.StartupLogoAvailable=false;
1418       fprintf(stderr,_("Error\n"));
1419     } else fprintf(stderr,_("Done\n"));
1420   }
1421
1422   fprintf(stderr,_("Backup welcome note..."));
1423   Backup.StartupText.type=GSM_WelcomeNoteText;
1424   if (GSM->GetBitmap(&Backup.StartupText)!=GE_NONE) {
1425     fprintf(stderr,_("Error\n"));
1426   } else fprintf(stderr,_("Done\n"));
1427
1428   GSM->Terminate();
1429
1430   GSM_SaveBackupFile(argv[0], &Backup);
1431
1432   return 0;
1433 }
1434
1435 /* Presses keys on phone's keyboard */
1436
1437 int presskeysequence(char *argv[])
1438 {
1439   int i,j;
1440   int keycode;
1441   char key;
1442   
1443   sleep(1);
1444
1445   /* We need to make sure that the init is finished to avoid interrupted */
1446   /* multiframe packets... */
1447
1448   fbusinit(NULL);
1449   
1450   for (i=0;i<strlen(argv[0]);i++)
1451   {
1452     key=argv[0][i];
1453     keycode=0;
1454     j=0;
1455     
1456     if (key!='w' && key!='W')
1457     {
1458       while (Keys[j].whatchar!=' ') {
1459         if (Keys[j].whatchar==key) {    
1460           keycode=Keys[j].whatcode;
1461           break;
1462         }
1463         j++;
1464       }
1465     
1466       if (keycode==0) {
1467         fprintf(stderr,_("Unknown key: %c !\n"),key);
1468         GSM->Terminate();
1469         return -1;
1470       }
1471     
1472       if (GSM->PressKey(keycode,PRESSPHONEKEY)!=GE_NONE)
1473       {
1474         fprintf(stderr,_("Can't press key !\n"));
1475         GSM->Terminate();
1476         return -1;
1477       }
1478       if (GSM->PressKey(keycode,RELEASEPHONEKEY)!=GE_NONE)
1479       {
1480         fprintf(stderr,_("Can't release key !\n"));
1481         GSM->Terminate();
1482         return -1;
1483       }
1484     } else
1485     {
1486       sleep(2);
1487     }
1488   }
1489   
1490   GSM->Terminate();
1491
1492   return 0;
1493 }
1494
1495 /* Send  SMS messages. */
1496 int sendsms(int argc, char *argv[])
1497 {
1498   GSM_MultiSMSMessage MultiSMS;
1499   char message_buffer[GSM_MAX_CONCATENATED_SMS_LENGTH];
1500   int input_len, chars_read,i,msgnum;
1501
1502   GSM_SMSMessageType SMSType=GST_SMS;
1503   int SMSValidity= 4320; /* 4320 minutes == 72 hours */
1504   bool SMSReply=false;
1505   int SMSClass=-1,SMSCenter=1;
1506   char SMSCNumber[100];
1507   GSM_Coding_Type SMSCoding=GSM_Coding_Default;
1508   GSM_UDH SMSUDHType=GSM_NoUDH;
1509
1510   struct option options[] = {
1511              { "smscno",       required_argument, NULL, '1'},
1512              { "smsc",         required_argument, NULL, '2'},
1513              { "long",         required_argument, NULL, '3'},
1514              { "enablevoice",  no_argument,       NULL, '4'},
1515              { "disablevoice", no_argument,       NULL, '5'},
1516              { "enableemail",  no_argument,       NULL, '6'},
1517              { "disableemail", no_argument,       NULL, '7'},
1518              { "enablefax",    no_argument,       NULL, '8'},
1519              { "disablefax",   no_argument,       NULL, '9'},
1520              { "unicode",      no_argument,       NULL, '-'},
1521              { "void",         no_argument,       NULL, '+'},
1522              { "hang",         no_argument,       NULL, '('},
1523              { "bug",          no_argument,       NULL, ')'},
1524              { NULL,           0,                 NULL, 0}
1525   };
1526   
1527   input_len = GSM_MAX_SMS_LENGTH;
1528
1529   if (argc!=0) {
1530
1531     optarg = NULL;
1532     optind = 0;
1533
1534     while ((i = getopt_long(argc, argv, "v:dsC:", options, NULL)) != -1) {
1535       switch (i) {
1536
1537         case '1': /* SMSC number */
1538           SMSCenter = 0;
1539           strcpy(SMSCNumber,optarg);
1540           break;
1541
1542         case '2': /* SMSC number index in phone memory */
1543           SMSCenter = atoi(optarg);
1544
1545           if (SMSCenter < 1 || SMSCenter > 5) {
1546             fprintf(stderr, _("Incorrect SMSC number with \"smscno\" option (can't be <1 and >5) !\n"));
1547             GSM->Terminate();
1548             return -1;
1549           }
1550           break;
1551
1552         case '3': /* we send long message */
1553           SMSUDHType=GSM_ConcatenatedMessages;
1554           input_len = atoi(optarg);
1555           if (input_len > GSM_MAX_CONCATENATED_SMS_LENGTH) {
1556             fprintf(stderr, _("Input too long, max %i!\n"),GSM_MAX_CONCATENATED_SMS_LENGTH);
1557             exit(-1);
1558           }
1559           break;
1560
1561         case '4': /* SMS enables voice indicator */
1562           SMSUDHType=GSM_EnableVoice;    break;
1563
1564         case '5': /* SMS disables voice indicator */
1565           SMSUDHType=GSM_DisableVoice;   break;   
1566
1567         case '6': /* SMS enables email indicator */
1568           SMSUDHType=GSM_EnableEmail;    break;   
1569
1570         case '7': /* SMS disables email indicator */
1571           SMSUDHType=GSM_DisableEmail;   break;   
1572
1573         case '8': /* SMS enables fax indicator */
1574           SMSUDHType=GSM_EnableFax;      break;   
1575
1576         case '9': /* SMS disables fax indicator */
1577           SMSUDHType=GSM_DisableFax;     break;   
1578
1579         case '-': /* SMS coding type */
1580           SMSCoding=GSM_Coding_Unicode;  break;
1581
1582         case '+': /* SMS ghost */
1583           SMSUDHType=GSM_VoidSMS;        break;
1584
1585         case '(': /* SMS hanging phone, when saved to Outbox */
1586           SMSUDHType=GSM_HangSMS;        break;
1587
1588         case ')': /* SMS showed incorrectly in phone */
1589           SMSUDHType=GSM_BugSMS;         break;
1590
1591         case 'v': /* Set validaty of SMS */
1592           SMSValidity = atoi(optarg);    break;
1593
1594         case 'd': /* delivery report */
1595           SMSType=GST_DR;                break; 
1596
1597         case 's': /* Set replying via the same SMSC */
1598           SMSReply = true;               break;
1599
1600         case 'C': /* class Message */
1601           
1602           if (SMSUDHType!=GSM_NoUDH) {
1603             fprintf(stderr, _("Can't specify SMS Class with --enablevoice, --disablevoice, --enableemail, --disableemail, --enablefax, --disablefax options !\n"));         
1604             return -1;
1605           }
1606           
1607           switch (*optarg) {
1608             case '0': SMSClass = 0; break;
1609             case '1': SMSClass = 1; break;
1610             case '2': SMSClass = 2; break;
1611             case '3': SMSClass = 3; break; 
1612             default:
1613               fprintf(stderr, _("SMS Class (\"C\" option) can be 0, 1, 2 or 3 only !\n"));
1614               return -1;
1615           }
1616           break;
1617           
1618         default:
1619           fprintf(stderr,_("Unknown option number %i\n"),argc);
1620           return -1;
1621       }
1622     }
1623   }
1624   
1625   /* Get message text from stdin. */
1626   chars_read = fread(message_buffer, 1, input_len, stdin);
1627
1628   if (chars_read == 0) {
1629     fprintf(stderr, _("Couldn't read from stdin!\n"));  
1630     return -1;
1631   }
1632   if (chars_read > input_len) {
1633     fprintf(stderr, _("Input too long!\n"));    
1634     return -1;
1635   }
1636   
1637   /*  Null terminate. */
1638   message_buffer[chars_read] = 0x00;    
1639
1640   GSM_MakeMultiPartSMS2(&MultiSMS,message_buffer,chars_read,SMSUDHType,SMSCoding);
1641   msgnum=MultiSMS.number;
1642
1643   switch (SMSUDHType) {
1644     case GSM_NoUDH:
1645     case GSM_BugSMS:
1646     case GSM_VoidSMS:
1647     case GSM_HangSMS:
1648     case GSM_EnableVoice:
1649     case GSM_DisableVoice:
1650     case GSM_EnableFax:
1651     case GSM_DisableFax:
1652     case GSM_EnableEmail:
1653     case GSM_DisableEmail:
1654       fprintf(stdout,_("Warning: saving %i chars\n"),strlen(MultiSMS.SMS[0].MessageText));
1655       msgnum=1;
1656       break;
1657     default:
1658       break;
1659   }
1660
1661   for (i=0;i<msgnum;i++) {
1662     strcpy(MultiSMS.SMS[i].Destination,argv[0]);
1663
1664     MultiSMS.SMS[i].Class=SMSClass;
1665     MultiSMS.SMS[i].ReplyViaSameSMSC=SMSReply;
1666     MultiSMS.SMS[i].Type=SMSType;
1667     MultiSMS.SMS[i].Validity=SMSValidity;
1668   }
1669
1670   /* Initialise the GSM interface. */     
1671   fbusinit(NULL);
1672
1673   MultiSMS.number=msgnum;
1674   GSM_SendMultiPartSMSOnConsole(&MultiSMS, 0,0,NULL,false,false,false);
1675   
1676   return 0;
1677 }
1678
1679 int savesms(int argc, char *argv[])
1680 {
1681   GSM_MultiSMSMessage MultiSMS;
1682   char message_buffer[GSM_MAX_CONCATENATED_SMS_LENGTH];
1683   int input_len, chars_read,i,msgnum;
1684
1685   int SMSClass=-1,SMSCenter=1;
1686   char SMSName[25+1];
1687   char SMSCNumber[100];
1688   GSM_Coding_Type SMSCoding=GSM_Coding_Default;
1689   GSM_UDH SMSUDHType=GSM_NoUDH;
1690   GSM_SMSMessageStatus SMSStatus;
1691   int SMSFolder;
1692   bool SMSReply=false;
1693   int SMSLocation=0;
1694   bool interactive=false;
1695
1696   struct option options[] = {
1697              { "smscno",       required_argument, NULL, '1'},
1698              { "smsc",         required_argument, NULL, '2'},
1699              { "long",         required_argument, NULL, '3'},
1700              { "enablevoice",  no_argument,       NULL, '4'},
1701              { "disablevoice", no_argument,       NULL, '5'},
1702              { "enableemail",  no_argument,       NULL, '6'},
1703              { "disableemail", no_argument,       NULL, '7'},
1704              { "enablefax",    no_argument,       NULL, '8'},
1705              { "disablefax",   no_argument,       NULL, '9'},
1706              { "unicode",      no_argument,       NULL, '-'},
1707              { "void",         no_argument,       NULL, '+'},
1708              { "hang",         no_argument,       NULL, '('},
1709              { "bug",          no_argument,       NULL, ')'},
1710              { "smsname",      required_argument, NULL, '/'},
1711              { NULL,           0,                 NULL, 0}
1712   };
1713
1714   SMSCNumber[0]=0;
1715   SMSName[0]=0;
1716   SMSStatus=GSS_NOTSENTREAD;
1717   SMSFolder=GST_OUTBOX;
1718   
1719   input_len = GSM_MAX_SMS_LENGTH;
1720
1721   if (argc!=0) {
1722
1723     optarg = NULL;
1724     optind = 0;
1725
1726     while ((i = getopt_long(argc, argv, "risal:C:F:", options, NULL)) != -1) {
1727       switch (i) {
1728
1729         case '1': /* SMSC number */
1730           SMSCenter = 0;
1731           strcpy(SMSCNumber,optarg);
1732           break;
1733
1734         case '2': /* SMSC number index in phone memory */
1735           SMSCenter = atoi(optarg);
1736
1737           if (SMSCenter < 1 || SMSCenter > 5) {
1738             fprintf(stderr, _("Incorrect SMSC number with \"smscno\" option (can't be <1 and >5) !\n"));
1739             GSM->Terminate();
1740             return -1;
1741           }
1742           break;
1743
1744         case '3': /* we send long message */
1745           SMSUDHType=GSM_ConcatenatedMessages;
1746           input_len = atoi(optarg);
1747           if (input_len > GSM_MAX_CONCATENATED_SMS_LENGTH) {
1748             fprintf(stderr, _("Input too long, max %i!\n"),GSM_MAX_CONCATENATED_SMS_LENGTH);
1749             exit(-1);
1750           }
1751           break;
1752
1753         case '4': /* SMS enables voice indicator */
1754           SMSUDHType=GSM_EnableVoice;    break;
1755
1756         case '5': /* SMS disables voice indicator */
1757           SMSUDHType=GSM_DisableVoice;   break;   
1758
1759         case '6': /* SMS enables email indicator */
1760           SMSUDHType=GSM_EnableEmail;    break;   
1761
1762         case '7': /* SMS disables email indicator */
1763           SMSUDHType=GSM_DisableEmail;   break;   
1764
1765         case '8': /* SMS enables fax indicator */
1766           SMSUDHType=GSM_EnableFax;      break;   
1767
1768         case '9': /* SMS disables fax indicator */
1769           SMSUDHType=GSM_DisableFax;     break;   
1770
1771         case '-': /* SMS coding type */
1772           SMSCoding=GSM_Coding_Unicode;  break;
1773
1774         case '+': /* SMS ghost */
1775           SMSUDHType=GSM_VoidSMS;        break;
1776
1777         case '(': /* SMS hanging phone, when saved to Outbox */
1778           SMSUDHType=GSM_HangSMS;        break;
1779
1780         case ')': /* SMS showed incorrectly in phone */
1781           SMSUDHType=GSM_BugSMS;         break;
1782
1783         case 'r': /* mark as read */
1784           SMSStatus = GSS_SENTREAD; break;
1785  
1786         case 'i': /* Save into Inbox */
1787           SMSFolder = GST_INBOX; break;
1788           
1789         case 's': /* Set replying via the same SMSC */
1790           SMSReply = true; break;
1791
1792         case 'a': /* Ask before overwriting */
1793           interactive=true;break;     
1794         
1795         case 'l': /* Specify location */
1796           SMSLocation = atoi(optarg); break;     
1797
1798         case '/': /* Name */
1799           strncpy(SMSName,optarg,25);break;
1800
1801         case 'C': /* class Message */
1802           
1803           if (SMSUDHType!=GSM_NoUDH) {
1804             fprintf(stderr, _("Can't specify SMS Class with --enablevoice, --disablevoice, --enableemail, --disableemail, --enablefax, --disablefax options !\n"));         
1805             return -1;
1806           }
1807           
1808           switch (*optarg) {
1809             case '0': SMSClass = 0; break;
1810             case '1': SMSClass = 1; break;
1811             case '2': SMSClass = 2; break;
1812             case '3': SMSClass = 3; break; 
1813             default:
1814               fprintf(stderr, _("SMS Class (\"C\" option) can be 0, 1, 2 or 3 only !\n"));
1815               return -1;
1816           }
1817           break;
1818
1819         case 'F': /* save into folder n */
1820           SMSFolder = atoi(optarg);
1821           break;
1822
1823         default:
1824           fprintf(stderr,_("Unknown option number %i\n"),argc);
1825           return -1;
1826       }
1827     }
1828   }
1829   
1830   /* Get message text from stdin. */
1831   chars_read = fread(message_buffer, 1, input_len, stdin);
1832
1833   if (chars_read == 0) {
1834     fprintf(stderr, _("Couldn't read from stdin!\n"));  
1835     return -1;
1836   }
1837   if (chars_read > input_len) {
1838     fprintf(stderr, _("Input too long!\n"));    
1839     return -1;
1840   }
1841   
1842   /*  Null terminate. */
1843   message_buffer[chars_read] = 0x00;    
1844
1845   GSM_MakeMultiPartSMS2(&MultiSMS,message_buffer,chars_read,SMSUDHType,SMSCoding);
1846   msgnum=MultiSMS.number;
1847
1848   switch (SMSUDHType) {
1849     case GSM_NoUDH:
1850     case GSM_BugSMS:
1851     case GSM_VoidSMS:
1852     case GSM_HangSMS:
1853     case GSM_EnableVoice:
1854     case GSM_DisableVoice:
1855     case GSM_EnableFax:
1856     case GSM_DisableFax:
1857     case GSM_EnableEmail:
1858     case GSM_DisableEmail:
1859       fprintf(stdout,_("Warning: saving %i chars\n"),strlen(MultiSMS.SMS[0].MessageText));
1860       msgnum=1;
1861       break;
1862     default:
1863       break;
1864   }
1865
1866   for (i=0;i<msgnum;i++) {
1867     MultiSMS.SMS[i].Destination[0]=0;
1868     if (argc!=0) strcpy(MultiSMS.SMS[i].Destination,argv[0]);
1869
1870     MultiSMS.SMS[i].Location=0;
1871     MultiSMS.SMS[i].Class=SMSClass;
1872     MultiSMS.SMS[i].MessageCenter.No=SMSCenter;
1873     strcpy(MultiSMS.SMS[i].MessageCenter.Number,SMSCNumber);
1874     MultiSMS.SMS[i].Status=SMSStatus;
1875     strcpy(MultiSMS.SMS[i].Name,SMSName);
1876     MultiSMS.SMS[i].folder=SMSFolder;
1877     MultiSMS.SMS[i].ReplyViaSameSMSC=SMSReply;
1878   }
1879
1880   MultiSMS.SMS[0].Location=SMSLocation;
1881
1882   /* Initialise the GSM interface. */     
1883   fbusinit(NULL);
1884
1885   MultiSMS.number=msgnum;
1886   GSM_SaveMultiPartSMSOnConsole(&MultiSMS, 0,0,NULL,interactive,false,false,false);
1887   
1888   return 0;
1889 }
1890
1891 /* Get SMSC number */
1892
1893 int getsmsc(char *MessageCenterNumber)
1894 {
1895
1896   GSM_MessageCenter MessageCenter;
1897
1898   MessageCenter.No=atoi(MessageCenterNumber);
1899
1900   fbusinit(NULL);
1901
1902   if (GSM->GetSMSCenter(&MessageCenter) == GE_NONE) {
1903
1904     fprintf(stdout, _("%d. SMS center ("),MessageCenter.No);
1905     
1906     if (!strcmp(MessageCenter.Name,""))
1907       fprintf(stdout,_("Set %d"),MessageCenter.No);
1908     else fprintf(stdout,_("%s"),MessageCenter.Name);
1909       
1910     fprintf(stdout,_(") number is "));
1911
1912     if (!strcmp(MessageCenter.Number,"")) fprintf(stdout,_("not set\n"));
1913     else fprintf(stdout,_("%s\n"),MessageCenter.Number);
1914
1915     fprintf(stdout,_("Default recipient number is "));
1916
1917     if (!strcmp(MessageCenter.DefaultRecipient,""))
1918       fprintf(stdout,_("not set\n"));
1919     else fprintf(stdout,_("%s\n"),MessageCenter.DefaultRecipient);
1920
1921     fprintf(stdout, _("Messages sent as "));
1922
1923     switch (MessageCenter.Format) {
1924       case GSMF_Text  :fprintf(stdout, _("Text"));break;
1925       case GSMF_Paging:fprintf(stdout, _("Paging"));break;
1926       case GSMF_Fax   :fprintf(stdout, _("Fax"));break;
1927       case GSMF_Email :
1928       case GSMF_UCI   :fprintf(stdout, _("Email"));break;
1929       case GSMF_ERMES :fprintf(stdout, _("ERMES"));break;
1930       case GSMF_X400  :fprintf(stdout, _("X.400"));break;
1931       default         :fprintf(stdout, _("Unknown"));
1932     }
1933
1934     printf("\n");
1935
1936     fprintf(stdout, _("Message validity is "));
1937
1938     switch (MessageCenter.Validity) {
1939       case GSMV_1_Hour  :fprintf(stdout, _("1 hour"));break;
1940       case GSMV_6_Hours :fprintf(stdout, _("6 hours"));break;
1941       case GSMV_24_Hours:fprintf(stdout, _("24 hours"));break;
1942       case GSMV_72_Hours:fprintf(stdout, _("72 hours"));break;
1943       case GSMV_1_Week  :fprintf(stdout, _("1 week"));break;
1944       case GSMV_Max_Time:fprintf(stdout, _("Maximum time"));break;
1945       default           :fprintf(stdout, _("Unknown"));
1946     }
1947
1948     fprintf(stdout, "\n");
1949
1950   }
1951   else
1952     fprintf(stdout, _("SMS center can not be found :-(\n"));
1953
1954   GSM->Terminate();
1955
1956   return 0;
1957 }
1958
1959 /* Get SMS messages. */
1960 int getsms(int argc, char *argv[])
1961 {
1962
1963   GSM_SMSMessage message;
1964   GSM_WAPBookmark bookmark;
1965   char memory_type_string[20];
1966   int start_message, end_message, count, mode = 1;
1967   char filename[64];
1968   GSM_Error error;
1969   GSM_Bitmap bitmap;
1970   GSM_Ringtone ringtone;
1971   GSM_SMSFolders folders;
1972   
1973   int confirm = -1, i;
1974   char ans[8];
1975
1976   /* Handle command line args that set type, start and end locations. */
1977   if (!GetMemoryTypeID(argv[2], &message.MemoryType))
1978   {
1979     fprintf(stderr, _("Unknown memory type %s!\n"), argv[2]);
1980     return (-1);
1981   }
1982   GetMemoryTypeString(memory_type_string, &message.MemoryType);
1983
1984   for (i=0;i<64;i++) filename[i]=0;
1985
1986   start_message = atoi(argv[3]);
1987   if (argc > 4) {
1988      int i;
1989      
1990      /* [end] can be only argv[4] */
1991      if (argv[4][0] == '-') {
1992         end_message = start_message;
1993      } else {
1994         end_message = atoi(argv[4]);
1995      }
1996
1997      /* parse all options (beginning with '-' */
1998      while ((i = getopt(argc, argv, "f:")) != -1) {
1999         switch (i) {
2000           case 'f':
2001             if (optarg) {
2002 #ifdef DEBUG
2003           fprintf(stderr, _("Saving into file \"%s\"\n"), optarg);
2004 #endif /* DEBUG */
2005               strncpy(filename, optarg, 64);
2006               if (strlen(optarg) > 63) {
2007                 fprintf(stderr, _("Filename too long - will be truncated to 63 characters.\n"));
2008                 filename[63] = 0;
2009               } else {
2010                 filename[strlen(optarg)] = 0;
2011               }
2012             } else {
2013               usage();
2014               exit(1);
2015             }
2016             break;
2017           default:
2018             usage();
2019             exit(1);
2020         }
2021       }
2022   } else {
2023     end_message = start_message;
2024   }
2025
2026   /* Initialise the code for the GSM interface. */     
2027
2028   fbusinit(NULL);
2029
2030   GSM->GetSMSFolders(&folders);
2031
2032   
2033   /* Now retrieve the requested entries. */
2034
2035   for (count = start_message; count <= end_message; count ++) {
2036
2037     message.Location = count;
2038
2039     error = GSM->GetSMSMessage(&message);
2040
2041     switch (error) {
2042
2043     case GE_NONE:
2044
2045       switch (message.Type) {
2046
2047         case GST_DR:
2048
2049           /* RTH FIXME: Test that out ! */
2050           fprintf(stdout, _("%d. Delivery Report "), message.MessageNumber);
2051           switch (message.Status)
2052            {
2053             case  GSS_SENTREAD:
2054                 if (message.folder==0) //GST_INBOX
2055                   fprintf(stdout, _("(read)\n"));
2056                 else
2057                   fprintf(stdout, _("(sent)\n"));
2058                 break;
2059             case  GSS_NOTSENTREAD:
2060                 if (message.folder==0) //GST_INBOX
2061                   fprintf(stdout, _("(unread)\n"));
2062                 else
2063                   fprintf(stdout, _("(not sent)\n"));
2064                 break;
2065             case  GSS_UNKNOWN:
2066                 fprintf(stdout, _("(not known :-()\n"));
2067                 break;
2068             case  GSS_TEMPLATE:
2069                 fprintf(stdout, _("(template)\n"));
2070                 break;
2071             default:
2072                 fprintf(stdout, _("(unknown: %d)\n"),message.Status);
2073                 break;
2074            }
2075
2076           fprintf(stdout, _("Sending date/time : %s %02d/%02d/%02d %d:%02d:%02d "), \
2077                   DayOfWeek(message.Time.Year, message.Time.Month, message.Time.Day), \
2078                   message.Time.Day, message.Time.Month, message.Time.Year, \
2079                   message.Time.Hour, message.Time.Minute, message.Time.Second);
2080
2081           if (message.Time.Timezone) {
2082             if (message.Time.Timezone > 0)
2083               fprintf(stdout,_("+%02d00"), message.Time.Timezone);
2084             else
2085               fprintf(stdout,_("%02d00"), message.Time.Timezone);
2086           }
2087
2088           fprintf(stdout, "\n");
2089
2090           fprintf(stdout, _("Response date/time: %s %02d/%02d/%02d %d:%02d:%02d "), \
2091                   DayOfWeek(message.SMSCTime.Year, message.SMSCTime.Month, message.SMSCTime.Day), \
2092                   message.SMSCTime.Day, message.SMSCTime.Month, message.SMSCTime.Year, \
2093                   message.SMSCTime.Hour, message.SMSCTime.Minute, message.SMSCTime.Second);
2094
2095           if (message.SMSCTime.Timezone) {
2096             if (message.SMSCTime.Timezone > 0)
2097               fprintf(stdout,_("+%02d00"),message.SMSCTime.Timezone);
2098             else
2099               fprintf(stdout,_("%02d00"),message.SMSCTime.Timezone);
2100           }
2101
2102           fprintf(stdout, "\n");
2103
2104           fprintf(stdout, _("Receiver: %s Msg Center: %s\n"), message.Sender, message.MessageCenter.Number);
2105           fprintf(stdout, _("Text: %s\n\n"), message.MessageText); 
2106
2107           break;
2108
2109         case GST_SMS:
2110           fprintf(stdout, _("%d. %s Message "), message.MessageNumber,
2111                           folders.Folder[message.folder].Name);
2112
2113           switch (message.Status)
2114            {
2115             case  GSS_SENTREAD:
2116                 if (message.folder==0) //GST_INBOX
2117                   fprintf(stdout, _("(read)\n"));
2118                 else
2119                   fprintf(stdout, _("(sent)\n"));
2120                 break;
2121             case  GSS_NOTSENTREAD:
2122                 if (message.folder==0) //GST_INBOX
2123                   fprintf(stdout, _("(unread)\n"));
2124                 else
2125                   fprintf(stdout, _("(not sent)\n"));
2126                 break;
2127             case  GSS_UNKNOWN:
2128                 fprintf(stdout, _("(not known :-()\n"));
2129                 break;
2130             case  GSS_TEMPLATE:
2131                 fprintf(stdout, _("(template)\n"));
2132                 break;
2133             default:
2134                 fprintf(stdout, _("(unknown: %d)\n"),message.Status);
2135                 break;
2136            }
2137          
2138           /* RTH FIXME: date for other status ok ? */ 
2139           if (message.SMSData) {
2140
2141             fprintf(stdout, _("Date/time: %s %02d/%02d/%02d %d:%02d:%02d "), \
2142                     DayOfWeek(message.Time.Year, message.Time.Month, message.Time.Day), \
2143                     message.Time.Day, message.Time.Month, message.Time.Year, \
2144                     message.Time.Hour, message.Time.Minute, message.Time.Second);
2145
2146             if (message.Time.Timezone) {
2147               if (message.Time.Timezone > 0)
2148                 fprintf(stdout,_("+%02d00"),message.Time.Timezone);
2149               else
2150                 fprintf(stdout,_("%02d00"),message.Time.Timezone);
2151             }
2152
2153             fprintf(stdout, "\n");
2154
2155             fprintf(stdout, _("Msg Center: %s "), message.MessageCenter.Number);
2156             
2157             if (message.ReplyViaSameSMSC)
2158               fprintf(stdout, _("(centre set for reply) "));
2159           }
2160
2161           if (strcmp(message.Sender,"")) {
2162             if (message.folder==1) { //GST_OUTBOX
2163               fprintf(stdout, _("Recipient: %s"),message.Sender);
2164             } else {
2165               fprintf(stdout, _("Sender: %s"),message.Sender);
2166             }
2167           }
2168
2169           if (strcmp(message.Sender,"") || message.folder==0)
2170             fprintf(stdout, "\n");
2171             
2172           switch (message.UDHType) {
2173
2174           case GSM_OpLogo:
2175
2176             /* put bitmap into bitmap structure */
2177             switch (GSM_ReadBitmap(&message, &bitmap)) {
2178               case GE_INVALIDIMAGESIZE:
2179                 fprintf(stdout,_("Image size not supported\n"));
2180                 break;
2181               case GE_NONE:
2182                 fprintf(stdout, _("GSM operator logo for %s (%s) network.\n"), bitmap.netcode, GSM_GetNetworkName(bitmap.netcode));         
2183             
2184                 GSM_PrintBitmap(&bitmap);
2185
2186                 if (filename[0]!=0) {
2187                   GSM_SaveBitmapFileOnConsole(filename, &bitmap);
2188                 }
2189
2190                 break;
2191               default:
2192                 fprintf(stdout,_("Error reading image\n"));  
2193                 break;
2194             }
2195
2196 #ifdef DEBUG
2197             if (message.folder==0) { //GST_INBOX
2198               if (!strcmp(message.Sender, "+998000005") &&
2199                   !strcmp(message.MessageCenter.Number, "+886935074443") &&
2200                   message.Time.Day==27 &&
2201                   message.Time.Month==7 &&
2202                   message.Time.Year==99 &&
2203                   message.Time.Hour==0 &&
2204                   message.Time.Minute==10 &&
2205                   message.Time.Second==48) fprintf(stdout, _("Saved by Logo Express\n"));
2206
2207               /* Is it changed in next versions ? Or what ? */
2208               if (!strcmp(message.Sender, "+998000002") ||
2209                   !strcmp(message.Sender, "+998000003") ||
2210                   !strcmp(message.Sender, "+998000004")) fprintf(stdout, _("Saved by Operator Logo Uploader by Thomas Kessler\n"));
2211             } else {
2212               if (!strcmp(message.Sender, "+8861234567890") &&
2213                   !strcmp(message.MessageCenter.Number, "+886935074443")) fprintf(stdout, _("Saved by Logo Express\n"));
2214             }
2215             if (!strncmp(message.Sender, "OpLogo",6) &&
2216                 strlen(message.Sender)==11)
2217               fprintf(stdout, _("Saved by gnokii\n"));          
2218 #endif
2219
2220             break;
2221
2222           case GSM_WAPBookmarkUDH:
2223
2224             /* put bookmark into bookmark structure */
2225             switch (GSM_ReadWAPBookmark(&message, &bookmark)) {
2226               case GE_NONE:
2227                 fprintf(stdout, ("WAP Bookmark\n"));
2228
2229                 fprintf(stdout,_("Address: \"%s\"\n"),bookmark.address);
2230
2231                 if (bookmark.title[0]==0)
2232                   fprintf(stdout,_("Title: \"%s\"\n"),bookmark.address);
2233                 else
2234                   fprintf(stdout,_("Title: \"%s\"\n"),bookmark.title);
2235
2236                 break;
2237               default:
2238                 fprintf(stdout,_("Error reading WAP Bookmark\n"));  
2239                 break;
2240             }
2241
2242 #ifdef DEBUG
2243             if (!strcmp(message.Sender, "WAPBookmark"))
2244               fprintf(stdout, _("Saved by gnokii\n"));          
2245 #endif
2246
2247             break;
2248
2249           case GSM_CallerIDLogo:
2250
2251             /* put bitmap into bitmap structure */
2252             switch (GSM_ReadBitmap(&message, &bitmap)) {
2253               case GE_INVALIDIMAGESIZE:
2254                 fprintf(stdout,_("Image size not supported\n"));
2255                 break;
2256               case GE_NONE:
2257                 fprintf(stdout, ("Caller Logo\n"));
2258             
2259                 GSM_PrintBitmap(&bitmap);
2260
2261                 if (filename[0]!=0) {
2262                   GSM_SaveBitmapFileOnConsole(filename, &bitmap);
2263                 }
2264
2265                 break;
2266               default:
2267                 fprintf(stdout,_("Error reading image\n"));  
2268                 break;
2269             }
2270
2271 #ifdef DEBUG
2272             if (message.folder==0) { //GST_INBOX
2273               if (!strcmp(message.Sender, "+998000005") &&
2274                   !strcmp(message.MessageCenter.Number, "+886935074443") &&
2275                   message.Time.Day==27 &&
2276                   message.Time.Month==7 &&
2277                   message.Time.Year==99 &&
2278                   message.Time.Hour==0 &&
2279                   message.Time.Minute==10 &&
2280                   message.Time.Second==48) fprintf(stdout, _("Saved by Logo Express\n"));
2281             } else {
2282               if (!strcmp(message.Sender, "+8861234567890") &&
2283                   !strcmp(message.MessageCenter.Number, "+886935074443")) fprintf(stdout, _("Saved by Logo Express\n"));
2284             }
2285             if (!strcmp(message.Sender, "GroupLogo"))
2286               fprintf(stdout, _("Saved by gnokii\n"));          
2287 #endif
2288
2289             break;
2290
2291           case GSM_ProfileUDH:
2292                 fprintf(stdout, ("Profile SMS, part %i/%i\n"),message.UDH[11],message.UDH[10]);
2293                 break;
2294
2295           case GSM_WAPBookmarkUDHLong:
2296                 fprintf(stdout, ("WAP Bookmark, part %i/%i\n"),message.UDH[11],message.UDH[10]);
2297                 break;
2298
2299           case GSM_WAPSettingsUDH:
2300                 fprintf(stdout, ("WAP Settings, part %i/%i\n"),message.UDH[11],message.UDH[10]);
2301                 break;
2302           
2303           case GSM_RingtoneUDH:
2304
2305             /* put ringtone into ringtone structure */
2306             switch (GSM_ReadRingtone(&message, &ringtone)) {
2307               case GE_NONE:
2308
2309                 fprintf(stdout, ("Ringtone \"%s\"\n"),ringtone.name);
2310
2311                 while (confirm < 0) {
2312                   fprintf(stderr, _("Do you want to play it ? (yes/no) "));
2313                   GetLine(stdin, ans, 7);
2314                   if (!strcmp(ans, "yes")) confirm = 1;
2315                   if (!strcmp(ans, "no")) confirm = 0;
2316                 }  
2317
2318                 if (confirm==1) GSM_PlayRingtoneOnConsole(&ringtone);
2319                 
2320                 if (filename[0]!=0) GSM_SaveRingtoneFileOnConsole(filename, &ringtone);
2321                 
2322                 break;
2323                 
2324               default:
2325                 fprintf(stdout,_("Gnokii can't read this ringtone - there is probably error inside\n"));
2326                 break;
2327             }
2328
2329             break;
2330
2331           case GSM_CalendarNoteUDH:
2332             fprintf(stdout, ("Calendar note SMS, part %i/%i\n"),message.UDH[11],message.UDH[10]);
2333             fprintf(stdout, _("Text:\n%s\n\n"), message.MessageText);
2334             if (filename[0]!=0 && mode != -1) mode = GSM_SaveTextFileOnConsole(filename, message.MessageText, mode);
2335             break;
2336
2337           case GSM_ConcatenatedMessages:
2338             fprintf(stdout, _("Linked (%d/%d)\nText:\n%s\n\n"),message.UDH[5],message.UDH[4], message.MessageText);
2339             if (filename[0]!=0 && mode != -1) mode = GSM_SaveTextFileOnConsole(filename, message.MessageText, mode);
2340             break;
2341
2342           case GSM_EnableVoice:
2343             fprintf(stdout, _("Enables voice indicator\nText:\n%s\n\n"), message.MessageText);
2344             if (filename[0]!=0 && mode != -1) mode = GSM_SaveTextFileOnConsole(filename, message.MessageText, mode);
2345             break;
2346
2347           case GSM_DisableVoice:
2348             fprintf(stdout, _("Disables voice indicator\nText:\n%s\n\n"), message.MessageText);
2349             if (filename[0]!=0 && mode != -1) mode = GSM_SaveTextFileOnConsole(filename, message.MessageText, mode);
2350             break;
2351
2352           case GSM_EnableFax:
2353             fprintf(stdout, _("Enables fax indicator\nText:\n%s\n\n"), message.MessageText);
2354             if (filename[0]!=0 && mode != -1) mode = GSM_SaveTextFileOnConsole(filename, message.MessageText, mode);
2355             break;
2356
2357           case GSM_DisableFax:
2358             fprintf(stdout, _("Disables fax indicator\nText:\n%s\n\n"), message.MessageText);
2359             if (filename[0]!=0 && mode != -1) mode = GSM_SaveTextFileOnConsole(filename, message.MessageText, mode);
2360             break;
2361
2362           case GSM_EnableEmail:
2363             fprintf(stdout, _("Enables email indicator\nText:\n%s\n\n"), message.MessageText);
2364             if (filename[0]!=0 && mode != -1) mode = GSM_SaveTextFileOnConsole(filename, message.MessageText, mode);
2365             break;
2366
2367           case GSM_DisableEmail:
2368             fprintf(stdout, _("Disables email indicator\nText:\n%s\n\n"), message.MessageText);
2369             if (filename[0]!=0 && mode != -1) mode = GSM_SaveTextFileOnConsole(filename, message.MessageText, mode);
2370             break;
2371
2372           case GSM_VoidSMS:
2373             fprintf(stdout, _("Void SMS\nText:\n%s\n\n"), message.MessageText);
2374             if (filename[0]!=0 && mode != -1) mode = GSM_SaveTextFileOnConsole(filename, message.MessageText, mode);
2375             break;
2376
2377           case GSM_NoUDH:
2378             if (message.Coding!=GSM_Coding_8bit) {
2379               fprintf(stdout, _("Text:\n%s\n\n"), message.MessageText);
2380               if (filename[0]!=0 && mode != -1) mode = GSM_SaveTextFileOnConsole(filename, message.MessageText, mode);
2381             } else {
2382               fprintf(stdout, _("Message cannot be displayed here\n")); // like in phone :-)
2383             }
2384             break;
2385
2386           default:  //GSM_UnknownUDH and other
2387             fprintf(stderr, _("Unknown\n"));
2388           }
2389
2390           break;
2391           
2392         default:
2393           fprintf(stdout,_("Unknown SMS type. Report it\n"));
2394           break;
2395       }
2396
2397       break;
2398
2399     case GE_NOTIMPLEMENTED:
2400
2401       fprintf(stderr, _("Function not implemented in %s model!\n"), model);
2402       GSM->Terminate();
2403       return -1;        
2404
2405     case GE_INVALIDSMSLOCATION:
2406
2407       fprintf(stderr, _("Invalid location: %s %d\n"), memory_type_string, count);
2408
2409       break;
2410
2411     case GE_EMPTYSMSLOCATION:
2412
2413       fprintf(stderr, _("SMS location %s %d empty.\n"), memory_type_string, count);
2414
2415       break;
2416
2417     case GE_NOACCESS:
2418
2419       fprintf(stderr, _("No access to %s memory.\n"), memory_type_string);
2420
2421       break;
2422
2423     default:
2424
2425       fprintf(stderr, _("GetSMS %s %d failed!(%d)\n\n"), memory_type_string, count, error);
2426     }
2427   }
2428
2429   GSM->Terminate();
2430
2431   return 0;
2432 }
2433
2434 int getsmsstatus(int argc, char *argv[])
2435 {
2436   GSM_SMSStatus SMSStatus;
2437   GSM_SMSFolders folders;
2438   GSM_Error error;
2439   GSM_SMSMessage SMS;
2440
2441   int i,j;
2442
2443   /* Initialise the code for the GSM interface. */     
2444   fbusinit(NULL);
2445
2446   error = GSM->GetSMSStatus(&SMSStatus);
2447   if (error!=GE_NONE) return error;
2448
2449   fprintf(stdout, _("SMS Messages: UnRead %d, Number %d\n"),SMSStatus.UnRead, SMSStatus.Number);
2450
2451   error=GSM->GetSMSFolders(&folders);  
2452   if (error!=GE_NONE) return error;
2453
2454   /* For not 7110 compatible phones we have to read all SMS and prepare sms table */
2455   if( GetModelFeature (FN_SMS)!=F_SMS71 )
2456   {
2457     i=1;j=0;
2458     while (true) {
2459       if (j==SMSStatus.Number) break;
2460       SMS.Location=i;
2461       if (GSM->GetSMSMessage(&SMS)==GE_NONE) {
2462         SMSStatus.foldertable[j].smsnum=i;
2463
2464         /* We set such folders ID like in 7110 compatible phones */
2465         if (SMS.Status==GSS_NOTSENTREAD && SMS.folder==0) //GST_INBOX
2466           SMSStatus.foldertable[j].folder=0;
2467         else {
2468           switch (SMS.folder) {
2469             case 0://GST_INBOX
2470               SMSStatus.foldertable[j].folder=GST_7110_INBOX;
2471               break;
2472             case 1://GST_OUTBOX
2473               SMSStatus.foldertable[j].folder=GST_7110_OUTBOX;
2474               break;
2475           }
2476         }
2477         j++;
2478       }
2479       i++;
2480     }
2481   }
2482
2483   printf("0.Unread         : ");
2484   for(j=0; j<SMSStatus.Number; j++)
2485   {
2486     if (SMSStatus.foldertable[j].folder == 0)
2487       printf("%d ",SMSStatus.foldertable[j].smsnum);
2488   }
2489   printf("\n");
2490
2491   for (i=0;i<folders.number;i++) {
2492     fprintf(stdout,_("%d.%-15s: "),i+1,folders.Folder[i].Name);
2493     for(j=0; j<SMSStatus.Number; j++)
2494     {
2495       if ( SMSStatus.foldertable[j].folder / 8 == i+1)
2496         printf("%d ",SMSStatus.foldertable[j].smsnum);
2497     }
2498     printf("\n");
2499   }
2500
2501   GSM->Terminate();
2502
2503   return 0;
2504 }
2505
2506 /* Delete SMS messages. */
2507 int deletesms(int argc, char *argv[])
2508 {
2509
2510   GSM_SMSMessage message;
2511   char memory_type_string[20];
2512   int start_message, end_message, count;
2513   GSM_Error error;
2514
2515   /* Handle command line args that set type, start and end locations. */
2516   if (!GetMemoryTypeID(argv[0], &message.MemoryType))
2517   {
2518     fprintf(stderr, _("Unknown memory type %s!\n"), argv[0]);
2519     return (-1);
2520   }
2521   GetMemoryTypeString(memory_type_string, &message.MemoryType);
2522
2523   start_message = atoi (argv[1]);
2524   if (argc > 2) end_message = atoi (argv[2]);
2525   else end_message = start_message;
2526
2527   /* Initialise the code for the GSM interface. */     
2528
2529   fbusinit(NULL);
2530
2531   /* Now delete the requested entries. */
2532
2533   for (count = start_message; count <= end_message; count ++) {
2534
2535     message.Location = count;
2536
2537     error = GSM->DeleteSMSMessage(&message);
2538
2539     if (error == GE_NONE)
2540       fprintf(stdout, _("Deleted SMS %s %d\n"), memory_type_string, count);
2541     else {
2542       if (error == GE_NOTIMPLEMENTED) {
2543         fprintf(stderr, _("Function not implemented in %s model!\n"), model);
2544         GSM->Terminate();
2545         return -1;      
2546       }
2547       fprintf(stdout, _("DeleteSMS %s %d failed!(%d)\n\n"), memory_type_string, count, error);
2548     }
2549   }
2550
2551   GSM->Terminate();
2552
2553   return 0;
2554 }
2555
2556 static volatile bool bshutdown = false;
2557
2558 /* SIGINT signal handler. */
2559
2560 static void interrupted(int sig)
2561 {
2562
2563   signal(sig, SIG_IGN);
2564   bshutdown = true;
2565
2566 }
2567
2568 #ifdef SECURITY
2569
2570 /* In this mode we get the code from the keyboard and send it to the mobile
2571    phone. */
2572
2573 int entersecuritycode(char *type)
2574 {
2575   GSM_Error test;
2576   GSM_SecurityCode SecurityCode;
2577
2578   if (!strcmp(type,"PIN"))      SecurityCode.Type=GSCT_Pin;
2579   else if (!strcmp(type,"PUK")) SecurityCode.Type=GSCT_Puk;
2580   else if (!strcmp(type,"PIN2"))SecurityCode.Type=GSCT_Pin2;
2581   else if (!strcmp(type,"PUK2"))SecurityCode.Type=GSCT_Puk2;
2582
2583   // FIXME: Entering of SecurityCode does not work :-(
2584   //  else if (!strcmp(type,"SecurityCode"))
2585   //    SecurityCode.Type=GSCT_SecurityCode;
2586
2587   else {
2588     fprintf(stdout, _("Wrong code in second parameter (allowed: PIN,PUK,PIN2,PUK2,SecurityCode)\n"));
2589     return -1;
2590   }
2591
2592 #ifdef WIN32
2593   printf("Enter your code: ");
2594   gets(SecurityCode.Code);
2595 #else
2596   strcpy(SecurityCode.Code,getpass(_("Enter your code: ")));
2597 #endif
2598
2599   fbusinit(NULL);
2600
2601   test = GSM->EnterSecurityCode(SecurityCode);
2602   if (test==GE_NONE)
2603     fprintf(stdout,_("Code OK !\n"));
2604   else
2605     fprintf(stderr,_("%s\n"),print_error(test));
2606
2607   GSM->Terminate();
2608
2609   return 0;
2610 }
2611
2612 int getsecuritycodestatus(void)
2613 {
2614
2615   int Status;
2616
2617   fbusinit(NULL);
2618
2619   if (GSM->GetSecurityCodeStatus(&Status) == GE_NONE) {
2620
2621     fprintf(stdout, _("Security code status: "));
2622
2623       switch(Status) {
2624       case GSCT_SecurityCode:fprintf(stdout, _("waiting for Security Code.\n"));break;
2625       case GSCT_Pin:         fprintf(stdout, _("waiting for PIN.\n"));          break;
2626       case GSCT_Pin2:        fprintf(stdout, _("waiting for PIN2.\n"));         break;
2627       case GSCT_Puk:         fprintf(stdout, _("waiting for PUK.\n"));          break;
2628       case GSCT_Puk2:        fprintf(stdout, _("waiting for PUK2.\n"));         break;
2629       case GSCT_None:        fprintf(stdout, _("nothing to enter.\n"));         break;
2630       default:               fprintf(stdout, _("Unknown!\n"));
2631       }
2632   }
2633
2634   GSM->Terminate();
2635
2636   return 0;
2637 }
2638
2639 int getsecuritycode(char *type)
2640 {
2641
2642   GSM_SecurityCode SecurityCode;
2643   GSM_Error error;
2644
2645   if (!strcmp(type,"PIN"))              SecurityCode.Type=GSCT_Pin;
2646   else if (!strcmp(type,"PUK"))         SecurityCode.Type=GSCT_Puk;
2647   else if (!strcmp(type,"PIN2"))        SecurityCode.Type=GSCT_Pin2;
2648   else if (!strcmp(type,"PUK2"))        SecurityCode.Type=GSCT_Puk2;
2649   else if (!strcmp(type,"SecurityCode"))SecurityCode.Type=GSCT_SecurityCode;
2650   else {
2651     fprintf(stdout, _("Wrong code in second parameter (allowed: PIN,PUK,PIN2,PUK2,SecurityCode)\n"));
2652     return -1;
2653   }
2654     
2655   fbusinit(NULL);
2656
2657   error=GSM->GetSecurityCode(&SecurityCode);
2658   
2659   switch (error) {
2660     case GE_INVALIDSECURITYCODE:
2661       fprintf(stdout, _("Error: getting "));
2662       switch (SecurityCode.Type) {
2663         case GSCT_SecurityCode:fprintf(stdout, _("security code"));break;
2664         case GSCT_Pin :fprintf(stdout, _("PIN"));break;
2665         case GSCT_Pin2:fprintf(stdout, _("PIN2"));break;
2666         case GSCT_Puk :fprintf(stdout, _("PUK"));break;
2667         case GSCT_Puk2:fprintf(stdout, _("PUK2"));break;
2668         default:break;
2669       }
2670       fprintf(stdout, _(" not allowed\n"));
2671       break;
2672     case GE_NONE:
2673       switch (SecurityCode.Type) {
2674         case GSCT_SecurityCode:fprintf(stdout, _("Security code"));break;
2675         case GSCT_Pin :fprintf(stdout, _("PIN"));break;
2676         case GSCT_Pin2:fprintf(stdout, _("PIN2"));break;
2677         case GSCT_Puk :fprintf(stdout, _("PUK"));break;
2678         case GSCT_Puk2:fprintf(stdout, _("PUK2"));break;
2679         default:break;
2680       }
2681       fprintf(stdout, _(" is %s\n"),SecurityCode.Code);
2682       break;
2683     default:
2684       fprintf(stderr, _("%s\n"),print_error(error));
2685       break;
2686   }
2687
2688   GSM->Terminate();
2689
2690   return 0;
2691 }
2692
2693 #endif
2694
2695 /* Voice dialing mode. */
2696
2697 int dialvoice(char *Number)
2698 {
2699   fbusinit(NULL);
2700
2701   if (GSM->DialVoice(Number)!=GE_NONE) fprintf(stdout,_("Error!\n"));
2702
2703   GSM->Terminate();
2704
2705   return 0;
2706 }
2707
2708 /* Cancel a call */
2709 int cancelcall(void)
2710 {
2711   fbusinit(NULL);
2712
2713   if (GSM->CancelCall()!=GE_NONE) fprintf(stdout,_("Error!\n"));
2714
2715   GSM->Terminate();
2716
2717   return 0;
2718 }
2719
2720 int savelogo(int argc, char *argv[])
2721 {
2722   GSM_Bitmap bitmap;
2723   GSM_NetworkInfo NetworkInfo;
2724   GSM_MultiSMSMessage MultiSMS;
2725
2726   /* Operator logos will be saved with this number */  
2727   char oplogonumber[]={'O','p','L','o','g','o',
2728                        '0','0','0','0','0',   /* MMC+MNC */
2729                        '\0'};
2730   int i=0;
2731   
2732   bool UnicodeText=false;
2733
2734   /* The first argument is the type of the logo. */
2735   if (!strcmp(argv[0], "op")) {
2736     fprintf(stdout, _("Saving operator logo.\n"));
2737   } else if (!strcmp(argv[0], "caller")) {
2738     fprintf(stdout, _("Saving caller line identification logo.\n"));
2739   } else if (!strcmp(argv[0], "startup")) {
2740     fprintf(stderr, _("It isn't possible to save startup logo!\n"));
2741     return (-1);
2742   } else if (!strcmp(argv[0], "7110startup")) {
2743     fprintf(stderr, _("It isn't possible to save startup logo!\n"));
2744     return (-1);
2745   } else if (!strcmp(argv[0], "6210startup")) {
2746     fprintf(stderr, _("It isn't possible to save startup logo!\n"));
2747     return (-1);
2748   } else if (!strcmp(argv[0], "7110op")) {
2749     fprintf(stderr, _("It isn't possible to save big operator logos!\n"));
2750     return (-1);
2751   } else if (!strcmp(argv[0], "picture")) {
2752     fprintf(stderr, _("Saving picture image.\n"));
2753   } else if (!strcmp(argv[0], "screensaver")) {
2754     fprintf(stderr, _("Saving screen saver.\n"));
2755   } else {
2756     fprintf(stderr, _("You should specify what kind of logo to save!\n"));
2757     return (-1);
2758   }
2759
2760   /* The second argument is the bitmap file. */
2761   if (GSM_ReadBitmapFileOnConsole(argv[1], &bitmap)!=GE_NONE) return -1;
2762
2763   /* Initialise the GSM interface. */
2764   fbusinit(NULL);
2765
2766   /* We check optional parameters from 2'rd */
2767   optind = 2;
2768
2769   if (!strcmp(argv[0], "op")) {
2770     GSM_ResizeBitmap(&bitmap,GSM_CallerLogo);
2771   
2772     /* The third argument, if present, is the Network code of the operator.
2773      * Network code is in this format: "xxx yy" */
2774     if (argc > 2) {
2775       strcpy(bitmap.netcode, argv[2]);
2776 #ifdef DEBUG
2777       fprintf(stdout, _("Operator code: %s\n"), argv[2]);
2778 #endif
2779       if (!strcmp(GSM_GetNetworkName(bitmap.netcode),"unknown")) {
2780         fprintf(stderr,"Sorry, gnokii doesn't know \"%s\" network !\n",bitmap.netcode);
2781         GSM->Terminate();
2782         return -1;
2783       }
2784       optind++;
2785     } else
2786     {
2787       if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE) strncpy(bitmap.netcode,NetworkInfo.NetworkCode,7);
2788     }
2789     bitmap.type=GSM_OperatorLogo;
2790
2791     /* Put bitmap into SMS structure */
2792     GSM_SaveBitmapToSMS(&MultiSMS,&bitmap,false,false);
2793
2794     oplogonumber[6]=bitmap.netcode[0];
2795     oplogonumber[7]=bitmap.netcode[1];
2796     oplogonumber[8]=bitmap.netcode[2];
2797     oplogonumber[9]=bitmap.netcode[4];
2798     oplogonumber[10]=bitmap.netcode[5];
2799     for(i=0;i<MultiSMS.number;i++)
2800       strcpy(MultiSMS.SMS[i].Destination,oplogonumber);
2801   }
2802   if (!strcmp(argv[0], "caller")) {
2803     GSM_ResizeBitmap(&bitmap,GSM_CallerLogo);
2804   
2805     bitmap.type=GSM_CallerLogo;
2806
2807     /* Put bitmap into SMS structure */
2808     GSM_SaveBitmapToSMS(&MultiSMS,&bitmap,false,false);
2809
2810     for(i=0;i<MultiSMS.number;i++)
2811       strcpy(MultiSMS.SMS[i].Destination,"GroupLogo");
2812   }
2813   if (!strcmp(argv[0], "screensaver")) {
2814     GSM_ResizeBitmap(&bitmap,GSM_PictureImage);
2815
2816     bitmap.text[0]=0;
2817
2818     for(i=0;i<argc;i++)
2819       if (!strcmp(argv[i],"--unicode")) UnicodeText=true;
2820
2821     /* Put bitmap into SMS structure */
2822     GSM_SaveBitmapToSMS(&MultiSMS,&bitmap,true,UnicodeText);
2823
2824     for(i=0;i<MultiSMS.number;i++)
2825       strcpy(MultiSMS.SMS[i].Destination,"ScreenSaver");
2826   }
2827   if (!strcmp(argv[0], "picture")) {  
2828     GSM_ResizeBitmap(&bitmap,GSM_PictureImage);
2829
2830     for(i=0;i<argc;i++)
2831       if (!strcmp(argv[i],"--unicode")) UnicodeText=true;
2832
2833     bitmap.text[0]=0;
2834     if (argc>2) {
2835       optind++;
2836       if (strlen(argv[2])>121) {
2837         fprintf(stdout,_("Sorry: length of text (parameter \"%s\") can be 121 chars or shorter only !\n"),argv[2]);
2838         return -1;
2839       }
2840       strcpy(bitmap.text,argv[2]);
2841     }
2842     
2843     /* Put bitmap into SMS structure */
2844     GSM_SaveBitmapToSMS(&MultiSMS,&bitmap,false,UnicodeText);
2845
2846     for(i=0;i<MultiSMS.number;i++)
2847       strcpy(MultiSMS.SMS[i].Destination,"Picture");
2848   }
2849
2850   GSM_SaveMultiPartSMSOnConsole(&MultiSMS, optind,argc,argv,false,true,false,false);
2851   
2852   return i;
2853 }
2854
2855 /* The following function allows to send logos using SMS */
2856 int sendlogo(int argc, char *argv[])
2857 {
2858   GSM_Bitmap bitmap;
2859   GSM_NetworkInfo NetworkInfo;
2860   GSM_MultiSMSMessage MultiSMS;
2861
2862   int i;
2863
2864   bool UnicodeText=false;
2865   bool ScreenSaver=false;
2866
2867   /* The first argument is the type of the logo. */
2868   if (!strcmp(argv[0], "op")) {
2869     fprintf(stdout, _("Sending operator logo.\n"));
2870   } else if (!strcmp(argv[0], "caller")) {
2871     fprintf(stdout, _("Sending caller line identification logo.\n"));
2872   } else if (!strcmp(argv[0], "picture")) {
2873     fprintf(stdout, _("Sending picture image.\n"));
2874   } else if (!strcmp(argv[0], "screensaver")) {
2875     fprintf(stdout, _("Sending screen saver.\n"));
2876   } else if (!strcmp(argv[0], "startup")) {
2877     fprintf(stderr, _("It isn't possible to send startup logo!\n"));
2878     return (-1);
2879   } else if (!strcmp(argv[0], "7110startup")) {
2880     fprintf(stderr, _("It isn't possible to send startup logo!\n"));
2881     return (-1);
2882   } else if (!strcmp(argv[0], "6210startup")) {
2883     fprintf(stderr, _("It isn't possible to send startup logo!\n"));
2884     return (-1);
2885   } else if (!strcmp(argv[0], "7110op")) {
2886     fprintf(stderr, _("It isn't possible to send big operator logos!\n"));
2887     return (-1);
2888   } else {
2889     fprintf(stderr, _("You should specify what kind of logo to send!\n"));
2890     return (-1);
2891   }
2892
2893   /* The third argument is the bitmap file. */
2894   if (GSM_ReadBitmapFileOnConsole(argv[2], &bitmap)!=GE_NONE) return -1;
2895
2896   /* Initialise the GSM interface. */
2897   fbusinit(NULL);
2898
2899   optind = 3;
2900
2901   if (!strcmp(argv[0], "op")) {
2902     GSM_ResizeBitmap(&bitmap,GSM_CallerLogo);
2903   
2904     /* The third argument, if present, is the Network code of the operator.
2905      * Network code is in this format: "xxx yy" */
2906     if (argc > 3) {
2907       strcpy(bitmap.netcode, argv[3]);
2908 #ifdef DEBUG
2909       fprintf(stdout, _("Operator code: %s\n"), argv[3]);
2910 #endif
2911       if (!strcmp(GSM_GetNetworkName(bitmap.netcode),"unknown")) {
2912         fprintf(stderr,"Sorry, gnokii doesn't know \"%s\" network !\n",bitmap.netcode);
2913         GSM->Terminate();
2914         return -1;
2915       }
2916       optind++;
2917     } else
2918     {
2919       if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE) strncpy(bitmap.netcode,NetworkInfo.NetworkCode,7);
2920     }
2921     bitmap.type=GSM_OperatorLogo;
2922   }
2923   if (!strcmp(argv[0], "caller")) {
2924     GSM_ResizeBitmap(&bitmap,GSM_CallerLogo);
2925   
2926     bitmap.type=GSM_CallerLogo;
2927   }
2928   if (!strcmp(argv[0], "screensaver")) {
2929     GSM_ResizeBitmap(&bitmap,GSM_PictureImage);
2930
2931     bitmap.text[0]=0;
2932
2933     for(i=0;i<argc;i++)
2934       if (!strcmp(argv[i],"--unicode")) UnicodeText=true;
2935     
2936     ScreenSaver=true;
2937   }
2938   if (!strcmp(argv[0], "picture")) {  
2939     GSM_ResizeBitmap(&bitmap,GSM_PictureImage);
2940
2941     for(i=0;i<argc;i++)
2942       if (!strcmp(argv[i],"--unicode")) UnicodeText=true;
2943
2944     bitmap.text[0]=0;
2945     if (argc>3) {
2946       optind++;
2947       if (strlen(argv[3])>121) {
2948         fprintf(stdout,_("Sorry: length of text (parameter \"%s\") can be 121 chars or shorter only !\n"),argv[3]);
2949         return -1;
2950       }
2951       strcpy(bitmap.text,argv[3]);
2952     }
2953   }
2954
2955   /* Put bitmap into SMS structure */
2956   GSM_SaveBitmapToSMS(&MultiSMS,&bitmap,ScreenSaver,UnicodeText);
2957
2958   /* The second argument is the destination, ie the phone number of recipient. */
2959   for(i=0;i<MultiSMS.number;i++)
2960     strcpy(MultiSMS.SMS[i].Destination,argv[1]);
2961
2962   GSM_SendMultiPartSMSOnConsole(&MultiSMS, optind,argc,argv,true,false,false);
2963
2964   return i;
2965 }
2966
2967 /* Getting logos. */
2968
2969 int getlogo(int argc, char *argv[])
2970 {
2971   GSM_Bitmap bitmap;
2972   GSM_Error error;
2973   int num;
2974
2975   bitmap.type=GSM_None;
2976
2977   if (!strcmp(argv[0],"7110op"))
2978     bitmap.type=GSM_7110OperatorLogo;
2979     
2980   if (!strcmp(argv[0],"op"))
2981     bitmap.type=GSM_OperatorLogo;
2982     
2983   if (!strcmp(argv[0],"caller")) {
2984     /* There is caller group number missing in argument list. */
2985     if (argc==3) {     
2986       num=argv[2][0]-'0';
2987       if ((num<1)||(num>9)) num=1;
2988       bitmap.number=num;
2989     } else
2990     {
2991       bitmap.number=1;
2992     }
2993     bitmap.number--;
2994     bitmap.type=GSM_CallerLogo;
2995   }
2996
2997   if (!strcmp(argv[0],"picture")) {
2998     /* There is a number missing in argument list. */
2999     if (argc==3) {     
3000       if (strlen(argv[2])==2) {
3001         num=(argv[2][0]-'0')*10+(argv[2][1]-'0');
3002       } else {
3003         num=argv[2][0]-'0';
3004       }
3005       if (num<1) num=1;
3006       bitmap.number=num;
3007     } else
3008     {
3009       bitmap.number=1;
3010     }
3011     bitmap.number--;
3012     bitmap.type=GSM_PictureImage;
3013   }    
3014
3015   if (!strcmp(argv[0],"startup"))
3016     bitmap.type=GSM_StartupLogo;
3017
3018   if (!strcmp(argv[0],"7110startup"))
3019     bitmap.type=GSM_7110StartupLogo;
3020
3021   if (!strcmp(argv[0],"6210startup"))
3022     bitmap.type=GSM_6210StartupLogo;
3023     
3024   if (!strcmp(argv[0],"dealer"))
3025     bitmap.type=GSM_DealerNoteText;  
3026     
3027   if (!strcmp(argv[0],"text"))
3028     bitmap.type=GSM_WelcomeNoteText;  
3029
3030   if (bitmap.type!=GSM_None) {
3031   
3032     fbusinit(NULL);
3033     
3034     fprintf(stdout, _("Getting Logo\n"));
3035         
3036     error=GSM->GetBitmap(&bitmap);
3037
3038     GSM->Terminate();
3039     
3040     switch (error)
3041     {
3042       case GE_NONE:
3043         if (bitmap.type==GSM_DealerNoteText) fprintf(stdout, _("Dealer welcome note "));
3044         if (bitmap.type==GSM_WelcomeNoteText) fprintf(stdout, _("Welcome note "));      
3045         if (bitmap.type==GSM_DealerNoteText || bitmap.type==GSM_WelcomeNoteText)
3046         {
3047           if (bitmap.text[0]!=0)
3048           {
3049             fprintf(stdout, _("currently set to \"%s\"\n"), bitmap.text);
3050           } else {
3051             fprintf(stdout, _("currently empty\n"));
3052           }
3053         } else
3054         {
3055           if (bitmap.width!=0)
3056           {
3057             if (bitmap.type==GSM_OperatorLogo || bitmap.type==GSM_7110OperatorLogo)
3058             {
3059               fprintf(stdout,"Operator logo for %s (%s) network got succesfully\n",bitmap.netcode,GSM_GetNetworkName(bitmap.netcode));
3060             }
3061             if (bitmap.type==GSM_StartupLogo || bitmap.type==GSM_7110StartupLogo || bitmap.type==GSM_6210StartupLogo)
3062             {
3063               fprintf(stdout,"Startup logo got successfully\n");
3064             }
3065             if (bitmap.type==GSM_CallerLogo)
3066             {
3067               fprintf(stdout,"Caller logo got successfully\n");
3068             }
3069             if (bitmap.type==GSM_PictureImage)
3070             {
3071               fprintf(stdout,"Picture Image got successfully");
3072               if (strcmp(bitmap.text,""))
3073                 fprintf(stdout,_(", text \"%s\""),bitmap.text);         
3074               if (strcmp(bitmap.Sender,""))
3075                 fprintf(stdout,_(", sender \"%s\""),bitmap.Sender);             
3076               fprintf(stdout,"\n");
3077             }
3078             if (argc>1)
3079             {
3080               if (GSM_SaveBitmapFileOnConsole(argv[1], &bitmap)!=GE_NONE) return(-1);
3081             }
3082           } else
3083           {
3084             fprintf(stdout,"Your phone doesn't have logo uploaded !\n");
3085             return -1;
3086           }
3087         }
3088         break;
3089       case GE_NOTIMPLEMENTED:
3090         fprintf(stderr, _("Function not implemented !\n"));
3091         return -1;
3092       case GE_NOTSUPPORTED:
3093         fprintf(stderr, _("This kind of logo is not supported !\n"));
3094         return -1;
3095       default:
3096         fprintf(stderr, _("Error getting logo (wrong location ?) !\n"));
3097         return -1;
3098     }
3099   } else
3100   {
3101     fprintf(stderr, _("What kind of logo do you want to get ?\n"));
3102     return -1;
3103   }
3104
3105   return 0;
3106 }
3107
3108 /* Setting logos. */
3109
3110 int setlogo(int argc, char *argv[])
3111 {
3112
3113   GSM_Bitmap bitmap,oldbit;
3114   GSM_NetworkInfo NetworkInfo;
3115   GSM_Error error;
3116   char model[64];
3117   int num;
3118   
3119   bool ok=true;
3120   
3121   int i;
3122   
3123   fbusinit(NULL);
3124   
3125   if (!strcmp(argv[0],"text") || !strcmp(argv[0],"dealer"))
3126   {
3127     if (!strcmp(argv[0],"text")) bitmap.type=GSM_WelcomeNoteText;
3128                             else bitmap.type=GSM_DealerNoteText;
3129     bitmap.text[0]=0x00;
3130     if (argc>1) strncpy(bitmap.text,argv[1],255);
3131   } else
3132   {
3133     if (!strcmp(argv[0],"op") || !strcmp(argv[0],"startup") || !strcmp(argv[0],"caller") ||
3134         !strcmp(argv[0],"7110op") || !strcmp(argv[0],"6210startup") || !strcmp(argv[0],"7110startup") ||
3135         !strcmp(argv[0],"picture"))
3136     {
3137       if (argc>1)
3138       {
3139         if (!strcmp(argv[0],"startup"))
3140         {
3141           bitmap.type=GSM_StartupLogo;
3142           bitmap.width=84;
3143           bitmap.height=48;
3144           bitmap.size=bitmap.width*bitmap.height/8;
3145           num=argv[1][0]-'0';
3146           if (num>=1 && num<=3) {
3147             bitmap.number=num;
3148           } else {
3149             if (GSM_ReadBitmapFileOnConsole(argv[1], &bitmap)!=GE_NONE) {
3150               GSM->Terminate();
3151               return(-1);
3152             }
3153             bitmap.number=0;
3154             GSM_ResizeBitmap(&bitmap,GSM_StartupLogo);
3155           }
3156         } else {
3157           if (GSM_ReadBitmapFileOnConsole(argv[1], &bitmap)!=GE_NONE) {
3158             GSM->Terminate();
3159             return(-1);
3160           }
3161         }
3162         if (!strcmp(argv[0],"op"))
3163         {
3164           if (bitmap.type!=GSM_OperatorLogo || argc<3)
3165           {
3166             if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE) strncpy(bitmap.netcode,NetworkInfo.NetworkCode,7);
3167           }
3168           GSM_ResizeBitmap(&bitmap,GSM_OperatorLogo);
3169           if (argc==3)
3170           {
3171             strncpy(bitmap.netcode,argv[2],7);
3172             if (!strcmp(GSM_GetNetworkName(bitmap.netcode),"unknown"))
3173             {
3174               fprintf(stderr,"Sorry, gnokii doesn't know \"%s\" network !\n",bitmap.netcode);
3175               return -1;
3176             }
3177           }
3178         }
3179         if (!strcmp(argv[0],"7110op"))
3180         {
3181           if (bitmap.type!=GSM_7110OperatorLogo || argc<3)
3182           {
3183             if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE) strncpy(bitmap.netcode,NetworkInfo.NetworkCode,7);
3184           }
3185           GSM_ResizeBitmap(&bitmap,GSM_7110OperatorLogo);
3186           if (argc==3)
3187           {
3188             strncpy(bitmap.netcode,argv[2],7);
3189             if (!strcmp(GSM_GetNetworkName(bitmap.netcode),"unknown"))
3190             {
3191               fprintf(stderr,"Sorry, gnokii doesn't know \"%s\" network !\n",bitmap.netcode);
3192               return -1;
3193             }
3194           }
3195         }
3196         if (!strcmp(argv[0],"picture"))
3197         {
3198           GSM_ResizeBitmap(&bitmap,GSM_PictureImage);
3199           bitmap.number=1;
3200           if (argc>2)
3201           {
3202             if (strlen(argv[2])==2) {
3203               num=(argv[2][0]-'0')*10+(argv[2][1]-'0');
3204             } else {
3205               num=argv[2][0]-'0';
3206             }
3207             if (num<1) num=1;   
3208             bitmap.number=num;
3209           }
3210           bitmap.number--;
3211           bitmap.text[0]=0;
3212           if (argc>3)
3213             strncpy(bitmap.text,argv[3],121);
3214           strcpy(bitmap.Sender,"\0");
3215           if (argc>4)
3216             strncpy(bitmap.Sender,argv[4],GSM_MAX_SENDER_LENGTH);
3217         }
3218         if (!strcmp(argv[0],"7110startup"))
3219         {
3220           GSM_ResizeBitmap(&bitmap,GSM_7110StartupLogo);
3221         }
3222         if (!strcmp(argv[0],"6210startup"))
3223         {
3224           GSM_ResizeBitmap(&bitmap,GSM_6210StartupLogo);
3225         }
3226         if (!strcmp(argv[0],"caller"))
3227         {
3228           GSM_ResizeBitmap(&bitmap,GSM_CallerLogo);
3229           if (argc>2)
3230           {
3231             num=argv[2][0]-'0';
3232             if ((num<0)||(num>9)) num=0;
3233             bitmap.number=num;
3234           } else
3235           {
3236             bitmap.number=0;
3237           }
3238           oldbit.type=GSM_CallerLogo;
3239           oldbit.number=bitmap.number;
3240           if (GSM->GetBitmap(&oldbit)==GE_NONE)
3241           {
3242             /* We have to get the old name and ringtone!! */
3243             bitmap.ringtone=oldbit.ringtone;
3244             strncpy(bitmap.text,oldbit.text,255);
3245           }
3246           if (argc>3) strncpy(bitmap.text,argv[3],255);   
3247         }
3248         fprintf(stdout, _("Setting Logo.\n"));
3249       } else
3250       {
3251         /* FIX ME: is it possible to permanently remove op logo ? */
3252         if (!strcmp(argv[0],"op"))
3253         {
3254           bitmap.type=GSM_OperatorLogo;
3255           strncpy(bitmap.netcode,"000 00",7);
3256           bitmap.width=72;
3257           bitmap.height=14;
3258           bitmap.size=bitmap.width*bitmap.height/8;
3259           GSM_ClearBitmap(&bitmap);
3260         }
3261         if (!strcmp(argv[0],"7110op"))
3262         {
3263           bitmap.type=GSM_7110OperatorLogo;
3264           strncpy(bitmap.netcode,"000 00",7);
3265           bitmap.width=78;
3266           bitmap.height=21;
3267           bitmap.size=(bitmap.width*bitmap.height + 7)/8;
3268           GSM_ClearBitmap(&bitmap);
3269         }
3270         /* FIX ME: how to remove startup and group logos ? */
3271         fprintf(stdout, _("Removing Logo.\n"));
3272       }  
3273     } else
3274     {
3275       fprintf(stderr, _("What kind of logo do you want to set ?\n"));
3276       GSM->Terminate();
3277       return -1;
3278     }
3279   }
3280     
3281   while (GSM->GetModel(model)  != GE_NONE)
3282     sleep(1);
3283   
3284   /* For Nokia 6110/6130/6150 we use different method of uploading.
3285      Phone will display menu, when received it */
3286   if (!strcmp(model,"NSE-3") || !strcmp(model,"NSK-3") || !strcmp(model,"NSM-1"))
3287   {
3288     if (!strcmp(argv[0],"caller") && argc<3)
3289       bitmap.number=255;
3290     if (!strcmp(argv[0],"op") && argc<3)
3291       bitmap.number=255;
3292   }
3293
3294   error=GSM->SetBitmap(&bitmap);
3295   
3296   switch (error)
3297   {
3298     case GE_NONE: oldbit.type=bitmap.type;
3299                   oldbit.number=bitmap.number;
3300                   if (GSM->GetBitmap(&oldbit)==GE_NONE) {
3301                     if (bitmap.type==GSM_WelcomeNoteText ||
3302                         bitmap.type==GSM_DealerNoteText) {
3303                       if (strcmp(bitmap.text,oldbit.text)) {
3304                         fprintf(stderr, _("Error setting"));
3305                         if (bitmap.type==GSM_DealerNoteText) fprintf(stderr, _(" dealer"));
3306                         fprintf(stderr, _(" welcome note - "));
3307
3308                         /* I know, it looks horrible, but... */
3309                         /* I set it to the short string - if it won't be set */
3310                         /* it means, PIN is required. If it will be correct, previous */
3311                         /* (user) text was too long */
3312
3313                         /* Without it, I could have such thing: */
3314                         /* user set text to very short string (for example, "Marcin") */
3315                         /* then enable phone without PIN and try to set it to the very long (too long for phone) */
3316                         /* string (which start with "Marcin"). If we compare them as only length different, we could think, */
3317                         /* that phone accepts strings 6 chars length only (length of "Marcin") */
3318                         /* When we make it correct, we don't have this mistake */
3319                         
3320                         strcpy(oldbit.text,"!\0");
3321                         GSM->SetBitmap(&oldbit);
3322                         GSM->GetBitmap(&oldbit);
3323                         if (oldbit.text[0]!='!') {
3324                           fprintf(stderr, _("SIM card and PIN is required\n"));
3325                         } else {
3326                           GSM->SetBitmap(&bitmap);
3327                           GSM->GetBitmap(&oldbit);
3328                           fprintf(stderr, _("too long, truncated to \"%s\" (length %i)\n"),oldbit.text,strlen(oldbit.text));
3329                         }
3330                         ok=false;
3331                       }
3332                     } else {
3333                       if (bitmap.type==GSM_StartupLogo) {
3334                         for (i=0;i<oldbit.size;i++) {
3335                           if (oldbit.bitmap[i]!=bitmap.bitmap[i]) {
3336                             fprintf(stderr, _("Error setting startup logo - SIM card and PIN is required\n"));
3337                             ok=false;
3338                             break;
3339                           }
3340                         }
3341                       }
3342                     }
3343                   }
3344                   if (ok) fprintf(stdout, _("Done.\n"));
3345                   break;
3346     case GE_NOTIMPLEMENTED:fprintf(stderr, _("Function not implemented.\n"));
3347                            break;
3348     case GE_NOTSUPPORTED:fprintf(stderr, _("This kind of logo is not supported.\n"));
3349                            break;
3350     default:fprintf(stderr, _("Error (wrong location ?) !\n"));
3351             break;
3352   }
3353   
3354   GSM->Terminate();
3355
3356   return 0;
3357 }
3358
3359 /* Calendar notes receiving. */
3360
3361 int getcalendarnote(int argc, char *argv[])
3362 {
3363   GSM_CalendarNote CalendarNote;
3364   GSM_NotesInfo NotesInfo;
3365   GSM_Error error;
3366   int i;
3367   int vCalVer=0;
3368   bool vInfo=false;
3369   int start, stop;
3370   bool was_note=false;
3371   char z_text[MAX_CALENDAR_TEXT_LENGTH+11];
3372
3373   /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */
3374   char model[64];
3375
3376   struct tm *now;
3377   time_t nowh;
3378   GSM_DateTime Date;
3379
3380   nowh=time(NULL);
3381   now=localtime(&nowh);
3382   
3383   Date.Year = now->tm_year;
3384
3385   /* I have 100 (for 2000) Year now :-) */
3386   if (Date.Year>99 && Date.Year<1900) {
3387     Date.Year=Date.Year+1900;
3388   }
3389
3390   start=atoi(argv[0]);  
3391   stop=start;
3392   
3393   switch (argc) {
3394     case 2:
3395       if (!strcmp(argv[argc-1],"-v10")) {
3396         vCalVer=10;
3397       } else {
3398         if (!strcmp(argv[argc-1],"-v30")) {
3399           vCalVer=30;
3400         } else {
3401           stop=atoi(argv[1]);
3402         }
3403       }
3404       break;
3405     case 3:
3406       stop=atoi(argv[1]);
3407       if (!strcmp(argv[argc-1],"-v10")) {
3408         vCalVer=10;
3409       } else {
3410         if (!strcmp(argv[argc-1],"-v30")) {
3411           vCalVer=30;
3412         } else {      
3413           usage();
3414           return -1;
3415         }
3416       }
3417       break;
3418   }
3419
3420   fbusinit(NULL);
3421
3422   while (GSM->GetModel(model)  != GE_NONE)
3423     sleep(1);
3424
3425   if (!strcmp(argv[0],"-s") || !strcmp(argv[0],"--short")) 
3426     vInfo=true;
3427   else if (!isdigit(argv[0][0])) {
3428     usage();
3429     return -1;
3430   }
3431     
3432   error=GSM->GetCalendarNotesInfo(&NotesInfo);
3433   if ( error == GE_NONE ) {
3434      if( NotesInfo.HowMany == 0 ) {
3435          fprintf(stderr, _("Sorry! No Calendar Notes present on phone.\n"));
3436          start=0; stop=(-1); /* This for skipping next 'for' loop ;-> */
3437       }
3438 #ifdef DEBUG
3439       fprintf(stdout, _(" CALENDAR NOTES INFO \n"));
3440       fprintf(stdout, _("---------------------\n"));
3441       fprintf(stdout, _("How Many Locations :%d\n"), NotesInfo.HowMany);
3442
3443       /* For 6210 (NPE-3) and 7110 (NSE-5), Locations have a different behaviour */
3444       if ( GetModelFeature (FN_CALENDAR)==F_CAL71 ) {
3445         fprintf(stdout, _("Locations are :\n"));
3446         for(i=0;i<NotesInfo.HowMany;i++)
3447             fprintf(stdout, _("%4d) %4d\n"), i+1, NotesInfo.Location[i]);
3448       }
3449 #endif
3450   } else {
3451       /* For 6210 (NPE-3) and 7110 (NSE-5), Locations have a different behaviour */
3452       if ( GetModelFeature (FN_CALENDAR)==F_CAL71 ) {
3453         fprintf(stderr, _("Can't read Notes Infos from phone.\n"));
3454         start=0; stop=(-1); /* This for skipping next 'for' loop ;-> */
3455       }
3456   }
3457
3458   if (GetModelFeature (FN_CALENDAR)!=F_CAL71) {
3459     error=GE_NONE;
3460     NotesInfo.HowMany=200;
3461     for (i=0;i<200;i++) {
3462       NotesInfo.Location[i]=i+1;
3463     }
3464   }
3465   
3466   if( vInfo && stop!=(-1) && error==GE_NONE )
3467   {
3468     /* Info datas (for 7110 and comp.) */
3469     fprintf(stdout, _(" CALENDAR NOTES SUMMARY INFORMATION \n"));
3470     fprintf(stdout, _(" ==================================\n"));
3471     if (GetModelFeature (FN_CALENDAR)==F_CAL71) {
3472       fprintf(stdout, _("Calendar notes present on phone: %d\n"), NotesInfo.HowMany);
3473       fprintf(stdout, _("Locations are :\n"));
3474     }
3475     fprintf(stdout,  "----------------------------------------------------------------------------\n");
3476     fprintf(stdout,_(" Loc Phys Type    Summary description              Dt start    Alarm  Recurs\n") );
3477     fprintf(stdout,  "----------------------------------------------------------------------------\n");
3478
3479     for(i=0;i<NotesInfo.HowMany;i++)
3480     {
3481       /* very short format ... */
3482       /*
3483       fprintf(stdout, _("%4d) %4d\n"), i, NotesInfo.Location[i]);
3484       */
3485       CalendarNote.Location=i+1;
3486       CalendarNote.ReadNotesInfo=false;
3487
3488       if (GSM->GetCalendarNote(&CalendarNote) == GE_NONE) {
3489         char z_type[11];
3490         char z_recur[15];
3491         switch (CalendarNote.Type) {
3492            case GCN_REMINDER:strcpy(z_type, "REMIND");  break;
3493            case GCN_CALL:    strcpy(z_type, "CALL");    break;
3494            case GCN_MEETING: strcpy(z_type, "MEETING"); break;
3495            case GCN_BIRTHDAY:strcpy(z_type, "BDAY");    break;
3496            default:          strcpy(z_type, "UNKNOWN"); break;
3497           }
3498
3499         if( CalendarNote.Recurrance ) {
3500           sprintf( z_recur,"%d ", CalendarNote.Recurrance/24 );
3501           strcat( z_recur, CalendarNote.Recurrance == 1 ? "day" : "days" );
3502         }
3503         else
3504           strcpy( z_recur, "No" );
3505
3506         strcpy(z_text,"");
3507         
3508         if( CalendarNote.Type == GCN_CALL )
3509           sprintf(z_text, "\"%s\"", CalendarNote.Phone );
3510           
3511         if (CalendarNote.Text[0]!=0)
3512           sprintf(z_text, "\"%s\"", CalendarNote.Text );
3513           
3514         if(CalendarNote.Type == GCN_BIRTHDAY) {
3515           int i_age;
3516           i_age = Date.Year - CalendarNote.Time.Year;
3517           sprintf(z_text, "\"%s (%d %s)\"", CalendarNote.Text,
3518              i_age, (i_age==1)?"year":"years");
3519           strcpy( z_recur, "-" );
3520           if (GetModelFeature (FN_CALENDAR)==F_CAL71)
3521             fprintf(stdout,
3522                 _("%4d %4d %-7.7s %-32.32s %04d-%02d-%02d  %s %s\n"), 
3523               i+1,NotesInfo.Location[i], z_type, z_text,
3524               CalendarNote.Time.Year, 
3525               CalendarNote.Time.Month, 
3526               CalendarNote.Time.Day,
3527               (CalendarNote.AlarmType==0x00) ? "Tone  " : "Silent",
3528               " " );
3529           else
3530             fprintf(stdout,
3531                 _("%4d %4d %-7.7s %-32.32s %04d-%02d-%02d  %s %s\n"), 
3532               i+1,NotesInfo.Location[i], z_type, z_text,
3533               CalendarNote.Time.Year, 
3534               CalendarNote.Time.Month, 
3535               CalendarNote.Time.Day,
3536               (CalendarNote.Alarm.Year) ? "Yes" : "No ",
3537               " " );
3538         } else
3539           if (GetModelFeature (FN_CALENDAR)==F_CAL71)
3540             fprintf(stdout,
3541                 _("%4d %4d %-7.7s %-32.32s %04d-%02d-%02d  %s    %s\n"), 
3542               i+1,NotesInfo.Location[i], z_type, z_text,
3543               CalendarNote.Time.Year, 
3544               CalendarNote.Time.Month, 
3545               CalendarNote.Time.Day,
3546               (CalendarNote.Alarm.Year) ? "Yes" : "No ",
3547               z_recur );
3548            else
3549             fprintf(stdout,
3550                 _("%4d %4d %-7.7s %-32.32s %04d-%02d-%02d  %s\n"), 
3551               i+1,NotesInfo.Location[i], z_type, z_text,
3552               CalendarNote.Time.Year, 
3553               CalendarNote.Time.Month, 
3554               CalendarNote.Time.Day,
3555               (CalendarNote.Alarm.Year) ? "Yes" : "No ");
3556       } else {
3557         if (GetModelFeature (FN_CALENDAR)!=F_CAL71) break;
3558       }
3559     }
3560   }
3561   else
3562   for (i=start;i<=stop;i++) {
3563     if (error==GE_NONE) {
3564         if( i>NotesInfo.HowMany ) {
3565             fprintf(stderr, _("Only %d Calendar Notes present on phone!\n"),NotesInfo.HowMany);
3566             break;
3567         }
3568         if( i==0 ) {
3569             fprintf(stderr, _("Calendar Notes location can't be zero... skipping.\n"));
3570             continue;
3571         }
3572     }
3573     
3574     CalendarNote.Location=i;
3575     CalendarNote.ReadNotesInfo=false;
3576
3577     if (GSM->GetCalendarNote(&CalendarNote) == GE_NONE) {
3578
3579       if (vCalVer!=0) {
3580         if (!was_note) {
3581           fprintf(stdout, GSM_GetVCALENDARStart(vCalVer));
3582           was_note=true;
3583         }
3584
3585         fprintf(stdout, GSM_GetVCALENDARNote(&CalendarNote,vCalVer));
3586
3587       } else {  /* not vCal */
3588
3589         if (was_note) {
3590           fprintf(stdout, "\n");
3591         } else {
3592           was_note=true;
3593         }
3594
3595         fprintf(stdout, _("   Type of the note: "));
3596
3597         switch (CalendarNote.Type) {
3598
3599           case GCN_REMINDER:fprintf(stdout, _("Reminder\n"));break;
3600           case GCN_CALL    :fprintf(stdout, _("Call\n"));    break;
3601           case GCN_MEETING :fprintf(stdout, _("Meeting\n")); break;
3602           case GCN_BIRTHDAY:fprintf(stdout, _("Birthday\n"));break;
3603           default:          fprintf(stdout, _("Unknown\n"));
3604
3605         }
3606
3607         /* For 3310: set date to 2090! */
3608         if (GetModelFeature (FN_CALENDAR)==F_CAL33) {
3609           fprintf(stdout, _("   Date: xxxx-%02d-%02d\n"), CalendarNote.Time.Month,
3610                                                           CalendarNote.Time.Day);
3611         } else {
3612           fprintf(stdout, _("   Date: %s %d-%02d-%02d\n"), 
3613                 DayOfWeek(CalendarNote.Time.Year, CalendarNote.Time.Month, CalendarNote.Time.Day),
3614                                                         CalendarNote.Time.Year,
3615                                                         CalendarNote.Time.Month,
3616                                                         CalendarNote.Time.Day);
3617         }
3618         
3619         fprintf(stdout, _("   Time: %02d:%02d:%02d\n"), CalendarNote.Time.Hour,
3620                                                         CalendarNote.Time.Minute,
3621                                                         CalendarNote.Time.Second);
3622
3623         if (CalendarNote.Alarm.Year!=0) {
3624           fprintf(stdout, _("   Alarm date: %s %d-%02d-%02d\n"), 
3625                         DayOfWeek(CalendarNote.Alarm.Year, CalendarNote.Alarm.Month, CalendarNote.Alarm.Day),
3626                                                               CalendarNote.Alarm.Year,
3627                                                               CalendarNote.Alarm.Month,
3628                                                               CalendarNote.Alarm.Day);
3629
3630           fprintf(stdout, _("   Alarm time: %02d:%02d:%02d\n"), CalendarNote.Alarm.Hour,
3631                                                                 CalendarNote.Alarm.Minute,
3632                                                                 CalendarNote.Alarm.Second);
3633           if ( GetModelFeature (FN_CALENDAR)==F_CAL71 ) 
3634             fprintf(stdout, _("   Alarm type: %s\n"), (CalendarNote.AlarmType==0x00) ?
3635                                                           "With Tone" : "Silent" );
3636         }
3637
3638         if ( GetModelFeature (FN_CALENDAR)==F_CAL71 && CalendarNote.Recurrance!= 0 ) 
3639            fprintf(stdout, "   It repeat every %d day%s\n", CalendarNote.Recurrance/24,
3640                        ((CalendarNote.Recurrance/24)>1) ? "s":"" );
3641
3642         if (CalendarNote.Type == GCN_BIRTHDAY)
3643         {
3644           int i_age;
3645           i_age = Date.Year - CalendarNote.Time.Year;
3646           fprintf(stdout, _("   Text: %s (%d %s)\n"), CalendarNote.Text,
3647               i_age, (i_age==1)?"year":"years");
3648         } else {
3649           if (CalendarNote.Text[0]!=0)
3650             fprintf(stdout, _("   Text: %s\n"), CalendarNote.Text);
3651         }
3652
3653         if (CalendarNote.Type == GCN_CALL)
3654           fprintf(stdout, _("   Phone: %s\n"), CalendarNote.Phone);
3655       }
3656     } else {
3657       fprintf(stderr, _("The calendar note %i can not be read\n"),i);
3658     }
3659   }
3660
3661   if (was_note && vCalVer!=0) {
3662     fprintf(stdout, GSM_GetVCALENDAREnd(vCalVer));
3663   }
3664   
3665   GSM->Terminate();
3666
3667   return 0;
3668 }
3669
3670 /* Writing calendar notes. */
3671
3672 int writecalendarnote(char *argv[])
3673 {
3674   GSM_CalendarNote CalendarNote;
3675   GSM_Error error;
3676   int number;
3677
3678   number=atoi(argv[1]);
3679   
3680   if (number<1) {
3681     fprintf(stdout, _("Number of calendar note must be 1 or higher\n"));
3682     return -1;
3683   }
3684   
3685   switch ( GSM_ReadVCalendarFile(argv[0], &CalendarNote, &number) ) {
3686     case GE_NONE:
3687       break;
3688     case GE_CANTOPENFILE:
3689       fprintf(stdout, _("Failed to open vCalendar file \"%s\"\n"),argv[0]);
3690       return -1;
3691     case GE_TOOSHORT:
3692       fprintf(stdout, _("Number of given calendar note is too high (max=%i)\n"),number);
3693       return(-1);
3694     default:
3695       fprintf(stdout, _("Failed to parse vCalendar file \"%s\"\n"),argv[0]);
3696       return -1;    
3697   }
3698
3699   fbusinit(NULL);
3700
3701   /* Error 22=Calendar full ;-) */
3702
3703   error=GSM->WriteCalendarNote(&CalendarNote);
3704   switch (error) {
3705     case GE_NONE:
3706       fprintf(stdout, _("Succesfully written!\n"));break;
3707     case GE_TOOLONG:
3708       fprintf(stdout, _("Too long text in calendar note!\n"));break;
3709     default:
3710       fprintf(stdout, _("Failed to write calendar note!\n"));break;
3711   }
3712
3713   GSM->Terminate();
3714
3715   return 0;
3716 }
3717
3718 /* Calendar note deleting. */
3719
3720 int deletecalendarnote(char *Index)
3721 {
3722
3723   GSM_CalendarNote CalendarNote;
3724
3725   CalendarNote.Location=atoi(Index);
3726
3727   fbusinit(NULL);
3728
3729   if (GSM->DeleteCalendarNote(&CalendarNote) == GE_NONE) {
3730     fprintf(stdout, _("   Calendar note deleted.\n"));
3731   }
3732   else {
3733     fprintf(stderr, _("The calendar note can not be deleted\n"));
3734
3735     GSM->Terminate();
3736     return -1;
3737   }
3738
3739   GSM->Terminate();
3740
3741   return 0;
3742 }
3743
3744 /* Setting the date and time. */
3745
3746 int setdatetime(int argc, char *argv[])
3747 {
3748   struct tm *now;
3749   time_t nowh;
3750   GSM_DateTime Date;
3751
3752   fbusinit(NULL);
3753
3754   nowh=time(NULL);
3755   now=localtime(&nowh);
3756
3757   Date.Year = now->tm_year;
3758   Date.Month = now->tm_mon+1;
3759   Date.Day = now->tm_mday;
3760   Date.Hour = now->tm_hour;
3761   Date.Minute = now->tm_min;
3762   Date.Second = now->tm_sec;
3763
3764   if (argc>0) Date.Year = atoi (argv[0]);
3765   if (argc>1) Date.Month = atoi (argv[1]);
3766   if (argc>2) Date.Day = atoi (argv[2]);
3767   if (argc>3) Date.Hour = atoi (argv[3]);
3768   if (argc>4) Date.Minute = atoi (argv[4]);
3769
3770   if (Date.Year<1900)
3771   {
3772
3773     /* Well, this thing is copyrighted in U.S. This technique is known as
3774        Windowing and you can read something about it in LinuxWeekly News:
3775        http://lwn.net/1999/features/Windowing.phtml. This thing is beeing
3776        written in Czech republic and Poland where algorithms are not allowed
3777        to be patented. */
3778
3779     if (Date.Year>90)
3780       Date.Year = Date.Year+1900;
3781     else
3782       Date.Year = Date.Year+2000;
3783   }
3784
3785   /* FIXME: Error checking should be here. */
3786   GSM->SetDateTime(&Date);
3787
3788   GSM->Terminate();
3789
3790   return 0;
3791 }
3792
3793 /* In this mode we receive the date and time from mobile phone. */
3794
3795 int getdatetime(void) {
3796
3797   GSM_DateTime date_time;
3798
3799   fbusinit(NULL);
3800
3801   if (GSM->GetDateTime(&date_time)==GE_NONE) {
3802     if (date_time.IsSet) {
3803       fprintf(stdout, _("Date: %s %4d/%02d/%02d\n"), 
3804           DayOfWeek(date_time.Year, date_time.Month, date_time.Day),
3805           date_time.Year, date_time.Month, date_time.Day);
3806       fprintf(stdout, _("Time: %02d:%02d:%02d\n"), date_time.Hour, date_time.Minute, date_time.Second);
3807     } else {
3808       fprintf(stdout, _("Date and time not set in phone\n"));
3809     }
3810   } else {
3811     fprintf(stdout,_("Error!\n"));
3812   }
3813
3814   GSM->Terminate();
3815
3816   return 0;
3817 }
3818
3819 /* Setting the alarm. */
3820
3821 int setalarm(char *argv[])
3822 {
3823
3824   GSM_DateTime Date;
3825
3826   fbusinit(NULL);
3827
3828   Date.Hour = atoi(argv[0]);
3829   Date.Minute = atoi(argv[1]);
3830
3831   GSM->SetAlarm(1, &Date);
3832
3833   GSM->Terminate();
3834
3835   return 0;
3836 }
3837
3838 /* Getting the alarm. */
3839
3840 int getalarm(void) {
3841
3842   GSM_DateTime date_time;
3843
3844   fbusinit(NULL);
3845
3846   if (GSM->GetAlarm(0, &date_time)==GE_NONE) {
3847     fprintf(stdout, _("Alarm: %s\n"), (date_time.IsSet)?"on":"off");
3848     fprintf(stdout, _("Time: %02d:%02d\n"), date_time.Hour, date_time.Minute);
3849   } else {
3850     fprintf(stdout,_("Error!\n"));
3851   }
3852
3853   GSM->Terminate();
3854
3855   return 0;
3856 }
3857
3858 /* In monitor mode we don't do much, we just initialise the fbus code.
3859    Note that the fbus code no longer has an internal monitor mode switch,
3860    instead compile with DEBUG enabled to get all the gumpf. */
3861
3862 int monitormode(int argc, char *argv[])
3863 {
3864
3865   float rflevel=-1, batterylevel=-1;
3866         unsigned char loop=1;
3867
3868   GSM_PowerSource powersource=-1;
3869   GSM_RFUnits rf_units = GRF_Arbitrary;
3870   GSM_BatteryUnits batt_units = GBU_Arbitrary;
3871
3872   GSM_NetworkInfo NetworkInfo;
3873   GSM_CBMessage CBMessage;
3874
3875   GSM_MemoryStatus SIMMemoryStatus = {GMT_SM, 0, 0};
3876   GSM_MemoryStatus PhoneMemoryStatus = {GMT_ME, 0, 0};
3877   GSM_MemoryStatus DC_MemoryStatus = {GMT_DC, 0, 0};
3878   GSM_MemoryStatus EN_MemoryStatus = {GMT_EN, 0, 0};
3879   GSM_MemoryStatus FD_MemoryStatus = {GMT_FD, 0, 0};
3880   GSM_MemoryStatus LD_MemoryStatus = {GMT_LD, 0, 0};
3881   GSM_MemoryStatus MC_MemoryStatus = {GMT_MC, 0, 0};
3882   GSM_MemoryStatus ON_MemoryStatus = {GMT_ON, 0, 0};
3883   GSM_MemoryStatus RC_MemoryStatus = {GMT_RC, 0, 0};
3884
3885   GSM_SMSStatus SMSStatus = {0, 0};
3886
3887   char Number[20];
3888
3889         /* evaluate for presence of "-noloop" argument in parameter */
3890         if(argc>0)
3891         {
3892                 if( strcmp(argv[0],"-noloop" ) && strcmp(argv[0],"-nl" ))
3893                 {
3894                         usage();
3895                         return -1;
3896                 }
3897                 else
3898                         loop=0;
3899         }
3900
3901   /* We do not want to monitor serial line forever - press Ctrl+C to stop the
3902      monitoring mode. */
3903
3904   signal(SIGINT, interrupted);
3905
3906   fprintf (stderr, _("Entering monitor mode...\n"));
3907   fprintf (stderr, _("Initialising GSM interface...\n"));
3908
3909   /* Initialise the code for the GSM interface. */     
3910
3911   fbusinit(NULL);
3912
3913   sleep(1);
3914   GSM->EnableCellBroadcast();
3915
3916   /* Loop here indefinitely - allows you to see messages from GSM code in
3917      response to unknown messages etc. The loops ends after pressing the
3918      Ctrl+C. */
3919   while (!bshutdown) {
3920     if (GSM->GetRFLevel(&rf_units, &rflevel) == GE_NONE)
3921       fprintf(stdout, _("RFLevel: %d\n"), (int)rflevel);
3922
3923     if (GSM->GetBatteryLevel(&batt_units, &batterylevel) == GE_NONE)
3924       fprintf(stdout, _("Battery: %d\n"), (int)batterylevel);
3925
3926     if (GSM->GetPowerSource(&powersource) == GE_NONE)
3927       fprintf(stdout, _("Power Source: %s\n"), (powersource==GPS_ACDC)?_("AC/DC"):_("battery"));
3928
3929     if (GSM->GetMemoryStatus(&SIMMemoryStatus) == GE_NONE)
3930       fprintf(stdout, _("SIM: Used %d, Free %d\n"), SIMMemoryStatus.Used, SIMMemoryStatus.Free);
3931
3932     if (GSM->GetMemoryStatus(&PhoneMemoryStatus) == GE_NONE)
3933       fprintf(stdout, _("Phone: Used %d, Free %d\n"), PhoneMemoryStatus.Used, PhoneMemoryStatus.Free);
3934
3935     if (GSM->GetMemoryStatus(&DC_MemoryStatus) == GE_NONE)
3936       fprintf(stdout, _("DC: Used %d, Free %d\n"), DC_MemoryStatus.Used, DC_MemoryStatus.Free);
3937
3938     if (GSM->GetMemoryStatus(&EN_MemoryStatus) == GE_NONE)
3939       fprintf(stdout, _("EN: Used %d, Free %d\n"), EN_MemoryStatus.Used, EN_MemoryStatus.Free);
3940
3941     if (GSM->GetMemoryStatus(&FD_MemoryStatus) == GE_NONE)
3942       fprintf(stdout, _("FD: Used %d, Free %d\n"), FD_MemoryStatus.Used, FD_MemoryStatus.Free);
3943
3944     if (GSM->GetMemoryStatus(&LD_MemoryStatus) == GE_NONE)
3945       fprintf(stdout, _("LD: Used %d, Free %d\n"), LD_MemoryStatus.Used, LD_MemoryStatus.Free);
3946
3947     if (GSM->GetMemoryStatus(&MC_MemoryStatus) == GE_NONE)
3948       fprintf(stdout, _("MC: Used %d, Free %d\n"), MC_MemoryStatus.Used, MC_MemoryStatus.Free);
3949
3950     if (GSM->GetMemoryStatus(&ON_MemoryStatus) == GE_NONE)
3951       fprintf(stdout, _("ON: Used %d, Free %d\n"), ON_MemoryStatus.Used, ON_MemoryStatus.Free);
3952
3953     if (GSM->GetMemoryStatus(&RC_MemoryStatus) == GE_NONE)
3954       fprintf(stdout, _("RC: Used %d, Free %d\n"), RC_MemoryStatus.Used, RC_MemoryStatus.Free);
3955
3956     if (GSM->GetSMSStatus(&SMSStatus) == GE_NONE)
3957       fprintf(stdout, _("SMS Messages: UnRead %d, Number %d\n"), SMSStatus.UnRead, SMSStatus.Number);
3958
3959     if (GSM->GetIncomingCallNr(Number) == GE_NONE)
3960       fprintf(stdout, _("Incoming call: %s\n"), Number);
3961
3962     if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE)
3963       fprintf(stdout, _("Network: %s (%s), LAC: %s, CellID: %s\n"), GSM_GetNetworkName (NetworkInfo.NetworkCode), GSM_GetCountryName(NetworkInfo.NetworkCode), NetworkInfo.LAC, NetworkInfo.CellID);
3964
3965     if (GSM->ReadCellBroadcast(&CBMessage) == GE_NONE)
3966       fprintf(stdout, _("Cell broadcast received on channel %d: %s\n"), CBMessage.Channel, CBMessage.Message);
3967
3968     if( !loop ) break;
3969             
3970     sleep(1);
3971   }
3972
3973   if( loop ) fprintf (stderr, _("Leaving monitor mode...\n"));
3974
3975   GSM->Terminate();
3976
3977   return 0;
3978 }
3979
3980 /* Shows texts from phone's display */
3981
3982 int displayoutput()
3983 {
3984
3985   GSM_Error error;
3986   
3987   fbusinit(NULL);
3988
3989   error=GSM->EnableDisplayOutput();
3990
3991   if (error == GE_NONE)
3992   {
3993
3994     /* We do not want to see texts forever - press Ctrl+C to stop. */
3995
3996     signal(SIGINT, interrupted);    
3997
3998     fprintf (stderr, _("Entering display monitoring mode...\n"));
3999
4000     /* Loop here indefinitely - allows you to read texts from phone's
4001        display. The loops ends after pressing the Ctrl+C. */
4002
4003     while (!bshutdown)
4004       sleep(1);
4005
4006     fprintf (stderr, _("Leaving display monitor mode...\n"));
4007
4008     error=GSM->DisableDisplayOutput();
4009     if (error!=GE_NONE)
4010       fprintf (stderr, _("Error!\n"));
4011   } else
4012       fprintf (stderr, _("Error!\n"));
4013
4014   GSM->Terminate();
4015
4016   return 0;
4017 }
4018
4019 /* Displays names of available ringtones */
4020 int allringtones()
4021 {
4022   char model[64], rev[64];
4023   int i;
4024
4025   fbusinit(NULL);
4026
4027   while (GSM->GetRevision(rev) != GE_NONE)
4028     sleep(1);
4029
4030   while (GSM->GetModel(model)  != GE_NONE)
4031     sleep(1);
4032
4033   strncpy(rev,rev+2,5);
4034   rev[5]=0;
4035   PrepareRingingTones(model,rev);
4036   
4037   for (i=1;i<=NumberOfRingtones();i++)
4038   {
4039     fprintf(stdout,_("%i. %s\n"),i,RingingToneName(0,i));
4040   }
4041   
4042   GSM->Terminate();
4043
4044   return 0;
4045
4046 }
4047
4048 /* Reads profile from phone and displays its' settings */
4049
4050 int getprofile(int argc, char *argv[])
4051 {
4052
4053   int max_profiles;
4054   int start, stop, i;
4055   GSM_Profile profile;
4056   GSM_Error error;
4057   
4058   /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */
4059   char model[64], rev[64];
4060
4061   /* Initialise the code for the GSM interface. */     
4062
4063   fbusinit(NULL);
4064
4065   profile.Number = 0;
4066   error=GSM->GetProfile(&profile);
4067
4068   if (error == GE_NONE)
4069   {
4070   
4071     while (GSM->GetModel(model)  != GE_NONE) sleep(1);
4072
4073     while (GSM->GetRevision(rev) != GE_NONE) sleep(1);
4074
4075     strncpy(rev,rev+2,5);
4076     rev[5]=0;
4077     PrepareRingingTones(model,rev);
4078
4079     switch(GetModelFeature (FN_PROFILES)) {
4080       case F_PROF33:max_profiles=6;break;
4081       case F_PROF51:max_profiles=3;break;
4082       default      :max_profiles=7;break;
4083     }
4084
4085     if (argc>0)
4086     {
4087       profile.Number=atoi(argv[0])-1;
4088       start=profile.Number;
4089       stop=start+1;
4090
4091       if (profile.Number < 0)
4092       {
4093          fprintf(stderr, _("Profile number must be value from 1 to %d!\n"), max_profiles);
4094          GSM->Terminate();
4095          return -1;
4096       }
4097
4098       if (profile.Number >= max_profiles)
4099       {
4100          fprintf(stderr, _("This phone supports only %d profiles!\n"), max_profiles);
4101          GSM->Terminate();
4102          return -1;
4103       }
4104     } else {
4105       start=0;
4106       stop=max_profiles;
4107     }
4108
4109     i=start;
4110     while (i<stop)
4111     {
4112       profile.Number=i;
4113
4114       if (profile.Number!=0) GSM->GetProfile(&profile);
4115
4116       printf("%d. \"%s\"", (profile.Number+1), profile.Name);
4117       if (profile.DefaultName==-1) printf(" (name defined)");
4118       printf("\n");
4119
4120 #ifdef DEBUG
4121       printf("Incoming call alert: %d\n", profile.CallAlert);
4122       printf("Ringtone ID: %d\n", profile.Ringtone);
4123       printf("Ringing volume: %d\n", profile.Volume);
4124       printf("Message alert tone: %d\n", profile.MessageTone);
4125       printf("Keypad tones: %d\n", profile.KeypadTone);
4126       printf("Warning and game tones: %d\n", profile.WarningTone);
4127       printf("Lights: %d\n", profile.Lights);
4128       printf("Vibration: %d\n", profile.Vibration);
4129       printf("Caller groups: 0x%02x\n", profile.CallerGroups);
4130       printf("Automatic answer: %d\n", profile.AutomaticAnswer);
4131       printf("Screen saver: %d\n", profile.ScreenSaver);
4132       printf("\n");
4133 #endif
4134       
4135       printf("Incoming call alert: %s\n", GetProfileCallAlertString(profile.CallAlert));
4136
4137       /* For different phones different ringtones names */
4138       if (strcmp(RingingToneName(profile.Ringtone,0),""))
4139         printf(_("Ringing tone: %s (number %d in phone menu)\n"), 
4140           RingingToneName(profile.Ringtone,0), RingingToneMenu(profile.Ringtone));
4141       else
4142         printf(_("Ringtone number: %d\n"), profile.Ringtone);
4143
4144       printf(_("Ringing volume: %s\n"), GetProfileVolumeString(profile.Volume));
4145
4146       printf(_("Message alert tone: %s\n"), GetProfileMessageToneString(profile.MessageTone));
4147
4148       printf(_("Keypad tones: %s\n"), GetProfileKeypadToneString(profile.KeypadTone));
4149
4150       printf(_("Warning and game tones: %s\n"), GetProfileWarningToneString(profile.WarningTone));
4151
4152       if (GetModelFeature (FN_SCREENSAVER)!=0)
4153         printf(_("Screen saver: %s\n"), GetProfileOnOffString(profile.ScreenSaver));
4154       
4155       printf(_("Vibration: %s\n"), GetProfileVibrationString(profile.Vibration));
4156
4157       /* It has been nice to add here reading caller group name. ;^) */
4158       if (GetModelFeature (FN_CALENDAR)==F_CAL71) 
4159         printf(_("Caller groups: %s\n"), 
4160                               GetProfileCallerGroups(profile.CallerGroups) );
4161
4162       /* FIXME: need make investigation for 3310 for these features. For now unknown */
4163       if (GetModelFeature (FN_PROFILES)!=F_PROF33) {
4164         /* FIXME: Light settings is only used for Car */
4165         if (profile.Number==(max_profiles-2)) printf(_("Lights: %s\n"), profile.Lights ? _("On") : _("Automatic"));
4166
4167         /* FIXME: Automatic answer is only used for Car and Headset. */
4168         if (profile.Number>=(max_profiles-2)) printf(_("Automatic answer: %s\n"), GetProfileOnOffString(profile.AutomaticAnswer));
4169       }
4170
4171       printf("\n");
4172
4173       i++;
4174     }
4175   } else {
4176     if (error == GE_NOTIMPLEMENTED) {
4177        fprintf(stderr, _("Function not implemented in %s model!\n"), model);
4178        GSM->Terminate();
4179        return -1;
4180     } else
4181     {
4182       fprintf(stderr, _("Unspecified error\n"));
4183       GSM->Terminate();
4184       return -1;
4185     }
4186   }
4187
4188   GSM->Terminate();
4189
4190   return 0;
4191
4192 }
4193
4194 /* Sets profile feature */
4195
4196 int setprofile(int argc, char *argv[])
4197 {
4198
4199 /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */
4200   char model[64], rev[64];
4201
4202   int max_profiles;
4203   GSM_Profile profile;
4204   GSM_Profile profile2, profile3;
4205   GSM_Error error;
4206   bool correct_arg1;
4207   bool correct_arg2;
4208   
4209 /* Initialise the code for the GSM interface. */     
4210
4211   fbusinit(NULL);
4212   
4213   profile.Number = 0;
4214
4215   error = GSM->GetProfile(&profile);
4216   
4217   if (error == GE_NONE)
4218   {
4219  
4220     while (GSM->GetModel(model)  != GE_NONE) sleep(1);
4221       
4222     while (GSM->GetRevision(rev) != GE_NONE) sleep(1);
4223
4224     strncpy(rev,rev+2,5);
4225     rev[5]=0;
4226     PrepareRingingTones(model,rev);
4227
4228     switch(GetModelFeature (FN_PROFILES)) {
4229       case F_PROF33:max_profiles=6;break;
4230       case F_PROF51:max_profiles=3;break;
4231       default      :max_profiles=7;break;
4232     }
4233
4234     profile.Number=atoi (argv[0]);
4235     profile.Number=profile.Number-1;
4236     
4237     if (profile.Number < 0)
4238     {
4239       fprintf(stderr, _("Profile number must be value from 1 to %i!\n"), max_profiles);
4240       GSM->Terminate();
4241       return -1;
4242     }
4243     
4244     if (profile.Number >= max_profiles)
4245     {
4246       fprintf(stderr, _("This phone supports only %i profiles!\n"), max_profiles);
4247       GSM->Terminate();
4248       return -1;
4249     }
4250       
4251     if (profile.Number!=0) GSM->GetProfile(&profile);
4252         
4253     correct_arg1=false;
4254     correct_arg2=false;
4255
4256     if (strcmp(argv[1], "callalert")==0)
4257     {
4258        if (strcmp(argv[2], "ringing")==0) {profile.CallAlert=PROFILE_CALLALERT_RINGING;correct_arg2=true;}
4259        if (strcmp(argv[2], "ascending")==0) {profile.CallAlert=PROFILE_CALLALERT_ASCENDING;correct_arg2=true;}
4260        if (strcmp(argv[2], "ringonce")==0) {profile.CallAlert=PROFILE_CALLALERT_RINGONCE;correct_arg2=true;}
4261        if (strcmp(argv[2], "beeponce")==0) {profile.CallAlert=PROFILE_CALLALERT_BEEPONCE;correct_arg2=true;}
4262        if (strcmp(argv[2], "groups")==0)
4263        {
4264          profile.CallAlert=PROFILE_CALLALERT_CALLERGROUPS;
4265          correct_arg2=true;
4266          /*Ignored by N5110*/
4267          /*FIX ME: it's ignored by N5130 and 3210 too*/
4268          if (max_profiles==3) fprintf(stdout, _("Warning: value \"groups\" for profile feature \"callalert\" will be ignored in this phone model !\n"));
4269        }
4270        if (strcmp(argv[2], "off")==0 || strcmp(argv[2], "0")==0) {profile.CallAlert=PROFILE_CALLALERT_OFF;correct_arg2=true;}
4271        if (!correct_arg2)
4272        {
4273          fprintf(stderr, _("Correct parameters for profile feature \"callalert\" are ringing|ascending|ringonce|beeponce|groups|off|0 !\n"));
4274          GSM->Terminate();
4275          return -1;
4276         }
4277         correct_arg1=true;
4278     }
4279     if (strcmp(argv[1], "volume")==0)
4280     {
4281        if (strcmp(argv[2], "1")==0) {profile.Volume=PROFILE_VOLUME_LEVEL1;correct_arg2=true;}
4282        if (strcmp(argv[2], "2")==0) {profile.Volume=PROFILE_VOLUME_LEVEL2;correct_arg2=true;}
4283        if (strcmp(argv[2], "3")==0) {profile.Volume=PROFILE_VOLUME_LEVEL3;correct_arg2=true;}
4284        if (strcmp(argv[2], "4")==0) {profile.Volume=PROFILE_VOLUME_LEVEL4;correct_arg2=true;}
4285        if (strcmp(argv[2], "5")==0) {profile.Volume=PROFILE_VOLUME_LEVEL5;correct_arg2=true;}
4286        if (!correct_arg2)
4287        {
4288          fprintf(stderr, _("Correct parameters for profile feature \"volume\" are 0|1|2|3|4|5 !\n"));
4289          GSM->Terminate();
4290          return -1;
4291         }
4292         correct_arg1=true;
4293     }
4294     if (strcmp(argv[1], "keypad")==0 || strcmp(argv[1], "keypadtone")==0)
4295     {
4296        if (strcmp(argv[2], "0")==0 || strcmp(argv[2], "off")==0) {profile.KeypadTone=PROFILE_KEYPAD_OFF;correct_arg2=true;}
4297        if (strcmp(argv[2], "1")==0) {profile.KeypadTone=PROFILE_KEYPAD_LEVEL1;correct_arg2=true;}
4298        if (strcmp(argv[2], "2")==0) {profile.KeypadTone=PROFILE_KEYPAD_LEVEL2;correct_arg2=true;}
4299        if (strcmp(argv[2], "3")==0) {profile.KeypadTone=PROFILE_KEYPAD_LEVEL3;correct_arg2=true;}
4300        if (!correct_arg2)
4301        {
4302          fprintf(stderr, _("Correct parameters for profile feature \"keypad|keypadtone\" are off|0|1|2|3 !\n"));
4303          GSM->Terminate();
4304          return -1;
4305         }
4306         correct_arg1=true;
4307     }
4308     if (strcmp(argv[1], "messagetone")==0 || strcmp(argv[1], "smstone")==0 || strcmp(argv[1], "sms")==0 || strcmp(argv[1], "message")==0)
4309     {
4310        if (strcmp(argv[2], "0")==0 || strcmp(argv[2], "off")==0) {profile.MessageTone=PROFILE_MESSAGE_NOTONE;correct_arg2=true;}
4311        if (strcmp(argv[2], "standard")==0) {profile.MessageTone=PROFILE_MESSAGE_STANDARD;correct_arg2=true;}
4312        if (strcmp(argv[2], "special")==0) {profile.MessageTone=PROFILE_MESSAGE_SPECIAL;correct_arg2=true;}
4313        if (strcmp(argv[2], "beeponce")==0 || strcmp(argv[2], "once")==0) {profile.MessageTone=PROFILE_MESSAGE_BEEPONCE;correct_arg2=true;}
4314        if (strcmp(argv[2], "ascending")==0) {profile.MessageTone=PROFILE_MESSAGE_ASCENDING;correct_arg2=true;}
4315        if (!correct_arg2)
4316        {
4317          fprintf(stderr, _("Correct parameters for profile feature \"messagetone|smstone|message|sms\" are 0|off|standard|special|beeponce|once|ascending !\n"));
4318          GSM->Terminate();
4319          return -1;
4320         }
4321         correct_arg1=true;
4322     }
4323     if (strcmp(argv[1], "warningtone")==0 || strcmp(argv[1], "warning")==0)
4324     {
4325        if (strcmp(argv[2], "0")==0 || strcmp(argv[2], "off")==0) {profile.WarningTone=PROFILE_WARNING_OFF;correct_arg2=true;}
4326        if (strcmp(argv[2], "1")==0 || strcmp(argv[2], "on")==0) {profile.WarningTone=PROFILE_WARNING_ON;correct_arg2=true;}
4327        if (!correct_arg2)
4328        {
4329          fprintf(stderr, _("Correct parameters for profile feature \"warningtone|warning\" are 0|off|1|on !\n"));
4330          GSM->Terminate();
4331          return -1;
4332         }
4333         correct_arg1=true;
4334     }
4335     if (strcmp(argv[1], "vibra")==0 || strcmp(argv[1], "vibration")==0)
4336     {
4337        if (strcmp(argv[2], "0")==0 || strcmp(argv[2], "off")==0) {profile.Vibration=PROFILE_VIBRATION_OFF;correct_arg2=true;}
4338        if (strcmp(argv[2], "1")==0 || strcmp(argv[2], "on")==0) {profile.Vibration=PROFILE_VIBRATION_ON;correct_arg2=true;}
4339        if (!correct_arg2)
4340        {
4341          fprintf(stderr, _("Correct parameters for profile feature \"vibration|vibra\" are 0|off|1|on !\n"));
4342          GSM->Terminate();
4343          return -1;
4344         }
4345         correct_arg1=true;
4346     }
4347     if (strcmp(argv[1], "lights")==0)
4348     {
4349        if (strcmp(argv[2], "0")==0 || strcmp(argv[2], "off")==0) {profile.Lights=-1;correct_arg2=true;}
4350        if (strcmp(argv[2], "1")==0 || strcmp(argv[2], "on")==0) {profile.Lights=0;correct_arg2=true;}
4351        if (!correct_arg2)
4352        {
4353          fprintf(stderr, _("Correct parameters for profile feature \"lights\" are 0|off|1|on !\n"));
4354          GSM->Terminate();
4355          return -1;
4356        }
4357        if (profile.Number!=(max_profiles-2))
4358        {
4359          profile2.Number=max_profiles-2;
4360          if (GSM->GetProfile(&profile2)==GE_NONE)
4361          {
4362            fprintf(stdout, _("Warning: \"Lights\" feature is ignored in this profile (only setting it for \"%s\" profile get some results) !\n"), profile2.Name);
4363          }
4364        }
4365        correct_arg1=true;
4366     }
4367     if (strcmp(argv[1], "answer")==0)
4368     {
4369        if (strcmp(argv[2], "0")==0 || strcmp(argv[2], "off")==0) {profile.AutomaticAnswer=-1;correct_arg2=true;}
4370        if (strcmp(argv[2], "1")==0 || strcmp(argv[2], "on")==0) {profile.AutomaticAnswer=0;correct_arg2=true;}
4371        if (!correct_arg2)
4372        {
4373          fprintf(stderr, _("Correct parameters for profile feature \"answer\" are 0|off|1|on !\n"));
4374          GSM->Terminate();
4375          return -1;
4376        }
4377        if (profile.Number<(max_profiles-2))
4378        {
4379          profile2.Number=max_profiles-2;
4380          if (GSM->GetProfile(&profile2)==GE_NONE)
4381          {
4382            profile3.Number=max_profiles-1;
4383            if (GSM->GetProfile(&profile3)==GE_NONE)
4384            {
4385              fprintf(stdout, _("Warning: \"Automatic Answer\" feature is ignored in this profile (only setting it for \"%s\" and \"%s\" profiles get some results) !\n"), profile2.Name, profile3.Name);
4386            }
4387          }
4388        }
4389        correct_arg1=true;
4390     }
4391     if (strcmp(argv[1], "name")==0)
4392     {
4393        strcpy(profile.Name,argv[2]);
4394        /*Ignored by N5110*/
4395        /*FIX ME: it's ignored by N5130 and 3210 too*/
4396        if (max_profiles==3) fprintf(stdout, _("Warning: this phone model doesn't allow to change profile name !\n"));
4397        correct_arg1=true;
4398     }
4399     if (strcmp(argv[1], "ringtone")==0)
4400     {
4401       profile.Ringtone=atoi(argv[2]);
4402       if (profile.Ringtone<1)
4403       {
4404         /*With value 0 results are interesting in N5110, but can't be used for anything*/
4405         fprintf(stderr, _("Ringtone number must be higher than 0 !\n"));
4406         GSM->Terminate();
4407         return -1; 
4408       } else
4409       {
4410         if (profile.Ringtone>NumberOfRingtones())
4411         {
4412           fprintf(stderr, _("Ringtone number too high (max %i) !\n"),NumberOfRingtones());
4413           GSM->Terminate();
4414           return -1;
4415         }  
4416         profile.Ringtone=RingingToneCode(profile.Ringtone);
4417         if (profile.Ringtone==0)
4418         {
4419           fprintf(stderr, _("Warning: we don't know ringtones codes for this model ! Can you contact with gnokii authors to add it into source ?\n"));
4420           GSM->Terminate();
4421           return -1;
4422         }
4423         if (max_profiles==3) fprintf(stdout, _("Warning: ringtone is changed for all profiles. You must reset phone or select profile in phone againg to see result.\n"));
4424       }
4425       correct_arg1=true;
4426     }
4427     if (strcmp(argv[1], "groups")==0)
4428     {
4429        /*Ignored by N5110*/
4430        /*FIX ME: it's ignored by N5130 and 3210 too*/
4431        if (max_profiles==3) fprintf(stdout, _("Warning: this phone model doesn't allow to change caller group name !\n"));
4432        profile.CallerGroups=atoi(argv[2]);
4433        correct_arg1=true;
4434     }
4435
4436     if (!correct_arg1)
4437     {
4438       fprintf(stderr, _("Correct profile feature names are callalert|volume|keypad|keypadtone|messagetone|smstone|message|sms|warningtone|warning|vibra|vibration|lights|answer|name|groups !\n"));
4439       GSM->Terminate();
4440       return -1;
4441     }
4442     
4443     GSM->SetProfile(&profile);
4444     
4445   } else {
4446     if (error == GE_NOTIMPLEMENTED) {
4447        fprintf(stderr, _("Function not implemented in %s model!\n"), model);
4448        GSM->Terminate();
4449        return -1;
4450     } else
4451     {
4452       fprintf(stderr, _("Unspecified error\n"));
4453       GSM->Terminate();
4454       return -1;
4455     }
4456   }
4457  
4458   GSM->Terminate();
4459
4460   return 0;
4461
4462 }
4463
4464 /* Get requested range of memory storage entries and output to stdout in
4465    easy-to-parse format */
4466
4467 int getmemory(int argc, char *argv[])
4468 {
4469
4470   GSM_PhonebookEntry entry;
4471   int count;
4472   register int i;
4473   GSM_Error error;
4474   GSM_Bitmap bitmap;
4475   char memory_type_string[20];
4476   int start_entry;
4477   int end_entry;
4478   int i_used = 0, n_used=0;
4479   int do_all;
4480   char *output_opt = NULL;
4481   bool wasdate=false;
4482   char az_group_name[5][MAX_BITMAP_TEXT_LENGTH];
4483   bool formatdone=false;
4484   char buf[64];
4485
4486   /* group names init */
4487   for(i=0;i<5;i++) az_group_name[i][0]='\0';
4488
4489   /* Handle command line args that set type, start and end locations. */
4490   if (!GetMemoryTypeID(argv[0], &entry.MemoryType))
4491   {
4492     fprintf(stderr, _("Unknown memory type %s!\n"), argv[0]);
4493     return (-1);
4494   }
4495   GetMemoryTypeString(memory_type_string, &entry.MemoryType);
4496
4497   if (argv[argc-1][0] == '-')
4498     output_opt = argv[--argc];
4499
4500   /* Do generic initialisation routine */
4501
4502   fbusinit(NULL);
4503
4504   while ((error = GSM->GetModel(buf)) != GE_NONE && i++ < 15)
4505     sleep(1);
4506
4507   if (argc > 1) {
4508     do_all = 0;
4509     start_entry = atoi (argv[1]);
4510     end_entry = argc > 2 ? atoi( argv[2]) : start_entry;
4511   } else {
4512     GSM_MemoryStatus stats = {entry.MemoryType, 0, 0};
4513
4514     do_all = 1;
4515     start_entry = 1;
4516     if (GSM->GetMemoryStatus( &stats) != GE_NONE) {
4517       fprintf( stderr, _("Error reading memory status.\n"));
4518       GSM->Terminate();
4519       return -1;
4520     }
4521     n_used = stats.Used;
4522     end_entry = stats.Used + stats.Free;
4523   }
4524     
4525
4526   /* Now retrieve the requested entries. */
4527
4528   for (count = start_entry;
4529        count <= end_entry && (!do_all || i_used < n_used);
4530        count++) {
4531
4532     entry.Location=count;
4533     
4534     error=GSM->GetMemoryLocation(&entry);
4535
4536     switch (error) {
4537     case GE_NONE:
4538       if (entry.SubEntriesCount || strcmp( entry.Number, ""))
4539         i_used++;
4540       else if (do_all)
4541         break;
4542       if (output_opt && !strcmp( output_opt,"-v30")) {
4543         semicolon_pipe_substitution( &entry, 0 );
4544         fprintf(stdout,_("%s"),GSM_GetVCARD(&entry,30));
4545         formatdone=true;
4546       } 
4547       if (output_opt && !strcmp(output_opt,"-v21")) {
4548         semicolon_pipe_substitution( &entry, 0 );
4549         fprintf(stdout,_("%s"),GSM_GetVCARD(&entry,21));
4550         formatdone=true;
4551       } 
4552       if (output_opt && !strcmp(output_opt,"-v")) {
4553         semicolon_pipe_substitution( &entry, 0 );
4554         fprintf(stdout,_("%s"),GSM_GetVCARD(&entry,10));
4555         formatdone=true;
4556       } 
4557       if (output_opt && !strcmp(output_opt,"-short")) {
4558         semicolon_pipe_substitution( &entry, 0 );
4559         fprintf(stdout, "%s;%s;%s;%d;%d;", entry.Name, entry.Number, memory_type_string, entry.Location, entry.Group);
4560         for( i = 0; i <  entry.SubEntriesCount; i++ )
4561         {
4562           if( entry.SubEntries[i].EntryType == GSM_Date )
4563             fprintf(stdout,_("%u;%u;%u;%02u.%02u.%04u;%02u:%02u:%02u;"),
4564                 entry.SubEntries[i].EntryType,
4565                 entry.SubEntries[i].NumberType,
4566                 entry.SubEntries[i].BlockNumber,
4567                 entry.SubEntries[i].data.Date.Day,
4568                 entry.SubEntries[i].data.Date.Month,
4569                 entry.SubEntries[i].data.Date.Year,
4570                 entry.SubEntries[i].data.Date.Hour,
4571                 entry.SubEntries[i].data.Date.Minute,
4572                 entry.SubEntries[i].data.Date.Second );
4573           else
4574             fprintf(stdout,_("%u;%u;%u;%s;"),
4575                 entry.SubEntries[i].EntryType,
4576                 entry.SubEntries[i].NumberType,
4577                 entry.SubEntries[i].BlockNumber,
4578                 entry.SubEntries[i].data.Number );
4579         }
4580         fprintf(stdout,_("\n"));
4581         formatdone=true;
4582       }
4583       if (!formatdone) {
4584           char z_gtype[12];
4585           wasdate=false;
4586           fprintf(stdout, "Memory %s, location %d\n",memory_type_string, entry.Location);
4587
4588           // check if some info in subentries 
4589           for( i = 0; i <  entry.SubEntriesCount; i++ )
4590                   if( entry.SubEntries[i].EntryType != GSM_Date &&
4591                           strcmp(entry.SubEntries[i].data.Number,"") )
4592                       break;
4593
4594           if (strcmp(entry.Number,"") || i <  entry.SubEntriesCount) {
4595             if (strcmp(entry.Name,"")) fprintf(stdout,_("   Name: %s\n"),entry.Name);
4596             if (strcmp(entry.Number,"")) fprintf(stdout,_("   Number: %s\n"),entry.Number);
4597             bitmap.type=GSM_CallerLogo;
4598             bitmap.number=entry.Group;
4599             strcpy(z_gtype,"unknown");
4600             if (entry.Group==5) strcpy(z_gtype,"No group");
4601             if (entry.Group<5 && entry.Group>=0) {
4602               if (!strcmp(az_group_name[entry.Group],"")) {
4603                 if (GetModelFeature (FN_CALLERGROUPS)!=0) {
4604                   if (GSM->GetBitmap(&bitmap)==GE_NONE)
4605                     strcpy( az_group_name[entry.Group], bitmap.text );
4606                 }
4607                 if ((!strcmp(az_group_name[entry.Group],""))) {
4608                   switch(entry.Group) {
4609                     case 0:strcpy(az_group_name[entry.Group],"Family");break;
4610                     case 1:strcpy(az_group_name[entry.Group],"VIP");break;
4611                     case 2:strcpy(az_group_name[entry.Group],"Friends");break;
4612                     case 3:strcpy(az_group_name[entry.Group],"Colleagues");break;
4613                     case 4:strcpy(az_group_name[entry.Group],"Other");break;
4614                     default:break;
4615                   }
4616                 }
4617               }
4618               strcpy(z_gtype,az_group_name[entry.Group]);
4619             }
4620             fprintf(stdout,_("   Group: %d (%s)\n"),entry.Group+1,z_gtype);
4621             for( i = 0; i <  entry.SubEntriesCount; i++ )
4622             {
4623               if( entry.SubEntries[i].EntryType == GSM_Date ) {
4624                  fprintf(stdout, "   Date and time: %s %02u.%02u.%04u %02u:%02u:%02u\n", 
4625                     DayOfWeek(entry.SubEntries[i].data.Date.Year,
4626                         entry.SubEntries[i].data.Date.Month,
4627                         entry.SubEntries[i].data.Date.Day),
4628                     entry.SubEntries[i].data.Date.Day,
4629                     entry.SubEntries[i].data.Date.Month,
4630                     entry.SubEntries[i].data.Date.Year,
4631                     entry.SubEntries[i].data.Date.Hour,
4632                     entry.SubEntries[i].data.Date.Minute,
4633                     entry.SubEntries[i].data.Date.Second);
4634                  wasdate=true;
4635               } else {
4636                  if( strcmp(entry.SubEntries[i].data.Number,"") ) {
4637                     char z_etype[19];
4638                     switch( entry.SubEntries[i].EntryType ) {
4639                       case GSM_Number:
4640                         switch( entry.SubEntries[i].NumberType ) {
4641                           case GSM_General: strcpy(z_etype,"General "); break;
4642                           case GSM_Home: strcpy(z_etype,"Home "); break;
4643                           case GSM_Mobile: strcpy(z_etype,"Mobile "); break;
4644                           case GSM_Work: strcpy(z_etype,"Work "); break;
4645                           case GSM_Fax: strcpy(z_etype,"Fax "); break;
4646                           default: strcpy(z_etype,""); break;
4647                         }
4648                         strcat(z_etype,"Number"); break;
4649                       case GSM_Note:
4650                         strcpy(z_etype,"Note"); break;
4651                       case GSM_Postal:
4652                         strcpy(z_etype,"Postal"); break;
4653                       case GSM_Email:
4654                         strcpy(z_etype,"E-Mail"); break;
4655                       default:
4656                         strcpy(z_etype,"unknown data"); break;
4657                     }
4658 #ifdef DEBUG
4659                     fprintf(stdout,_("   ---> Subentry: %u\n"),i+1);
4660                     fprintf(stdout,_("   Entry type: %u (%s)\n"),entry.SubEntries[i].EntryType,z_etype);
4661                     fprintf(stdout,_("   Number type: %u\n"),entry.SubEntries[i].NumberType);
4662                     fprintf(stdout,_("   Block Number: %u\n"),entry.SubEntries[i].BlockNumber);
4663 #endif
4664                     fprintf(stdout,_("   %s: %s\n"),z_etype,entry.SubEntries[i].data.Number);
4665                   }
4666               }
4667             }
4668             if ((entry.MemoryType==GMT_DC ||
4669                  entry.MemoryType==GMT_RC ||
4670                  entry.MemoryType==GMT_MC) && !wasdate)
4671               fprintf(stdout,_("   Date and time not available\n"));        
4672           } else
4673             fprintf(stdout,_("   Location empty\n"));
4674       }
4675       break;
4676     case GE_NOTIMPLEMENTED:
4677       fprintf( stderr, _("Function not implemented in %s model!\n"), model);
4678       GSM->Terminate();
4679       return -1;
4680     case GE_INVALIDMEMORYTYPE:
4681       fprintf( stderr, _("Memory type %s not supported!\n"),
4682                memory_type_string);
4683       GSM->Terminate();
4684       return -1;
4685     default:
4686       fprintf(stdout, _("%s|%d|Bad location or other error!(%d)\n"),
4687               memory_type_string, count, error);
4688     }
4689   }
4690         
4691   GSM->Terminate();
4692
4693   return 0;
4694 }
4695
4696 /* Read data from stdin, parse and write to phone.  The parsing is relatively
4697    crude and doesn't allow for much variation from the stipulated format. */
4698
4699 int writephonebook(int argc, char *args[])
4700 {
4701
4702   GSM_PhonebookEntry entry;
4703   GSM_Error error;
4704   char *memory_type_string;
4705   int line_count=0,current,i;
4706   int subentry;
4707
4708   char *Line, OLine[1024], BackLine[1024];
4709   char *ptr;
4710
4711   /* Check argument */
4712   if (argc) {
4713     if (strcmp("-i", args[0])) {
4714       usage();
4715       return 0;
4716     }
4717   }
4718   /* Initialise fbus code */
4719
4720   fbusinit(NULL);
4721
4722   Line = OLine;
4723
4724   /* Go through data from stdin. */
4725
4726   while (GetLine(stdin, Line, sizeof(OLine))!=-1) {
4727
4728     current=0;BackLine[current++]=Line[0];
4729     for (i=1;i<strlen(Line);i++) {
4730       if (Line[i-1]==';' && Line[i]==';') BackLine[current++]=' ';
4731       BackLine[current++]=Line[i];
4732     }
4733     BackLine[current++]=0;
4734
4735     strcpy(Line,BackLine);
4736
4737     line_count++;
4738
4739 #if defined(__svr4__) || defined(__FreeBSD__)
4740     ptr=strtok(Line, ";"); if (ptr) strcpy(entry.Name, ptr);
4741
4742     entry.Number[0]=0;
4743     ptr=strtok(NULL, ";"); if (ptr && ptr[0]!=' ') strcpy(entry.Number, ptr);
4744
4745     ptr=strtok(NULL, ";");
4746 #else
4747     ptr=strsep(&Line, ";"); if (ptr) strcpy(entry.Name, ptr);
4748
4749     entry.Number[0]=0;
4750     ptr=strsep(&Line, ";"); if (ptr && ptr[0]!=' ') strcpy(entry.Number, ptr);
4751
4752     ptr=strsep(&Line, ";");
4753 #endif
4754
4755     if (!ptr) {
4756       fprintf(stderr, _("Format problem on line %d [%s] 1\n"), line_count, BackLine);
4757       Line = OLine;
4758       continue;
4759     }
4760
4761     if (!strncmp(ptr,"ME", 2))
4762     {
4763       memory_type_string = "int";
4764       entry.MemoryType = GMT_ME;
4765     }
4766     else if (!strncmp(ptr,"SM", 2))
4767     {
4768         memory_type_string = "sim";
4769         entry.MemoryType = GMT_SM;
4770     }
4771     else
4772     {
4773       fprintf(stderr, _("Format problem on line %d [%s] 2: %s\n"),
4774         line_count, BackLine,ptr);
4775       break;
4776     }
4777
4778 #if defined(__svr4__) || defined(__FreeBSD__)
4779     ptr=strtok(NULL, ";"); if (ptr) entry.Location=atoi(ptr);
4780
4781     ptr=strtok(NULL, ";"); if (ptr) entry.Group=atoi(ptr);
4782 #else
4783     ptr=strsep(&Line, ";"); if (ptr) entry.Location=atoi(ptr);
4784
4785     ptr=strsep(&Line, ";"); if (ptr) entry.Group=atoi(ptr);
4786 #endif
4787
4788     if (!ptr) {
4789       fprintf(stderr, _("Format problem on line %d [%s] 3\n"),
4790         line_count, BackLine);
4791       continue;
4792     }
4793
4794     for( subentry = 0; ; subentry++ )
4795     {
4796 #if defined(__svr4__) || defined(__FreeBSD__)
4797       ptr=strtok(NULL, ";");
4798 #else
4799       ptr=strsep(&Line, ";");
4800 #endif
4801       if( ptr &&  *ptr != 0 )
4802         entry.SubEntries[subentry].EntryType=atoi(ptr);
4803       else
4804         break;
4805
4806 #if defined(__svr4__) || defined(__FreeBSD__)
4807       ptr=strtok(NULL, ";");
4808 #else
4809       ptr=strsep(&Line, ";");
4810 #endif
4811       if(ptr)
4812         entry.SubEntries[subentry].NumberType=atoi(ptr);
4813       // Phone Numbers need to have a number type.
4814       if(!ptr && entry.SubEntries[subentry].EntryType == GSM_Number)
4815       {
4816         fprintf(stderr, _("Missing phone number type on line %d"
4817           " entry %d [%s]\n"), line_count, subentry, BackLine);
4818         subentry--;
4819         break;
4820       }
4821
4822 #if defined(__svr4__) || defined(__FreeBSD__)
4823       ptr=strtok(NULL, ";");
4824 #else
4825       ptr=strsep(&Line, ";");
4826 #endif
4827       if(ptr)
4828         entry.SubEntries[subentry].BlockNumber=atoi(ptr);
4829
4830 #if defined(__svr4__) || defined(__FreeBSD__)
4831       ptr=strtok(NULL, ";");
4832 #else
4833       ptr=strsep(&Line, ";");
4834 #endif
4835       // 0x13 Date Type; it is only for Dailed Numbers, etc.
4836       // we don't store to this memories so it's an error to use it.
4837       if(!ptr || entry.SubEntries[subentry].EntryType == GSM_Date) 
4838       {
4839         fprintf(stderr, _("Is not a phone number on line %d entry %d [%s]\n"),
4840           line_count, subentry, BackLine);
4841         subentry--;
4842         break;
4843       }
4844       else
4845         strcpy( entry.SubEntries[subentry].data.Number, ptr );
4846     }
4847
4848     entry.SubEntriesCount = subentry;
4849
4850
4851     /* This is to send other exports (like from 6110) to 7110 */
4852     if (!entry.SubEntriesCount) {
4853         entry.SubEntriesCount = 1;
4854         entry.SubEntries[subentry].EntryType   = GSM_Number;
4855         entry.SubEntries[subentry].NumberType  = GSM_General;
4856         entry.SubEntries[subentry].BlockNumber = 2;
4857         strcpy(entry.SubEntries[subentry].data.Number, entry.Number);
4858     }
4859
4860     Line = OLine;
4861
4862     if (argc) {
4863       GSM_PhonebookEntry tmp_entry;
4864
4865       memcpy(&tmp_entry, &entry, sizeof(GSM_PhonebookEntry) );
4866       error = GSM->GetMemoryLocation(&tmp_entry);
4867       if (error == GE_NONE) {
4868         if (!tmp_entry.Empty) {
4869           int confirm = -1;
4870           char ans[8];
4871           FILE *input_flow; //for reading from console, even when input redir.
4872                                 
4873           input_flow = fopen(DEV_CONSOLE, "r");
4874
4875           if (!input_flow) {
4876                 fprintf(stderr, _("Can't open \"%s\" for input !\n"),DEV_CONSOLE);
4877                 return(-1);
4878           }
4879           
4880           fprintf(stderr, _("Location busy. "));
4881           while (confirm < 0) {
4882             fprintf(stderr, _("Overwrite? (yes/no) "));
4883             GetLine(input_flow, ans, 7);
4884             if (!strcmp(ans, "yes")) confirm = 1;
4885             else if (!strcmp(ans, "no")) confirm = 0;
4886           }
4887           if (!confirm) continue;
4888         }
4889       } else {
4890         fprintf(stderr, _("Unknown error (%d)\n"), error);
4891         GSM->Terminate();
4892         return 0;
4893       }
4894     }
4895
4896     /* Do write and report success/failure. */
4897     semicolon_pipe_substitution( &entry, 1 );
4898
4899     error = GSM->WritePhonebookLocation(&entry);
4900
4901     if (error == GE_NONE)
4902       fprintf (stdout, _("Write Succeeded: memory type: %s, loc: %d, name: %s, number: %s\n"), memory_type_string, entry.Location, entry.Name, entry.Number);
4903     else
4904       fprintf (stdout, _("Write FAILED(%d): memory type: %s, loc: %d, name: %s, number: %s\n"), error, memory_type_string, entry.Location, entry.Name, entry.Number);
4905
4906   }
4907
4908   GSM->Terminate();
4909
4910   return 0;
4911 }
4912
4913 /* Getting speed dials. */
4914
4915 int getspeeddial(char *Number) {
4916
4917   GSM_SpeedDial entry;
4918   GSM_Error error;
4919   GSM_PhonebookEntry pbentry;
4920
4921   entry.Number = atoi(Number);
4922
4923   fbusinit(NULL);
4924
4925   if (GSM->GetSpeedDial(&entry)==GE_NONE) {
4926         pbentry.Location=entry.Location;
4927         if (pbentry.Location==0) pbentry.Location=entry.Number;
4928         pbentry.MemoryType=entry.MemoryType;
4929
4930         error=GSM->GetMemoryLocation(&pbentry);
4931
4932         if (error == GE_NONE)
4933         {
4934           fprintf(stdout, _("SpeedDial nr. %d: %d:%d (%s)\n"), entry.Number, entry.MemoryType, entry.Location,pbentry.Name);
4935         } else
4936           fprintf(stdout, _("Error\n"));
4937   } else {
4938     fprintf(stdout, _("Error\n"));
4939   }
4940   
4941   GSM->Terminate();
4942
4943   return 0;
4944 }
4945
4946 /* Setting speed dials. */
4947
4948 int setspeeddial(char *argv[]) {
4949
4950   GSM_SpeedDial entry;
4951
4952   char *memory_type_string;
4953
4954   /* Handle command line args that set type, start and end locations. */
4955
4956   if (strcmp(argv[1], "ME") == 0) {
4957     entry.MemoryType = GMT_ME;
4958     memory_type_string = "ME";
4959   }
4960   else if (strcmp(argv[1], "SM") == 0) {
4961     entry.MemoryType = GMT_SM;
4962     memory_type_string = "SM";
4963   }
4964   else {
4965     fprintf(stderr, _("Unknown memory type %s!\n"), argv[1]);
4966
4967     return -1;
4968   }
4969   
4970   entry.Number = atoi(argv[0]);
4971   entry.Location = atoi(argv[2]);
4972
4973   fbusinit(NULL);
4974
4975   if (GSM->SetSpeedDial(&entry) == GE_NONE) {
4976     fprintf(stdout, _("Succesfully written!\n"));
4977   }
4978
4979   GSM->Terminate();
4980
4981   return 0;
4982 }
4983
4984 /* Getting the status of the display. */
4985
4986 int getdisplaystatus()
4987
4988
4989   int Status;
4990
4991   /* Initialise the code for the GSM interface. */     
4992
4993   fbusinit(NULL);
4994
4995   if (GSM->GetDisplayStatus(&Status)==GE_NONE) {
4996
4997     printf(_("Call in progress: %s\n"), Status & (1<<DS_Call_In_Progress)?_("on"):_("off"));
4998     printf(_("Unknown: %s\n"),          Status & (1<<DS_Unknown)?_("on"):_("off"));
4999     printf(_("Unread SMS: %s\n"),       Status & (1<<DS_Unread_SMS)?_("on"):_("off"));
5000     printf(_("Voice call: %s\n"),       Status & (1<<DS_Voice_Call)?_("on"):_("off"));
5001     printf(_("Fax call active: %s\n"),  Status & (1<<DS_Fax_Call)?_("on"):_("off"));
5002     printf(_("Data call active: %s\n"), Status & (1<<DS_Data_Call)?_("on"):_("off"));
5003     printf(_("Keyboard lock: %s\n"),    Status & (1<<DS_Keyboard_Lock)?_("on"):_("off"));
5004     printf(_("SMS storage full: %s\n"), Status & (1<<DS_SMS_Storage_Full)?_("on"):_("off"));
5005
5006   } else {
5007     printf(_("Error\n"));
5008   }
5009   
5010   GSM->Terminate();
5011
5012   return 0;
5013 }
5014
5015 int netmonitor(char *Mode)
5016 {
5017
5018   unsigned char mode=atoi(Mode);
5019   char Screen[NM_MAX_SCREEN_WIDTH];
5020   int i;
5021
5022   fbusinit(NULL);
5023
5024   if (!strcmp(Mode,"reset"))     mode=0xf0;
5025   else if (!strcmp(Mode,"off"))  mode=0xf1;
5026   else if (!strcmp(Mode,"field"))mode=0xf2;
5027   else if (!strcmp(Mode,"devel"))mode=0xf3;
5028   else if (!strcmp(Mode,"next")) mode=0x00;
5029
5030   /* We clear it */
5031   for (i=0;i<NM_MAX_SCREEN_WIDTH;i++) Screen[i]=0;
5032
5033   GSM->NetMonitor(mode, Screen);
5034
5035   if (Screen)
5036     printf("%s\n", Screen);
5037
5038   GSM->Terminate();
5039
5040   return 0;
5041 }
5042
5043 int identify( void )
5044 {
5045   /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */
5046   char imei[64], model[64], rev[64], manufacturer[64];
5047
5048   fbusinit(NULL);
5049
5050   while (GSM->GetIMEI(imei)    != GE_NONE) sleep(1);
5051   while (GSM->GetRevision(rev) != GE_NONE) sleep(1);
5052   while (GSM->GetModel(model)  != GE_NONE) sleep(1);
5053
5054   strcpy(manufacturer, "(unknown)");
5055   GSM->GetManufacturer(manufacturer);
5056
5057   fprintf(stdout, _("IMEI:     %s\n"), imei);
5058   fprintf(stdout, _("Model:    %s %s (%s)\n"), manufacturer, GetModelName (model), model);
5059   fprintf(stdout, _("Revision: %s\n"), rev);
5060
5061   GSM->Terminate();
5062
5063   return 0;
5064 }
5065
5066 int senddtmf(char *String)
5067 {
5068
5069   fbusinit(NULL);
5070
5071   if (GSM->SendDTMF(String)!=GE_NONE) fprintf(stdout,_("Error!\n"));
5072
5073   GSM->Terminate();
5074
5075   return 0;
5076 }
5077
5078 /* Resets the phone */
5079 int reset(int argc, char *argv[])
5080 {
5081
5082   unsigned char _type=0x03;
5083
5084   if (argc>0) {
5085     _type=0x10;
5086
5087     if (!strcmp(argv[0],"soft")) _type = 0x03;
5088     
5089     /* Doesn't work with 5110 */
5090     if (!strcmp(argv[0],"hard")) _type = 0x04;
5091
5092     if (_type==0x10) {
5093       fprintf(stderr, _("What kind of reset do you want (second parameter can be \"soft\" or \"hard\") ?\n"));
5094       return -1;
5095     }
5096   }
5097
5098   fbusinit(NULL);
5099
5100   GSM->Reset(_type);
5101
5102   GSM->Terminate();
5103
5104   return 0;
5105 }
5106
5107 /* This is a "convenience" function to allow quick test of new API stuff which
5108    doesn't warrant a "proper" command line function. */
5109
5110 int foogle(char *argv[])
5111 {
5112   /* Initialise the code for the GSM interface. */     
5113
5114   fbusinit(NULL);
5115
5116   // Fill in what you would like to test here...
5117
5118   sleep(5);
5119   
5120   GSM->Terminate();
5121
5122   return 0;
5123 }
5124
5125 int phonetests()
5126 {
5127   /* Initialise the code for the GSM interface. */     
5128
5129   fbusinit(NULL);
5130
5131   if (GSM->PhoneTests()!=GE_NONE) fprintf(stderr,_("Error\n"));
5132   
5133   GSM->Terminate();
5134
5135   return 0;
5136 }
5137
5138 /* pmon allows fbus code to run in a passive state - it doesn't worry about
5139    whether comms are established with the phone.  A debugging/development
5140    tool. */
5141
5142 int pmon()
5143
5144
5145   GSM_Error error;
5146   GSM_ConnectionType connection=GCT_FBUS;
5147
5148   /* Initialise the code for the GSM interface. */     
5149
5150   error = GSM_Initialise(model, Port, Initlength, connection, RLP_DisplayF96Frame, SynchronizeTime);
5151
5152   if (error != GE_NONE) {
5153     fprintf(stderr, _("GSM/FBUS init failed! (Unknown model ?). Quitting.\n"));
5154     return -1;
5155   }
5156
5157
5158   while (1) {
5159     usleep(50000);
5160   }
5161
5162   return 0;
5163 }
5164
5165 int setringtone(int argc, char *argv[])
5166 {
5167   GSM_Ringtone ringtone;
5168   GSM_BinRingtone binringtone,binringtone2;
5169
5170   GSM_Error error;
5171
5172   int current=0; //number of packed notes or location
5173   int i;
5174
5175   char model[64];
5176
5177   /* If not binary ringtone */
5178   if (GSM_ReadBinRingtoneFile(argv[0],&binringtone2)!=GE_NONE) {
5179     fprintf(stdout,_("Not binary ringtone, trying RTTL\n"));
5180
5181     if (GSM_ReadRingtoneFileOnConsole(argv[0], &ringtone)!=GE_NONE) return(-1);
5182
5183     ringtone.location=1;
5184     if (argc>1) ringtone.location=atoi(argv[1]);
5185
5186     ringtone.allnotesscale=false;
5187   
5188     /* Initialise the GSM interface. */
5189     fbusinit(NULL);
5190
5191     while (GSM->GetModel(model)  != GE_NONE)
5192       sleep(1);
5193
5194     /* For Nokia 6110/6130/6150/6210 we use different method of uploading.
5195        Phone will display menu, when received it */
5196     if ( !strcmp(model,"NSE-3") || !strcmp(model,"NSK-3") ||
5197          !strcmp(model,"NSM-1") || !strcmp(model,"NPE-3") ) {
5198       if (argc==1) ringtone.location=255;
5199     }
5200
5201     error=GSM->SetRingtone(&ringtone,&current);
5202   
5203     if (current!=ringtone.NrNotes) {
5204       if (current>FB61_MAX_RINGTONE_NOTES) {
5205         fprintf(stderr,_("Warning: due to phone limitation"));
5206       } else {
5207         fprintf(stderr,_("Warning: ringtone was too long to be saved into frame,"));
5208       }
5209       fprintf(stderr, _(" only %i first notes were packed (%i cut)\n"),current,ringtone.NrNotes-current);
5210     }
5211
5212     if (error==GE_NONE) 
5213       fprintf(stdout, _("Set succeeded!\n"));
5214     else
5215       fprintf(stdout, _("Setting failed\n"));
5216
5217   } else { /* This IS binary ringtone */
5218     fprintf(stdout,_("Binary ringtone format\n"));
5219
5220     if (argc==3) {
5221       binringtone.frame[current++]=0x00;
5222       binringtone.frame[current++]=0x00;
5223       binringtone.frame[current++]=0x0c;
5224       binringtone.frame[current++]=0x01;
5225       binringtone.frame[current++]=0x2c;
5226     
5227       //copy new name
5228       memcpy(binringtone.frame+current,argv[2],strlen(argv[2]));
5229       current=current+strlen(argv[2]);
5230
5231       /*don't use old*/
5232       i=2;
5233       while(binringtone2.frame[i]!=0x00) {
5234         if (i==binringtone.length) break;
5235         i++;
5236       }
5237     
5238       //copy binringtone
5239       memcpy(binringtone.frame+current,binringtone2.frame+i,binringtone2.length-i);
5240       binringtone.length=binringtone2.length-i+current;    
5241     } else
5242     {
5243       memcpy(binringtone.frame+current,binringtone2.frame,binringtone2.length);
5244       binringtone.length=binringtone2.length;
5245     }
5246   
5247     binringtone.location=1;
5248     if (argc>1) binringtone.location=atoi(argv[1]);
5249   
5250     /* Initialise the GSM interface. */
5251     fbusinit(NULL);
5252
5253     error=GSM->SetBinRingtone(&binringtone);
5254
5255     switch (error) {
5256       case GE_NONE:
5257         fprintf(stdout, _("Set succeeded!\n"));
5258         break;
5259       case GE_INVALIDRINGLOCATION:
5260         fprintf(stdout, _("Invalid location %i!\n"),binringtone.location);
5261         break;
5262       case GE_UNKNOWNMODEL:
5263         fprintf(stdout, _("Mygnokii doesn't know format for this model!\n"));
5264         break;
5265       case GE_NOTIMPLEMENTED:
5266         fprintf(stdout, _("Not implemented for this model!\n"));
5267         break;
5268       default:
5269         fprintf(stdout, _("Not supported by this model!\n"));
5270         break;
5271     }
5272   }
5273
5274   GSM->Terminate();
5275
5276   return 0;
5277 }
5278
5279 int ringtoneconvert(int argc, char *argv[])
5280 {
5281   GSM_Ringtone ringtone;
5282
5283   if (!strcmp(argv[0],argv[1]))
5284   {
5285     fprintf(stderr, _("Files can't have the same names !\n"));
5286     return -1;  
5287   }
5288   
5289   if (GSM_ReadRingtoneFileOnConsole(argv[0], &ringtone)!=GE_NONE) return(-1);
5290
5291   ringtone.allnotesscale=false;
5292
5293   GSM_SaveRingtoneFileOnConsole(argv[1], &ringtone);
5294   
5295   return 0;
5296 }
5297
5298 int playringtone(int argc, char *argv[])
5299 {
5300   GSM_Ringtone ringtone;
5301
5302   GSM_BinRingtone binringtone;
5303   
5304   int i,j,z;
5305   int Hz;
5306   bool isok;
5307
5308 //{ "c", "c#", "d", "d#", "e",  "f", "f#", "g", "g#", "a", "a#", "h" };
5309   int binary_notes[12] =
5310   { 0,    1,    2,   3,    4,   6,   7,    8,   9,    10,  11 ,   12};
5311
5312   if (GSM_ReadBinRingtoneFile(argv[0],&binringtone)!=GE_NONE) {
5313     fprintf(stdout,_("Not binary ringtone, trying RTTL\n"));
5314
5315     if (GSM_ReadRingtoneFileOnConsole(argv[0], &ringtone)!=GE_NONE) return(-1);
5316
5317     /* Initialise the GSM interface. */
5318     fbusinit(NULL);
5319
5320     fprintf(stdout,_("Playing \"%s\" (%i notes)\n"),ringtone.name,ringtone.NrNotes);
5321   
5322     GSM_PlayRingtoneOnConsole(&ringtone);
5323
5324   } else {
5325
5326     fprintf(stdout,_("Binary ringtone format\n"));  
5327
5328     /* Initialise the GSM interface. */
5329     fbusinit(NULL);
5330
5331     i=5;
5332     while (true) { //skipping name
5333       if (binringtone.frame[i]==0) break;
5334       i++;
5335     }
5336
5337     i=i+5;j=0;z=0;
5338     while (true) {
5339       if (binringtone.frame[i]!=j) {
5340         if (j!=0) {
5341 //#ifdef DEBUG
5342           fprintf(stdout,_("Block in binary ringtone %i %i\n"),j,z);
5343 //#endif
5344           isok=false;
5345           if (j==64) {
5346             j=255;//Pause
5347             isok=true;
5348           }
5349           if (!isok && j>=114 && j<=125) {
5350             j=14*3+binary_notes[j-114];
5351             isok=true;
5352           }
5353           if (!isok && j>=126 && j<=137) {
5354             j=14*1+binary_notes[j-126];
5355             isok=true;
5356           }
5357           if (!isok && j>=138 && j<=149) {
5358             j=14*2+binary_notes[j-138];
5359             isok=true;
5360           }
5361           if (!isok && j>=150 && j<=161) {
5362             j=14*4+binary_notes[j-150];
5363             isok=true;
5364           }
5365           if (!isok) {
5366 //#ifdef DEBUG
5367             fprintf(stdout,_("Unknown block in binary ringtone %i %i\n"),j,z);
5368 //#endif
5369           } else {
5370             Hz=GSM_GetFrequency(j);
5371             if (GSM->PlayTone(Hz,5)!=GE_NONE) fprintf(stdout,_("error during playing\n"));
5372             usleep(z*5000);
5373           }
5374         }
5375         j=binringtone.frame[i];
5376         z=binringtone.frame[i+1];
5377       } else {
5378         z=z+binringtone.frame[i+1];
5379       }
5380       i=i+2;
5381       if (i>=binringtone.length) break;
5382     }
5383   
5384     GSM->PlayTone(0,0);
5385   }
5386
5387   GSM->Terminate();    
5388
5389   return 0;
5390 }
5391
5392 int composer(int argc, char *argv[])
5393 {
5394   GSM_Ringtone ringtone;
5395   int i;
5396   bool unknown;
5397   int oldnoteslen=4,nownoteslen,oldnoteslen2;
5398   int oldnotesscale=1,nownotesscale;  
5399   bool firstnote=true;
5400   int DefNoteTempo=63;
5401   
5402   if (GSM_ReadRingtoneFileOnConsole(argv[0], &ringtone)!=GE_NONE) return(-1);
5403  
5404   if (ringtone.NrNotes!=0)
5405     DefNoteTempo=ringtone.notes[0].tempo;
5406
5407   fprintf(stdout,_("Ringtone \"%s\" (tempo = %i Beats Per Minute)\n\n"),ringtone.name,GSM_GetTempo(DefNoteTempo));
5408   
5409   for (i=0;i<ringtone.NrNotes;i++) {    
5410     if (DefNoteTempo!=ringtone.notes[i].tempo) {
5411       fprintf(stdout,_("WARNING: IN FACT RINGTONE HAS DIFFERENT TEMPO FOR DIFFERENT NOTES AND THAT'S WHY YOU CAN'T ENTER IT ALL IN THE COMPOSITOR\n\n"));
5412       break;
5413     }
5414   }
5415     
5416   for (i=0;i<ringtone.NrNotes;i++) {
5417
5418     if (firstnote) {
5419       if (GSM_GetNote(ringtone.notes[i].note)!=Note_Pause)
5420         firstnote=false;
5421     }
5422     
5423     if (!firstnote) {
5424       break;
5425     }
5426     
5427   }
5428
5429   if ((ringtone.NrNotes-i)>50)
5430     fprintf(stdout,_("WARNING: LENGTH=%i, BUT YOU WILL ENTER ONLY FIRST 50 TONES. TO ENTER FULL RINGTONE MUST SEND IT (--sendringtone) OR DOWNLOAD (--setringtone)\n\n"),ringtone.NrNotes-i);
5431
5432   fprintf(stdout,_("This ringtone in Nokia Composer in phone should look: "));  
5433
5434   firstnote=true;
5435     
5436   for (i=0;i<ringtone.NrNotes;i++) {
5437
5438     if (firstnote) {
5439       if (GSM_GetNote(ringtone.notes[i].note)!=Note_Pause)
5440         firstnote=false;
5441     }
5442     
5443     if (!firstnote) {
5444     
5445       switch (ringtone.notes[i].duration) {
5446         case 192:fprintf(stdout,_("1."));break; //192=128*1.5
5447         case 128:fprintf(stdout,_("1"));break;
5448         case 96 :fprintf(stdout,_("2."));break; //96=64*1.5
5449         case 64 :fprintf(stdout,_("2"));break;
5450         case 48 :fprintf(stdout,_("4."));break; //48=32*1.5
5451         case 32 :fprintf(stdout,_("4"));break;
5452         case 24 :fprintf(stdout,_("8."));break; //24=16*1.5
5453         case 16 :fprintf(stdout,_("8"));break;
5454         case 12 :fprintf(stdout,_("16."));break; //12=8*1.5
5455         case 8  :fprintf(stdout,_("16"));break;
5456         case 6  :fprintf(stdout,_("32."));break; //6=4*1.5
5457         case 4  :fprintf(stdout,_("32"));break;
5458       }
5459     
5460     unknown=false;
5461     
5462     /* What note here ? */
5463     switch (GSM_GetNote(ringtone.notes[i].note)) {
5464       case Note_C  :fprintf(stdout,_("c"));break;
5465       case Note_Cis:fprintf(stdout,_("#c"));break;
5466       case Note_D  :fprintf(stdout,_("d"));break;
5467       case Note_Dis:fprintf(stdout,_("#d"));break;
5468       case Note_E  :fprintf(stdout,_("e"));break;
5469       case Note_F  :fprintf(stdout,_("f"));break;
5470       case Note_Fis:fprintf(stdout,_("#f"));break;
5471       case Note_G  :fprintf(stdout,_("g"));break;
5472       case Note_Gis:fprintf(stdout,_("#g"));break;
5473       case Note_A  :fprintf(stdout,_("a"));break;
5474       case Note_Ais:fprintf(stdout,_("#a"));break;
5475       case Note_H  :fprintf(stdout,_("h"));break;
5476       default      :fprintf(stdout,_("-"));unknown=true;break; //Pause ?
5477     }
5478
5479     if (!unknown)
5480       fprintf(stdout,_("%i"),ringtone.notes[i].note/14);
5481     
5482     /* And separator before next note */
5483     if (i!=ringtone.NrNotes-1)
5484       fprintf(stdout,_(" "));
5485       
5486     }
5487
5488   }
5489
5490   fprintf(stdout,_("\n\nTo enter it please press: "));  
5491   
5492   firstnote=true;
5493   
5494   for (i=0;i<ringtone.NrNotes;i++) {
5495
5496     if (firstnote) {
5497       if (GSM_GetNote(ringtone.notes[i].note)!=Note_Pause)
5498         firstnote=false;
5499     }
5500     
5501     if (!firstnote) {
5502
5503     unknown=false;
5504     
5505     /* What note here ? */
5506     switch (GSM_GetNote(ringtone.notes[i].note)) {
5507       case Note_C  :fprintf(stdout,_("1"));break;
5508       case Note_Cis:fprintf(stdout,_("1"));break;
5509       case Note_D  :fprintf(stdout,_("2"));break;
5510       case Note_Dis:fprintf(stdout,_("2"));break;
5511       case Note_E  :fprintf(stdout,_("3"));break;
5512       case Note_F  :fprintf(stdout,_("4"));break;
5513       case Note_Fis:fprintf(stdout,_("4"));break;
5514       case Note_G  :fprintf(stdout,_("5"));break;
5515       case Note_Gis:fprintf(stdout,_("5"));break;
5516       case Note_A  :fprintf(stdout,_("6"));break;
5517       case Note_Ais:fprintf(stdout,_("6"));break;
5518       case Note_H  :fprintf(stdout,_("7"));break;
5519       default      :fprintf(stdout,_("0"));unknown=true;break;
5520     }
5521
5522       switch (ringtone.notes[i].duration) {
5523         case 192:fprintf(stdout,_("(longer)"));break; //192=128*1.5
5524         case 96 :fprintf(stdout,_("(longer)"));break; //96=64*1.5
5525         case 48 :fprintf(stdout,_("(longer)"));break; //48=32*1.5
5526         case 24 :fprintf(stdout,_("(longer)"));break; //24=16*1.5
5527         case 12 :fprintf(stdout,_("(longer)"));break; //12=8*1.5
5528         case 6  :fprintf(stdout,_("(longer)"));break; //6=4*1.5
5529         default:break;
5530       }
5531
5532     /* What note here ? */
5533     switch (GSM_GetNote(ringtone.notes[i].note)) {
5534       case Note_Cis:fprintf(stdout,_("#"));break;
5535       case Note_Dis:fprintf(stdout,_("#"));break;
5536       case Note_Fis:fprintf(stdout,_("#"));break;
5537       case Note_Gis:fprintf(stdout,_("#"));break;
5538       case Note_Ais:fprintf(stdout,_("#"));break;
5539       default      :break;
5540     }
5541
5542     if (!unknown)
5543     {
5544       nownotesscale=ringtone.notes[i].note/14;
5545
5546       if (nownotesscale!=oldnotesscale) {
5547         switch (nownotesscale) {
5548           case 1:
5549             switch (oldnotesscale) {
5550               case 2:fprintf(stdout,_("**"));break;
5551               case 3:fprintf(stdout,_("*"));break;
5552             }
5553             break;
5554           case 2:
5555             switch (oldnotesscale) {
5556               case 1:fprintf(stdout,_("*"));break;
5557               case 3:fprintf(stdout,_("**"));break;
5558             }
5559             break;
5560           case 3:
5561             switch (oldnotesscale) {
5562               case 1:fprintf(stdout,_("**"));break;
5563               case 2:fprintf(stdout,_("*"));break;
5564             }
5565             break;
5566         }
5567       }
5568       
5569       oldnotesscale=nownotesscale;
5570     }
5571
5572      nownoteslen=0;
5573      oldnoteslen2=oldnoteslen;
5574      
5575       switch (ringtone.notes[i].duration) {
5576         case 192:nownoteslen=1;break; //192=128*1.5
5577         case 128:nownoteslen=1;break;
5578         case 96 :nownoteslen=2;break; //96=64*1.5
5579         case 64 :nownoteslen=2;break;
5580         case 48 :nownoteslen=4;break; //48=32*1.5
5581         case 32 :nownoteslen=4;break;
5582         case 24 :nownoteslen=8;break; //24=16*1.5
5583         case 16 :nownoteslen=8;break;
5584         case 12 :nownoteslen=16;break; //12=8*1.5
5585         case 8  :nownoteslen=16;break;
5586         case 6  :nownoteslen=32;break; //6=4*1.5
5587         case 4  :nownoteslen=32;break;
5588       }    
5589       
5590       if (nownoteslen>oldnoteslen) {
5591         while (oldnoteslen!=nownoteslen) {
5592           fprintf(stdout,_("8"));
5593           oldnoteslen=oldnoteslen*2;
5594         }
5595       }
5596
5597       if (nownoteslen<oldnoteslen) {
5598         while (oldnoteslen!=nownoteslen) {
5599           fprintf(stdout,_("9"));
5600           oldnoteslen=oldnoteslen/2;
5601         }
5602       }      
5603
5604     if (GSM_GetNote(ringtone.notes[i].note)==Note_Pause)
5605       oldnoteslen=oldnoteslen2;
5606       
5607     /* And separator before next note */
5608     if (i!=ringtone.NrNotes-1)
5609       fprintf(stdout,_("  "));
5610
5611   }
5612   }  
5613
5614   fprintf(stdout,_("\n"));
5615
5616   return 0;
5617
5618 }
5619
5620 int sendringtone(int argc, char *argv[])
5621 {
5622   GSM_Ringtone ringtone;
5623   GSM_MultiSMSMessage SMS;
5624   int current,i;
5625   bool ProfileStyle=false; /* If we use profile style available in new Nokia models */
5626
5627   if (GSM_ReadRingtoneFileOnConsole(argv[1], &ringtone)!=GE_NONE) return(-1);
5628
5629   ringtone.allnotesscale=false;
5630
5631   for (i=0;i<argc;i++) {
5632     if (!strcmp(argv[i],"--profilestyle")) ProfileStyle=true;
5633     if (!strcmp(argv[i],"--scale")) ringtone.allnotesscale=true;
5634   }
5635
5636   current=GSM_SaveRingtoneToSMS(&SMS,&ringtone,ProfileStyle);
5637
5638   if (current!=ringtone.NrNotes) {
5639     if (current>FB61_MAX_RINGTONE_NOTES) {
5640       fprintf(stderr,_("Warning: due to phone limitation"));
5641     } else {
5642       fprintf(stderr,_("Warning: ringtone was too long to be saved into SMS,"));
5643     }
5644     fprintf(stderr, _(" only %i first notes were packed (%i cut)\n"),current,ringtone.NrNotes-current);
5645   }
5646
5647   for (i=0;i<SMS.number;i++) {
5648     strcpy(SMS.SMS[i].Destination,argv[0]);
5649   }
5650
5651   /* Initialise the GSM interface. */
5652   fbusinit(NULL);
5653
5654   GSM_SendMultiPartSMSOnConsole(&SMS, 2,argc,argv,false,true,true);
5655
5656   return 0;
5657 }
5658
5659 int saveringtone(int argc, char *argv[])
5660 {
5661   GSM_Ringtone ringtone;
5662   GSM_MultiSMSMessage SMS;
5663   int current,i;
5664   bool ProfileStyle=false; /* If we use profile style available in new Nokia models */
5665
5666   if (GSM_ReadRingtoneFileOnConsole(argv[0], &ringtone)!=GE_NONE) return(-1);
5667
5668   ringtone.allnotesscale=false;
5669
5670   for (i=0;i<argc;i++) {
5671     if (!strcmp(argv[i],"--profilestyle")) ProfileStyle=true;
5672     if (!strcmp(argv[i],"--scale")) ringtone.allnotesscale=true;
5673   }
5674
5675   current=GSM_SaveRingtoneToSMS(&SMS,&ringtone,ProfileStyle);
5676
5677   if (current!=ringtone.NrNotes) {
5678     if (current>FB61_MAX_RINGTONE_NOTES) {
5679       fprintf(stderr,_("Warning: due to phone limitation"));
5680     } else {
5681       fprintf(stderr,_("Warning: ringtone was too long to be saved into SMS,"));
5682     }
5683     fprintf(stderr, _(" only %i first notes were packed (%i cut)\n"),current,ringtone.NrNotes-current);
5684   }
5685
5686   for (i=0;i<SMS.number;i++) {
5687     /* Only 11 chars could be here */
5688     strncpy(SMS.SMS[i].Destination,ringtone.name,11);
5689   }
5690
5691   /* Initialise the GSM interface. */
5692   fbusinit(NULL);
5693
5694   GSM_SaveMultiPartSMSOnConsole(&SMS,1,argc,argv,false,false,true,true);
5695
5696   return 0;
5697 }
5698
5699 /* Converts logo files. */
5700
5701 int bitmapconvert(int argc, char *argv[])
5702 {
5703   GSM_Bitmap bitmap;
5704   GSM_NetworkInfo NetworkInfo;
5705   bool doit;
5706   int num;
5707   
5708   if (!strcmp(argv[0],argv[1]))
5709   {
5710     fprintf(stderr, _("Files can't have the same names !\n"));
5711     return -1;  
5712   }
5713   
5714   if (GSM_ReadBitmapFileOnConsole(argv[0], &bitmap)!=GE_NONE) return(-1);
5715
5716   if (argc>2)
5717   {
5718     doit=false;
5719     if (!strcmp(argv[2],"op"))
5720     {
5721       doit=false;
5722       if (argc<4) doit=true;
5723       if (argc<4 && bitmap.type!=GSM_OperatorLogo) doit=true;
5724       if (doit)
5725       {
5726         fbusinit(NULL);
5727         if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE) strncpy(bitmap.netcode,NetworkInfo.NetworkCode,7);
5728         GSM->Terminate();
5729       }
5730       GSM_ResizeBitmap(&bitmap,GSM_OperatorLogo);
5731       if (argc==4)
5732       {
5733         strncpy(bitmap.netcode,argv[3],7);
5734         if (!strcmp(GSM_GetNetworkName(bitmap.netcode),"unknown"))
5735         {
5736           fprintf(stderr,"Sorry, gnokii doesn't know \"%s\" network !\n",bitmap.netcode);
5737           return -1;
5738         }
5739       }
5740       doit=true;
5741     }
5742     if (!strcmp(argv[2],"7110op"))
5743     {
5744       doit=false;
5745       if (argc<4) doit=true;
5746       if (argc<4 && bitmap.type!=GSM_7110OperatorLogo) doit=true;
5747       if (doit)
5748       {
5749         fbusinit(NULL);
5750         if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE) strncpy(bitmap.netcode,NetworkInfo.NetworkCode,7);
5751         GSM->Terminate();
5752       }
5753       GSM_ResizeBitmap(&bitmap,GSM_7110OperatorLogo);
5754       if (argc==4)
5755       {
5756         strncpy(bitmap.netcode,argv[3],7);
5757         if (!strcmp(GSM_GetNetworkName(bitmap.netcode),"unknown"))
5758         {
5759           fprintf(stderr,"Sorry, gnokii doesn't know \"%s\" network !\n",bitmap.netcode);
5760           return -1;
5761         }
5762       }
5763       doit=true;
5764     }
5765     if (!strcmp(argv[2],"caller"))
5766     {
5767       GSM_ResizeBitmap(&bitmap,GSM_CallerLogo);
5768       if (argc>3)
5769       {
5770         num=argv[3][0]-'0';
5771         if ((num<0)||(num>9)) num=0;
5772         bitmap.number=num;
5773       } else
5774       {
5775         bitmap.number=0;
5776       }
5777       doit=true;
5778     }
5779     if (!strcmp(argv[2],"startup"))
5780     {
5781       GSM_ResizeBitmap(&bitmap,GSM_StartupLogo);
5782       doit=true;
5783     }
5784     if (!strcmp(argv[2],"7110startup"))
5785     {
5786       GSM_ResizeBitmap(&bitmap,GSM_7110StartupLogo);
5787       doit=true;
5788     }
5789     if (!strcmp(argv[2],"6210startup"))
5790     {
5791       GSM_ResizeBitmap(&bitmap,GSM_6210StartupLogo);
5792       doit=true;
5793     }
5794     if (!strcmp(argv[2],"picture"))
5795     {
5796       GSM_ResizeBitmap(&bitmap,GSM_PictureImage);
5797       doit=true;
5798     }
5799     if (!doit)
5800     {
5801       fprintf(stderr,"Unknown type of logo: %s !\n",argv[2]);
5802       return -1;
5803     }
5804   }
5805     
5806   if (GSM_SaveBitmapFileOnConsole(argv[1], &bitmap)!=GE_NONE) return(-1);
5807   
5808   return 0;
5809 }
5810
5811 int getphoneprofile()
5812 {
5813   GSM_PPS PPS;
5814   GSM_Error error;
5815
5816   /* Initialise the GSM interface. */
5817   fbusinit(NULL);
5818
5819   PPS.Name=PPS_ALS;
5820   error=GSM->GetProductProfileSetting(&PPS);
5821   if (error!=GE_NONE) {
5822     fprintf(stdout,_("Error!\n"));
5823     GSM->Terminate();    
5824     return -1;
5825   }
5826   fprintf(stdout,_("ALS           : "));
5827   if (PPS.bool_value) fprintf(stdout,_("on\n"));
5828                  else fprintf(stdout,_("off\n"));
5829
5830   PPS.Name=PPS_VibraMenu;
5831   GSM->GetProductProfileSetting(&PPS);
5832   fprintf(stdout,_("Vibra menu    : "));
5833   if (PPS.bool_value) fprintf(stdout,_("on\n"));
5834                  else fprintf(stdout,_("off\n"));
5835
5836   PPS.Name=PPS_GamesMenu;
5837   GSM->GetProductProfileSetting(&PPS);
5838   fprintf(stdout,_("Games menu    : "));
5839   if (PPS.bool_value) fprintf(stdout,_("on\n"));
5840                  else fprintf(stdout,_("off\n"));
5841
5842   PPS.Name=PPS_HRData;
5843   GSM->GetProductProfileSetting(&PPS);
5844   fprintf(stdout,_("HR Data       : "));
5845   if (PPS.bool_value) fprintf(stdout,_("on\n"));
5846                  else fprintf(stdout,_("off\n"));
5847
5848   PPS.Name=PPS_14400Data;
5849   GSM->GetProductProfileSetting(&PPS);
5850   fprintf(stdout,_("14400 Data    : "));
5851   if (PPS.bool_value) fprintf(stdout,_("on\n"));
5852                  else fprintf(stdout,_("off\n"));
5853
5854   PPS.Name=PPS_LCDContrast;
5855   GSM->GetProductProfileSetting(&PPS);
5856   fprintf(stdout,_("LCD Contrast  : %i%%\n"),PPS.int_value);
5857
5858   PPS.Name=PPS_EFR;
5859   GSM->GetProductProfileSetting(&PPS);
5860   fprintf(stdout,_("EFR           : "));
5861   switch (PPS.int_value) {
5862     case 0: fprintf(stdout,_("off\n"));   break;
5863     case 1: fprintf(stdout,_("last\n"));  break;
5864     case 2: fprintf(stdout,_("second\n"));break;
5865     case 3: fprintf(stdout,_("first\n")); break;
5866   }
5867
5868   PPS.Name=PPS_FR;
5869   GSM->GetProductProfileSetting(&PPS);
5870   fprintf(stdout,_("FR            : "));
5871   switch (PPS.int_value) {
5872     case 0: fprintf(stdout,_("off\n"));   break;
5873     case 1: fprintf(stdout,_("last\n"));  break;
5874     case 2: fprintf(stdout,_("second\n"));break;
5875     case 3: fprintf(stdout,_("first\n")); break;
5876   }
5877
5878   PPS.Name=PPS_HR;
5879   GSM->GetProductProfileSetting(&PPS);
5880   fprintf(stdout,_("HR            : "));
5881   switch (PPS.int_value) {
5882     case 0: fprintf(stdout,_("off\n"));   break;
5883     case 1: fprintf(stdout,_("last\n"));  break;
5884     case 2: fprintf(stdout,_("second\n"));break;
5885     case 3: fprintf(stdout,_("first\n")); break;
5886   }
5887     
5888   GSM->Terminate();    
5889
5890   return 0;
5891
5892 }
5893
5894 int setphoneprofile(int argc, char *argv[])
5895 {
5896   GSM_PPS PPS;
5897   GSM_Error error;
5898   bool correct_arg1=false, correct_arg2=false;
5899
5900   if (!strcmp(argv[0],"ALS")) {
5901     PPS.Name=PPS_ALS;
5902     correct_arg1=true;
5903     if (!strcmp(argv[1],"1")) {
5904       PPS.bool_value=true;
5905       correct_arg2=true;
5906     }
5907     if (!strcmp(argv[1],"0")) {
5908       PPS.bool_value=false;
5909       correct_arg2=true;
5910     }
5911     if (!correct_arg2) {
5912       fprintf(stdout,_("Settings for ALS parameter can be \"0\" or \"1\" !\n"));
5913       return -1;
5914     }
5915   }
5916   if (!strcmp(argv[0],"HRData")) {
5917     PPS.Name=PPS_HRData;
5918     correct_arg1=true;
5919     if (!strcmp(argv[1],"1")) {
5920       PPS.bool_value=true;
5921       correct_arg2=true;
5922     }
5923     if (!strcmp(argv[1],"0")) {
5924       PPS.bool_value=false;
5925       correct_arg2=true;
5926     }
5927     if (!correct_arg2) {
5928       fprintf(stdout,_("Settings for HRData parameter can be \"0\" or \"1\" !\n"));
5929       return -1;
5930     }
5931   }  
5932   if (!correct_arg1) {
5933     fprintf(stdout,_("First parameter can be \"ALS\" or \"HRData\" only !\n"));
5934     return -1;
5935   }
5936
5937   /* Initialise the GSM interface. */
5938   fbusinit(NULL);
5939
5940   error=GSM->SetProductProfileSetting(&PPS);
5941
5942   if (error!=GE_NONE) {
5943     fprintf(stdout,_("Error!\n"));
5944     GSM->Terminate();    
5945     return -1;
5946   }
5947
5948   GSM->Reset(0x03);
5949   
5950   GSM->Terminate();    
5951
5952   return 0;
5953
5954 }
5955
5956 int getoperatorname()
5957 {
5958
5959   GSM_Network network;
5960
5961   /* Initialise the GSM interface. */
5962   fbusinit(NULL);
5963
5964   if (GSM->GetOperatorName(&network)==GE_NONE)
5965   {
5966     if (!strcmp(network.Name,"")) {
5967       fprintf(stdout,_("Phone doesn't have downloaded operator name\n"));
5968     } else {
5969       fprintf(stdout,_("Phone has downloaded operator name (\"%s\") for \"%s\" (\"%s\") network\n"),
5970               network.Name,network.Code,GSM_GetNetworkName(network.Code));
5971     }
5972   }
5973   
5974   GSM->Terminate();    
5975
5976   return 0;
5977
5978 }
5979
5980 int setoperatorname(int argc, char *argv[])
5981 {
5982
5983   GSM_Network network;
5984
5985   /* Initialise the GSM interface. */
5986   fbusinit(NULL);
5987
5988   if (argc==2) {
5989     strncpy(network.Code,argv[0],7);
5990     strncpy(network.Name,argv[1],50);
5991   } else {
5992     strcpy(network.Code,"000 00\0");
5993     strcpy(network.Name,"\0");
5994   }
5995   
5996   if (GSM->SetOperatorName(&network)==GE_NONE) {
5997     if (GSM->GetOperatorName(&network)==GE_NONE) {
5998       if (!strcmp(network.Name,"")) {
5999         fprintf(stdout,_("Downloaded operator name is removed\n"));
6000       } else {
6001         fprintf(stdout,_("Downloaded operator name changed for \"%s\" network (\"%s\") to \"%s\"\n"),
6002                 network.Code,GSM_GetNetworkName(network.Code),network.Name);
6003       }
6004     }
6005   }
6006
6007   GSM->Terminate();    
6008
6009   return 0;
6010
6011 }
6012
6013 int getvoicemailbox()
6014 {
6015   GSM_PhonebookEntry entry;
6016
6017   /* Initialise the GSM interface. */
6018   fbusinit(NULL);
6019   
6020   if (GSM->GetVoiceMailbox(&entry)==GE_NONE) {
6021     fprintf(stdout,_("Voice mailbox number is "));
6022     if (!strcmp(entry.Number,""))
6023       fprintf(stdout,_("not set\n"));
6024     else
6025       fprintf(stdout,_("\"%s\"\n"),entry.Number);
6026   }
6027
6028   GSM->Terminate();    
6029
6030   return 0;
6031
6032 }
6033
6034 ///////////////////////////////////////////////////////////////////////////////
6035 // flow diagram of netmonitordata():
6036 ///////////////////////////////////////////////////////////////////////////////
6037 //
6038 //              get command line argument
6039 //                      |                       
6040 //                      v       
6041 //
6042 //              if specific phone model
6043 //                  use that model
6044 //              else
6045 //                  identify-phone:     (((((((( TO DO )))))))))))))
6046 //
6047 //                      |
6048 //                      v
6049 //              get_mon_param_info()    get phone netmonitor parameters name
6050 //                                      specifically to a 'model'
6051 //                      |
6052 //                      v
6053 //              parse_check()           check command line arguments
6054 //                      |               if all OK, go on else stop.
6055 //                      |               because we can have a input file
6056 //                      v               containing multiple
6057 //              parse_process()         command lines, we process each at once
6058 //                                      so we can exit early on errors.
6059 //
6060 ///////////////////////////////////////////////////////////////////////////////
6061
6062 // private functions, see netmonitordata()
6063 void free_nm_info(PARAM_INFO_MON *info)
6064 {
6065         PARAM_INFO_MON *tmp;    // pointer, iterator on info
6066
6067         // go to end of list
6068
6069         while (info->next != NULL)
6070         {       tmp = info->next;
6071                 free(info->name);
6072                 free(info->mname);
6073                 free(info);
6074                 info = tmp;
6075         }
6076         free(info);
6077 }
6078
6079 ///////////////////////////////////////////////////////////////////////////////
6080 // this func retrieve parameters info from a file
6081 // and load it in a dynamic array, NULL terminated,
6082 // if 2rd parameter is not NULL, it load also description of screen
6083 // return (PARAM_INFO_MON *start) if all is OK, else NULL
6084 ///////////////////////////////////////////////////////////////////////////////
6085 // start->->next->next->next-> ...->next->NULL
6086 //   |      |     |     |           |
6087 //   V      V     V     V           V
6088 //        par0  par1  par2        parN
6089 ///////////////////////////////////////////////////////////////////////////////
6090 // this should be de-allocated from calling function,
6091 // also, screen_name should be deallocated from calling function
6092 ///////////////////////////////////////////////////////////////////////////////
6093
6094 PARAM_INFO_MON *get_mon_param_info(char *f_name, char *screen_name[NM_MAX_SCREEN+1])
6095 {
6096         PARAM_INFO_MON *start;  // pointer to netmonitor parameters info
6097         PARAM_INFO_MON *info;   // pointer, iterator on info
6098         PARAM_INFO_MON *check;  // pointer, iterator on info, for check usage
6099
6100         FILE *f_info;
6101
6102         char buf[256];
6103         char *param;
6104         char *param_name;
6105         char *tmp;
6106
6107         char tmp_mname[55];             // very larger, but if netmon bug ...
6108         int x, y, len, s, t;            // x & y coord, len, screen nr, type
6109         int i;
6110
6111         if (screen_name != NULL)
6112                 for (i = 0; i <= NM_MAX_SCREEN; i++)
6113                         screen_name[i] = NULL;
6114                 
6115
6116         if ((f_info = fopen(f_name, "r")) == NULL)
6117         {       fprintf(stderr, "Can' t open file parameter info: <%s>\n", f_name);
6118                 return(NULL);
6119         }
6120         
6121         if ((start = malloc(sizeof(PARAM_INFO_MON))) == NULL)
6122         {       fprintf(stderr, "no mem\n");
6123                 return(NULL);
6124         }
6125         else
6126         {       start->next = NULL;
6127         }
6128
6129         info = start;
6130         while (fgets(buf, 256, f_info) != NULL)
6131         {
6132                 param = buf;
6133
6134                 // Truncate from '#' at right of comments
6135                 if ((tmp = strchr(param, '#')) != NULL)
6136                         *tmp = '\0';
6137
6138                 // Strip leading, trailing whitespace
6139                 while(isspace((int) *param))
6140                         param++;
6141
6142                 while((strlen(param) > 0) && isspace((int) param[strlen(param) - 1]))
6143                         param[strlen(param) - 1] = '\0';
6144         
6145                 // Ignore blank lines
6146                 if ((*param == '\n') || (*param == '\0'))
6147                         continue;
6148
6149
6150 #ifdef DEBUG
6151                 fprintf(stderr, "%s: info line: <%s>\n", f_name, param);
6152 #endif
6153                 // check for param name
6154                 if ((param_name = strtok(param, "=\t\n")) == NULL)
6155                         continue;
6156
6157                 // check if screen name
6158                 if (strncmp("SCREEN", param_name, 6) == 0)
6159                 {       
6160                         // if we do not want screen names ...
6161                         if (screen_name == NULL)
6162                                 continue;
6163
6164 // FIXME check for screen nr
6165                         if ((tmp = strtok(NULL, ":\n")) == NULL)
6166                                 continue;
6167         
6168                         i = atoi(tmp);
6169 // FIXME: check if already defined screen
6170
6171                         if ((i <= 0) || (i > NM_MAX_SCREEN))
6172                                 continue;
6173                         // check for screen name
6174                         if ((tmp = strtok(NULL, ":\n")) == NULL)
6175                                 continue;
6176
6177                         screen_name[i] = strdup(tmp);
6178                 }
6179                 else 
6180                 {
6181                         // parameter
6182
6183 // FIXME: check for NM_MAX_FIELDS
6184
6185                         // check for x coord
6186                         if ((tmp = strtok(NULL, ":\t\n")) == NULL)
6187                                 continue;
6188                         x = atoi(tmp);
6189
6190                         // check for y coord
6191                         if ((tmp = strtok(NULL, ":\t\n")) == NULL)
6192                                 continue;
6193                         y = atoi(tmp);
6194
6195                         // check for len
6196                         if ((tmp = strtok(NULL, ":\t\n")) == NULL)
6197                                 continue;
6198                         len = atoi(tmp);
6199         
6200                         // check for screen
6201                         if ((tmp = strtok(NULL, ":\t\n")) == NULL)
6202                                 continue;
6203                         s = atoi(tmp);
6204
6205                         // check for netmon manual name
6206                         if ((tmp = strtok(NULL, ":\t\n")) == NULL)
6207                         {       fprintf(stderr,
6208                                         "%s: PARAMETER <%s> in screen <%d>, not have netmon manual reference\n",
6209                                         f_name, param_name, s);
6210                                 free_nm_info(start);
6211                                 return(NULL);
6212                         }
6213                         strcpy(tmp_mname, tmp);
6214
6215                         // check for data type (optional)
6216                         if ((tmp = strtok(NULL, ":\t\n")) != NULL)      
6217                                 t = *tmp;
6218                         else
6219                                 t = '\0';
6220
6221                         // check len, here, so we print parameter name
6222                         if (len == 0)
6223                         {       fprintf(stderr,
6224                                         "%s: PARAMETER <%s> in screen <%d>, has invalid data lenght\n",
6225                                         f_name, param_name, s);
6226                                 free_nm_info(start);
6227                                 return(NULL);
6228                         }
6229
6230                         // check if already defined same param_name
6231                         check = start;
6232                         while (check->next != NULL)
6233                         {       check = check->next;
6234                                 if (strcmp(param_name, check->name) == 0)
6235                                 {
6236                                         fprintf(stderr,
6237                                         "%s: PARAMETER <%s> in screen <%d> already defined as in screen <%d>\n",
6238                                         f_name, param_name, s, check->s_nr);
6239                                         free_nm_info(start);
6240                                         return(NULL);
6241                                 }
6242                         }
6243
6244                         // make space, and add parameter
6245                         if ((info->next = malloc(sizeof(PARAM_INFO_MON))) != NULL)
6246                         {
6247                                 info = info->next;
6248                                 info->name = strdup(param_name);
6249                                 info->x = x;
6250                                 info->y = y;
6251                                 info->len = len;
6252                                 info->s_nr = s;
6253                                 info->mname = strdup(tmp_mname);
6254                                 info->type = t;
6255
6256                                 info->next = NULL;      // mark end
6257                         }
6258                         else
6259                         {
6260                                 fprintf(stderr, "no mem");
6261                                 free_nm_info(start);
6262                                 return(NULL);
6263                         }
6264
6265                 }
6266         
6267         }
6268
6269         fclose(f_info);
6270         
6271 #ifdef DEBUG
6272         info = start;
6273         while (info->next != NULL)
6274         {
6275                 info = info->next;
6276                 fprintf(stderr, "info name %s\n", info->name);
6277         }
6278 #endif
6279         return(start);
6280 }
6281
6282 // 2, parse the arguments and check command(s) line 
6283 // command line, phone spec input, and output are complex,
6284 // so we exit printing info about error instead of std help
6285 ///////////////////////////////////////////////////////////////////////////////
6286
6287 int parse_check(int argc, char *argv[], PARAM_INFO_MON *start, char *f_name, int line)
6288 {
6289         int ctr;
6290         int i;
6291         int time_spec;
6292         int found_data;
6293         char *p;
6294         char *tmp;
6295         char *o;
6296         PARAM_INFO_MON *info;                   // iterator on this list
6297
6298 #ifdef DEBUG
6299         for (i = 0; i < argc; i++)
6300                 fprintf(stderr, "argv[%d] = <%s>\n",i, argv[i]);
6301 #endif
6302
6303         time_spec = 0;
6304         ctr = 0; 
6305         i = 0;
6306         while (i < argc)
6307         {
6308                 p = argv[i];
6309                 if (*p == '-')
6310                 {                       // should be one of the short option
6311                         if (strcmp(argv[i], "-fs") == 0)
6312                         {               // field separator, next arg should be a string
6313                                 if (((i+1) < argc) && (strlen(argv[i+1]) < 10))
6314                                 {       i++;
6315                                         // arg OK, do nothing
6316                                 }
6317                                 else
6318                                 {       if (line)
6319                                                 fprintf(stderr,
6320                                                         "-fs: Invalid field separator in <%s> at line %d\n",
6321                                                         f_name, line);
6322                                         else
6323                                                 fprintf(stderr, "-fs: Invalid field separator\n");
6324                                         return(-1);
6325                                 }
6326                         }
6327                         else if (strcmp(argv[i], "-ls") == 0) 
6328                         {               // line separator, next arg should be a string
6329                                 if (((i+1) < argc) && (strlen(argv[i+1]) < 10))
6330                                 {       i++;
6331                                         // arg OK, do nothing
6332                                 }
6333                                 else
6334                                 {       if (line)
6335                                                 fprintf(stderr,
6336                                                         "-ls: Invalid line separator in <%s> at line %d\n",
6337                                                         f_name, line);
6338                                         else
6339                                                 fprintf(stderr, "-ls: Invalid line separator\n");
6340                                         return(-1);
6341                                 }
6342                         }
6343                         else if (strcmp(argv[i], "-tm") == 0) 
6344                         {               // time separator, next arg should be a millisecond (200-10000)
6345                                 if (time_spec)
6346                                 {       if (line)
6347                                                 fprintf(stderr,
6348                                                 "-tm, -ts, are mutually exclusive in <%s> at line %d\n",
6349                                                 f_name, line);
6350                                         else
6351                                                 fprintf(stderr, "-tm, -ts, are mutually exclusive\n");
6352                                         return(-1);
6353                                 }
6354
6355                                 if (((i+1) < argc) && (atoi(argv[i+1]) >= 200) && (atoi(argv[i+1]) <= 10000))
6356                                 {       i++;
6357                                         time_spec = 1;
6358                                         // arg OK, do nothing
6359                                 }
6360                                 else
6361                                 {       if (line)
6362                                                 fprintf(stderr,
6363                         "-tm: Invalid argument (200-10000 milliseconds), in <%s> at line %d\n",
6364                                                         f_name, line);
6365                                         else
6366                                                 fprintf(stderr, "-tm: Invalid argument (200-10000 milliseconds)\n");
6367                                         return(-1);
6368                                 }
6369                         }
6370                         else if (strcmp(argv[i], "-ts") == 0) 
6371                         {               // time separator, next arg should be a seconds (1-3600)
6372                                 if (time_spec)
6373                                 {       if (line)
6374                                                 fprintf(stderr,
6375                                                 "-tm, -ts, are mutually exclusive, in <%s> at line %d\n",
6376                                                         f_name, line);
6377                                         else
6378                                                 fprintf(stderr, "-tm, -ts, are mutually exclusive\n");
6379                                         return(-1);
6380                                 }
6381
6382                                 if (((i+1) < argc) && (atoi(argv[i+1]) >= 1) && (atoi(argv[i+1]) <= 3600))
6383                                 {       i++;
6384                                         time_spec = 1;
6385                                         // arg OK, do nothing
6386                                 }
6387                                 else
6388                                 {       if (line)
6389                                                 fprintf(stderr,
6390                                         "-ts: Invalid argument (1-3600 seconds) in <%s> at line %d\n",  
6391                                                         f_name, line);
6392                                         else
6393                                                 fprintf(stderr, "-ts: Invalid argument (1-3600 seconds)\n");
6394                                         return(-1);
6395                                 }
6396                         }
6397                         else if (strcmp(argv[i], "-n") == 0) 
6398                         {               // nr of data pump, before stop collection,
6399                                         // next arg should be a int > 0
6400                                 if (((i+1) < argc) && (atoi(argv[i+1]) >= 1) && (atoi(argv[i+1]) <= 99999))
6401                                 {       i++;
6402                                         // arg OK, do nothing
6403                                 }
6404                                 else
6405                                 {       if (line)
6406                                                 fprintf(stderr,
6407                                                 "-n: Invalid argument (1-99999 times) in <%s> at line %d\n",
6408                                                         f_name, line);
6409                                         else
6410                                                 fprintf(stderr, "-n: Invalid argument (1-99999 times)\n");
6411                                         return(-1);
6412                                 }
6413                         }
6414                         else if (strcmp(argv[i], "-h") == 0) 
6415                         {               // we do NOT want header (default with header)
6416                                         // arg OK, do nothing
6417                         }
6418                         else if (strcmp(argv[i], "-S") == 0) 
6419                         {               // we have used use specs from a file instead of standard info,
6420                                         // next arg is an existing readable filename
6421                                         // as already parsed correctly, we skip here.
6422                                 i++;
6423                         }
6424                         else if (strcmp(argv[i], "-I") == 0) 
6425                         {               // we have used input from a file instead of command line
6426                                         // next arg is an existing readable filename
6427                                         // as already parsed correctly, we skip here.
6428                                 i++;
6429                         }       
6430                         else
6431                         {       
6432                                 if (line)
6433                                         fprintf(stderr, "Unrecognized option %s in <%s> at line %d\n",
6434                                                 argv[i], f_name, line);
6435                                         else
6436                                                 fprintf(stderr, "Unrecognized option %s\n", argv[i]);
6437                                 return(-1);
6438                         }
6439                 }
6440                 else
6441                 {                       // should be required data
6442                         tmp = strdup(argv[i]);
6443                         p = strtok(tmp, ":\t\n");
6444                         while (p != NULL)
6445                         {
6446                                 // check if there is an output format specification
6447                                 o = p;
6448                                 while (*o)
6449                                 {
6450                                         o++;
6451                                         if (*o == '-')
6452                                         {       *o = '\0';
6453                                                 o++;
6454                                                 if (strlen(o) == 0)
6455                                                 {
6456                                                         // we have 'minus', so, probably forget format ...
6457
6458                                                         if (line)
6459                                                                 fprintf(stderr,
6460                                          "Required data <%s->, without format specifiers in <%s> at line %d\n",
6461                                                                         p, f_name, line);
6462                                                         else
6463                                                                 fprintf(stderr,
6464                                          "Required data <%s->, without format specifiers\n", p);
6465                                                         return(-1);
6466                                                 }
6467                                         }
6468                                 }
6469                         
6470                                                                 // we check for params
6471                                 found_data = 0;
6472                                 info = start;
6473                                 while (info->next != NULL)
6474                                 {       
6475                                         info = info->next;
6476                                         if (strcmp(p, info->name) == 0)
6477                                         {
6478                                                 if (ctr > NM_MAX_FIELDS)
6479                                                 {
6480                                                         if (line)
6481                                                                 fprintf(stderr,
6482                                                 "too much data field ... in file <%s> at line %d\n",
6483                                                                         f_name, line);
6484                                                         else
6485                                                 fprintf(stderr, "too much data field ...\n");
6486                                                         return (-1);
6487                                                 }
6488 /*
6489                                                 data[ctr] = info;
6490                                                 out_f[ctr] = *o;
6491 */
6492                                                 found_data = 1;
6493                                                 ctr++;
6494                                                 break;
6495                                         }
6496                                 }
6497                         
6498                                 if (found_data == 0)
6499                                 {
6500                                         if (line)
6501                                                 fprintf(stderr,
6502                         "Required data <%s>, not found in info-mon specifications in <%s> at line %d\n",
6503                                                         p, f_name, line);
6504                                         else
6505                                                 fprintf(stderr,
6506                         "Required data <%s>, not found in info-mon specifications\n", p);
6507                                         return(-1);
6508                                 }
6509         
6510                                 p = strtok(NULL, ":\t\n");
6511
6512                         } // end while strtok
6513
6514                 } // end else '-' (short options)
6515                 
6516                 i++;
6517
6518         } // end while
6519         
6520         if (ctr == 0)
6521         {
6522                 if (line)
6523                         fprintf(stderr, "no required data! in <%s> at line %d\n", f_name, line);
6524                 else
6525                         fprintf(stderr, "no required data!\n");
6526                 return(-1);
6527         }
6528
6529         return 0;
6530 }
6531                                                           
6532 // 2, parse the arguments and process the command line
6533 // no checks are needed here, because already do in parse_check
6534 // it return a pointer to info needed for make output, or NULL if errors
6535 ///////////////////////////////////////////////////////////////////////////////
6536 OUT_INFO_MON *parse_process(int argc, char *argv[], PARAM_INFO_MON *start)
6537 {
6538         int ctr;
6539         int i;
6540         int time_spec;
6541         int found_data;
6542         int req_tm;
6543         int req_ts;
6544         char *p;
6545         char *tmp;
6546         char *o;
6547         PARAM_INFO_MON *info;                   // iterator on this list
6548         OUT_INFO_MON *out_param;                // iterator on this list
6549
6550         if ((out_param = malloc(sizeof(OUT_INFO_MON))) == NULL)
6551         {       fprintf(stderr, "no mem\n");
6552                 return(NULL);
6553         }
6554
6555 #ifdef DEBUG
6556         fprintf(stderr, "parse_process: argc = %d\n", argc);
6557                 for (i = 0; i < argc; i++)
6558                         fprintf(stderr, "argv[%d] = <%s>\n",i, argv[i]);
6559 #endif
6560
6561         for (i = 0; i < NM_MAX_FIELDS; i++)
6562                 out_param->data[i] = NULL;
6563
6564         strcpy(out_param->req_fs, " ");
6565 #ifdef WIN32
6566         strcpy(out_param->req_ls, "\n\r");
6567 #else
6568         strcpy(out_param->req_ls, "\n");
6569 #endif
6570         time_spec = 0;
6571         out_param->req_n = 0;
6572         out_param->req_header = 1;
6573
6574         time_spec = 0;
6575         req_tm = 200;                   /* default wait */
6576         req_ts = 0;     
6577         
6578         ctr = 0; 
6579         i = 0;
6580         while (i < argc)
6581         {
6582                 p = argv[i];
6583                 if (*p == '-')
6584                 {                       // should be one of the short option
6585                         if (strcmp(argv[i], "-fs") == 0)
6586                         {               // field separator, next arg should be a string
6587                                 if (((i+1) < argc) && (strlen(argv[i+1]) < 10))
6588                                 {       i++;
6589                                         strcpy(out_param->req_fs, argv[i]);
6590                                 }
6591                                 else
6592                                 {       fprintf(stderr, "NEVER BE:-fs: Invalid field separator\n");
6593                                         return(NULL);
6594                                 }
6595                         }
6596                         else if (strcmp(argv[i], "-ls") == 0) 
6597                         {               // line separator, next arg should be a string
6598                                 if (((i+1) < argc) && (strlen(argv[i+1]) < 10))
6599                                 {       i++;
6600                                         strcpy(out_param->req_ls, argv[i]);
6601                                 }
6602                                 else
6603                                 {       fprintf(stderr, "NEVER BE:-ls: Invalid line separator\n");
6604                                         return(NULL);
6605                                 }
6606                         }
6607                         else if (strcmp(argv[i], "-tm") == 0) 
6608                         {               // time separator, next arg should be a millisecond (200-10000)
6609                                 if (time_spec)
6610                                 {       fprintf(stderr, "NEVER BE:-tm, -ts, are mutually exclusive");
6611                                         return(NULL);
6612                                 }
6613
6614                                 if (((i+1) < argc) && (atoi(argv[i+1]) >= 200) && (atoi(argv[i+1]) <= 10000))
6615                                 {       i++;
6616                                         req_tm = atoi(argv[i]);
6617                                         time_spec = 1;
6618                                 }
6619                                 else
6620                                 {       fprintf(stderr, "NEVER BE:-tm: Invalid argument (200-10000 milliseconds)\n");
6621                                         return(NULL);
6622                                 }
6623                         }
6624                         else if (strcmp(argv[i], "-ts") == 0) 
6625                         {               // time separator, next arg should be a seconds (1-3600)
6626                                 if (time_spec)
6627                                 {       fprintf(stderr, "NEVER BE:-tm, -ts, are mutually exclusive");
6628                                         return(NULL);
6629                                 }
6630
6631                                 if (((i+1) < argc) && (atoi(argv[i+1]) >= 1) && (atoi(argv[i+1]) <= 3600))
6632                                 {       i++;
6633                                         req_ts = atoi(argv[i]);
6634                                         time_spec = 1;
6635
6636                                         // delete default
6637                                         req_tm = 0;
6638                                 }
6639                                 else
6640                                 {       fprintf(stderr, "NEVER BE:-ts: Invalid argument (1-3600 seconds)\n");
6641                                         return(NULL);
6642                                 }
6643                         }
6644                         else if (strcmp(argv[i], "-n") == 0) 
6645                         {               // nr of data pump, before stop collection,
6646                                         // next arg should be a int > 0
6647                                 if (((i+1) < argc) && (atoi(argv[i+1]) >= 1) && (atoi(argv[i+1]) <= 99999))
6648                                 {       i++;
6649                                         out_param->req_n = atoi(argv[i]);
6650                                 }
6651                                 else
6652                                 {       fprintf(stderr, "NEVER BE:-n: Invalid argument (1-99999 times)\n");
6653                                         return(NULL);
6654                                 }
6655                         }
6656                         else if (strcmp(argv[i], "-h") == 0) 
6657                         {               // we do NOT want header (default with header)
6658                                 out_param->req_header = 0;
6659                         }
6660                         else if (strcmp(argv[i], "-S") == 0) 
6661                         {               // we have used use specs from a file instead of standard info,
6662                                         // next arg is an existing readable filename
6663                                         // as already parsed correctly, we skip here.
6664                                 i++;
6665                         }
6666                         else if (strcmp(argv[i], "-I") == 0) 
6667                         {               // we have used input from a file instead of command line
6668                                         // next arg is an existing readable filename
6669                                         // as already parsed correctly, we skip here.
6670                                 i++;
6671                         }       
6672                         else
6673                         {       
6674                                 fprintf(stderr, "NEVER BE:Unrecognized option %s\n", argv[i]);
6675                                 return(NULL);
6676                         }
6677                 }
6678                 else
6679                 {                       // should be required data
6680                         tmp = strdup(argv[i]);
6681                         p = strtok(tmp, ":\t\n");
6682                         while (p != NULL)
6683                         {
6684                                 // check if there is an output format specification
6685                                 o = p;
6686                                 while (*o)
6687                                 {
6688                                         o++;
6689                                         if (*o == '-')
6690                                         {       *o = '\0';
6691                                                 o++;
6692                                                 if (strlen(o) == 0)
6693                                                 {
6694                                                         // we have 'minus', so, probably forget format ...
6695
6696                                                         fprintf(stderr,
6697                                                          "NEVER BE:Required data <%s->, without format specifiers\n", p);
6698                                                         return(NULL);
6699                                                 }
6700                                         }
6701                                 }
6702                         
6703                                                         // we check for params
6704                                 found_data = 0;
6705                                 info = start;
6706                                 while (info->next != NULL)
6707                                 {       
6708                                         info = info->next;
6709                                         if (strcmp(p, info->name) == 0)
6710                                         {
6711                                                 if (ctr > NM_MAX_FIELDS)
6712                                                 {
6713                                                         fprintf(stderr, "NEVER BE:too much data field ...");
6714                                                         return(NULL);
6715                                                 }
6716                                                 out_param->data[ctr] = info;
6717                                                 out_param->out_f[ctr] = *o;
6718                                                 found_data = 1;
6719                                                 ctr++;
6720                                                 break;
6721                                         }
6722                                 }
6723                                 
6724                                 if (found_data == 0)
6725                                 {
6726                                         fprintf(stderr,
6727                                                 "NEVER BE:Required data <%s>, not found in info-mon specifications\n", p);
6728                                         return(NULL);
6729                                 }
6730         
6731
6732                                 p = strtok(NULL, ":\t\n");
6733
6734                         } // end while strtok
6735
6736                         // here, we have an array of pointers to required data
6737                         // and an array of output specifiers, from 0 to [ctr-1]
6738
6739                 } // end else '-' (short options)
6740                 
6741                 i++;
6742
6743         } // end while
6744         
6745         if (ctr == 0)
6746         {
6747                 fprintf(stderr, "NEVER BE:no required data!\n");
6748                 return(NULL);
6749         }
6750         
6751         // now, what netmon screen we need to retrieve ?
6752         // we need somewhat were checking is faster, as our goal is lower cicle time
6753
6754         // we can have NM_MAX_SCREEN=254 screens, so we use an array, of unsigned char,
6755         // each char contain number of needed screen, 255 is list terminator
6756         
6757         for (i = 0; i <= NM_MAX_SCREEN; i++)
6758                 out_param->req_screen[i] = 255;
6759
6760         ctr = 0;
6761 #ifdef DEBUG
6762 fprintf(stderr, "Start Required data %s screen %d\n", out_param->data[ctr]->name, out_param->data[ctr]->s_nr);
6763 #endif
6764         while (out_param->data[ctr] != NULL)
6765         {
6766 #ifdef DEBUG
6767 fprintf(stderr, "Required data %s screen %d\n", out_param->data[ctr]->name, out_param->data[ctr]->s_nr);
6768 #endif
6769                 // check if screen already in 
6770                 found_data = 0;
6771                 i = 0;
6772                 while (out_param->req_screen[i] != 255)
6773                 {
6774                         if (out_param->req_screen[i] == out_param->data[ctr]->s_nr)
6775                         {               // already load, skip
6776                                 found_data = 1;
6777                                 break;
6778                         }
6779                         i++;
6780                 }
6781
6782                 if (found_data == 0)
6783                 {       
6784 #ifdef DEBUG
6785 fprintf(stderr, "i = %d, out_param->req_screen[%d] = %d\n", i, i, out_param->data[ctr]->s_nr);
6786 #endif
6787                         out_param->req_screen[i] = out_param->data[ctr]->s_nr;
6788                         i++;
6789                 }
6790
6791                 ctr++;
6792         }
6793
6794 #ifdef DEBUG
6795 i = 0;
6796 while (out_param->req_screen[i] != 255)
6797 {
6798         fprintf(stderr, "Required screen %d\n", out_param->req_screen[i]);
6799         i++;
6800 }
6801 #endif
6802         
6803         if (req_tm)
6804                 out_param->req_wait = req_tm * 1000;
6805         else if (req_ts)
6806                 out_param->req_wait = req_ts * 1000000;
6807         else
6808                 out_param->req_wait = req_tm * 1000;
6809         
6810
6811         return(out_param);
6812 }
6813
6814 int nmd_output(OUT_INFO_MON *out_param)
6815 {
6816         int d;
6817         int len;
6818         int ctr;
6819         int i;
6820         int nr_line;
6821         char *p;
6822         int nr_chr;
6823         int n;
6824         char Screen[NM_MAX_SCREEN_WIDTH];
6825         time_t sec;
6826         struct tm *date_time;
6827
6828         if (out_param->req_header)
6829         {
6830 // print phone help header
6831                 d = 0;
6832                 while (out_param->data[d] != NULL)
6833                 {       len = out_param->data[d]->len;
6834                         if (strlen(out_param->data[d]->name) > len)
6835                                 len = strlen(out_param->data[d]->name);
6836                         if (strlen(out_param->data[d]->mname) > len)
6837                                 len = strlen(out_param->data[d]->mname);
6838                         printf("%*.*s%s", len, len, out_param->data[d]->name, out_param->req_fs);
6839                         d++;
6840                 }
6841                 printf("%s", out_param->req_ls);
6842
6843 // print netmon manual header
6844                 d = 0;
6845                 while (out_param->data[d] != NULL)
6846                 {       len = out_param->data[d]->len;
6847                         if (strlen(out_param->data[d]->name) > len)
6848                                 len = strlen(out_param->data[d]->name);
6849                         if (strlen(out_param->data[d]->mname) > len)
6850                                 len = strlen(out_param->data[d]->mname);
6851                         printf("%*.*s%s", len, len, out_param->data[d]->mname, out_param->req_fs);
6852                         d++;
6853                 }
6854                 printf("%s", out_param->req_ls);
6855                 printf("%s", out_param->req_ls);
6856         }
6857
6858         ctr = 0;
6859         while (!bshutdown)
6860         {
6861 // stop after n data punp
6862
6863                 ctr++;
6864                 if ((out_param->req_n) && (ctr > out_param->req_n))
6865                         break;
6866
6867 //              datapump: for each screen, for each required data, load data info->value
6868
6869                 i = 0;
6870                 while(out_param->req_screen[i] != 255)
6871                 {       
6872                         if (out_param->req_screen[i] == 0)
6873                         {       
6874                                 sec = time(0);
6875                                 date_time = localtime(&sec);
6876                                 sprintf(Screen, "%02d-%02d-%04d\n%02d:%02d:%02d\n",
6877                                         date_time->tm_mday,
6878                                         date_time->tm_mon+1,
6879                                         date_time->tm_year+1900,
6880                                         date_time->tm_hour,
6881                                         date_time->tm_min,
6882                                         date_time->tm_sec);
6883 #ifdef DEBUG
6884                                 fprintf(stderr, "%02d-%02d-%04d\n%02d:%02d:%02d\n",
6885                                         date_time->tm_mday,
6886                                         date_time->tm_mon+1,
6887                                         date_time->tm_year+1900,
6888                                         date_time->tm_hour,
6889                                         date_time->tm_min,
6890                                         date_time->tm_sec);
6891 #endif
6892                         }
6893                         else
6894                         {
6895                                 GSM->NetMonitor(out_param->req_screen[i], Screen);
6896                         }
6897
6898 // we have one screen of data, load those required
6899
6900                         d = 0;
6901                         while (out_param->data[d] != NULL)
6902                         {       
6903                                 if (out_param->data[d]->s_nr == out_param->req_screen[i])
6904                                 {
6905                                         p = Screen;
6906 // goto req y           
6907                                         nr_line = out_param->data[d]->y;
6908                                         while ((*p) && (nr_line))
6909                                         {       
6910                                                 if (*p == '\n')
6911                                                 {       nr_line--;
6912                                                 }
6913                                                 p++;
6914                                         }
6915 #ifdef DEBUG
6916 fprintf(stderr, "\nthis line: %s\n\n", p);
6917 #endif
6918
6919 // goto req x
6920                                         nr_chr = out_param->data[d]->x;
6921                                         while ((*p) && (nr_chr))
6922                                         {       p++;
6923                                                 nr_chr--;
6924                                         }
6925 // this the start of data
6926                                         n = 0;
6927                                         len = out_param->data[d]->len;
6928                                         while ((*p) && (len))
6929                                         {       out_param->data[d]->value[n] = *p;
6930                                                 p++;
6931                                                 n++;
6932                                                 len--;
6933                                         }
6934 // pad with space if shorter than presumed
6935                                         while ((*p) && (len))
6936                                         {       out_param->data[d]->value[n] = ' ';
6937                                                 n++;
6938                                                 len--;
6939                                         }
6940
6941                                         out_param->data[d]->value[n] = '\0';
6942                                 }
6943
6944                                 d++;    // next screen
6945                         }
6946
6947                         i++;            // next screen
6948                 }
6949
6950 // print row of data
6951                 d = 0;
6952                 while (out_param->data[d] != NULL)
6953                 {       
6954                         len = out_param->data[d]->len;
6955                         if (out_param->req_header)
6956                         {       if (strlen(out_param->data[d]->name) > len)
6957                                         len = strlen(out_param->data[d]->name);
6958                                 if (strlen(out_param->data[d]->mname) > len)
6959                                         len = strlen(out_param->data[d]->mname);
6960                         }
6961 // FIXME check format
6962                         printf("%*.*s%s", len, len, out_param->data[d]->value, out_param->req_fs);
6963                         d++;
6964                 }
6965                 printf("%s", out_param->req_ls);
6966
6967                 usleep(out_param->req_wait);
6968                 
6969         }
6970
6971         printf("%s%s", out_param->req_ls, out_param->req_ls);
6972
6973         return(0);
6974 }
6975
6976 // main func
6977 ///////////////////////////////////////////////////////////////////////////////
6978 int netmonitordata(int argc, char *argv[])
6979 {
6980         char *loc_info = NULL;                  // path to --netmonitordata directory
6981         char *f_name;                           // absolute path of phone info-file
6982         int flag_phone_spec = 0;                // flags, set if used -S option
6983
6984         char model[20] = "phonepar";            // TO DO: PHONE AUTODETECTION
6985 //      char phver[20] = "";
6986
6987         PARAM_INFO_MON *start;                  // pointer to list of parsed phone params
6988         OUT_INFO_MON *out_param;                // pointer to struct of output data
6989
6990         char *f_commands = NULL;                // file containings input line arguments
6991         FILE *commands;                         // Handle for this file
6992         char buf[1024];                         // buffer
6993         char *f_argv[NM_MAX_FIELDS+30];         // space for parameters and cmdline options
6994         int f_argc;
6995         char *p, *tmp;                          // various counter, flags, tmp area ...
6996         int i;
6997         int line;
6998         
6999
7000         fbusinit(NULL);
7001
7002         signal(SIGINT, interrupted);
7003         
7004 // FIXME model, phone_version
7005
7006         // before parsing phone-info-file, we check for user specified phone-info-file
7007
7008         i = 0;
7009         while (i < argc)
7010         {
7011                 if (strcmp(argv[i], "-S") == 0)
7012                 {
7013                         if ((i+1) < argc)
7014                         {
7015                                 flag_phone_spec = 1;
7016                                 loc_info = strdup(argv[i+1]);
7017                                 break;
7018                         }
7019                         else
7020                         {       fprintf(stderr, "option -S require an argument ...\n");
7021                                 return -1;
7022                         }
7023                 }
7024
7025                 i++;
7026         }
7027         
7028         if (loc_info != NULL)
7029         {       f_name = strdup(loc_info);
7030         }
7031         else                            // we use standard file specification
7032         {
7033                 if ((tmp = getenv("INFOMONPATH")) == NULL)
7034                 {       loc_info = strdup(".");
7035                 }
7036                 else
7037                 {       loc_info = strdup(tmp);
7038                 }
7039
7040                 f_name = malloc(strlen(loc_info)+strlen(model)+10); 
7041                 sprintf(f_name, "%s/%s", loc_info, model);
7042         }
7043
7044
7045 #ifdef DEBUG
7046 //      fprintf(stderr, "Loc_info <%s> model <%s> version <%s>\n", loc_info, model, phver);
7047         fprintf(stderr, "Info file: <%s>\n", f_name);
7048 #endif
7049         if ((start = get_mon_param_info(f_name, NULL)) == NULL)
7050                 return(-1);             
7051
7052         // option -I give us the possibility of specify a filename,
7053         // containing a "sequence" of command line args.
7054         // if you specify this option, you can use (on command line) only -S option.
7055         // other options may be specified inside the input-file.
7056         // contents of this file as the same sintax as the command line,
7057         // except it must not contain "--netmonitordata" or "-I" or "-S" options 
7058         ///////////////////////////////////////////////////////////////////////
7059
7060         i = 0;
7061         while (i < argc)
7062         {
7063                 if (strcmp(argv[i], "-I") == 0)
7064                 {
7065                         if ((i+1) < argc)
7066                         {
7067                                 if ((argc == 2) || ((argc == 4) && flag_phone_spec == 1))
7068                                 {       f_commands = strdup(argv[i+1]);
7069                                 }
7070                                 else
7071                                 {       fprintf(stderr, "option -I accept only additional -S option.\n");
7072                                         return -1;
7073                                 }
7074
7075                                 break;
7076                         }
7077                         else
7078                         {       fprintf(stderr, "option -I require an argument ...\n");
7079                                 return -1;
7080                         }
7081                 }
7082
7083                 i++;
7084         }
7085         
7086         // before all, we check all command line
7087         
7088         if (f_commands != NULL)
7089         {       
7090 #ifdef DEBUG
7091                 fprintf(stderr, "netmonitordata(check): commands from <%s>\n", f_commands);
7092 #endif
7093                 // for each line
7094                 // do
7095                 //      read line, make array f_argv, and counter f_argc
7096                 //      parse & check args, so errors are checked before real processing
7097                 //                             (-I option here is ignored)
7098                 //                             (-S option can be here, and it is used)
7099                 // done
7100
7101                 if ((commands = fopen(f_commands, "r")) == NULL)
7102                 {       fprintf(stderr, "Can' t open file commands input :<%s>n", f_commands);
7103                         return(-1);
7104                 }
7105         
7106 // FIXME line may be be splitted
7107                 line = 0;
7108                 while (fgets(buf, 1024, commands) != NULL)
7109                 {       
7110                         p = buf;
7111                         line++;
7112
7113                         // Truncate from '#' at right of comments
7114                         if ((tmp = strchr(p, '#')) != NULL)
7115                                 *tmp = '\0';
7116
7117                         // Strip leading, trailing whitespace
7118                         while(isspace((int) *p))
7119                                 p++;
7120
7121                         while((strlen(p) > 0) && isspace((int) p[strlen(p) - 1]))
7122                                 p[strlen(p) - 1] = '\0';
7123         
7124                         // Ignore blank lines
7125                         if ((*p == '\n') || (*p == '\0'))
7126                                 continue;
7127                         
7128 #ifdef DEBUG
7129 fprintf(stderr, "netmonitordata(check): row <%s>\n", p);
7130 #endif
7131                         // make args
7132                         f_argc = 0;
7133
7134                         p = strtok(p, " \t");
7135                         do
7136                         {       f_argv[f_argc++] = strdup(p);
7137 #ifdef DEBUG
7138 fprintf(stderr, "netmonitordata(check): token <%s>\n", p);
7139 #endif
7140                                 p = strtok(NULL, " \t");                // OK p,  (NULL)
7141                         }
7142                         while ((p != NULL) && (*p));
7143         
7144                         // here we have f_argc, f_argv, this line is OK
7145                 
7146                         if (parse_check(f_argc, f_argv, start, f_commands, line) != 0)
7147                         {       free_nm_info(start);
7148                                 return(-1);
7149                         }
7150                 }
7151         
7152                 fclose(commands);
7153         }
7154         else    // as above, but we have only command line, argv, argc.
7155         {
7156                 if (parse_check(argc, argv, start, NULL, 0) != 0)
7157                 {       free_nm_info(start);
7158                         return(-1);
7159                 }
7160         }
7161         
7162         // here, all commands line are checked, and are correct
7163
7164         if (f_commands != NULL)
7165         {       
7166 #ifdef DEBUG
7167                 fprintf(stderr, "netmonitordata(process): commands from <%s>\n", f_commands);
7168 #endif
7169
7170                 // for each line
7171                 // do
7172                 //      read line, make array f_argv, and counter f_argc
7173                 //      parse_process argument,   (-I option here is ignored)
7174                 //                                (-S option can be here, and it is used)
7175                 //      (make header                    // these are in nmd_output();
7176                 //       loop
7177                 //              get net-mon-info 
7178                 //              make output
7179                 //       done)
7180                 // done
7181
7182                 if ((commands = fopen(f_commands, "r")) == NULL)
7183                 {       fprintf(stderr, "Can' t open file commands input :<%s>n", f_commands);
7184                         return(-1);
7185                 }
7186         
7187 // FIXME line may be be splitted
7188                 while (fgets(buf, 1024, commands) != NULL)
7189                 {       
7190                         p = buf;
7191
7192                         // Truncate from '#' at right of comments
7193                         if ((tmp = strchr(p, '#')) != NULL)
7194                                 *tmp = '\0';
7195
7196                         // Strip leading, trailing whitespace
7197                         while(isspace((int) *p))
7198                                 p++;
7199
7200                         while((strlen(p) > 0) && isspace((int) p[strlen(p) - 1]))
7201                                 p[strlen(p) - 1] = '\0';
7202         
7203                         // Ignore blank lines
7204                         if ((*p == '\n') || (*p == '\0'))
7205                                 continue;
7206                         
7207                         // make args
7208
7209                         f_argc = 0;
7210                         p = strtok(p, " \t");
7211                         do
7212                         {       f_argv[f_argc++] = strdup(p);
7213                                 p = strtok(NULL, " \t");                // OK p,  (NULL)
7214                         }
7215                         while ((p != NULL) && (*p));
7216         
7217                         // here we have f_argc, f_argv, this line is OK
7218                 
7219                         if ((out_param = parse_process(f_argc, f_argv, start)) == NULL)
7220                         {       free_nm_info(start);
7221                                 return(-1);     /* NEVER BE */
7222                         }
7223                 
7224                         // here, command line has no error ...
7225
7226                         nmd_output(out_param);
7227
7228                         free(out_param);
7229                 }
7230         
7231                 fclose(commands);
7232         }
7233         else    // as above, but we have only command line, argv, argc.
7234         {
7235                 if ((out_param = parse_process(argc, argv, start)) == NULL)
7236                 {       free_nm_info(start);
7237                         return(-1);     /* NEVER BE */
7238                 }
7239                 nmd_output(out_param);
7240
7241                 free(out_param);
7242         }
7243         GSM->Terminate();
7244
7245         free(loc_info);
7246         free(f_name);
7247
7248 /* I analised this source and this should be done. But when compile with VC6 */
7249 /* I have error. So, commented... MW */
7250 #ifndef VC6
7251         free_nm_info(start);
7252 #endif
7253
7254         return(0);
7255 }
7256
7257
7258 // used by nm_collect()
7259 ///////////////////////////////////////////////////////////////////////////////
7260 char *rowScreen(char *s)
7261 {
7262         char *p;
7263         
7264         // make Screen in one row
7265         p = s;
7266         while(*p)
7267         {
7268             if (*p == '\n')
7269                         *p = ' ';
7270             p++;
7271         }
7272
7273         return(s);
7274 }
7275
7276 void printtime(void)
7277 {
7278
7279   struct mydate {
7280     int Year;          /* The complete year specification - e.g. 1999. Y2K :-) */
7281     int Month;         /* January = 1 */
7282     int Day;
7283     int Hour;
7284     int Minute;
7285     int Second;
7286     int Timezone;      /* The difference between local time and GMT */
7287   } Date;
7288
7289   struct tm *now;
7290   time_t nowh;
7291   nowh=time(NULL);
7292   now=localtime(&nowh);
7293
7294   Date.Year = now->tm_year;
7295   Date.Month = now->tm_mon+1;
7296   Date.Day = now->tm_mday;
7297   Date.Hour = now->tm_hour;
7298   Date.Minute = now->tm_min;
7299   Date.Second = now->tm_sec;
7300
7301   /* I have 100 (for 2000) Year now :-) */
7302   if (Date.Year>99 && Date.Year<1900) {
7303     Date.Year=Date.Year+1900;
7304   }
7305
7306   printf("%d:%d:%d:%d:%d:%d      ",Date.Day,Date.Month,Date.Year,Date.Hour,Date.Minute,Date.Second);
7307
7308 }
7309
7310 // like netmonitor(), but print in one row, 1, 2 or 3 screen, every ~0.3 s
7311 ///////////////////////////////////////////////////////////////////////////////
7312 int nm_collect(int argc, char *argv[])
7313 {
7314         int mode[MAX_NM_COLLECT];
7315         char Screen[NM_MAX_SCREEN_WIDTH];
7316         int i;
7317
7318         for (i=0;i<argc;i++) {
7319             argc > i ? (mode[i] = atoi(argv[i])): (mode[i] = 0);
7320         }
7321
7322         for (i=0;i<argc;i++) {
7323             if (mode[i]==0 && strcmp(argv[i],"-d")) {
7324                 fprintf(stderr, "Wrong %i parameter (not number and not -d)\n",i);
7325                 return(-1);
7326             }
7327         }
7328
7329         signal(SIGINT, interrupted);
7330
7331         fbusinit(NULL);
7332
7333         // end on CTRL-C
7334         while (!bshutdown) 
7335         {
7336                 for (i=0;i<argc;i++) {
7337                   if (!strcmp(argv[i],"-d")) {
7338                      printtime();
7339                      break;
7340                   }
7341                 }
7342                 
7343                 for (i=0;i<argc;i++) {
7344                   if (mode[i]!=0)
7345                   {
7346                         GSM->NetMonitor(mode[i], Screen);
7347                         printf("%s::", rowScreen(Screen));
7348                   }
7349                 }
7350                 
7351                 printf("\n\n");
7352
7353                 usleep(150000);
7354         }
7355
7356         GSM->Terminate();
7357
7358         return 0;
7359 }
7360
7361 #ifdef DEBUG
7362 int sniff(int argc, char *argv[])
7363 {
7364   /* base model comes from gnokiirc */
7365   strcat(model,"sniff");
7366   
7367   if (argc>0) strcpy(Port,argv[0]);
7368     
7369   /* Initialise the GSM interface. */
7370   fbusinit(NULL);
7371
7372   /* Loop here indefinitely - allows you to see messages from GSM code in
7373      response to unknown messages etc. The loops ends after pressing the
7374      Ctrl+C. */
7375   while (!bshutdown) {
7376     sleep(1);
7377   }
7378
7379   GSM->Terminate();    
7380
7381   return 0;
7382
7383 }
7384
7385 int decodefile(int argc, char *argv[])
7386 {
7387  FILE *infile;
7388  unsigned char in_buffer[255];
7389  int nr_read = 0;
7390  int i = 0;
7391
7392   /* base model comes from gnokiirc */
7393   strcat(model,"decode");
7394
7395  /* Initialise the GSM interface. */
7396  fbusinit(NULL);
7397
7398  printf ("open InPutFile: %s\n", argv[0]);
7399  if ( (infile = fopen( argv[0], "rb")) == NULL ) {
7400    printf ("Failed to open InPutFile: %s\n", argv[0]);
7401    exit (1); }
7402
7403  while ( (nr_read = fread(in_buffer, 1, 16, infile)) > 0 ) {
7404   for (i=0; i < nr_read; i++)
7405      Protocol->StateMachine(in_buffer[i]);
7406   }
7407
7408    return 0;
7409 }
7410
7411 #endif
7412
7413 int getringtone(int argc, char *argv[])
7414 {
7415   GSM_BinRingtone ringtone;
7416   GSM_Error error;
7417   GSM_Ringtone SMringtone;
7418
7419   int i;
7420   
7421   char model[64];
7422
7423   FILE *file;
7424
7425   ringtone.location=1;
7426   if (argc>1) ringtone.location=atoi(argv[1]);
7427
7428   /* Initialise the GSM interface. */
7429   fbusinit(NULL);
7430
7431   error=GSM->GetBinRingtone(&ringtone);
7432
7433   while (GSM->GetModel(model)  != GE_NONE)
7434     sleep(1);
7435
7436   GSM->Terminate();
7437
7438   fprintf(stdout, _("Downloaded ringtone, location %i: "),ringtone.location);
7439   
7440   switch (error) {
7441     case GE_NONE:
7442       fprintf(stdout, _("get succeeded!\n"));
7443       fprintf(stdout, _("Name: %s (binary format)\n"),ringtone.name);
7444       break;
7445     case GE_INVALIDRINGLOCATION:
7446       fprintf(stdout, _("invalid location %i!\n"),ringtone.location);
7447       break;
7448     case GE_UNKNOWNMODEL:
7449     
7450       /* In 3310 we have normal "Smart Messaging" format */
7451       if (GetModelFeature (FN_RINGTONES)==F_RING_SM) {
7452       
7453         i=7;
7454         if (ringtone.frame[9]==0x4a && ringtone.frame[10]==0x3a) i=8;
7455         ringtone.frame[i]=0x02;
7456         
7457         GSM_UnPackRingtone(&SMringtone, ringtone.frame+i, ringtone.length-i);
7458
7459         fprintf(stdout, _("Name: %s (normal format)\n"),SMringtone.name);
7460
7461         GSM_SaveRingtoneFileOnConsole(argv[0], &SMringtone);
7462         
7463         return 0;
7464       }
7465
7466       fprintf(stdout, _("mygnokii doesn't know format for this model!\n"));
7467       break;
7468     case GE_NOTIMPLEMENTED:
7469       fprintf(stdout, _("not implemented for this model!\n"));
7470       break;
7471     default:
7472       fprintf(stdout, _("not supported by this model!\n"));
7473       break;
7474   }
7475   
7476   if (error!=GE_NONE)
7477     return(-1);
7478   
7479   file = fopen(argv[0], "wb");
7480       
7481   if (!file)
7482     return(GE_CANTOPENFILE);
7483
7484   fwrite(ringtone.frame, 1, ringtone.length, file);     
7485   
7486   fclose(file);
7487   
7488   return 0;
7489
7490 }
7491
7492 int binringtoneconvert(int argc, char *argv[])
7493 {
7494   GSM_BinRingtone ringtone;
7495   
7496   int i,j,z;
7497   bool isok;
7498   int deflen=7,m,w;
7499   bool pause;
7500
7501   FILE *file;
7502   
7503 //{ "c", "c#", "d", "d#", "e",  "f", "f#", "g", "g#", "a", "a#", "h" };
7504   int binary_notes[12] =
7505   { 0,    1,    2,   3,    4,   6,   7,    8,   9,    10,  11 ,   12};
7506
7507   if (GSM_ReadBinRingtoneFile(argv[0],&ringtone)!=GE_NONE) {
7508     fprintf(stdout,_("Failed to read %s file!\n"),argv[0]);
7509     return -1;
7510   }
7511
7512   file = fopen(argv[1], "wb");
7513       
7514   if (!file)
7515     return(GE_CANTOPENFILE);
7516
7517   i=5;
7518   while (true) {
7519     if (ringtone.frame[i]==0) break;
7520     fprintf(file,_("%c"),ringtone.frame[i]);
7521     i++;
7522   }
7523
7524   fprintf(file,_(":d=32,o=5,b=300:"));
7525     
7526   i=i+5;j=0;z=0;
7527   while (true) {
7528     if (ringtone.frame[i]!=j) {
7529       if (j!=0) {
7530         isok=false;
7531         if (j==64) {
7532           j=255;//Pause
7533           isok=true;
7534         }
7535         if (!isok && j>=114 && j<=125) {
7536           j=14*3+binary_notes[j-114];
7537           isok=true;
7538         }
7539         if (!isok && j>=126 && j<=137) {
7540           j=14*1+binary_notes[j-126];
7541           isok=true;
7542         }
7543         if (!isok && j>=138 && j<=149) {
7544           j=14*2+binary_notes[j-138];
7545           isok=true;
7546         }
7547         if (!isok && j>=150 && j<=161) {
7548           j=14*4+binary_notes[j-150];
7549           isok=true;
7550         }
7551         if (!isok) {
7552           if (j!=10) { 
7553             fprintf(stdout,_("Unknown block in binary ringtone %i %i\n"),j,z);
7554           }
7555         } else {
7556           w=deflen;
7557           for (m=0;m<6;m++) {
7558             w=w*2;
7559             if (w>z && (w/2)<=z) {
7560               switch (m) {
7561                 case 1:fprintf(file,_("16"));break;\r
7562                 case 2:fprintf(file,_("8"));break;\r
7563                 case 3:fprintf(file,_("4"));break;\r
7564                 case 4:fprintf(file,_("2"));break;\r
7565                 case 5:fprintf(file,_("1"));break;\r
7566               }
7567               break;
7568             }
7569           }
7570           if (z>w) fprintf(file,_("1"));
7571           pause=false;
7572           switch (GSM_GetNote(j)) {\r
7573             case Note_C  :fprintf(file,_("c"));break;\r
7574             case Note_Cis:fprintf(file,_("c#"));break;\r
7575             case Note_D  :fprintf(file,_("d"));break;\r
7576             case Note_Dis:fprintf(file,_("d#"));break;\r
7577             case Note_E  :fprintf(file,_("e"));break;\r
7578             case Note_F  :fprintf(file,_("f"));break;\r
7579             case Note_Fis:fprintf(file,_("f#"));break;\r
7580             case Note_G  :fprintf(file,_("g"));break;\r
7581             case Note_Gis:fprintf(file,_("g#"));break;\r
7582             case Note_A  :fprintf(file,_("a"));break;\r
7583             case Note_Ais:fprintf(file,_("a#"));break;\r
7584             case Note_H  :fprintf(file,_("h"));break;\r
7585             default      :pause=true;fprintf(file,_("p"));break; //Pause ?\r
7586           }\r
7587           w=deflen*1.5;
7588           for (m=0;m<6;m++) {
7589             w=w*2;
7590             if (w>z && (w/2)<=z) {
7591               fprintf(file,_("."));
7592               break;
7593             }
7594           }
7595           if ((j/14)!=1 && !pause) fprintf(file,_("%i"),j/14);
7596           fprintf(file,_(","));
7597         }
7598       }
7599       j=ringtone.frame[i];
7600       z=ringtone.frame[i+1];
7601     } else {
7602       z=z+ringtone.frame[i+1];
7603     }
7604     i=i+2;
7605     if (i>=ringtone.length) break;
7606   }
7607
7608   fclose(file);
7609   
7610   return 0;
7611
7612 }
7613
7614 int renamesmsc(int argc, char *argv[])
7615 {
7616   GSM_MessageCenter MessageCenter;
7617
7618   MessageCenter.No=atoi(argv[0]);
7619
7620   /* Initialise the GSM interface. */
7621   fbusinit(NULL);
7622
7623   if (GSM->GetSMSCenter(&MessageCenter) == GE_NONE) {
7624     fprintf(stdout,_("SMSC number %i get OK\n"),MessageCenter.No);  
7625   } else {
7626     GSM->Terminate();
7627     fprintf(stdout,_("Error getting SMSC number %i\n"),MessageCenter.No);
7628     return 0;  
7629   }
7630
7631   strncpy(MessageCenter.Name,argv[1],10);
7632
7633   if (GSM->SetSMSCenter(&MessageCenter) == GE_NONE) {
7634     fprintf(stdout,_("SMSC number %i set OK (renamed to \"%s\")\n"),MessageCenter.No,MessageCenter.Name);
7635   } else {
7636     GSM->Terminate();
7637     fprintf(stdout,_("Error setting SMSC number %i\n"),MessageCenter.No);
7638     return 0;  
7639   }
7640   
7641   GSM->Terminate();
7642
7643   return 0;
7644 }
7645
7646 /*
7647  * Returns number of sostituited characters.
7648  * ... may be useful one day ??
7649  */
7650 int semicolon_pipe_substitution( GSM_PhonebookEntry *pentry, unsigned int direction )
7651         /* direction = 0 : after reading phone memory (
7652          *             1 : writing phone memory
7653          */
7654 {
7655         register int i;
7656         register int count=0;
7657         char charfrom, charto;
7658
7659         charfrom= (direction==0) ? ';' : '|';
7660         charto  = (direction==0) ? '|' : ';';
7661
7662         count+=str_substch(pentry->Name, charfrom, charto );
7663         count+=str_substch(pentry->Number, charfrom, charto );
7664
7665         for( i = 0; i < pentry->SubEntriesCount; i++ )
7666         {
7667                 if( pentry->SubEntries[i].EntryType != GSM_Date )
7668                                 count+=str_substch(pentry->SubEntries[i].data.Number ,charfrom,charto);
7669         }
7670
7671         return( count );
7672 }
7673
7674 int str_substch( char *str, const char toric, const char sost )
7675 {
7676         unsigned int ct;
7677         int i_sost=0;
7678          
7679                 for( ct = 0; ct < strlen(str); ct++ )
7680                         if( str[ct] == (unsigned char) toric )
7681                         { str[ct] = sost; i_sost++; }
7682                  
7683         return( i_sost );
7684 }                                                                               
7685
7686 /* Allows to set simlock state.
7687    With older phone (older 51xx, 61xx) can open them, with older
7688    and newer should be able to close them */
7689 /* DO NOT TRY, IF DON'T WANT, WHAT YOU DO !!!!!!!!!! */
7690 int setsimlock()
7691 {
7692   GSM_AllSimlocks siml;
7693
7694   unsigned char closebuffer[20]=
7695                              { 0x00, 0x01, 0x82, 0x01,
7696                                0x00,                         /* which simlock */
7697                                0x00, 0x00,
7698                                0x00, 0x00, 0x00,             /* lock 1 info */
7699                                0x00, 0x00, 0x00, 0x00, 0x00, /* lock 4 info */
7700                                0x00, 0x00,                   /* lock 2 info */
7701                                0x00, 0x00,                   /* lock 3 info */
7702                                0x00};
7703   unsigned char openbuffer[10]= { 0x00, 0x01, 0x81, 0x01,
7704                                   0x00, /* lock number */
7705                                   0x10, 0x10, 0x10, 0x10, 0x10 };
7706   unsigned char openbuffer0[10]= {0x00, 0x01, 0x02, 0x03, 0x1f, 0x11, 0x01, 0x01, 0x10, 0x00 };
7707
7708   unsigned char info[120];
7709   int i,j;
7710   
7711   /* Initialise the code for the GSM interface. */     
7712   fbusinit(NULL);
7713   if (strstr(GSM_Info->FBUSModels, "3310") == NULL)
7714   {
7715     fprintf(stderr,("Not supported\n"));
7716     GSM->Terminate();
7717     return -1;
7718   }
7719   N6110_EnableExtendedCommands(0x02);
7720   /* Initial info */
7721   if (GSM->SimlockInfo(&siml)!=GE_NONE) {
7722     fprintf(stderr,_("Error getting simlock info\n"));GSM->Terminate();return -1;
7723   }
7724   /* Opening all locks (we must check, if we can open them) */
7725   NULL_SendMessageSequence\r(50, &CurrentMagicError, 10, 0x40,openbuffer0);
7726   openbuffer[4]=1;NULL_SendMessageSequence\r(50, &CurrentMagicError, 10, 0x40,openbuffer);
7727   openbuffer[4]=2;NULL_SendMessageSequence\r(50, &CurrentMagicError, 10, 0x40,openbuffer);
7728   openbuffer[4]=4;NULL_SendMessageSequence\r(50, &CurrentMagicError, 10, 0x40,openbuffer);
7729   openbuffer[4]=8;NULL_SendMessageSequence\r(50, &CurrentMagicError, 10, 0x40,openbuffer);
7730   if (GSM->SimlockInfo(&siml)!=GE_NONE) {
7731     fprintf(stderr,_("Error getting simlock info\n"));GSM->Terminate();return -1;
7732   }
7733   for (i=0;i<4;i++) {
7734     if (siml.simlocks[i].enabled) {
7735       fprintf(stderr,_("Can not open simlock %i\n"),i+1);GSM->Terminate();return -1;
7736     }
7737   }
7738   /* Making frame for closing simlocks */
7739   strcpy(info,"00101");
7740   j=0;i=7;
7741   while (j!=strlen(info)) {
7742     if (j+2<=strlen(info)) {
7743       closebuffer[i]=((info[j] & 0x0f)<<4) | (info[j+1] & 0x0f);j=j+2;
7744     } else {
7745       closebuffer[i]=(info[j] & 0x0f) << 4;j++;
7746     }i++;
7747   }
7748   strcpy(info,"0000");j=0;i=15;
7749   while (j!=strlen(info)) {
7750     if (j+2<=strlen(info)) {
7751       closebuffer[i]=((info[j] & 0x0f)<<4) | (info[j+1] & 0x0f);j=j+2;
7752     } else {
7753       closebuffer[i]=(info[j] & 0x0f) << 4;j++;
7754     }i++;
7755   }
7756   strcpy(info,"0000");j=0;i=17;
7757   while (j!=strlen(info)) {
7758     if (j+2<=strlen(info)) {
7759       closebuffer[i]=((info[j] & 0x0f)<<4) | (info[j+1] & 0x0f);j=j+2;
7760     } else {
7761       closebuffer[i]=(info[j] & 0x0f) << 4;j++;
7762     }i++;
7763   }
7764   strcpy(info,"0000000001");j=0;i=9;
7765   while (j!=strlen(info)) {
7766     if (j+2<=strlen(info)) {
7767       if (j==0) {
7768         closebuffer[i]=closebuffer[i] | (info[j] & 0x0f);j++;
7769       } else {
7770         closebuffer[i]=((info[j] & 0x0f)<<4) | (info[j+1] & 0x0f);j=j+2;
7771       }
7772     } else {
7773       closebuffer[i]=(info[j] & 0x0f) << 4;j++;
7774     }i++;
7775   }  
7776   /* Closing simlock with given values */
7777   closebuffer[4]=1+2+4+8;
7778   NULL_SendMessageSequence\r(50, &CurrentMagicError, 20, 0x40,closebuffer);  
7779   /* Opening all locks */
7780   NULL_SendMessageSequence\r(50, &CurrentMagicError, 10, 0x40,openbuffer0);
7781   openbuffer[4]=1;NULL_SendMessageSequence\r(50, &CurrentMagicError, 10, 0x40,openbuffer);
7782   openbuffer[4]=2;NULL_SendMessageSequence\r(50, &CurrentMagicError, 10, 0x40,openbuffer);
7783   openbuffer[4]=4;NULL_SendMessageSequence\r(50, &CurrentMagicError, 10, 0x40,openbuffer);
7784   openbuffer[4]=8;NULL_SendMessageSequence\r(50, &CurrentMagicError, 10, 0x40,openbuffer);
7785   GSM->Reset(0x03);
7786   GSM->Terminate();
7787   return 0;
7788 }
7789
7790 int simlockinfo()
7791 {
7792   GSM_AllSimlocks siml;
7793   char s[7];
7794
7795   /* Initialise the code for the GSM interface. */     
7796   fbusinit(NULL);
7797
7798   if (GSM->SimlockInfo(&siml)!=GE_NONE) fprintf(stderr,_("Error\n"));
7799
7800   fprintf(stdout,_("MCC + MNC : %s      ("),siml.simlocks[0].data);
7801   if (siml.simlocks[0].enabled) fprintf(stdout,_("CLOSED"));
7802                            else fprintf(stdout,_("opened"));
7803   if (siml.simlocks[0].factory) fprintf(stdout,_(") (factory"));
7804                            else fprintf(stdout,_(")    (user"));
7805   fprintf(stdout,_(") (counter %i"),siml.simlocks[0].counter);
7806
7807   s[0]=siml.simlocks[0].data[0];
7808   s[1]=siml.simlocks[0].data[1];
7809   s[2]=siml.simlocks[0].data[2];
7810   s[3]=' ';
7811   s[4]=siml.simlocks[0].data[3];
7812   s[5]=siml.simlocks[0].data[4];
7813   s[6]=0;
7814
7815   if (strcmp(GSM_GetNetworkName(s),"unknown"))
7816     fprintf(stdout,_(") (network \"%s\""),GSM_GetNetworkName(s));
7817
7818   fprintf(stdout,_(")\n"));
7819
7820   fprintf(stdout,_("GID1      : %s       ("),siml.simlocks[1].data);
7821   if (siml.simlocks[1].enabled) fprintf(stdout,_("CLOSED"));
7822                            else fprintf(stdout,_("opened"));
7823   if (siml.simlocks[1].factory) fprintf(stdout,_(") (factory"));
7824                            else fprintf(stdout,_(")    (user"));
7825   fprintf(stdout,_(") (counter %i"),siml.simlocks[1].counter);
7826   fprintf(stdout,_(")\n"));
7827
7828   fprintf(stdout,_("GID2      : %s       ("),siml.simlocks[2].data);
7829   if (siml.simlocks[2].enabled) fprintf(stdout,_("CLOSED"));
7830                            else fprintf(stdout,_("opened"));
7831   if (siml.simlocks[2].factory) fprintf(stdout,_(") (factory"));
7832                            else fprintf(stdout,_(")    (user"));
7833   fprintf(stdout,_(") (counter %i"),siml.simlocks[2].counter);
7834   fprintf(stdout,_(")\n"));
7835
7836   fprintf(stdout,_("MSIN      : %s ("),siml.simlocks[3].data);
7837   if (siml.simlocks[3].enabled) fprintf(stdout,_("CLOSED"));
7838                            else fprintf(stdout,_("opened"));
7839   if (siml.simlocks[3].factory) fprintf(stdout,_(") (factory"));
7840                            else fprintf(stdout,_(")    (user"));
7841   fprintf(stdout,_(") (counter %i"),siml.simlocks[3].counter);
7842   fprintf(stdout,_(")\n"));
7843
7844   GSM->Terminate();
7845
7846   return 0;
7847 }
7848
7849 /* Getting EEPROM from older phones */
7850 /* Tested with N5110 5.07, 6150 5.22 */
7851 int geteeprom()
7852 {
7853   int i=0x40;
7854
7855   unsigned char buffer[1000]={ 0x00, 0x01, 0xd4, 0x02, 0x00, 0xa0, 
7856                                0x00, 0x00, /* location Lo and Hi */
7857                                0x10 };     /* how many bytes */
7858
7859   strcpy(Connection,"mbus");
7860   fprintf(stderr,_("Switching connection type to MBUS\n"));
7861
7862   strcpy(model,"5110");  
7863   
7864   /* Initialise the code for the GSM interface. */     
7865   fbusinit(NULL);
7866
7867   if (strstr(GSM_Info->FBUSModels, "3310") == NULL)
7868   {
7869     fprintf(stderr,("Not supported\n"));
7870     GSM->Terminate();
7871     return -1;
7872   }
7873
7874   for (i=0;i<64;i++) {
7875     fprintf(stdout,_("%c"),0xff);
7876   }
7877   
7878   while (i<300000) {
7879     buffer[6] = i/256;
7880     buffer[7] = i%256;
7881     
7882     if ((i/256)!=((i-1)/256)) fprintf(stderr,_("."));
7883     
7884     if (NULL_SendMessageSequence(50, &CurrentMagicError, 9, 0x40,buffer)!=GE_NONE)\r       break;
7885
7886     i=i+0x10;
7887   }
7888
7889   fprintf(stderr,_("\n"));
7890   
7891   GSM->Terminate();
7892
7893   return 0;
7894 }
7895
7896 int getsmsfolders()
7897 {
7898   GSM_SMSFolders folders;
7899   GSM_Error error;
7900
7901   int i;
7902     
7903   /* Initialise the code for the GSM interface. */     
7904   fbusinit(NULL);
7905
7906   folders.number = 0;
7907
7908   error=GSM->GetSMSFolders(&folders);
7909   
7910   GSM->Terminate();
7911
7912   if (error!=GE_NONE && !folders.number) {
7913     fprintf(stdout,_("Error!\n"));
7914     return -1;
7915   }
7916   
7917   for (i=0;i<folders.number;i++) {
7918       fprintf(stdout,_("%i. %s\n"),i+1,folders.Folder[i].Name);
7919   }
7920   
7921   return 0;
7922 }
7923
7924 int resetphonesettings()
7925 {
7926   /* Initialise the code for the GSM interface. */     
7927   fbusinit(NULL);
7928
7929   GSM->ResetPhoneSettings();
7930
7931   GSM->Reset(0x03);  
7932   
7933   GSM->Terminate();
7934
7935   return 0;
7936 }
7937
7938 /* Checked on 3310 4.02 and doesn't work.
7939    Possible reasons: SMSC has problems (possible), bug in phone firmware
7940    (very possible) or here in code.
7941    I quess, that the second is the most possible - 3310 treat only 3 SMS
7942    as linked (the most often profile needs 4 - 2 and few bytes in 3'th
7943    for screen saver, few bytes for profile name and 1 or 2 sms for ringtone).
7944    When send separate ringtone (see --sendringtone with --profilestyle)
7945    and screen saver (--sendlogo screensaver...), it's received OK.
7946    It's for checking in higher firmware. */
7947 int sendprofile(int argc, char *argv[])
7948 {
7949   GSM_Ringtone ringtone;
7950   GSM_Bitmap bitmap;
7951   GSM_MultiSMSMessage MultiSMS;
7952
7953   int current=0,i,j;
7954
7955   u8 MessageBuffer[140*4];
7956   u16 MessageLength=0;
7957   
7958   char profilename[10+1];
7959   
7960   if (GSM_ReadRingtoneFileOnConsole(argv[2], &ringtone)!=GE_NONE) return(-1);
7961
7962   ringtone.allnotesscale=false;
7963   for (i=0;i<argc;i++)
7964     if (!strcmp(argv[i],"--scale")) ringtone.allnotesscale=true;
7965
7966   /* The fourth argument is the bitmap file. */
7967   if (GSM_ReadBitmapFileOnConsole(argv[3], &bitmap)!=GE_NONE) return -1;
7968
7969   GSM_ResizeBitmap(&bitmap,GSM_PictureImage);
7970
7971   strncpy(profilename,argv[1],10);
7972
7973   MessageBuffer[MessageLength++]=0x30;               //SM version. Here 3.0
7974
7975   MessageBuffer[MessageLength++]=SM30_PROFILENAME;   //ID for profile name
7976   MessageBuffer[MessageLength++]=0x00;               //length hi  
7977   MessageBuffer[MessageLength++]=strlen(profilename);//length lo
7978   
7979   EncodeUnicode (MessageBuffer+MessageLength,profilename ,strlen(profilename));
7980   MessageLength=MessageLength+2*strlen(profilename);
7981
7982   MessageBuffer[MessageLength++]=SM30_RINGTONE; //ID for ringtone
7983   i=MessageLength;
7984   MessageBuffer[MessageLength++]=0x01;          //length hi
7985   MessageBuffer[MessageLength++]=0x00;          //length lo
7986
7987   j=SM30_MAX_RINGTONE_FRAME_LENGTH;
7988   current=GSM_PackRingtone(&ringtone, MessageBuffer+MessageLength, &j);
7989   MessageLength=MessageLength+j;
7990
7991   if (current!=ringtone.NrNotes) {
7992     if (current>FB61_MAX_RINGTONE_NOTES) {
7993       fprintf(stderr,_("Warning: due to phone limitation"));
7994     } else {
7995       fprintf(stderr,_("Warning: ringtone was too long to be saved into SMS,"));
7996     }
7997     fprintf(stderr, _(" only %i first notes were packed (%i cut)\n"),current,ringtone.NrNotes-current);
7998   }
7999     
8000   MessageBuffer[i]=(j)/256;
8001   MessageBuffer[i+1]=(j)%256;
8002
8003   MessageBuffer[MessageLength++]=SM30_SCREENSAVER; //ID for OTA screen saver
8004   MessageBuffer[MessageLength++]=0x01;             //length hi
8005   MessageBuffer[MessageLength++]=0x00;             //length lo
8006   MessageBuffer[MessageLength++]=0x00;
8007   MessageBuffer[MessageLength++]=bitmap.width;
8008   MessageBuffer[MessageLength++]=bitmap.height;   
8009   MessageBuffer[MessageLength++]=0x01;    
8010
8011   memcpy(MessageBuffer+MessageLength,bitmap.bitmap,bitmap.size);
8012   MessageLength=MessageLength+bitmap.size;
8013
8014   GSM_MakeMultiPartSMS2(&MultiSMS,MessageBuffer,MessageLength, GSM_ProfileUDH, GSM_Coding_Default);
8015
8016   optind = 4;
8017
8018   /* Initialise the GSM interface. */
8019   fbusinit(NULL);
8020
8021   for (i=0;i<MultiSMS.number;i++)
8022     strcpy(MultiSMS.SMS[i].Destination,argv[0]);
8023
8024   return GSM_SaveMultiPartSMSOnConsole(&MultiSMS, optind,argc,argv,false,false,false,false);
8025 }
8026
8027 int showbitmap(int argc, char *argv[])
8028 {
8029   GSM_Bitmap bitmap;
8030
8031   if (GSM_ReadBitmapFileOnConsole(argv[0], &bitmap)!=GE_NONE) return(-1);
8032
8033   GSM_PrintBitmap(&bitmap);
8034
8035   return 0;
8036 }
8037
8038 int getwapsettings(int argc, char *argv[])
8039 {
8040   GSM_WAPSettings settings;
8041   GSM_Error error;
8042
8043   settings.location=atoi(argv[0]);
8044   
8045   /* Initialise the GSM interface. */
8046   fbusinit(NULL);
8047
8048   error=GSM->GetWAPSettings(&settings);
8049   
8050   switch (error) {
8051     case GE_NONE:
8052       fprintf(stdout,_("%s."),argv[0]);
8053       if (!(strcmp(settings.title,""))) fprintf(stdout,_("Set %s\n"),argv[0]);
8054                                    else fprintf(stdout,_("%s\n"),settings.title);
8055       fprintf(stdout,_("Homepage: %s\n"),settings.homepage);
8056       if (settings.iscontinuous) fprintf(stdout,_("Connection type: continuous\n"));
8057                             else fprintf(stdout,_("Connection type: temporary\n"));
8058       if (settings.issecurity) fprintf(stdout,_("Connection security: on\n"));
8059                           else fprintf(stdout,_("Connection security: off\n"));
8060       switch (settings.bearer) {
8061         case WAPSETTINGS_BEARER_SMS:
8062           fprintf(stdout,_("Bearer: SMS\n"));
8063           fprintf(stdout,_("Server number: %s\n"),settings.server);
8064           fprintf(stdout,_("Service number: %s\n"),settings.service);
8065           break;
8066         case WAPSETTINGS_BEARER_DATA:
8067           fprintf(stdout,_("Bearer: Data (CSD)\n"));
8068           fprintf(stdout,_("Dial-up number: %s\n"),settings.dialup);
8069           fprintf(stdout,_("IP address: %s\n"),settings.ipaddress);
8070           if (settings.isnormalauthentication) fprintf(stdout,_("Authentication type: normal\n"));
8071                                           else fprintf(stdout,_("Authentication type: secure\n"));  
8072           if (settings.isISDNcall) fprintf(stdout,_("Data call type: ISDN\n"));
8073                               else fprintf(stdout,_("Data call type: analogue\n"));  
8074           if (settings.isspeed14400) fprintf(stdout,_("Data call speed: 14400\n"));
8075                                 else fprintf(stdout,_("Data call speed: 9600\n"));  
8076           fprintf(stdout,_("User name: %s\n"),settings.user);
8077           fprintf(stdout,_("Password: %s\n"),settings.password);
8078           break;
8079         case WAPSETTINGS_BEARER_USSD:
8080           fprintf(stdout,_("Bearer: USSD\n"));
8081           fprintf(stdout,_("Service code: %s\n"),settings.code);
8082           if (settings.isIP) fprintf(stdout,_("Address type: IP address\nIPaddress: %s\n"),settings.service);
8083                         else fprintf(stdout,_("Address type: service number\nService number: %s\n"),settings.service);
8084           break;
8085       }
8086       break;
8087     default:
8088       fprintf(stderr,_("%s\n"),print_error(error));
8089   }
8090
8091   GSM->Terminate();    
8092
8093   return 0;
8094
8095 }
8096
8097 /* Not full done now */
8098 int savewapsettings(int argc, char *argv[])
8099 {
8100   GSM_WAPSettings settings;
8101   GSM_MultiSMSMessage MultiSMS;
8102   GSM_Error error;
8103   int w;
8104
8105   settings.location=atoi(argv[0]);
8106   
8107   /* Initialise the GSM interface. */
8108   fbusinit(NULL);
8109
8110   error=GSM->GetWAPSettings(&settings);
8111 //  strcpy(settings.homepage,"http://OtherSites/");
8112 //  strcpy(settings.title,"Orange");
8113
8114   error=GE_NONE;
8115   
8116   switch (error) {
8117     case GE_NONE:
8118       /* Put settings into SMS structure */
8119       GSM_SaveWAPSettingsToSMS(&MultiSMS,&settings);
8120
8121       for (w=0;w<MultiSMS.number;w++)
8122         strcpy(MultiSMS.SMS[w].Destination,"WAPSettings");
8123
8124       GSM_SaveMultiPartSMSOnConsole(&MultiSMS,1,argc,argv,false,false,false,false);
8125       return 0;
8126
8127       break;
8128     default:
8129       fprintf(stderr,_("%s\n"),print_error(error));
8130   }
8131
8132   GSM->Terminate();    
8133
8134   return 0;
8135 }
8136
8137 int sendwapsettings(int argc, char *argv[])
8138 {
8139   GSM_WAPSettings settings;
8140   GSM_MultiSMSMessage MultiSMS;
8141   GSM_Error error;
8142   int w;
8143
8144   settings.location=atoi(argv[0]);
8145   
8146   /* Initialise the GSM interface. */
8147   fbusinit(NULL);
8148
8149   error=GSM->GetWAPSettings(&settings);
8150 //  strcpy(settings.homepage,"http://OtherSites/");
8151 //  strcpy(settings.title,"Orange");
8152
8153   error=GE_NONE;
8154   
8155   switch (error) {
8156     case GE_NONE:
8157       /* Put settings into SMS structure */
8158       GSM_SaveWAPSettingsToSMS(&MultiSMS,&settings);
8159
8160       for (w=0;w<MultiSMS.number;w++)
8161         strcpy(MultiSMS.SMS[w].Destination,argv[1]);
8162
8163       GSM_SendMultiPartSMSOnConsole(&MultiSMS, 2,argc,argv,false,false,false);
8164
8165       return 0;
8166
8167       break;
8168     default:
8169       fprintf(stderr,_("%s\n"),print_error(error));
8170   }
8171
8172   GSM->Terminate();    
8173
8174   return 0;
8175 }
8176
8177 int getwapbookmark(int argc, char *argv[])
8178 {
8179   GSM_WAPBookmark bookmark;
8180   GSM_Error error;
8181
8182   bookmark.location=atoi(argv[0]);
8183   
8184   /* Initialise the GSM interface. */
8185   fbusinit(NULL);
8186
8187   error=GSM->GetWAPBookmark(&bookmark);
8188   
8189   switch (error) {
8190     case GE_NONE:
8191       if (bookmark.address[0]==0) {
8192         fprintf(stdout,_("Empty bookmark location\n"));
8193       } else {
8194         fprintf(stdout,_("Address: \"%s\"\n"),bookmark.address);
8195         if (bookmark.title[0]==0)
8196           fprintf(stdout,_("Title: \"%s\"\n"),bookmark.address);
8197         else
8198           fprintf(stdout,_("Title: \"%s\"\n"),bookmark.title);
8199       }
8200       break;
8201     default:
8202       fprintf(stderr,_("%s\n"),print_error(error));
8203   }
8204
8205   GSM->Terminate();    
8206
8207   return 0;
8208
8209 }
8210
8211 int setwapbookmark(int argc, char *argv[])
8212 {
8213   GSM_WAPBookmark bookmark;
8214   GSM_Error error;
8215
8216   if (argc == 3)        /* if location given, use it */
8217     bookmark.location=atoi(argv[2]);
8218   else                  /* else use first empty location */
8219     bookmark.location=0xffff;
8220
8221   strcpy(bookmark.title, argv[0]);
8222   strcpy(bookmark.address, argv[1]);
8223
8224   /* Initialise the GSM interface. */
8225   fbusinit(NULL);
8226
8227   error=GSM->SetWAPBookmark(&bookmark);
8228   
8229   switch (error) {
8230     case GE_NONE:
8231       fprintf(stdout,_("No errors\n"));
8232       break;
8233     default:
8234       fprintf(stderr,_("%s\n"),print_error(error));
8235   }
8236
8237   GSM->Terminate();    
8238
8239   return 0;
8240
8241 }
8242
8243 int savewapbookmark(int argc, char *argv[])
8244 {
8245   GSM_WAPBookmark bookmark;
8246   GSM_MultiSMSMessage MultiSMS;
8247   GSM_Error error;
8248   int w;
8249
8250   bookmark.location=atoi(argv[0]);
8251   
8252   /* Initialise the GSM interface. */
8253   fbusinit(NULL);
8254
8255   error=GSM->GetWAPBookmark(&bookmark);
8256
8257 //  strcpy(bookmark.title,"tytulagagagagagagagagagagagagagagagagagagagagagend");
8258 //  strcpy(bookmark.address,"http://jajajajajajajajajajajajagagagagagagagagagagagagagagagagagagagagagpapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapÂ¥papapapapapapapapagagagagagagagagagagagagagagagagagagagagagagagagagadadadadadadadajdjdjdjdjdjdjdjdjdjdjdjdjdjdjdjdstp");  
8259   error=GE_NONE;
8260
8261   switch (error) {
8262     case GE_NONE:
8263
8264       if (bookmark.address[0]==0) {
8265         fprintf(stdout,_("Empty bookmark location\n"));
8266         GSM->Terminate();   
8267         return 1;
8268       }
8269
8270       /* Put bookmark into SMS structure */
8271       GSM_SaveWAPBookmarkToSMS(&MultiSMS,&bookmark);
8272
8273       for (w=0;w<MultiSMS.number;w++)
8274         strcpy(MultiSMS.SMS[w].Destination,"WAPBookmark");
8275
8276       GSM_SaveMultiPartSMSOnConsole(&MultiSMS, 1,argc,argv,false,false,false,false);
8277       return 0;
8278
8279       break;
8280     default:
8281       fprintf(stderr,_("%s\n"),print_error(error));
8282   }
8283
8284   GSM->Terminate();    
8285
8286   return 0;
8287
8288 }
8289
8290 int sendwapbookmark(int argc, char *argv[])
8291 {
8292   GSM_WAPBookmark bookmark;
8293   GSM_MultiSMSMessage MultiSMS;
8294   GSM_Error error;
8295   int w;
8296
8297   bookmark.location=atoi(argv[0]);
8298   
8299   /* Initialise the GSM interface. */
8300   fbusinit(NULL);
8301
8302   error=GSM->GetWAPBookmark(&bookmark);
8303   
8304   switch (error) {
8305     case GE_NONE:
8306
8307       if (bookmark.address[0]==0) {
8308         fprintf(stdout,_("Empty bookmark location\n"));
8309         GSM->Terminate();   
8310         return 1;
8311       }
8312
8313       /* Put bookmark into SMS structure */
8314       GSM_SaveWAPBookmarkToSMS(&MultiSMS,&bookmark);
8315
8316       for (w=0;w<MultiSMS.number;w++)
8317         strcpy(MultiSMS.SMS[w].Destination,argv[1]);
8318
8319       GSM_SendMultiPartSMSOnConsole(&MultiSMS, 2,argc,argv,false,false,false);
8320       return 0;
8321
8322       break;
8323     default:
8324       fprintf(stderr,_("%s\n"),print_error(error));
8325   }
8326
8327   GSM->Terminate();    
8328
8329   return 0;
8330
8331 }
8332
8333 int savecalendarnote(int argc, char *argv[])
8334 {
8335   GSM_MultiSMSMessage MultiSMS;
8336   int w;
8337   GSM_CalendarNote CalendarNote;
8338   int number;
8339
8340   number=atoi(argv[1]);
8341   
8342   if (number<1) {
8343     fprintf(stdout, _("Number of calendar note must be 1 or higher\n"));
8344     return -1;
8345   }
8346   
8347   switch ( GSM_ReadVCalendarFile(argv[0], &CalendarNote, &number) ) {
8348     case GE_NONE:
8349       break;
8350     case GE_CANTOPENFILE:
8351       fprintf(stdout, _("Failed to open vCalendar file \"%s\"\n"),argv[0]);
8352       return -1;
8353     case GE_TOOSHORT:
8354       fprintf(stdout, _("Number of given calendar note is too high (max=%i)\n"),number);
8355       return(-1);
8356     default:
8357       fprintf(stdout, _("Failed to parse vCalendar file \"%s\"\n"),argv[0]);
8358       return -1;    
8359   }
8360
8361   fbusinit(NULL);
8362
8363   /* Put note into SMS structure */
8364   GSM_SaveCalendarNoteToSMS(&MultiSMS,&CalendarNote);
8365
8366   for (w=0;w<MultiSMS.number;w++)
8367     strcpy(MultiSMS.SMS[w].Destination,"Calendar");
8368
8369   GSM_SaveMultiPartSMSOnConsole(&MultiSMS, 2,argc,argv,false,false,false,false);
8370
8371   return 0;
8372 }
8373
8374 int sendcalendarnote(int argc, char *argv[])
8375 {
8376   GSM_MultiSMSMessage MultiSMS;
8377   int w;
8378   GSM_CalendarNote CalendarNote;
8379   int number;
8380
8381   number=atoi(argv[2]);
8382   
8383   if (number<1) {
8384     fprintf(stdout, _("Number of calendar note must be 1 or higher\n"));
8385     return -1;
8386   }
8387   
8388   switch ( GSM_ReadVCalendarFile(argv[1], &CalendarNote, &number) ) {
8389     case GE_NONE:
8390       break;
8391     case GE_CANTOPENFILE:
8392       fprintf(stdout, _("Failed to open vCalendar file \"%s\"\n"),argv[1]);
8393       return -1;
8394     case GE_TOOSHORT:
8395       fprintf(stdout, _("Number of given calendar note is too high (max=%i)\n"),number);
8396       return(-1);
8397     default:
8398       fprintf(stdout, _("Failed to parse vCalendar file \"%s\"\n"),argv[1]);
8399       return -1;    
8400   }
8401
8402   fbusinit(NULL);
8403
8404   /* Put note into SMS structure */
8405   GSM_SaveCalendarNoteToSMS(&MultiSMS,&CalendarNote);
8406
8407   for (w=0;w<MultiSMS.number;w++)
8408     strcpy(MultiSMS.SMS[w].Destination,argv[0]);
8409
8410   GSM_SendMultiPartSMSOnConsole(&MultiSMS, 3,argc,argv,false,false,false);
8411
8412   return 0;
8413 }
8414
8415 /* Example function for continuous receiving SMS */
8416 /* When phone receives SMS, it's read by mygnokii, ID number is created
8417    and SMS is saved to file. After it it's deleted
8418    Checking many errors is also done */   
8419 int receivesms(int argc, char *argv[])
8420 {
8421   char Dir[500];
8422
8423   GSM_SMSStatus SMSStatus = {0, 0};
8424   GSM_SMSMessage SMS;
8425   int read, location, number;
8426   unsigned char name[50],filename[400];
8427   char nowdate[12]="", nowtime[12]="";
8428   FILE *file;
8429   FILE *logfile;
8430   struct CFG_Header *cfg_info;
8431
8432   /* We do not want to monitor serial line forever - press Ctrl+C to stop the
8433      monitoring mode. */
8434
8435   signal(SIGINT, interrupted);
8436
8437   fprintf (stderr, _("Entering monitor mode (press CTRL+C to break)...\n"));
8438
8439   cfg_info=CFG_FindGnokiirc();
8440
8441   strcpy(Dir,"");
8442   if (cfg_info!=NULL) { 
8443     if (CFG_Get(cfg_info, "receivesms", "path")) {
8444       strcpy(Dir,CFG_Get(cfg_info, "receivesms", "path"));
8445     }
8446   }
8447
8448   fprintf(stderr,_("Path for sms files is \"%s\"\n"),Dir);
8449
8450   fprintf (stderr, _("Initialising GSM interface..."));
8451
8452   /* Initialise the code for the GSM interface. */     
8453   fbusinit(NULL);
8454
8455   fprintf (stderr, _("done\n"));
8456
8457   sleep(1);
8458
8459   /* Loop here indefinitely - allows you to see messages from GSM code in
8460      response to unknown messages etc. The loops ends after pressing the
8461      Ctrl+C. */
8462   while (!bshutdown) {
8463     if (GSM->GetSMSStatus(&SMSStatus) == GE_NONE) {
8464       if (SMSStatus.Number!=0) {
8465
8466         GetMachineDateTime(nowdate, nowtime );
8467         logfile = fopen("log", "a");
8468         if (logfile) {
8469           fprintf(logfile, _("%s %s SMS Messages: UnRead %d, Number %d\n"),
8470              nowdate, nowtime, SMSStatus.UnRead, SMSStatus.Number);
8471           fclose(logfile);
8472         }
8473
8474         read=0;
8475         location=1;
8476
8477         while (!bshutdown) {
8478
8479           SMS.Location=location;
8480           if (GSM->GetSMSMessage(&SMS)==GE_NONE) {
8481             if (SMS.folder==0 || SMS.folder==0x08) { //GST_7110_INBOX
8482
8483               GetMachineDateTime(nowdate, nowtime );
8484               logfile = fopen("log", "a");
8485               if (logfile) {
8486                 fprintf(logfile,_("%s %s SMS on location %i\n"),
8487                   nowdate,nowtime,SMS.MessageNumber);
8488                 fclose(logfile);
8489               }
8490
8491               number=             16*(SMS.MessageText[2] >> 4)+      (SMS.MessageText[2] & 0x0f);
8492               number=number+  256*16*(SMS.MessageText[1] >> 4)+  256*(SMS.MessageText[1] & 0x0f);
8493               number=number+65536*16*(SMS.MessageText[0] >> 4)+65536*(SMS.MessageText[0] & 0x0f);
8494
8495               sprintf( name, "%07i_%02d%02d%02d_%02d%02d%02d.sms", number,
8496                  SMS.Time.Year, SMS.Time.Month, SMS.Time.Day,
8497                  SMS.Time.Hour, SMS.Time.Minute, SMS.Time.Second);
8498
8499               strcpy(filename,Dir);
8500               strcat(filename,name);
8501
8502               logfile = fopen("log", "a");
8503               if (logfile) {
8504                 fprintf(logfile,_("%s %s Name is \"%s\"\n"),nowdate,nowtime,filename);
8505                 fclose(logfile);
8506               }
8507
8508               file = fopen(filename, "rb");
8509               if (!file) {
8510                 file = fopen(filename, "wb");
8511                 if (!file) {
8512                   GetMachineDateTime(nowdate, nowtime );
8513                   fprintf(stderr,_("%s %s ERROR: opening file \"%s\" failed !\n"),nowdate,nowtime,filename);
8514                   logfile = fopen("log", "a");
8515                   if (logfile) {
8516                     fprintf(logfile,_("%s %s ERROR: opening file \"%s\" failed !\n"),nowdate,nowtime,filename);
8517                     fclose(logfile);
8518                   }
8519                 } else {
8520                   fwrite(SMS.MessageText,1,SMS.Length,file);
8521                   fclose(file);
8522                 }
8523               } else {
8524                 fclose(file);
8525   
8526                 GetMachineDateTime(nowdate, nowtime );
8527                 fprintf(stderr,_("%s %s ERROR: file \"%s\" already exist !\n"),nowdate,nowtime,filename);
8528                 logfile = fopen("log", "a");
8529                 if (logfile) { 
8530                   fprintf(logfile,_("%s %s ERROR: file \"%s\" already exist !\n"),nowdate,nowtime,filename);
8531                   fclose(logfile);
8532                 }
8533               }
8534   
8535               SMS.Location=SMS.MessageNumber;
8536               if (GSM->DeleteSMSMessage(&SMS)!=GE_NONE) {
8537                 GetMachineDateTime(nowdate, nowtime );
8538                 fprintf(stderr,_("%s %s ERROR: Deleting SMS location %i failed !\n"),nowdate,nowtime,SMS.MessageNumber);
8539                 logfile = fopen("log", "a");
8540                 if (logfile) {
8541                   fprintf(logfile,_("%s %s ERROR: Deleting SMS location %i failed !\n"),nowdate,nowtime,SMS.MessageNumber);
8542                   fclose(logfile);
8543                 }
8544               }
8545             }
8546             read++;
8547           }
8548           location++;
8549           if (read==SMSStatus.Number) break;
8550         }
8551       }
8552     } else {
8553       GetMachineDateTime(nowdate, nowtime );
8554       fprintf(stderr,_("%s %s ERROR: Can't get SMS status !\n"),nowdate,nowtime);
8555       logfile = fopen("log", "a");
8556       if (logfile) {
8557         fprintf(logfile,_("%s %s ERROR: Can't get SMS status !\n"),nowdate,nowtime);
8558         fclose(logfile);
8559       }
8560     }
8561
8562     sleep(1);
8563   }
8564
8565   fprintf (stderr, _("Leaving monitor mode...\n"));
8566
8567   GSM->Terminate();
8568   
8569   return 0;
8570 }
8571
8572 int divert(int argc, char *argv[])
8573 {
8574         GSM_CallDivert cd;
8575         GSM_Error error;
8576
8577         memset(&cd, 0, sizeof(GSM_CallDivert));
8578
8579              if (!strcmp("register", argv[0])){cd.Operation = GSM_CDV_Register ;} 
8580         else if (!strcmp("enable"  , argv[0])){cd.Operation = GSM_CDV_Enable   ;} 
8581         else if (!strcmp("disable" , argv[0])){cd.Operation = GSM_CDV_Disable  ;}
8582         else if (!strcmp("erasure" , argv[0])){cd.Operation = GSM_CDV_Erasure  ;}
8583         else if (!strcmp("query"   , argv[0])){cd.Operation = GSM_CDV_Query    ;}
8584         else {
8585                 usage();
8586                 exit(-1);
8587         }
8588
8589              if (!strcmp("all"       , argv[1])) {cd.DType = GSM_CDV_AllTypes  ;}
8590         else if (!strcmp("busy"      , argv[1])) {cd.DType = GSM_CDV_Busy      ;}
8591         else if (!strcmp("noans"     , argv[1])) {cd.DType = GSM_CDV_NoAnswer  ;}
8592         else if (!strcmp("outofreach", argv[1])) {cd.DType = GSM_CDV_OutOfReach;}
8593         else {
8594                 usage();
8595                 exit(-1);
8596         }
8597
8598              if (!strcmp("all"  , argv[2])) {cd.CType = GSM_CDV_AllCalls  ;}
8599         else if (!strcmp("voice", argv[2])) {cd.CType = GSM_CDV_VoiceCalls;}
8600         else if (!strcmp("fax"  , argv[2])) {cd.CType = GSM_CDV_FaxCalls  ;}
8601         else if (!strcmp("data" , argv[2])) {cd.CType = GSM_CDV_DataCalls ;}
8602         else {
8603                 usage();
8604                 exit(-1);
8605         }
8606
8607         if (argc>3) strcpy(cd.Number, argv[3]);
8608
8609         if (argc>4) cd.Timeout = atoi(argv[4]);
8610
8611         /* Initialise the code for the GSM interface. */     
8612         fbusinit(NULL);
8613
8614         error=GSM->CallDivert(&cd);
8615
8616         if (error == GE_NONE) {
8617           switch (cd.Operation)
8618           {
8619             case GSM_CDV_Query:
8620               fprintf(stdout, _("Divert type: "));
8621               switch (cd.DType) {
8622                 case GSM_CDV_Busy      :fprintf(stdout, _("when busy"));break;
8623                 case GSM_CDV_NoAnswer  :fprintf(stdout, _("when not answered"));break;
8624                 case GSM_CDV_OutOfReach:fprintf(stdout, _("when phone off or no coverage"));break;
8625                 case GSM_CDV_AllTypes  :fprintf(stdout, _("all call diverts"));break; //?
8626                 default:                fprintf(stdout, _("unknown %i"),cd.DType);break;
8627               }
8628
8629               fprintf(stdout, _("\nCalls type : "));
8630               switch (cd.CType) {
8631                 case GSM_CDV_VoiceCalls: fprintf(stdout, _("voice"));break;
8632                 case GSM_CDV_FaxCalls  : fprintf(stdout, _("fax"));break;
8633                 case GSM_CDV_DataCalls : fprintf(stdout, _("data"));break;
8634                 case GSM_CDV_AllCalls  : fprintf(stdout, _("voice, fax & data"));break;
8635                 default:   fprintf(stdout, _("unknown %i"),cd.CType);break;
8636               }
8637               fprintf(stdout, _("\n"));
8638
8639               if (cd.Enabled) {
8640                 fprintf(stdout, _("Status     : active\n"));
8641                 fprintf(stdout, _("Timeout    : %i seconds\n"),cd.Timeout);
8642                 fprintf(stdout, _("Number     : %s\n"),cd.Number);
8643               } else {
8644                 fprintf(stdout, _("Status     : deactivated\n"));
8645               }
8646
8647               break;
8648             default:
8649               fprintf(stdout,_("Divert done\n"));
8650           }
8651         } else 
8652           fprintf(stderr,_("%s\n"),print_error(error));
8653
8654         GSM->Terminate();
8655
8656         return 0;
8657 }
8658
8659 int savephonebookentry(int argc, char *argv[])
8660 {
8661   GSM_MultiSMSMessage MultiSMS;
8662   GSM_PhonebookEntry entry;
8663   GSM_Error error;
8664   int w;
8665
8666   fbusinit(NULL);
8667
8668   /* Handle command line args that set type, start and end locations. */
8669   if (!GetMemoryTypeID(argv[0], &entry.MemoryType))
8670   {
8671     fprintf(stderr, _("Unknown memory type %s!\n"), argv[0]);
8672     return (-1);
8673   }
8674
8675   entry.Location=atoi(argv[1]);
8676
8677   fbusinit(NULL);
8678
8679   error=GSM->GetMemoryLocation(&entry);
8680
8681   switch (error) {
8682     case GE_NONE:
8683
8684       /* Put entry into SMS structure */
8685       if (GetModelFeature(FN_PHONEBOOK)==F_PBK71) {
8686         GSM_SavePhonebookEntryToSMS(&MultiSMS,&entry,21);
8687       } else {
8688         GSM_SavePhonebookEntryToSMS(&MultiSMS,&entry,10);
8689       }
8690
8691       for (w=0;w<MultiSMS.number;w++)
8692         strcpy(MultiSMS.SMS[w].Destination,"Phonebook");
8693
8694       GSM_SaveMultiPartSMSOnConsole(&MultiSMS, 2,argc,argv,false,false,false,false);
8695       break;
8696
8697     default:
8698       fprintf(stdout,_("Error\n"));break;
8699   }
8700
8701   return 0;
8702 }
8703
8704 int sendphonebookentry(int argc, char *argv[])
8705 {
8706   GSM_MultiSMSMessage MultiSMS;
8707   GSM_PhonebookEntry entry;
8708   GSM_Error error;
8709   int w;
8710
8711   fbusinit(NULL);
8712
8713   /* Handle command line args that set type, start and end locations. */
8714   if (!GetMemoryTypeID(argv[1], &entry.MemoryType))
8715   {
8716     fprintf(stderr, _("Unknown memory type %s!\n"), argv[1]);
8717     return (-1);
8718   }
8719
8720   entry.Location=atoi(argv[2]);
8721
8722   fbusinit(NULL);
8723
8724   error=GSM->GetMemoryLocation(&entry);
8725
8726   switch (error) {
8727     case GE_NONE:
8728
8729       /* Put entry into SMS structure */
8730       if (GetModelFeature(FN_PHONEBOOK)==F_PBK71) {
8731         GSM_SavePhonebookEntryToSMS(&MultiSMS,&entry,21);
8732       } else {
8733         GSM_SavePhonebookEntryToSMS(&MultiSMS,&entry,10);
8734       }
8735
8736       for (w=0;w<MultiSMS.number;w++)
8737         strcpy(MultiSMS.SMS[w].Destination,argv[0]);
8738
8739       GSM_SendMultiPartSMSOnConsole(&MultiSMS, 3,argc,argv,false,false,false);
8740
8741       break;
8742
8743     default:
8744       fprintf(stdout,_("Error\n"));break;
8745   }
8746
8747   return 0;
8748 }