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