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