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