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