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