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