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