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