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