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