Implemented renicing (-20) in gnokiid mode
[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 #define NICE_LEVEL (-20)
4123
4124 static void gnokiid_SIGCHLD(int signo)
4125 {
4126         fprintf (stderr, _("Child process exited, aborting...\n"));
4127         exit(2);
4128 }
4129
4130 static int gnokiid(int argc, char *argv[])
4131 {
4132         bool    DebugMode;  /* When true, run in debug mode */
4133         char    *Model;   /* Model from .gnokiirc file. */
4134         char    *Port;    /* Port from .gnokiirc file */
4135         char    *Initlength;  /* Init length from .gnokiirc file */
4136         char    *Connection;  /* Connection type from .gnokiirc file */
4137         char    *BinDir;  /* Directory of the mgnokiidev command */
4138
4139         /* evaluate for presence of "--debug" argument in parameter */
4140         DebugMode = false;
4141         if(argc>0)
4142         {
4143                 if( !strcmp(argv[0],"--debug" ))
4144                 {
4145                         DebugMode = true;
4146                         argv++;
4147                         argc--;
4148                 }
4149         }
4150
4151 #ifdef DEBUG
4152   fprintf (stderr, _("Initializing gnokiid mode...\n"));
4153 #endif
4154
4155         if (CFG_ReadConfig(&Model, &Port, &Initlength, &Connection, &BinDir, true) < 0)
4156                 return(-1);
4157
4158   if (VM_Initialise(Model, Port, Initlength, GCT_FBUS, BinDir, DebugMode, true, ""/*SynchronizeTime*/) == false)
4159                 return (-1);
4160
4161         if (argc>0) {
4162 #ifdef DEBUG
4163                 fprintf (stderr, _("Spawning gnokiid startup child process \"%s\"...\n"), *argv);
4164 #endif
4165                 signal(SIGCHLD,gnokiid_SIGCHLD);
4166                 errno=0;
4167                 switch (vfork()) {
4168                         case -1: /* vfork() failure */
4169                                 fprintf (stderr, _("vfork() failed! (%s)\n"),strerror(errno));
4170                                 return -1;
4171                         case 0: /* child */
4172                                 execv(*argv,argv);
4173                                 fprintf (stderr, _("Spawn of child process failed! (%s)\n"),strerror(errno));
4174                                 _exit(9);
4175                                 break;
4176                         default: /* parent */
4177                                 /* PASSTHRU */
4178                                 break;
4179                         }
4180                 }
4181
4182 #ifdef DEBUG
4183   fprintf (stderr, _("Entering gnokiid virtual modem main loop...\n"));
4184 #endif
4185         if (nice(NICE_LEVEL))
4186                 fprintf (stderr, _("WARNING: nice level change failed (by %d)\n"),NICE_LEVEL);
4187
4188         VM_ThreadLoop();
4189
4190         VM_Terminate();
4191
4192   return 0;
4193 }
4194
4195 #endif /* UCLINUX */
4196
4197 #ifndef UCLINUX
4198
4199 /* Shows texts from phone's display */
4200
4201 int displayoutput()
4202 {
4203
4204   GSM_Error error;
4205   
4206   fbusinit(NULL);
4207
4208   error=GSM->EnableDisplayOutput();
4209
4210   if (error == GE_NONE)
4211   {
4212
4213     /* We do not want to see texts forever - press Ctrl+C to stop. */
4214
4215     signal(SIGINT, interrupted);    
4216
4217     fprintf (stderr, _("Entering display monitoring mode...\n"));
4218
4219     /* Loop here indefinitely - allows you to read texts from phone's
4220        display. The loops ends after pressing the Ctrl+C. */
4221
4222     while (!bshutdown)
4223       sleep(1);
4224
4225     fprintf (stderr, _("Leaving display monitor mode...\n"));
4226
4227     error=GSM->DisableDisplayOutput();
4228     if (error!=GE_NONE)
4229       fprintf (stderr, _("Error!\n"));
4230   } else
4231       fprintf (stderr, _("Error!\n"));
4232
4233   GSM->Terminate();
4234
4235   return 0;
4236 }
4237
4238 /* Displays names of available ringtones */
4239 int allringtones()
4240 {
4241   char model[64], rev[64];
4242   int i;
4243
4244   fbusinit(NULL);
4245
4246   while (GSM->GetRevision(rev) != GE_NONE)
4247     sleep(1);
4248
4249   while (GSM->GetModel(model)  != GE_NONE)
4250     sleep(1);
4251
4252   strncpy(rev,rev+2,5);
4253   rev[5]=0;
4254   PrepareRingingTones(model,rev);
4255   
4256   for (i=1;i<=NumberOfRingtones();i++)
4257   {
4258     fprintf(stdout,_("%i. %s\n"),i,RingingToneName(0,i));
4259   }
4260   
4261   GSM->Terminate();
4262
4263   return 0;
4264
4265 }
4266
4267 /* Reads profile from phone and displays its' settings */
4268
4269 int getprofile(int argc, char *argv[])
4270 {
4271
4272   int max_profiles;
4273   int start, stop, i;
4274   GSM_Profile profile;
4275   GSM_Error error;
4276   
4277   /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */
4278   char model[64], rev[64];
4279
4280   /* Initialise the code for the GSM interface. */     
4281
4282   fbusinit(NULL);
4283
4284   profile.Number = 0;
4285   error=GSM->GetProfile(&profile);
4286
4287   if (error == GE_NONE)
4288   {
4289   
4290     while (GSM->GetModel(model)  != GE_NONE) sleep(1);
4291
4292     while (GSM->GetRevision(rev) != GE_NONE) sleep(1);
4293
4294     strncpy(rev,rev+2,5);
4295     rev[5]=0;
4296     PrepareRingingTones(model,rev);
4297
4298     switch(GetModelFeature (FN_PROFILES)) {
4299       case F_PROF33:max_profiles=6;break;
4300       case F_PROF51:max_profiles=3;break;
4301       default      :max_profiles=7;break;
4302     }
4303
4304     if (argc>0)
4305     {
4306       profile.Number=atoi(argv[0])-1;
4307       start=profile.Number;
4308       stop=start+1;
4309
4310       if (profile.Number < 0)
4311       {
4312          fprintf(stderr, _("Profile number must be value from 1 to %d!\n"), max_profiles);
4313          GSM->Terminate();
4314          return -1;
4315       }
4316
4317       if (profile.Number >= max_profiles)
4318       {
4319          fprintf(stderr, _("This phone supports only %d profiles!\n"), max_profiles);
4320          GSM->Terminate();
4321          return -1;
4322       }
4323     } else {
4324       start=0;
4325       stop=max_profiles;
4326     }
4327
4328     i=start;
4329     while (i<stop)
4330     {
4331       profile.Number=i;
4332
4333       if (profile.Number!=0) GSM->GetProfile(&profile);
4334
4335       printf("%d. \"%s\"", (profile.Number+1), profile.Name);
4336       if (profile.DefaultName==-1) printf(" (name defined)");
4337       printf("\n");
4338
4339 #ifdef DEBUG
4340       printf("Incoming call alert: %d\n", profile.CallAlert);
4341       printf("Ringtone ID: %d\n", profile.Ringtone);
4342       printf("Ringing volume: %d\n", profile.Volume);
4343       printf("Message alert tone: %d\n", profile.MessageTone);
4344       printf("Keypad tones: %d\n", profile.KeypadTone);
4345       printf("Warning and game tones: %d\n", profile.WarningTone);
4346       printf("Lights: %d\n", profile.Lights);
4347       printf("Vibration: %d\n", profile.Vibration);
4348       printf("Caller groups: 0x%02x\n", profile.CallerGroups);
4349       printf("Automatic answer: %d\n", profile.AutomaticAnswer);
4350       printf("Screen saver: %d\n", profile.ScreenSaver);
4351       printf("\n");
4352 #endif
4353       
4354       printf("Incoming call alert: %s\n", GetProfileCallAlertString(profile.CallAlert));
4355
4356       /* For different phones different ringtones names */
4357       if (strcmp(RingingToneName(profile.Ringtone,0),""))
4358         printf(_("Ringing tone: %s (number %d in phone menu)\n"), 
4359           RingingToneName(profile.Ringtone,0), RingingToneMenu(profile.Ringtone));
4360       else
4361         printf(_("Ringtone number: %d\n"), profile.Ringtone);
4362
4363       printf(_("Ringing volume: %s\n"), GetProfileVolumeString(profile.Volume));
4364
4365       printf(_("Message alert tone: %s\n"), GetProfileMessageToneString(profile.MessageTone));
4366
4367       printf(_("Keypad tones: %s\n"), GetProfileKeypadToneString(profile.KeypadTone));
4368
4369       printf(_("Warning and game tones: %s\n"), GetProfileWarningToneString(profile.WarningTone));
4370
4371       if (GetModelFeature (FN_SCREENSAVER)!=0)
4372         printf(_("Screen saver: %s\n"), GetProfileOnOffString(profile.ScreenSaver));
4373       
4374       printf(_("Vibration: %s\n"), GetProfileVibrationString(profile.Vibration));
4375
4376       /* It has been nice to add here reading caller group name. ;^) */
4377       if (GetModelFeature (FN_CALENDAR)==F_CAL71) 
4378         printf(_("Caller groups: %s\n"), 
4379                               GetProfileCallerGroups(profile.CallerGroups) );
4380
4381       /* FIXME: need make investigation for 3310 for these features. For now unknown */
4382       if (GetModelFeature (FN_PROFILES)!=F_PROF33) {
4383         /* FIXME: Light settings is only used for Car */
4384         if (profile.Number==(max_profiles-2)) printf(_("Lights: %s\n"), profile.Lights ? _("On") : _("Automatic"));
4385
4386         /* FIXME: Automatic answer is only used for Car and Headset. */
4387         if (profile.Number>=(max_profiles-2)) printf(_("Automatic answer: %s\n"), GetProfileOnOffString(profile.AutomaticAnswer));
4388       }
4389
4390       printf("\n");
4391
4392       i++;
4393     }
4394   } else {
4395     if (error == GE_NOTIMPLEMENTED) {
4396        fprintf(stderr, _("Function not implemented in %s model!\n"), model);
4397        GSM->Terminate();
4398        return -1;
4399     } else
4400     {
4401       fprintf(stderr, _("Unspecified error\n"));
4402       GSM->Terminate();
4403       return -1;
4404     }
4405   }
4406
4407   GSM->Terminate();
4408
4409   return 0;
4410
4411 }
4412
4413 /* Sets profile feature */
4414
4415 int setprofile(int argc, char *argv[])
4416 {
4417
4418 /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */
4419   char model[64], rev[64];
4420
4421   int max_profiles;
4422   GSM_Profile profile;
4423   GSM_Profile profile2, profile3;
4424   GSM_Error error;
4425   bool correct_arg1;
4426   bool correct_arg2;
4427   
4428 /* Initialise the code for the GSM interface. */     
4429
4430   fbusinit(NULL);
4431   
4432   profile.Number = 0;
4433
4434   error = GSM->GetProfile(&profile);
4435   
4436   if (error == GE_NONE)
4437   {
4438  
4439     while (GSM->GetModel(model)  != GE_NONE) sleep(1);
4440       
4441     while (GSM->GetRevision(rev) != GE_NONE) sleep(1);
4442
4443     strncpy(rev,rev+2,5);
4444     rev[5]=0;
4445     PrepareRingingTones(model,rev);
4446
4447     switch(GetModelFeature (FN_PROFILES)) {
4448       case F_PROF33:max_profiles=6;break;
4449       case F_PROF51:max_profiles=3;break;
4450       default      :max_profiles=7;break;
4451     }
4452
4453     profile.Number=atoi (argv[0]);
4454     profile.Number=profile.Number-1;
4455     
4456     if (profile.Number < 0)
4457     {
4458       fprintf(stderr, _("Profile number must be value from 1 to %i!\n"), max_profiles);
4459       GSM->Terminate();
4460       return -1;
4461     }
4462     
4463     if (profile.Number >= max_profiles)
4464     {
4465       fprintf(stderr, _("This phone supports only %i profiles!\n"), max_profiles);
4466       GSM->Terminate();
4467       return -1;
4468     }
4469       
4470     if (profile.Number!=0) GSM->GetProfile(&profile);
4471         
4472     correct_arg1=false;
4473     correct_arg2=false;
4474
4475     if (strcmp(argv[1], "callalert")==0)
4476     {
4477        if (strcmp(argv[2], "ringing")==0) {profile.CallAlert=PROFILE_CALLALERT_RINGING;correct_arg2=true;}
4478        if (strcmp(argv[2], "ascending")==0) {profile.CallAlert=PROFILE_CALLALERT_ASCENDING;correct_arg2=true;}
4479        if (strcmp(argv[2], "ringonce")==0) {profile.CallAlert=PROFILE_CALLALERT_RINGONCE;correct_arg2=true;}
4480        if (strcmp(argv[2], "beeponce")==0) {profile.CallAlert=PROFILE_CALLALERT_BEEPONCE;correct_arg2=true;}
4481        if (strcmp(argv[2], "groups")==0)
4482        {
4483          profile.CallAlert=PROFILE_CALLALERT_CALLERGROUPS;
4484          correct_arg2=true;
4485          /*Ignored by N5110*/
4486          /*FIX ME: it's ignored by N5130 and 3210 too*/
4487          if (max_profiles==3) fprintf(stdout, _("Warning: value \"groups\" for profile feature \"callalert\" will be ignored in this phone model !\n"));
4488        }
4489        if (strcmp(argv[2], "off")==0 || strcmp(argv[2], "0")==0) {profile.CallAlert=PROFILE_CALLALERT_OFF;correct_arg2=true;}
4490        if (!correct_arg2)
4491        {
4492          fprintf(stderr, _("Correct parameters for profile feature \"callalert\" are ringing|ascending|ringonce|beeponce|groups|off|0 !\n"));
4493          GSM->Terminate();
4494          return -1;
4495         }
4496         correct_arg1=true;
4497     }
4498     if (strcmp(argv[1], "volume")==0)
4499     {
4500        if (strcmp(argv[2], "1")==0) {profile.Volume=PROFILE_VOLUME_LEVEL1;correct_arg2=true;}
4501        if (strcmp(argv[2], "2")==0) {profile.Volume=PROFILE_VOLUME_LEVEL2;correct_arg2=true;}
4502        if (strcmp(argv[2], "3")==0) {profile.Volume=PROFILE_VOLUME_LEVEL3;correct_arg2=true;}
4503        if (strcmp(argv[2], "4")==0) {profile.Volume=PROFILE_VOLUME_LEVEL4;correct_arg2=true;}
4504        if (strcmp(argv[2], "5")==0) {profile.Volume=PROFILE_VOLUME_LEVEL5;correct_arg2=true;}
4505        if (!correct_arg2)
4506        {
4507          fprintf(stderr, _("Correct parameters for profile feature \"volume\" are 0|1|2|3|4|5 !\n"));
4508          GSM->Terminate();
4509          return -1;
4510         }
4511         correct_arg1=true;
4512     }
4513     if (strcmp(argv[1], "keypad")==0 || strcmp(argv[1], "keypadtone")==0)
4514     {
4515        if (strcmp(argv[2], "0")==0 || strcmp(argv[2], "off")==0) {profile.KeypadTone=PROFILE_KEYPAD_OFF;correct_arg2=true;}
4516        if (strcmp(argv[2], "1")==0) {profile.KeypadTone=PROFILE_KEYPAD_LEVEL1;correct_arg2=true;}
4517        if (strcmp(argv[2], "2")==0) {profile.KeypadTone=PROFILE_KEYPAD_LEVEL2;correct_arg2=true;}
4518        if (strcmp(argv[2], "3")==0) {profile.KeypadTone=PROFILE_KEYPAD_LEVEL3;correct_arg2=true;}
4519        if (!correct_arg2)
4520        {
4521          fprintf(stderr, _("Correct parameters for profile feature \"keypad|keypadtone\" are off|0|1|2|3 !\n"));
4522          GSM->Terminate();
4523          return -1;
4524         }
4525         correct_arg1=true;
4526     }
4527     if (strcmp(argv[1], "messagetone")==0 || strcmp(argv[1], "smstone")==0 || strcmp(argv[1], "sms")==0 || strcmp(argv[1], "message")==0)
4528     {
4529        if (strcmp(argv[2], "0")==0 || strcmp(argv[2], "off")==0) {profile.MessageTone=PROFILE_MESSAGE_NOTONE;correct_arg2=true;}
4530        if (strcmp(argv[2], "standard")==0) {profile.MessageTone=PROFILE_MESSAGE_STANDARD;correct_arg2=true;}
4531        if (strcmp(argv[2], "special")==0) {profile.MessageTone=PROFILE_MESSAGE_SPECIAL;correct_arg2=true;}
4532        if (strcmp(argv[2], "beeponce")==0 || strcmp(argv[2], "once")==0) {profile.MessageTone=PROFILE_MESSAGE_BEEPONCE;correct_arg2=true;}
4533        if (strcmp(argv[2], "ascending")==0) {profile.MessageTone=PROFILE_MESSAGE_ASCENDING;correct_arg2=true;}
4534        if (!correct_arg2)
4535        {
4536          fprintf(stderr, _("Correct parameters for profile feature \"messagetone|smstone|message|sms\" are 0|off|standard|special|beeponce|once|ascending !\n"));
4537          GSM->Terminate();
4538          return -1;
4539         }
4540         correct_arg1=true;
4541     }
4542     if (strcmp(argv[1], "warningtone")==0 || strcmp(argv[1], "warning")==0)
4543     {
4544        if (strcmp(argv[2], "0")==0 || strcmp(argv[2], "off")==0) {profile.WarningTone=PROFILE_WARNING_OFF;correct_arg2=true;}
4545        if (strcmp(argv[2], "1")==0 || strcmp(argv[2], "on")==0) {profile.WarningTone=PROFILE_WARNING_ON;correct_arg2=true;}
4546        if (!correct_arg2)
4547        {
4548          fprintf(stderr, _("Correct parameters for profile feature \"warningtone|warning\" are 0|off|1|on !\n"));
4549          GSM->Terminate();
4550          return -1;
4551         }
4552         correct_arg1=true;
4553     }
4554     if (strcmp(argv[1], "vibra")==0 || strcmp(argv[1], "vibration")==0)
4555     {
4556        if (strcmp(argv[2], "0")==0 || strcmp(argv[2], "off")==0) {profile.Vibration=PROFILE_VIBRATION_OFF;correct_arg2=true;}
4557        if (strcmp(argv[2], "1")==0 || strcmp(argv[2], "on")==0) {profile.Vibration=PROFILE_VIBRATION_ON;correct_arg2=true;}
4558        if (!correct_arg2)
4559        {
4560          fprintf(stderr, _("Correct parameters for profile feature \"vibration|vibra\" are 0|off|1|on !\n"));
4561          GSM->Terminate();
4562          return -1;
4563         }
4564         correct_arg1=true;
4565     }
4566     if (strcmp(argv[1], "lights")==0)
4567     {
4568        if (strcmp(argv[2], "0")==0 || strcmp(argv[2], "off")==0) {profile.Lights=-1;correct_arg2=true;}
4569        if (strcmp(argv[2], "1")==0 || strcmp(argv[2], "on")==0) {profile.Lights=0;correct_arg2=true;}
4570        if (!correct_arg2)
4571        {
4572          fprintf(stderr, _("Correct parameters for profile feature \"lights\" are 0|off|1|on !\n"));
4573          GSM->Terminate();
4574          return -1;
4575        }
4576        if (profile.Number!=(max_profiles-2))
4577        {
4578          profile2.Number=max_profiles-2;
4579          if (GSM->GetProfile(&profile2)==GE_NONE)
4580          {
4581            fprintf(stdout, _("Warning: \"Lights\" feature is ignored in this profile (only setting it for \"%s\" profile get some results) !\n"), profile2.Name);
4582          }
4583        }
4584        correct_arg1=true;
4585     }
4586     if (strcmp(argv[1], "answer")==0)
4587     {
4588        if (strcmp(argv[2], "0")==0 || strcmp(argv[2], "off")==0) {profile.AutomaticAnswer=-1;correct_arg2=true;}
4589        if (strcmp(argv[2], "1")==0 || strcmp(argv[2], "on")==0) {profile.AutomaticAnswer=0;correct_arg2=true;}
4590        if (!correct_arg2)
4591        {
4592          fprintf(stderr, _("Correct parameters for profile feature \"answer\" are 0|off|1|on !\n"));
4593          GSM->Terminate();
4594          return -1;
4595        }
4596        if (profile.Number<(max_profiles-2))
4597        {
4598          profile2.Number=max_profiles-2;
4599          if (GSM->GetProfile(&profile2)==GE_NONE)
4600          {
4601            profile3.Number=max_profiles-1;
4602            if (GSM->GetProfile(&profile3)==GE_NONE)
4603            {
4604              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);
4605            }
4606          }
4607        }
4608        correct_arg1=true;
4609     }
4610     if (strcmp(argv[1], "name")==0)
4611     {
4612        strcpy(profile.Name,argv[2]);
4613        /*Ignored by N5110*/
4614        /*FIX ME: it's ignored by N5130 and 3210 too*/
4615        if (max_profiles==3) fprintf(stdout, _("Warning: this phone model doesn't allow to change profile name !\n"));
4616        correct_arg1=true;
4617     }
4618     if (strcmp(argv[1], "ringtone")==0)
4619     {
4620       profile.Ringtone=atoi(argv[2]);
4621       if (profile.Ringtone<1)
4622       {
4623         /*With value 0 results are interesting in N5110, but can't be used for anything*/
4624         fprintf(stderr, _("Ringtone number must be higher than 0 !\n"));
4625         GSM->Terminate();
4626         return -1; 
4627       } else
4628       {
4629         if (profile.Ringtone>NumberOfRingtones())
4630         {
4631           fprintf(stderr, _("Ringtone number too high (max %i) !\n"),NumberOfRingtones());
4632           GSM->Terminate();
4633           return -1;
4634         }  
4635         profile.Ringtone=RingingToneCode(profile.Ringtone);
4636         if (profile.Ringtone==0)
4637         {
4638           fprintf(stderr, _("Warning: we don't know ringtones codes for this model ! Can you contact with gnokii authors to add it into source ?\n"));
4639           GSM->Terminate();
4640           return -1;
4641         }
4642         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"));
4643       }
4644       correct_arg1=true;
4645     }
4646     if (strcmp(argv[1], "groups")==0)
4647     {
4648        /*Ignored by N5110*/
4649        /*FIX ME: it's ignored by N5130 and 3210 too*/
4650        if (max_profiles==3) fprintf(stdout, _("Warning: this phone model doesn't allow to change caller group name !\n"));
4651        profile.CallerGroups=atoi(argv[2]);
4652        correct_arg1=true;
4653     }
4654
4655     if (!correct_arg1)
4656     {
4657       fprintf(stderr, _("Correct profile feature names are callalert|volume|keypad|keypadtone|messagetone|smstone|message|sms|warningtone|warning|vibra|vibration|lights|answer|name|groups !\n"));
4658       GSM->Terminate();
4659       return -1;
4660     }
4661     
4662     GSM->SetProfile(&profile);
4663     
4664   } else {
4665     if (error == GE_NOTIMPLEMENTED) {
4666        fprintf(stderr, _("Function not implemented in %s model!\n"), model);
4667        GSM->Terminate();
4668        return -1;
4669     } else
4670     {
4671       fprintf(stderr, _("Unspecified error\n"));
4672       GSM->Terminate();
4673       return -1;
4674     }
4675   }
4676  
4677   GSM->Terminate();
4678
4679   return 0;
4680
4681 }
4682
4683 #endif /* UCLINUX */
4684
4685 /* Get requested range of memory storage entries and output to stdout in
4686    easy-to-parse format */
4687
4688 static int getmemory(int argc, char *argv[])
4689 {
4690
4691   GSM_PhonebookEntry entry;
4692   int count;
4693   register int i;
4694   GSM_Error error;
4695   GSM_Bitmap bitmap;
4696   char memory_type_string[20];
4697   int start_entry;
4698   int end_entry;
4699   int i_used = 0, n_used=0;
4700   int do_all;
4701   char *output_opt = NULL;
4702   bool wasdate=false;
4703   char az_group_name[5][MAX_BITMAP_TEXT_LENGTH];
4704   bool formatdone=false;
4705   char buf[64];
4706
4707   /* group names init */
4708   for(i=0;i<5;i++) az_group_name[i][0]='\0';
4709
4710   /* Handle command line args that set type, start and end locations. */
4711   if (!GetMemoryTypeID(argv[0], &entry.MemoryType))
4712   {
4713     fprintf(stderr, _("Unknown memory type %s!\n"), argv[0]);
4714     return (-1);
4715   }
4716
4717   GetMemoryTypeString(memory_type_string, &entry.MemoryType);
4718
4719   if (argv[argc-1][0] == '-')
4720     output_opt = argv[--argc];
4721
4722   /* Do generic initialisation routine */
4723
4724   fbusinit(NULL);
4725
4726   while ((error = GSM->GetModel(buf)) != GE_NONE && i++ < 15)
4727     sleep(1);
4728
4729   if (argc > 1) {
4730     do_all = 0;
4731     start_entry = atoi (argv[1]);
4732     end_entry = argc > 2 ? atoi( argv[2]) : start_entry;
4733   } else {
4734     GSM_MemoryStatus stats = {entry.MemoryType, 0, 0};
4735
4736     do_all = 1;
4737     start_entry = 1;
4738     if (GSM->GetMemoryStatus( &stats) != GE_NONE) {
4739       fprintf( stderr, _("Error reading memory status.\n"));
4740       GSM->Terminate();
4741       return -1;
4742     }
4743     n_used = stats.Used;
4744     end_entry = stats.Used + stats.Free;
4745   }
4746     
4747
4748   /* Now retrieve the requested entries. */
4749
4750   for (count = start_entry;
4751        count <= end_entry && (!do_all || i_used < n_used);
4752        count++) {
4753
4754     entry.Location=count;
4755     
4756     error=GSM->GetMemoryLocation(&entry);
4757
4758     switch (error) {
4759     case GE_NONE:
4760       if (entry.SubEntriesCount || strcmp( entry.Number, ""))
4761         i_used++;
4762       else if (do_all)
4763         break;
4764 #ifndef UCLINUX
4765       if (output_opt && !strcmp( output_opt,"-v30")) {
4766         semicolon_pipe_substitution( &entry, 0 );
4767         fprintf(stdout,_("%s"),GSM_GetVCARD(&entry,30));
4768         formatdone=true;
4769       } 
4770       if (output_opt && !strcmp(output_opt,"-v21")) {
4771         semicolon_pipe_substitution( &entry, 0 );
4772         fprintf(stdout,_("%s"),GSM_GetVCARD(&entry,21));
4773         formatdone=true;
4774       } 
4775       if (output_opt && !strcmp(output_opt,"-v")) {
4776         semicolon_pipe_substitution( &entry, 0 );
4777         fprintf(stdout,_("%s"),GSM_GetVCARD(&entry,10));
4778         formatdone=true;
4779       } 
4780 #endif /* UCLINUX */
4781       if (output_opt && !strcmp(output_opt,"-short")) {
4782         semicolon_pipe_substitution( &entry, 0 );
4783         fprintf(stdout, "%s;%s;%s;%d;%d;", entry.Name, entry.Number, memory_type_string, entry.Location, entry.Group);
4784         for( i = 0; i <  entry.SubEntriesCount; i++ )
4785         {
4786           if( entry.SubEntries[i].EntryType == GSM_Date )
4787             fprintf(stdout,_("%u;%u;%u;%02u.%02u.%04u;%02u:%02u:%02u;"),
4788                 entry.SubEntries[i].EntryType,
4789                 entry.SubEntries[i].NumberType,
4790                 entry.SubEntries[i].BlockNumber,
4791                 entry.SubEntries[i].data.Date.Day,
4792                 entry.SubEntries[i].data.Date.Month,
4793                 entry.SubEntries[i].data.Date.Year,
4794                 entry.SubEntries[i].data.Date.Hour,
4795                 entry.SubEntries[i].data.Date.Minute,
4796                 entry.SubEntries[i].data.Date.Second );
4797           else
4798             fprintf(stdout,_("%u;%u;%u;%s;"),
4799                 entry.SubEntries[i].EntryType,
4800                 entry.SubEntries[i].NumberType,
4801                 entry.SubEntries[i].BlockNumber,
4802                 entry.SubEntries[i].data.Number );
4803         }
4804         fprintf(stdout,_("\n"));
4805         formatdone=true;
4806       }
4807       if (!formatdone) {
4808           char z_gtype[12];
4809           wasdate=false;
4810           fprintf(stdout, "Memory %s, location %d\n",memory_type_string, entry.Location);
4811
4812           // check if some info in subentries 
4813           for( i = 0; i <  entry.SubEntriesCount; i++ )
4814                   if( entry.SubEntries[i].EntryType != GSM_Date &&
4815                           strcmp(entry.SubEntries[i].data.Number,"") )
4816                       break;
4817
4818           if (strcmp(entry.Number,"") || i <  entry.SubEntriesCount) {
4819             if (strcmp(entry.Name,"")) fprintf(stdout,_("   Name: %s\n"),entry.Name);
4820             if (strcmp(entry.Number,"")) fprintf(stdout,_("   Number: %s\n"),entry.Number);
4821             bitmap.type=GSM_CallerLogo;
4822             bitmap.number=entry.Group;
4823             strcpy(z_gtype,"unknown");
4824             if (entry.Group==5) strcpy(z_gtype,"No group");
4825             if (entry.Group<5 && entry.Group>=0) {
4826               if (!strcmp(az_group_name[entry.Group],"")) {
4827                 if (GetModelFeature (FN_CALLERGROUPS)!=0) {
4828                   if (GSM->GetBitmap(&bitmap)==GE_NONE)
4829                     strcpy( az_group_name[entry.Group], bitmap.text );
4830                 }
4831                 if ((!strcmp(az_group_name[entry.Group],""))) {
4832                   switch(entry.Group) {
4833                     case 0:strcpy(az_group_name[entry.Group],"Family");break;
4834                     case 1:strcpy(az_group_name[entry.Group],"VIP");break;
4835                     case 2:strcpy(az_group_name[entry.Group],"Friends");break;
4836                     case 3:strcpy(az_group_name[entry.Group],"Colleagues");break;
4837                     case 4:strcpy(az_group_name[entry.Group],"Other");break;
4838                     default:break;
4839                   }
4840                 }
4841               }
4842               strcpy(z_gtype,az_group_name[entry.Group]);
4843             }
4844             fprintf(stdout,_("   Group: %d (%s)\n"),entry.Group+1,z_gtype);
4845             for( i = 0; i <  entry.SubEntriesCount; i++ )
4846             {
4847               if( entry.SubEntries[i].EntryType == GSM_Date ) {
4848                  fprintf(stdout, "   Date and time: %s %02u.%02u.%04u %02u:%02u:%02u\n", 
4849                     DayOfWeek(entry.SubEntries[i].data.Date.Year,
4850                         entry.SubEntries[i].data.Date.Month,
4851                         entry.SubEntries[i].data.Date.Day),
4852                     entry.SubEntries[i].data.Date.Day,
4853                     entry.SubEntries[i].data.Date.Month,
4854                     entry.SubEntries[i].data.Date.Year,
4855                     entry.SubEntries[i].data.Date.Hour,
4856                     entry.SubEntries[i].data.Date.Minute,
4857                     entry.SubEntries[i].data.Date.Second);
4858                  wasdate=true;
4859               } else {
4860                  if( strcmp(entry.SubEntries[i].data.Number,"") ) {
4861                     char z_etype[19];
4862                     switch( entry.SubEntries[i].EntryType ) {
4863                       case GSM_Number:
4864                         switch( entry.SubEntries[i].NumberType ) {
4865                           case GSM_General: strcpy(z_etype,"General "); break;
4866                           case GSM_Home: strcpy(z_etype,"Home "); break;
4867                           case GSM_Mobile: strcpy(z_etype,"Mobile "); break;
4868                           case GSM_Work: strcpy(z_etype,"Work "); break;
4869                           case GSM_Fax: strcpy(z_etype,"Fax "); break;
4870                           default: strcpy(z_etype,""); break;
4871                         }
4872                         strcat(z_etype,"Number"); break;
4873                       case GSM_Note:
4874                         strcpy(z_etype,"Note"); break;
4875                       case GSM_Postal:
4876                         strcpy(z_etype,"Postal"); break;
4877                       case GSM_Email:
4878                         strcpy(z_etype,"E-Mail"); break;
4879                       default:
4880                         strcpy(z_etype,"unknown data"); break;
4881                     }
4882 #ifdef DEBUG
4883                     fprintf(stdout,_("   ---> Subentry: %u\n"),i+1);
4884                     fprintf(stdout,_("   Entry type: %u (%s)\n"),entry.SubEntries[i].EntryType,z_etype);
4885                     fprintf(stdout,_("   Number type: %u\n"),entry.SubEntries[i].NumberType);
4886                     fprintf(stdout,_("   Block Number: %u\n"),entry.SubEntries[i].BlockNumber);
4887 #endif
4888                     fprintf(stdout,_("   %s: %s\n"),z_etype,entry.SubEntries[i].data.Number);
4889                   }
4890               }
4891             }
4892             if ((entry.MemoryType==GMT_DC ||
4893                  entry.MemoryType==GMT_RC ||
4894                  entry.MemoryType==GMT_MC) && !wasdate)
4895               fprintf(stdout,_("   Date and time not available\n"));        
4896           } else
4897             fprintf(stdout,_("   Location empty\n"));
4898       }
4899       break;
4900     case GE_NOTIMPLEMENTED:
4901       fprintf( stderr, _("Function not implemented in %s model!\n"), model);
4902       GSM->Terminate();
4903       return -1;
4904     case GE_INVALIDMEMORYTYPE:
4905       fprintf( stderr, _("Memory type %s not supported!\n"),
4906                memory_type_string);
4907       GSM->Terminate();
4908       return -1;
4909     default:
4910       fprintf(stdout, _("%s|%d|Bad location or other error!(%d)\n"),
4911               memory_type_string, count, error);
4912     }
4913   }
4914         
4915   GSM->Terminate();
4916
4917   return 0;
4918 }
4919
4920 /* Read data from stdin, parse and write to phone.  The parsing is relatively
4921    crude and doesn't allow for much variation from the stipulated format. */
4922
4923 static int writephonebook(int argc, char *args[])
4924 {
4925
4926   GSM_PhonebookEntry entry;
4927   GSM_Error error;
4928   char *memory_type_string;
4929   int line_count=0,current,i;
4930   int subentry;
4931
4932   char *Line, OLine[1024], BackLine[1024];
4933   char *ptr;
4934
4935   /* Check argument */
4936   if (argc) {
4937     if (strcmp("-i", args[0])) {
4938       usage();
4939       return 0;
4940     }
4941   }
4942   /* Initialise fbus code */
4943
4944   fbusinit(NULL);
4945
4946   Line = OLine;
4947
4948   /* Go through data from stdin. */
4949
4950   while (GetLine(stdin, Line, sizeof(OLine))!=-1) {
4951
4952     current=0;BackLine[current++]=Line[0];
4953     for (i=1;i<strlen(Line);i++) {
4954       if (Line[i-1]==';' && Line[i]==';') BackLine[current++]=' ';
4955       BackLine[current++]=Line[i];
4956     }
4957     BackLine[current++]=0;
4958
4959     strcpy(Line,BackLine);
4960
4961     line_count++;
4962
4963 #if defined(__svr4__) || defined(__FreeBSD__)
4964     ptr=strtok(Line, ";"); if (ptr) strcpy(entry.Name, ptr);
4965
4966     entry.Number[0]=0;
4967     ptr=strtok(NULL, ";"); if (ptr && ptr[0]!=' ') strcpy(entry.Number, ptr);
4968
4969     ptr=strtok(NULL, ";");
4970 #else
4971     ptr=strsep(&Line, ";"); if (ptr) strcpy(entry.Name, ptr);
4972
4973     entry.Number[0]=0;
4974     ptr=strsep(&Line, ";"); if (ptr && ptr[0]!=' ') strcpy(entry.Number, ptr);
4975
4976     ptr=strsep(&Line, ";");
4977 #endif
4978
4979     if (!ptr) {
4980       fprintf(stderr, _("Format problem on line %d [%s] 1\n"), line_count, BackLine);
4981       Line = OLine;
4982       continue;
4983     }
4984
4985     if (!strncmp(ptr,"ME", 2))
4986     {
4987       memory_type_string = "int";
4988       entry.MemoryType = GMT_ME;
4989     }
4990     else if (!strncmp(ptr,"SM", 2))
4991     {
4992         memory_type_string = "sim";
4993         entry.MemoryType = GMT_SM;
4994     }
4995     else
4996     {
4997       fprintf(stderr, _("Format problem on line %d [%s] 2: %s\n"),
4998         line_count, BackLine,ptr);
4999       break;
5000     }
5001
5002 #if defined(__svr4__) || defined(__FreeBSD__)
5003     ptr=strtok(NULL, ";"); if (ptr) entry.Location=atoi(ptr);
5004
5005     ptr=strtok(NULL, ";"); if (ptr) entry.Group=atoi(ptr);
5006 #else
5007     ptr=strsep(&Line, ";"); if (ptr) entry.Location=atoi(ptr);
5008
5009     ptr=strsep(&Line, ";"); if (ptr) entry.Group=atoi(ptr);
5010 #endif
5011
5012     if (!ptr) {
5013       fprintf(stderr, _("Format problem on line %d [%s] 3\n"),
5014         line_count, BackLine);
5015       continue;
5016     }
5017
5018     for( subentry = 0; ; subentry++ )
5019     {
5020 #if defined(__svr4__) || defined(__FreeBSD__)
5021       ptr=strtok(NULL, ";");
5022 #else
5023       ptr=strsep(&Line, ";");
5024 #endif
5025       if( ptr &&  *ptr != 0 )
5026         entry.SubEntries[subentry].EntryType=atoi(ptr);
5027       else
5028         break;
5029
5030 #if defined(__svr4__) || defined(__FreeBSD__)
5031       ptr=strtok(NULL, ";");
5032 #else
5033       ptr=strsep(&Line, ";");
5034 #endif
5035       if(ptr)
5036         entry.SubEntries[subentry].NumberType=atoi(ptr);
5037       // Phone Numbers need to have a number type.
5038       if(!ptr && entry.SubEntries[subentry].EntryType == GSM_Number)
5039       {
5040         fprintf(stderr, _("Missing phone number type on line %d"
5041           " entry %d [%s]\n"), line_count, subentry, BackLine);
5042         subentry--;
5043         break;
5044       }
5045
5046 #if defined(__svr4__) || defined(__FreeBSD__)
5047       ptr=strtok(NULL, ";");
5048 #else
5049       ptr=strsep(&Line, ";");
5050 #endif
5051       if(ptr)
5052         entry.SubEntries[subentry].BlockNumber=atoi(ptr);
5053
5054 #if defined(__svr4__) || defined(__FreeBSD__)
5055       ptr=strtok(NULL, ";");
5056 #else
5057       ptr=strsep(&Line, ";");
5058 #endif
5059       // 0x13 Date Type; it is only for Dailed Numbers, etc.
5060       // we don't store to this memories so it's an error to use it.
5061       if(!ptr || entry.SubEntries[subentry].EntryType == GSM_Date) 
5062       {
5063         fprintf(stderr, _("Is not a phone number on line %d entry %d [%s]\n"),
5064           line_count, subentry, BackLine);
5065         subentry--;
5066         break;
5067       }
5068       else
5069         strcpy( entry.SubEntries[subentry].data.Number, ptr );
5070     }
5071
5072     entry.SubEntriesCount = subentry;
5073
5074
5075     /* This is to send other exports (like from 6110) to 7110 */
5076     if (!entry.SubEntriesCount) {
5077         entry.SubEntriesCount = 1;
5078         entry.SubEntries[subentry].EntryType   = GSM_Number;
5079         entry.SubEntries[subentry].NumberType  = GSM_General;
5080         entry.SubEntries[subentry].BlockNumber = 2;
5081         strcpy(entry.SubEntries[subentry].data.Number, entry.Number);
5082     }
5083
5084     Line = OLine;
5085
5086     if (argc) {
5087       GSM_PhonebookEntry tmp_entry;
5088
5089       memcpy(&tmp_entry, &entry, sizeof(GSM_PhonebookEntry) );
5090       error = GSM->GetMemoryLocation(&tmp_entry);
5091       if (error == GE_NONE) {
5092         if (!tmp_entry.Empty) {
5093           int confirm = -1;
5094           char ans[8];
5095           FILE *input_flow; //for reading from console, even when input redir.
5096                                 
5097           input_flow = fopen(DEV_CONSOLE, "r");
5098
5099           if (!input_flow) {
5100                 fprintf(stderr, _("Can't open \"%s\" for input !\n"),DEV_CONSOLE);
5101                 return(-1);
5102           }
5103           
5104           fprintf(stderr, _("Location busy. "));
5105           while (confirm < 0) {
5106             fprintf(stderr, _("Overwrite? (yes/no) "));
5107             GetLine(input_flow, ans, 7);
5108             if (!strcmp(ans, "yes")) confirm = 1;
5109             else if (!strcmp(ans, "no")) confirm = 0;
5110           }
5111           if (!confirm) continue;
5112         }
5113       } else {
5114         fprintf(stderr, _("Unknown error (%d)\n"), error);
5115         GSM->Terminate();
5116         return 0;
5117       }
5118     }
5119
5120     /* Do write and report success/failure. */
5121     semicolon_pipe_substitution( &entry, 1 );
5122
5123     error = GSM->WritePhonebookLocation(&entry);
5124
5125     if (error == GE_NONE)
5126       fprintf (stdout, _("Write Succeeded: memory type: %s, loc: %d, name: %s, number: %s\n"), memory_type_string, entry.Location, entry.Name, entry.Number);
5127     else
5128       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);
5129
5130   }
5131
5132   GSM->Terminate();
5133
5134   return 0;
5135 }
5136
5137 /* Getting speed dials. */
5138
5139 static int getspeeddial(char *Number) {
5140
5141   GSM_SpeedDial entry;
5142   GSM_Error error;
5143   GSM_PhonebookEntry pbentry;
5144
5145   entry.Number = atoi(Number);
5146
5147   fbusinit(NULL);
5148
5149   if (GSM->GetSpeedDial(&entry)==GE_NONE) {
5150         pbentry.Location=entry.Location;
5151         if (pbentry.Location==0) pbentry.Location=entry.Number;
5152         pbentry.MemoryType=entry.MemoryType;
5153
5154         error=GSM->GetMemoryLocation(&pbentry);
5155
5156         if (error == GE_NONE)
5157         {
5158           fprintf(stdout, _("SpeedDial nr. %d: %d:%d (%s)\n"), entry.Number, entry.MemoryType, entry.Location,pbentry.Name);
5159         } else
5160           fprintf(stdout, _("Error\n"));
5161   } else {
5162     fprintf(stdout, _("Error\n"));
5163   }
5164   
5165   GSM->Terminate();
5166
5167   return 0;
5168 }
5169
5170 /* Setting speed dials. */
5171
5172 static int setspeeddial(char *argv[]) {
5173
5174   GSM_SpeedDial entry;
5175
5176   char *memory_type_string;
5177
5178   /* Handle command line args that set type, start and end locations. */
5179
5180   if (strcmp(argv[1], "ME") == 0) {
5181     entry.MemoryType = GMT_ME;
5182     memory_type_string = "ME";
5183   }
5184   else if (strcmp(argv[1], "SM") == 0) {
5185     entry.MemoryType = GMT_SM;
5186     memory_type_string = "SM";
5187   }
5188   else {
5189     fprintf(stderr, _("Unknown memory type %s!\n"), argv[1]);
5190
5191     return -1;
5192   }
5193   
5194   entry.Number = atoi(argv[0]);
5195   entry.Location = atoi(argv[2]);
5196
5197   fbusinit(NULL);
5198
5199   if (GSM->SetSpeedDial(&entry) == GE_NONE) {
5200     fprintf(stdout, _("Succesfully written!\n"));
5201   }
5202
5203   GSM->Terminate();
5204
5205   return 0;
5206 }
5207
5208 #ifndef UCLINUX
5209
5210 /* Getting the status of the display. */
5211
5212 int getdisplaystatus()
5213
5214
5215   int Status;
5216
5217   /* Initialise the code for the GSM interface. */     
5218
5219   fbusinit(NULL);
5220
5221   if (GSM->GetDisplayStatus(&Status)==GE_NONE) {
5222
5223     printf(_("Call in progress: %s\n"), Status & (1<<DS_Call_In_Progress)?_("on"):_("off"));
5224     printf(_("Unknown: %s\n"),          Status & (1<<DS_Unknown)?_("on"):_("off"));
5225     printf(_("Unread SMS: %s\n"),       Status & (1<<DS_Unread_SMS)?_("on"):_("off"));
5226     printf(_("Voice call: %s\n"),       Status & (1<<DS_Voice_Call)?_("on"):_("off"));
5227     printf(_("Fax call active: %s\n"),  Status & (1<<DS_Fax_Call)?_("on"):_("off"));
5228     printf(_("Data call active: %s\n"), Status & (1<<DS_Data_Call)?_("on"):_("off"));
5229     printf(_("Keyboard lock: %s\n"),    Status & (1<<DS_Keyboard_Lock)?_("on"):_("off"));
5230     printf(_("SMS storage full: %s\n"), Status & (1<<DS_SMS_Storage_Full)?_("on"):_("off"));
5231
5232   } else {
5233     printf(_("Error\n"));
5234   }
5235   
5236   GSM->Terminate();
5237
5238   return 0;
5239 }
5240
5241 int netmonitor(char *Mode)
5242 {
5243
5244   unsigned char mode=atoi(Mode);
5245   char Screen[NM_MAX_SCREEN_WIDTH];
5246   int i;
5247
5248   fbusinit(NULL);
5249
5250   if (!strcmp(Mode,"reset"))     mode=0xf0;
5251   else if (!strcmp(Mode,"off"))  mode=0xf1;
5252   else if (!strcmp(Mode,"field"))mode=0xf2;
5253   else if (!strcmp(Mode,"devel"))mode=0xf3;
5254   else if (!strcmp(Mode,"next")) mode=0x00;
5255
5256   /* We clear it */
5257   for (i=0;i<NM_MAX_SCREEN_WIDTH;i++) Screen[i]=0;
5258
5259   GSM->NetMonitor(mode, Screen);
5260
5261   if (Screen)
5262     printf("%s\n", Screen);
5263
5264   GSM->Terminate();
5265
5266   return 0;
5267 }
5268
5269 #endif /* UCLINUX */
5270
5271 static int identify( void )
5272 {
5273   /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */
5274   char imei[64], model[64], rev[64], manufacturer[64];
5275
5276   LIVE;
5277   fbusinit(NULL);
5278
5279   LIVE;
5280   while (GSM->GetIMEI(imei)    != GE_NONE) sleep(1);
5281   LIVE;
5282   while (GSM->GetRevision(rev) != GE_NONE) sleep(1);
5283   LIVE;
5284   while (GSM->GetModel(model)  != GE_NONE) sleep(1);
5285   LIVE;
5286
5287   strcpy(manufacturer, "(unknown)");
5288   LIVE;
5289   GSM->GetManufacturer(manufacturer);
5290   LIVE;
5291
5292   fprintf(stdout, _("IMEI:     %s\n"), imei);
5293   fprintf(stdout, _("Model:    %s %s (%s)\n"), manufacturer, GetModelName (model), model);
5294   fprintf(stdout, _("Revision: %s\n"), rev);
5295
5296   LIVE;
5297   GSM->Terminate();
5298   LIVE;
5299
5300   return 0;
5301 }
5302
5303 #ifndef UCLINUX
5304
5305 int senddtmf(char *String)
5306 {
5307
5308   fbusinit(NULL);
5309
5310   if (GSM->SendDTMF(String)!=GE_NONE) fprintf(stdout,_("Error!\n"));
5311
5312   GSM->Terminate();
5313
5314   return 0;
5315 }
5316
5317 #endif /* UCLINUX */
5318
5319 /* Resets the phone */
5320 static int reset(int argc, char *argv[])
5321 {
5322
5323   unsigned char _type=0x03;
5324
5325   if (argc>0) {
5326     _type=0x10;
5327
5328     if (!strcmp(argv[0],"soft")) _type = 0x03;
5329     
5330     /* Doesn't work with 5110 */
5331     if (!strcmp(argv[0],"hard")) _type = 0x04;
5332
5333     if (_type==0x10) {
5334       fprintf(stderr, _("What kind of reset do you want (second parameter can be \"soft\" or \"hard\") ?\n"));
5335       return -1;
5336     }
5337   }
5338
5339   fbusinit(NULL);
5340
5341   GSM->Reset(_type);
5342
5343   GSM->Terminate();
5344
5345   return 0;
5346 }
5347
5348 #ifndef UCLINUX
5349
5350 /* This is a "convenience" function to allow quick test of new API stuff which
5351    doesn't warrant a "proper" command line function. */
5352
5353 int foogle(char *argv[])
5354 {
5355   /* Initialise the code for the GSM interface. */     
5356
5357   fbusinit(NULL);
5358
5359   // Fill in what you would like to test here...
5360
5361   sleep(5);
5362   
5363   GSM->Terminate();
5364
5365   return 0;
5366 }
5367
5368 int phonetests()
5369 {
5370   /* Initialise the code for the GSM interface. */     
5371
5372   fbusinit(NULL);
5373
5374   if (GSM->PhoneTests()!=GE_NONE) fprintf(stderr,_("Error\n"));
5375   
5376   GSM->Terminate();
5377
5378   return 0;
5379 }
5380
5381 /* pmon allows fbus code to run in a passive state - it doesn't worry about
5382    whether comms are established with the phone.  A debugging/development
5383    tool. */
5384
5385 int pmon()
5386
5387
5388   GSM_Error error;
5389   GSM_ConnectionType connection=GCT_FBUS;
5390
5391   /* Initialise the code for the GSM interface. */     
5392
5393   error = GSM_Initialise(model, Port, Initlength, connection, RLP_DisplayF96Frame, ""/*SynchronizeTime*/);
5394
5395   if (error != GE_NONE) {
5396     fprintf(stderr, _("GSM/FBUS init failed! (Unknown model ?). Quitting.\n"));
5397     return -1;
5398   }
5399
5400
5401   while (1) {
5402     usleep(50000);
5403   }
5404
5405   return 0;
5406 }
5407
5408 int setringtone(int argc, char *argv[])
5409 {
5410   GSM_Ringtone ringtone;
5411   GSM_BinRingtone binringtone,binringtone2;
5412
5413   GSM_Error error;
5414
5415   int current=0; //number of packed notes or location
5416   int i;
5417
5418   char model[64];
5419
5420   /* If not binary ringtone */
5421   if (GSM_ReadBinRingtoneFile(argv[0],&binringtone2)!=GE_NONE) {
5422     fprintf(stdout,_("Not binary ringtone, trying RTTL\n"));
5423
5424     if (GSM_ReadRingtoneFileOnConsole(argv[0], &ringtone)!=GE_NONE) return(-1);
5425
5426     ringtone.location=1;
5427     if (argc>1) ringtone.location=atoi(argv[1]);
5428
5429     ringtone.allnotesscale=false;
5430   
5431     /* Initialise the GSM interface. */
5432     fbusinit(NULL);
5433
5434     while (GSM->GetModel(model)  != GE_NONE)
5435       sleep(1);
5436
5437     /* For Nokia 6110/6130/6150/6210 we use different method of uploading.
5438        Phone will display menu, when received it */
5439     if ( !strcmp(model,"NSE-3") || !strcmp(model,"NSK-3") ||
5440          !strcmp(model,"NSM-1") || !strcmp(model,"NPE-3") ) {
5441       if (argc==1) ringtone.location=255;
5442     }
5443
5444     error=GSM->SetRingtone(&ringtone,&current);
5445   
5446     if (current!=ringtone.NrNotes) {
5447       if (current>FB61_MAX_RINGTONE_NOTES) {
5448         fprintf(stderr,_("Warning: due to phone limitation"));
5449       } else {
5450         fprintf(stderr,_("Warning: ringtone was too long to be saved into frame,"));
5451       }
5452       fprintf(stderr, _(" only %i first notes were packed (%i cut)\n"),current,ringtone.NrNotes-current);
5453     }
5454
5455     if (error==GE_NONE) 
5456       fprintf(stdout, _("Set succeeded!\n"));
5457     else
5458       fprintf(stdout, _("Setting failed\n"));
5459
5460   } else { /* This IS binary ringtone */
5461     fprintf(stdout,_("Binary ringtone format\n"));
5462
5463     if (argc==3) {
5464       binringtone.frame[current++]=0x00;
5465       binringtone.frame[current++]=0x00;
5466       binringtone.frame[current++]=0x0c;
5467       binringtone.frame[current++]=0x01;
5468       binringtone.frame[current++]=0x2c;
5469     
5470       //copy new name
5471       memcpy(binringtone.frame+current,argv[2],strlen(argv[2]));
5472       current=current+strlen(argv[2]);
5473
5474       /*don't use old*/
5475       i=2;
5476       while(binringtone2.frame[i]!=0x00) {
5477         if (i==binringtone.length) break;
5478         i++;
5479       }
5480     
5481       //copy binringtone
5482       memcpy(binringtone.frame+current,binringtone2.frame+i,binringtone2.length-i);
5483       binringtone.length=binringtone2.length-i+current;    
5484     } else
5485     {
5486       memcpy(binringtone.frame+current,binringtone2.frame,binringtone2.length);
5487       binringtone.length=binringtone2.length;
5488     }
5489   
5490     binringtone.location=1;
5491     if (argc>1) binringtone.location=atoi(argv[1]);
5492   
5493     /* Initialise the GSM interface. */
5494     fbusinit(NULL);
5495
5496     error=GSM->SetBinRingtone(&binringtone);
5497
5498     switch (error) {
5499       case GE_NONE:
5500         fprintf(stdout, _("Set succeeded!\n"));
5501         break;
5502       case GE_INVALIDRINGLOCATION:
5503         fprintf(stdout, _("Invalid location %i!\n"),binringtone.location);
5504         break;
5505       case GE_UNKNOWNMODEL:
5506         fprintf(stdout, _("Mygnokii doesn't know format for this model!\n"));
5507         break;
5508       case GE_NOTIMPLEMENTED:
5509         fprintf(stdout, _("Not implemented for this model!\n"));
5510         break;
5511       default:
5512         fprintf(stdout, _("Not supported by this model!\n"));
5513         break;
5514     }
5515   }
5516
5517   GSM->Terminate();
5518
5519   return 0;
5520 }
5521
5522 int ringtoneconvert(int argc, char *argv[])
5523 {
5524   GSM_Ringtone ringtone;
5525
5526   if (!strcmp(argv[0],argv[1]))
5527   {
5528     fprintf(stderr, _("Files can't have the same names !\n"));
5529     return -1;  
5530   }
5531   
5532   if (GSM_ReadRingtoneFileOnConsole(argv[0], &ringtone)!=GE_NONE) return(-1);
5533
5534   ringtone.allnotesscale=false;
5535
5536   GSM_SaveRingtoneFileOnConsole(argv[1], &ringtone);
5537   
5538   return 0;
5539 }
5540
5541 int playringtone(int argc, char *argv[])
5542 {
5543   GSM_Ringtone ringtone;
5544
5545   GSM_BinRingtone binringtone;
5546   
5547   int i,j,z;
5548   int Hz;
5549   bool isok;
5550
5551 //{ "c", "c#", "d", "d#", "e",  "f", "f#", "g", "g#", "a", "a#", "h" };
5552   int binary_notes[12] =
5553   { 0,    1,    2,   3,    4,   6,   7,    8,   9,    10,  11 ,   12};
5554
5555   if (GSM_ReadBinRingtoneFile(argv[0],&binringtone)!=GE_NONE) {
5556     fprintf(stdout,_("Not binary ringtone, trying RTTL\n"));
5557
5558     if (GSM_ReadRingtoneFileOnConsole(argv[0], &ringtone)!=GE_NONE) return(-1);
5559
5560     /* Initialise the GSM interface. */
5561     fbusinit(NULL);
5562
5563     fprintf(stdout,_("Playing \"%s\" (%i notes)\n"),ringtone.name,ringtone.NrNotes);
5564   
5565     GSM_PlayRingtoneOnConsole(&ringtone);
5566
5567   } else {
5568
5569     fprintf(stdout,_("Binary ringtone format\n"));  
5570
5571     /* Initialise the GSM interface. */
5572     fbusinit(NULL);
5573
5574     i=5;
5575     while (true) { //skipping name
5576       if (binringtone.frame[i]==0) break;
5577       i++;
5578     }
5579
5580     i=i+5;j=0;z=0;
5581     while (true) {
5582       if (binringtone.frame[i]!=j) {
5583         if (j!=0) {
5584 //#ifdef DEBUG
5585           fprintf(stdout,_("Block in binary ringtone %i %i\n"),j,z);
5586 //#endif
5587           isok=false;
5588           if (j==64) {
5589             j=255;//Pause
5590             isok=true;
5591           }
5592           if (!isok && j>=114 && j<=125) {
5593             j=14*3+binary_notes[j-114];
5594             isok=true;
5595           }
5596           if (!isok && j>=126 && j<=137) {
5597             j=14*1+binary_notes[j-126];
5598             isok=true;
5599           }
5600           if (!isok && j>=138 && j<=149) {
5601             j=14*2+binary_notes[j-138];
5602             isok=true;
5603           }
5604           if (!isok && j>=150 && j<=161) {
5605             j=14*4+binary_notes[j-150];
5606             isok=true;
5607           }
5608           if (!isok) {
5609 //#ifdef DEBUG
5610             fprintf(stdout,_("Unknown block in binary ringtone %i %i\n"),j,z);
5611 //#endif
5612           } else {
5613             Hz=GSM_GetFrequency(j);
5614             if (GSM->PlayTone(Hz,5)!=GE_NONE) fprintf(stdout,_("error during playing\n"));
5615             usleep(z*5000);
5616           }
5617         }
5618         j=binringtone.frame[i];
5619         z=binringtone.frame[i+1];
5620       } else {
5621         z=z+binringtone.frame[i+1];
5622       }
5623       i=i+2;
5624       if (i>=binringtone.length) break;
5625     }
5626   
5627     GSM->PlayTone(0,0);
5628   }
5629
5630   GSM->Terminate();    
5631
5632   return 0;
5633 }
5634
5635 int composer(int argc, char *argv[])
5636 {
5637   GSM_Ringtone ringtone;
5638   int i;
5639   bool unknown;
5640   int oldnoteslen=4,nownoteslen,oldnoteslen2;
5641   int oldnotesscale=1,nownotesscale;  
5642   bool firstnote=true;
5643   int DefNoteTempo=63;
5644   
5645   if (GSM_ReadRingtoneFileOnConsole(argv[0], &ringtone)!=GE_NONE) return(-1);
5646  
5647   if (ringtone.NrNotes!=0)
5648     DefNoteTempo=ringtone.notes[0].tempo;
5649
5650   fprintf(stdout,_("Ringtone \"%s\" (tempo = %i Beats Per Minute)\n\n"),ringtone.name,GSM_GetTempo(DefNoteTempo));
5651   
5652   for (i=0;i<ringtone.NrNotes;i++) {    
5653     if (DefNoteTempo!=ringtone.notes[i].tempo) {
5654       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"));
5655       break;
5656     }
5657   }
5658     
5659   for (i=0;i<ringtone.NrNotes;i++) {
5660
5661     if (firstnote) {
5662       if (GSM_GetNote(ringtone.notes[i].note)!=Note_Pause)
5663         firstnote=false;
5664     }
5665     
5666     if (!firstnote) {
5667       break;
5668     }
5669     
5670   }
5671
5672   if ((ringtone.NrNotes-i)>50)
5673     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);
5674
5675   fprintf(stdout,_("This ringtone in Nokia Composer in phone should look: "));  
5676
5677   firstnote=true;
5678     
5679   for (i=0;i<ringtone.NrNotes;i++) {
5680
5681     if (firstnote) {
5682       if (GSM_GetNote(ringtone.notes[i].note)!=Note_Pause)
5683         firstnote=false;
5684     }
5685     
5686     if (!firstnote) {
5687     
5688       switch (ringtone.notes[i].duration) {
5689         case 192:fprintf(stdout,_("1."));break; //192=128*1.5
5690         case 128:fprintf(stdout,_("1"));break;
5691         case 96 :fprintf(stdout,_("2."));break; //96=64*1.5
5692         case 64 :fprintf(stdout,_("2"));break;
5693         case 48 :fprintf(stdout,_("4."));break; //48=32*1.5
5694         case 32 :fprintf(stdout,_("4"));break;
5695         case 24 :fprintf(stdout,_("8."));break; //24=16*1.5
5696         case 16 :fprintf(stdout,_("8"));break;
5697         case 12 :fprintf(stdout,_("16."));break; //12=8*1.5
5698         case 8  :fprintf(stdout,_("16"));break;
5699         case 6  :fprintf(stdout,_("32."));break; //6=4*1.5
5700         case 4  :fprintf(stdout,_("32"));break;
5701       }
5702     
5703     unknown=false;
5704     
5705     /* What note here ? */
5706     switch (GSM_GetNote(ringtone.notes[i].note)) {
5707       case Note_C  :fprintf(stdout,_("c"));break;
5708       case Note_Cis:fprintf(stdout,_("#c"));break;
5709       case Note_D  :fprintf(stdout,_("d"));break;
5710       case Note_Dis:fprintf(stdout,_("#d"));break;
5711       case Note_E  :fprintf(stdout,_("e"));break;
5712       case Note_F  :fprintf(stdout,_("f"));break;
5713       case Note_Fis:fprintf(stdout,_("#f"));break;
5714       case Note_G  :fprintf(stdout,_("g"));break;
5715       case Note_Gis:fprintf(stdout,_("#g"));break;
5716       case Note_A  :fprintf(stdout,_("a"));break;
5717       case Note_Ais:fprintf(stdout,_("#a"));break;
5718       case Note_H  :fprintf(stdout,_("h"));break;
5719       default      :fprintf(stdout,_("-"));unknown=true;break; //Pause ?
5720     }
5721
5722     if (!unknown)
5723       fprintf(stdout,_("%i"),ringtone.notes[i].note/14);
5724     
5725     /* And separator before next note */
5726     if (i!=ringtone.NrNotes-1)
5727       fprintf(stdout,_(" "));
5728       
5729     }
5730
5731   }
5732
5733   fprintf(stdout,_("\n\nTo enter it please press: "));  
5734   
5735   firstnote=true;
5736   
5737   for (i=0;i<ringtone.NrNotes;i++) {
5738
5739     if (firstnote) {
5740       if (GSM_GetNote(ringtone.notes[i].note)!=Note_Pause)
5741         firstnote=false;
5742     }
5743     
5744     if (!firstnote) {
5745
5746     unknown=false;
5747     
5748     /* What note here ? */
5749     switch (GSM_GetNote(ringtone.notes[i].note)) {
5750       case Note_C  :fprintf(stdout,_("1"));break;
5751       case Note_Cis:fprintf(stdout,_("1"));break;
5752       case Note_D  :fprintf(stdout,_("2"));break;
5753       case Note_Dis:fprintf(stdout,_("2"));break;
5754       case Note_E  :fprintf(stdout,_("3"));break;
5755       case Note_F  :fprintf(stdout,_("4"));break;
5756       case Note_Fis:fprintf(stdout,_("4"));break;
5757       case Note_G  :fprintf(stdout,_("5"));break;
5758       case Note_Gis:fprintf(stdout,_("5"));break;
5759       case Note_A  :fprintf(stdout,_("6"));break;
5760       case Note_Ais:fprintf(stdout,_("6"));break;
5761       case Note_H  :fprintf(stdout,_("7"));break;
5762       default      :fprintf(stdout,_("0"));unknown=true;break;
5763     }
5764
5765       switch (ringtone.notes[i].duration) {
5766         case 192:fprintf(stdout,_("(longer)"));break; //192=128*1.5
5767         case 96 :fprintf(stdout,_("(longer)"));break; //96=64*1.5
5768         case 48 :fprintf(stdout,_("(longer)"));break; //48=32*1.5
5769         case 24 :fprintf(stdout,_("(longer)"));break; //24=16*1.5
5770         case 12 :fprintf(stdout,_("(longer)"));break; //12=8*1.5
5771         case 6  :fprintf(stdout,_("(longer)"));break; //6=4*1.5
5772         default:break;
5773       }
5774
5775     /* What note here ? */
5776     switch (GSM_GetNote(ringtone.notes[i].note)) {
5777       case Note_Cis:fprintf(stdout,_("#"));break;
5778       case Note_Dis:fprintf(stdout,_("#"));break;
5779       case Note_Fis:fprintf(stdout,_("#"));break;
5780       case Note_Gis:fprintf(stdout,_("#"));break;
5781       case Note_Ais:fprintf(stdout,_("#"));break;
5782       default      :break;
5783     }
5784
5785     if (!unknown)
5786     {
5787       nownotesscale=ringtone.notes[i].note/14;
5788
5789       if (nownotesscale!=oldnotesscale) {
5790         switch (nownotesscale) {
5791           case 1:
5792             switch (oldnotesscale) {
5793               case 2:fprintf(stdout,_("**"));break;
5794               case 3:fprintf(stdout,_("*"));break;
5795             }
5796             break;
5797           case 2:
5798             switch (oldnotesscale) {
5799               case 1:fprintf(stdout,_("*"));break;
5800               case 3:fprintf(stdout,_("**"));break;
5801             }
5802             break;
5803           case 3:
5804             switch (oldnotesscale) {
5805               case 1:fprintf(stdout,_("**"));break;
5806               case 2:fprintf(stdout,_("*"));break;
5807             }
5808             break;
5809         }
5810       }
5811       
5812       oldnotesscale=nownotesscale;
5813     }
5814
5815      nownoteslen=0;
5816      oldnoteslen2=oldnoteslen;
5817      
5818       switch (ringtone.notes[i].duration) {
5819         case 192:nownoteslen=1;break; //192=128*1.5
5820         case 128:nownoteslen=1;break;
5821         case 96 :nownoteslen=2;break; //96=64*1.5
5822         case 64 :nownoteslen=2;break;
5823         case 48 :nownoteslen=4;break; //48=32*1.5
5824         case 32 :nownoteslen=4;break;
5825         case 24 :nownoteslen=8;break; //24=16*1.5
5826         case 16 :nownoteslen=8;break;
5827         case 12 :nownoteslen=16;break; //12=8*1.5
5828         case 8  :nownoteslen=16;break;
5829         case 6  :nownoteslen=32;break; //6=4*1.5
5830         case 4  :nownoteslen=32;break;
5831       }    
5832       
5833       if (nownoteslen>oldnoteslen) {
5834         while (oldnoteslen!=nownoteslen) {
5835           fprintf(stdout,_("8"));
5836           oldnoteslen=oldnoteslen*2;
5837         }
5838       }
5839
5840       if (nownoteslen<oldnoteslen) {
5841         while (oldnoteslen!=nownoteslen) {
5842           fprintf(stdout,_("9"));
5843           oldnoteslen=oldnoteslen/2;
5844         }
5845       }      
5846
5847     if (GSM_GetNote(ringtone.notes[i].note)==Note_Pause)
5848       oldnoteslen=oldnoteslen2;
5849       
5850     /* And separator before next note */
5851     if (i!=ringtone.NrNotes-1)
5852       fprintf(stdout,_("  "));
5853
5854   }
5855   }  
5856
5857   fprintf(stdout,_("\n"));
5858
5859   return 0;
5860
5861 }
5862
5863 int sendringtone(int argc, char *argv[])
5864 {
5865   GSM_Ringtone ringtone;
5866   GSM_MultiSMSMessage SMS;
5867   int current,i;
5868   bool ProfileStyle=false; /* If we use profile style available in new Nokia models */
5869
5870   if (GSM_ReadRingtoneFileOnConsole(argv[1], &ringtone)!=GE_NONE) return(-1);
5871
5872   ringtone.allnotesscale=false;
5873
5874   for (i=0;i<argc;i++) {
5875     if (!strcmp(argv[i],"--profilestyle")) ProfileStyle=true;
5876     if (!strcmp(argv[i],"--scale")) ringtone.allnotesscale=true;
5877   }
5878
5879   current=GSM_SaveRingtoneToSMS(&SMS,&ringtone,ProfileStyle);
5880
5881   if (current!=ringtone.NrNotes) {
5882     if (current>FB61_MAX_RINGTONE_NOTES) {
5883       fprintf(stderr,_("Warning: due to phone limitation"));
5884     } else {
5885       fprintf(stderr,_("Warning: ringtone was too long to be saved into SMS,"));
5886     }
5887     fprintf(stderr, _(" only %i first notes were packed (%i cut)\n"),current,ringtone.NrNotes-current);
5888   }
5889
5890   for (i=0;i<SMS.number;i++) {
5891     strcpy(SMS.SMS[i].Destination,argv[0]);
5892   }
5893
5894   /* Initialise the GSM interface. */
5895   fbusinit(NULL);
5896
5897   GSM_SendMultiPartSMSOnConsole(&SMS, 2,argc,argv,false,true,true);
5898
5899   return 0;
5900 }
5901
5902 int saveringtone(int argc, char *argv[])
5903 {
5904   GSM_Ringtone ringtone;
5905   GSM_MultiSMSMessage SMS;
5906   int current,i;
5907   bool ProfileStyle=false; /* If we use profile style available in new Nokia models */
5908
5909   if (GSM_ReadRingtoneFileOnConsole(argv[0], &ringtone)!=GE_NONE) return(-1);
5910
5911   ringtone.allnotesscale=false;
5912
5913   for (i=0;i<argc;i++) {
5914     if (!strcmp(argv[i],"--profilestyle")) ProfileStyle=true;
5915     if (!strcmp(argv[i],"--scale")) ringtone.allnotesscale=true;
5916   }
5917
5918   current=GSM_SaveRingtoneToSMS(&SMS,&ringtone,ProfileStyle);
5919
5920   if (current!=ringtone.NrNotes) {
5921     if (current>FB61_MAX_RINGTONE_NOTES) {
5922       fprintf(stderr,_("Warning: due to phone limitation"));
5923     } else {
5924       fprintf(stderr,_("Warning: ringtone was too long to be saved into SMS,"));
5925     }
5926     fprintf(stderr, _(" only %i first notes were packed (%i cut)\n"),current,ringtone.NrNotes-current);
5927   }
5928
5929   for (i=0;i<SMS.number;i++) {
5930     /* Only 11 chars could be here */
5931     strncpy(SMS.SMS[i].Destination,ringtone.name,11);
5932   }
5933
5934   /* Initialise the GSM interface. */
5935   fbusinit(NULL);
5936
5937   GSM_SaveMultiPartSMSOnConsole(&SMS,1,argc,argv,false,false,true,true);
5938
5939   return 0;
5940 }
5941
5942 /* Converts logo files. */
5943
5944 int bitmapconvert(int argc, char *argv[])
5945 {
5946   GSM_Bitmap bitmap;
5947   GSM_NetworkInfo NetworkInfo;
5948   bool doit;
5949   int num;
5950   
5951   if (!strcmp(argv[0],argv[1]))
5952   {
5953     fprintf(stderr, _("Files can't have the same names !\n"));
5954     return -1;  
5955   }
5956   
5957   if (GSM_ReadBitmapFileOnConsole(argv[0], &bitmap)!=GE_NONE) return(-1);
5958
5959   if (argc>2)
5960   {
5961     doit=false;
5962     if (!strcmp(argv[2],"op"))
5963     {
5964       doit=false;
5965       if (argc<4) doit=true;
5966       if (argc<4 && bitmap.type!=GSM_OperatorLogo) doit=true;
5967       if (doit)
5968       {
5969         fbusinit(NULL);
5970         if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE) strncpy(bitmap.netcode,NetworkInfo.NetworkCode,7);
5971         GSM->Terminate();
5972       }
5973       GSM_ResizeBitmap(&bitmap,GSM_OperatorLogo);
5974       if (argc==4)
5975       {
5976         strncpy(bitmap.netcode,argv[3],7);
5977         if (!strcmp(GSM_GetNetworkName(bitmap.netcode),"unknown"))
5978         {
5979           fprintf(stderr,"Sorry, gnokii doesn't know \"%s\" network !\n",bitmap.netcode);
5980           return -1;
5981         }
5982       }
5983       doit=true;
5984     }
5985     if (!strcmp(argv[2],"7110op"))
5986     {
5987       doit=false;
5988       if (argc<4) doit=true;
5989       if (argc<4 && bitmap.type!=GSM_7110OperatorLogo) doit=true;
5990       if (doit)
5991       {
5992         fbusinit(NULL);
5993         if (GSM->GetNetworkInfo(&NetworkInfo) == GE_NONE) strncpy(bitmap.netcode,NetworkInfo.NetworkCode,7);
5994         GSM->Terminate();
5995       }
5996       GSM_ResizeBitmap(&bitmap,GSM_7110OperatorLogo);
5997       if (argc==4)
5998       {
5999         strncpy(bitmap.netcode,argv[3],7);
6000         if (!strcmp(GSM_GetNetworkName(bitmap.netcode),"unknown"))
6001         {
6002           fprintf(stderr,"Sorry, gnokii doesn't know \"%s\" network !\n",bitmap.netcode);
6003           return -1;
6004         }
6005       }
6006       doit=true;
6007     }
6008     if (!strcmp(argv[2],"caller"))
6009     {
6010       GSM_ResizeBitmap(&bitmap,GSM_CallerLogo);
6011       if (argc>3)
6012       {
6013         num=argv[3][0]-'0';
6014         if ((num<0)||(num>9)) num=0;
6015         bitmap.number=num;
6016       } else
6017       {
6018         bitmap.number=0;
6019       }
6020       doit=true;
6021     }
6022     if (!strcmp(argv[2],"startup"))
6023     {
6024       GSM_ResizeBitmap(&bitmap,GSM_StartupLogo);
6025       doit=true;
6026     }
6027     if (!strcmp(argv[2],"7110startup"))
6028     {
6029       GSM_ResizeBitmap(&bitmap,GSM_7110StartupLogo);
6030       doit=true;
6031     }
6032     if (!strcmp(argv[2],"6210startup"))
6033     {
6034       GSM_ResizeBitmap(&bitmap,GSM_6210StartupLogo);
6035       doit=true;
6036     }
6037     if (!strcmp(argv[2],"picture"))
6038     {
6039       GSM_ResizeBitmap(&bitmap,GSM_PictureImage);
6040       doit=true;
6041     }
6042     if (!doit)
6043     {
6044       fprintf(stderr,"Unknown type of logo: %s !\n",argv[2]);
6045       return -1;
6046     }
6047   }
6048     
6049   if (GSM_SaveBitmapFileOnConsole(argv[1], &bitmap)!=GE_NONE) return(-1);
6050   
6051   return 0;
6052 }
6053
6054 int getphoneprofile()
6055 {
6056   GSM_PPS PPS;
6057   GSM_Error error;
6058
6059   /* Initialise the GSM interface. */
6060   fbusinit(NULL);
6061
6062   PPS.Name=PPS_ALS;
6063   error=GSM->GetProductProfileSetting(&PPS);
6064   if (error!=GE_NONE) {
6065     fprintf(stdout,_("Error!\n"));
6066     GSM->Terminate();    
6067     return -1;
6068   }
6069   fprintf(stdout,_("ALS           : "));
6070   if (PPS.bool_value) fprintf(stdout,_("on\n"));
6071                  else fprintf(stdout,_("off\n"));
6072
6073   PPS.Name=PPS_VibraMenu;
6074   GSM->GetProductProfileSetting(&PPS);
6075   fprintf(stdout,_("Vibra menu    : "));
6076   if (PPS.bool_value) fprintf(stdout,_("on\n"));
6077                  else fprintf(stdout,_("off\n"));
6078
6079   PPS.Name=PPS_GamesMenu;
6080   GSM->GetProductProfileSetting(&PPS);
6081   fprintf(stdout,_("Games menu    : "));
6082   if (PPS.bool_value) fprintf(stdout,_("on\n"));
6083                  else fprintf(stdout,_("off\n"));
6084
6085   PPS.Name=PPS_HRData;
6086   GSM->GetProductProfileSetting(&PPS);
6087   fprintf(stdout,_("HR Data       : "));
6088   if (PPS.bool_value) fprintf(stdout,_("on\n"));
6089                  else fprintf(stdout,_("off\n"));
6090
6091   PPS.Name=PPS_14400Data;
6092   GSM->GetProductProfileSetting(&PPS);
6093   fprintf(stdout,_("14400 Data    : "));
6094   if (PPS.bool_value) fprintf(stdout,_("on\n"));
6095                  else fprintf(stdout,_("off\n"));
6096
6097   PPS.Name=PPS_LCDContrast;
6098   GSM->GetProductProfileSetting(&PPS);
6099   fprintf(stdout,_("LCD Contrast  : %i%%\n"),PPS.int_value);
6100
6101   PPS.Name=PPS_EFR;
6102   GSM->GetProductProfileSetting(&PPS);
6103   fprintf(stdout,_("EFR           : "));
6104   switch (PPS.int_value) {
6105     case 0: fprintf(stdout,_("off\n"));   break;
6106     case 1: fprintf(stdout,_("last\n"));  break;
6107     case 2: fprintf(stdout,_("second\n"));break;
6108     case 3: fprintf(stdout,_("first\n")); break;
6109   }
6110
6111   PPS.Name=PPS_FR;
6112   GSM->GetProductProfileSetting(&PPS);
6113   fprintf(stdout,_("FR            : "));
6114   switch (PPS.int_value) {
6115     case 0: fprintf(stdout,_("off\n"));   break;
6116     case 1: fprintf(stdout,_("last\n"));  break;
6117     case 2: fprintf(stdout,_("second\n"));break;
6118     case 3: fprintf(stdout,_("first\n")); break;
6119   }
6120
6121   PPS.Name=PPS_HR;
6122   GSM->GetProductProfileSetting(&PPS);
6123   fprintf(stdout,_("HR            : "));
6124   switch (PPS.int_value) {
6125     case 0: fprintf(stdout,_("off\n"));   break;
6126     case 1: fprintf(stdout,_("last\n"));  break;
6127     case 2: fprintf(stdout,_("second\n"));break;
6128     case 3: fprintf(stdout,_("first\n")); break;
6129   }
6130     
6131   GSM->Terminate();    
6132
6133   return 0;
6134
6135 }
6136
6137 int setphoneprofile(int argc, char *argv[])
6138 {
6139   GSM_PPS PPS;
6140   GSM_Error error;
6141   bool correct_arg1=false, correct_arg2=false;
6142
6143   if (!strcmp(argv[0],"ALS")) {
6144     PPS.Name=PPS_ALS;
6145     correct_arg1=true;
6146     if (!strcmp(argv[1],"1")) {
6147       PPS.bool_value=true;
6148       correct_arg2=true;
6149     }
6150     if (!strcmp(argv[1],"0")) {
6151       PPS.bool_value=false;
6152       correct_arg2=true;
6153     }
6154     if (!correct_arg2) {
6155       fprintf(stdout,_("Settings for ALS parameter can be \"0\" or \"1\" !\n"));
6156       return -1;
6157     }
6158   }
6159   if (!strcmp(argv[0],"HRData")) {
6160     PPS.Name=PPS_HRData;
6161     correct_arg1=true;
6162     if (!strcmp(argv[1],"1")) {
6163       PPS.bool_value=true;
6164       correct_arg2=true;
6165     }
6166     if (!strcmp(argv[1],"0")) {
6167       PPS.bool_value=false;
6168       correct_arg2=true;
6169     }
6170     if (!correct_arg2) {
6171       fprintf(stdout,_("Settings for HRData parameter can be \"0\" or \"1\" !\n"));
6172       return -1;
6173     }
6174   }  
6175   if (!correct_arg1) {
6176     fprintf(stdout,_("First parameter can be \"ALS\" or \"HRData\" only !\n"));
6177     return -1;
6178   }
6179
6180   /* Initialise the GSM interface. */
6181   fbusinit(NULL);
6182
6183   error=GSM->SetProductProfileSetting(&PPS);
6184
6185   if (error!=GE_NONE) {
6186     fprintf(stdout,_("Error!\n"));
6187     GSM->Terminate();    
6188     return -1;
6189   }
6190
6191   GSM->Reset(0x03);
6192   
6193   GSM->Terminate();    
6194
6195   return 0;
6196
6197 }
6198
6199 int getoperatorname()
6200 {
6201
6202   GSM_Network network;
6203
6204   /* Initialise the GSM interface. */
6205   fbusinit(NULL);
6206
6207   if (GSM->GetOperatorName(&network)==GE_NONE)
6208   {
6209     if (!strcmp(network.Name,"")) {
6210       fprintf(stdout,_("Phone doesn't have downloaded operator name\n"));
6211     } else {
6212       fprintf(stdout,_("Phone has downloaded operator name (\"%s\") for \"%s\" (\"%s\") network\n"),
6213               network.Name,network.Code,GSM_GetNetworkName(network.Code));
6214     }
6215   }
6216   
6217   GSM->Terminate();    
6218
6219   return 0;
6220
6221 }
6222
6223 int setoperatorname(int argc, char *argv[])
6224 {
6225
6226   GSM_Network network;
6227
6228   /* Initialise the GSM interface. */
6229   fbusinit(NULL);
6230
6231   if (argc==2) {
6232     strncpy(network.Code,argv[0],7);
6233     strncpy(network.Name,argv[1],50);
6234   } else {
6235     strcpy(network.Code,"000 00\0");
6236     strcpy(network.Name,"\0");
6237   }
6238   
6239   if (GSM->SetOperatorName(&network)==GE_NONE) {
6240     if (GSM->GetOperatorName(&network)==GE_NONE) {
6241       if (!strcmp(network.Name,"")) {
6242         fprintf(stdout,_("Downloaded operator name is removed\n"));
6243       } else {
6244         fprintf(stdout,_("Downloaded operator name changed for \"%s\" network (\"%s\") to \"%s\"\n"),
6245                 network.Code,GSM_GetNetworkName(network.Code),network.Name);
6246       }
6247     }
6248   }
6249
6250   GSM->Terminate();    
6251
6252   return 0;
6253
6254 }
6255
6256 int getvoicemailbox()
6257 {
6258   GSM_PhonebookEntry entry;
6259
6260   /* Initialise the GSM interface. */
6261   fbusinit(NULL);
6262   
6263   if (GSM->GetVoiceMailbox(&entry)==GE_NONE) {
6264     fprintf(stdout,_("Voice mailbox number is "));
6265     if (!strcmp(entry.Number,""))
6266       fprintf(stdout,_("not set\n"));
6267     else
6268       fprintf(stdout,_("\"%s\"\n"),entry.Number);
6269   }
6270
6271   GSM->Terminate();    
6272
6273   return 0;
6274
6275 }
6276
6277 ///////////////////////////////////////////////////////////////////////////////
6278 // flow diagram of netmonitordata():
6279 ///////////////////////////////////////////////////////////////////////////////
6280 //
6281 //              get command line argument
6282 //                      |                       
6283 //                      v       
6284 //
6285 //              if specific phone model
6286 //                  use that model
6287 //              else
6288 //                  identify-phone:     (((((((( TO DO )))))))))))))
6289 //
6290 //                      |
6291 //                      v
6292 //              get_mon_param_info()    get phone netmonitor parameters name
6293 //                                      specifically to a 'model'
6294 //                      |
6295 //                      v
6296 //              parse_check()           check command line arguments
6297 //                      |               if all OK, go on else stop.
6298 //                      |               because we can have a input file
6299 //                      v               containing multiple
6300 //              parse_process()         command lines, we process each at once
6301 //                                      so we can exit early on errors.
6302 //
6303 ///////////////////////////////////////////////////////////////////////////////
6304
6305 // private functions, see netmonitordata()
6306 void free_nm_info(PARAM_INFO_MON *info)
6307 {
6308         PARAM_INFO_MON *tmp;    // pointer, iterator on info
6309
6310         // go to end of list
6311
6312         while (info->next != NULL)
6313         {       tmp = info->next;
6314                 free(info->name);
6315                 free(info->mname);
6316                 free(info);
6317                 info = tmp;
6318         }
6319         free(info);
6320 }
6321
6322 ///////////////////////////////////////////////////////////////////////////////
6323 // this func retrieve parameters info from a file
6324 // and load it in a dynamic array, NULL terminated,
6325 // if 2rd parameter is not NULL, it load also description of screen
6326 // return (PARAM_INFO_MON *start) if all is OK, else NULL
6327 ///////////////////////////////////////////////////////////////////////////////
6328 // start->->next->next->next-> ...->next->NULL
6329 //   |      |     |     |           |
6330 //   V      V     V     V           V
6331 //        par0  par1  par2        parN
6332 ///////////////////////////////////////////////////////////////////////////////
6333 // this should be de-allocated from calling function,
6334 // also, screen_name should be deallocated from calling function
6335 ///////////////////////////////////////////////////////////////////////////////
6336
6337 PARAM_INFO_MON *get_mon_param_info(char *f_name, char *screen_name[NM_MAX_SCREEN+1])
6338 {
6339         PARAM_INFO_MON *start;  // pointer to netmonitor parameters info
6340         PARAM_INFO_MON *info;   // pointer, iterator on info
6341         PARAM_INFO_MON *check;  // pointer, iterator on info, for check usage
6342
6343         FILE *f_info;
6344
6345         char buf[256];
6346         char *param;
6347         char *param_name;
6348         char *tmp;
6349
6350         char tmp_mname[55];             // very larger, but if netmon bug ...
6351         int x, y, len, s, t;            // x & y coord, len, screen nr, type
6352         int i;
6353
6354         if (screen_name != NULL)
6355                 for (i = 0; i <= NM_MAX_SCREEN; i++)
6356                         screen_name[i] = NULL;
6357                 
6358
6359         if ((f_info = fopen(f_name, "r")) == NULL)
6360         {       fprintf(stderr, "Can' t open file parameter info: <%s>\n", f_name);
6361                 return(NULL);
6362         }
6363         
6364         if ((start = malloc(sizeof(PARAM_INFO_MON))) == NULL)
6365         {       fprintf(stderr, "no mem\n");
6366                 return(NULL);
6367         }
6368         else
6369         {       start->next = NULL;
6370         }
6371
6372         info = start;
6373         while (fgets(buf, 256, f_info) != NULL)
6374         {
6375                 param = buf;
6376
6377                 // Truncate from '#' at right of comments
6378                 if ((tmp = strchr(param, '#')) != NULL)
6379                         *tmp = '\0';
6380
6381                 // Strip leading, trailing whitespace
6382                 while(isspace((int) *param))
6383                         param++;
6384
6385                 while((strlen(param) > 0) && isspace((int) param[strlen(param) - 1]))
6386                         param[strlen(param) - 1] = '\0';
6387         
6388                 // Ignore blank lines
6389                 if ((*param == '\n') || (*param == '\0'))
6390                         continue;
6391
6392
6393 #ifdef DEBUG
6394                 fprintf(stderr, "%s: info line: <%s>\n", f_name, param);
6395 #endif
6396                 // check for param name
6397                 if ((param_name = strtok(param, "=\t\n")) == NULL)
6398                         continue;
6399
6400                 // check if screen name
6401                 if (strncmp("SCREEN", param_name, 6) == 0)
6402                 {       
6403                         // if we do not want screen names ...
6404                         if (screen_name == NULL)
6405                                 continue;
6406
6407 // FIXME check for screen nr
6408                         if ((tmp = strtok(NULL, ":\n")) == NULL)
6409                                 continue;
6410         
6411                         i = atoi(tmp);
6412 // FIXME: check if already defined screen
6413
6414                         if ((i <= 0) || (i > NM_MAX_SCREEN))
6415                                 continue;
6416                         // check for screen name
6417                         if ((tmp = strtok(NULL, ":\n")) == NULL)
6418                                 continue;
6419
6420                         screen_name[i] = strdup(tmp);
6421                 }
6422                 else 
6423                 {
6424                         // parameter
6425
6426 // FIXME: check for NM_MAX_FIELDS
6427
6428                         // check for x coord
6429                         if ((tmp = strtok(NULL, ":\t\n")) == NULL)
6430                                 continue;
6431                         x = atoi(tmp);
6432
6433                         // check for y coord
6434                         if ((tmp = strtok(NULL, ":\t\n")) == NULL)
6435                                 continue;
6436                         y = atoi(tmp);
6437
6438                         // check for len
6439                         if ((tmp = strtok(NULL, ":\t\n")) == NULL)
6440                                 continue;
6441                         len = atoi(tmp);
6442         
6443                         // check for screen
6444                         if ((tmp = strtok(NULL, ":\t\n")) == NULL)
6445                                 continue;
6446                         s = atoi(tmp);
6447
6448                         // check for netmon manual name
6449                         if ((tmp = strtok(NULL, ":\t\n")) == NULL)
6450                         {       fprintf(stderr,
6451                                         "%s: PARAMETER <%s> in screen <%d>, not have netmon manual reference\n",
6452                                         f_name, param_name, s);
6453                                 free_nm_info(start);
6454                                 return(NULL);
6455                         }
6456                         strcpy(tmp_mname, tmp);
6457
6458                         // check for data type (optional)
6459                         if ((tmp = strtok(NULL, ":\t\n")) != NULL)      
6460                                 t = *tmp;
6461                         else
6462                                 t = '\0';
6463
6464                         // check len, here, so we print parameter name
6465                         if (len == 0)
6466                         {       fprintf(stderr,
6467                                         "%s: PARAMETER <%s> in screen <%d>, has invalid data lenght\n",
6468                                         f_name, param_name, s);
6469                                 free_nm_info(start);
6470                                 return(NULL);
6471                         }
6472
6473                         // check if already defined same param_name
6474                         check = start;
6475                         while (check->next != NULL)
6476                         {       check = check->next;
6477                                 if (strcmp(param_name, check->name) == 0)
6478                                 {
6479                                         fprintf(stderr,
6480                                         "%s: PARAMETER <%s> in screen <%d> already defined as in screen <%d>\n",
6481                                         f_name, param_name, s, check->s_nr);
6482                                         free_nm_info(start);
6483                                         return(NULL);
6484                                 }
6485                         }
6486
6487                         // make space, and add parameter
6488                         if ((info->next = malloc(sizeof(PARAM_INFO_MON))) != NULL)
6489                         {
6490                                 info = info->next;
6491                                 info->name = strdup(param_name);
6492                                 info->x = x;
6493                                 info->y = y;
6494                                 info->len = len;
6495                                 info->s_nr = s;
6496                                 info->mname = strdup(tmp_mname);
6497                                 info->type = t;
6498
6499                                 info->next = NULL;      // mark end
6500                         }
6501                         else
6502                         {
6503                                 fprintf(stderr, "no mem");
6504                                 free_nm_info(start);
6505                                 return(NULL);
6506                         }
6507
6508                 }
6509         
6510         }
6511
6512         fclose(f_info);
6513         
6514 #ifdef DEBUG
6515         info = start;
6516         while (info->next != NULL)
6517         {
6518                 info = info->next;
6519                 fprintf(stderr, "info name %s\n", info->name);
6520         }
6521 #endif
6522         return(start);
6523 }
6524
6525 // 2, parse the arguments and check command(s) line 
6526 // command line, phone spec input, and output are complex,
6527 // so we exit printing info about error instead of std help
6528 ///////////////////////////////////////////////////////////////////////////////
6529
6530 int parse_check(int argc, char *argv[], PARAM_INFO_MON *start, char *f_name, int line)
6531 {
6532         int ctr;
6533         int i;
6534         int time_spec;
6535         int found_data;
6536         char *p;
6537         char *tmp;
6538         char *o;
6539         PARAM_INFO_MON *info;                   // iterator on this list
6540
6541 #ifdef DEBUG
6542         for (i = 0; i < argc; i++)
6543                 fprintf(stderr, "argv[%d] = <%s>\n",i, argv[i]);
6544 #endif
6545
6546         time_spec = 0;
6547         ctr = 0; 
6548         i = 0;
6549         while (i < argc)
6550         {
6551                 p = argv[i];
6552                 if (*p == '-')
6553                 {                       // should be one of the short option
6554                         if (strcmp(argv[i], "-fs") == 0)
6555                         {               // field separator, next arg should be a string
6556                                 if (((i+1) < argc) && (strlen(argv[i+1]) < 10))
6557                                 {       i++;
6558                                         // arg OK, do nothing
6559                                 }
6560                                 else
6561                                 {       if (line)
6562                                                 fprintf(stderr,
6563                                                         "-fs: Invalid field separator in <%s> at line %d\n",
6564                                                         f_name, line);
6565                                         else
6566                                                 fprintf(stderr, "-fs: Invalid field separator\n");
6567                                         return(-1);
6568                                 }
6569                         }
6570                         else if (strcmp(argv[i], "-ls") == 0) 
6571                         {               // line separator, next arg should be a string
6572                                 if (((i+1) < argc) && (strlen(argv[i+1]) < 10))
6573                                 {       i++;
6574                                         // arg OK, do nothing
6575                                 }
6576                                 else
6577                                 {       if (line)
6578                                                 fprintf(stderr,
6579                                                         "-ls: Invalid line separator in <%s> at line %d\n",
6580                                                         f_name, line);
6581                                         else
6582                                                 fprintf(stderr, "-ls: Invalid line separator\n");
6583                                         return(-1);
6584                                 }
6585                         }
6586                         else if (strcmp(argv[i], "-tm") == 0) 
6587                         {               // time separator, next arg should be a millisecond (200-10000)
6588                                 if (time_spec)
6589                                 {       if (line)
6590                                                 fprintf(stderr,
6591                                                 "-tm, -ts, are mutually exclusive in <%s> at line %d\n",
6592                                                 f_name, line);
6593                                         else
6594                                                 fprintf(stderr, "-tm, -ts, are mutually exclusive\n");
6595                                         return(-1);
6596                                 }
6597
6598                                 if (((i+1) < argc) && (atoi(argv[i+1]) >= 200) && (atoi(argv[i+1]) <= 10000))
6599                                 {       i++;
6600                                         time_spec = 1;
6601                                         // arg OK, do nothing
6602                                 }
6603                                 else
6604                                 {       if (line)
6605                                                 fprintf(stderr,
6606                         "-tm: Invalid argument (200-10000 milliseconds), in <%s> at line %d\n",
6607                                                         f_name, line);
6608                                         else
6609                                                 fprintf(stderr, "-tm: Invalid argument (200-10000 milliseconds)\n");
6610                                         return(-1);
6611                                 }
6612                         }
6613                         else if (strcmp(argv[i], "-ts") == 0) 
6614                         {               // time separator, next arg should be a seconds (1-3600)
6615                                 if (time_spec)
6616                                 {       if (line)
6617                                                 fprintf(stderr,
6618                                                 "-tm, -ts, are mutually exclusive, in <%s> at line %d\n",
6619                                                         f_name, line);
6620                                         else
6621                                                 fprintf(stderr, "-tm, -ts, are mutually exclusive\n");
6622                                         return(-1);
6623                                 }
6624
6625                                 if (((i+1) < argc) && (atoi(argv[i+1]) >= 1) && (atoi(argv[i+1]) <= 3600))
6626                                 {       i++;
6627                                         time_spec = 1;
6628                                         // arg OK, do nothing
6629                                 }
6630                                 else
6631                                 {       if (line)
6632                                                 fprintf(stderr,
6633                                         "-ts: Invalid argument (1-3600 seconds) in <%s> at line %d\n",  
6634                                                         f_name, line);
6635                                         else
6636                                                 fprintf(stderr, "-ts: Invalid argument (1-3600 seconds)\n");
6637                                         return(-1);
6638                                 }
6639                         }
6640                         else if (strcmp(argv[i], "-n") == 0) 
6641                         {               // nr of data pump, before stop collection,
6642                                         // next arg should be a int > 0
6643                                 if (((i+1) < argc) && (atoi(argv[i+1]) >= 1) && (atoi(argv[i+1]) <= 99999))
6644                                 {       i++;
6645                                         // arg OK, do nothing
6646                                 }
6647                                 else
6648                                 {       if (line)
6649                                                 fprintf(stderr,
6650                                                 "-n: Invalid argument (1-99999 times) in <%s> at line %d\n",
6651                                                         f_name, line);
6652                                         else
6653                                                 fprintf(stderr, "-n: Invalid argument (1-99999 times)\n");
6654                                         return(-1);
6655                                 }
6656                         }
6657                         else if (strcmp(argv[i], "-h") == 0) 
6658                         {               // we do NOT want header (default with header)
6659                                         // arg OK, do nothing
6660                         }
6661                         else if (strcmp(argv[i], "-S") == 0) 
6662                         {               // we have used use specs from a file instead of standard info,
6663                                         // next arg is an existing readable filename
6664                                         // as already parsed correctly, we skip here.
6665                                 i++;
6666                         }
6667                         else if (strcmp(argv[i], "-I") == 0) 
6668                         {               // we have used input from a file instead of command line
6669                                         // next arg is an existing readable filename
6670                                         // as already parsed correctly, we skip here.
6671                                 i++;
6672                         }       
6673                         else
6674                         {       
6675                                 if (line)
6676                                         fprintf(stderr, "Unrecognized option %s in <%s> at line %d\n",
6677                                                 argv[i], f_name, line);
6678                                         else
6679                                                 fprintf(stderr, "Unrecognized option %s\n", argv[i]);
6680                                 return(-1);
6681                         }
6682                 }
6683                 else
6684                 {                       // should be required data
6685                         tmp = strdup(argv[i]);
6686                         p = strtok(tmp, ":\t\n");
6687                         while (p != NULL)
6688                         {
6689                                 // check if there is an output format specification
6690                                 o = p;
6691                                 while (*o)
6692                                 {
6693                                         o++;
6694                                         if (*o == '-')
6695                                         {       *o = '\0';
6696                                                 o++;
6697                                                 if (strlen(o) == 0)
6698                                                 {
6699                                                         // we have 'minus', so, probably forget format ...
6700
6701                                                         if (line)
6702                                                                 fprintf(stderr,
6703                                          "Required data <%s->, without format specifiers in <%s> at line %d\n",
6704                                                                         p, f_name, line);
6705                                                         else
6706                                                                 fprintf(stderr,
6707                                          "Required data <%s->, without format specifiers\n", p);
6708                                                         return(-1);
6709                                                 }
6710                                         }
6711                                 }
6712                         
6713                                                                 // we check for params
6714                                 found_data = 0;
6715                                 info = start;
6716                                 while (info->next != NULL)
6717                                 {       
6718                                         info = info->next;
6719                                         if (strcmp(p, info->name) == 0)
6720                                         {
6721                                                 if (ctr > NM_MAX_FIELDS)
6722                                                 {
6723                                                         if (line)
6724                                                                 fprintf(stderr,
6725                                                 "too much data field ... in file <%s> at line %d\n",
6726                                                                         f_name, line);
6727                                                         else
6728                                                 fprintf(stderr, "too much data field ...\n");
6729                                                         return (-1);
6730                                                 }
6731 /*
6732                                                 data[ctr] = info;
6733                                                 out_f[ctr] = *o;
6734 */
6735                                                 found_data = 1;
6736                                                 ctr++;
6737                                                 break;
6738                                         }
6739                                 }
6740                         
6741                                 if (found_data == 0)
6742                                 {
6743                                         if (line)
6744                                                 fprintf(stderr,
6745                         "Required data <%s>, not found in info-mon specifications in <%s> at line %d\n",
6746                                                         p, f_name, line);
6747                                         else
6748                                                 fprintf(stderr,
6749                         "Required data <%s>, not found in info-mon specifications\n", p);
6750                                         return(-1);
6751                                 }
6752         
6753                                 p = strtok(NULL, ":\t\n");
6754
6755                         } // end while strtok
6756
6757                 } // end else '-' (short options)
6758                 
6759                 i++;
6760
6761         } // end while
6762         
6763         if (ctr == 0)
6764         {
6765                 if (line)
6766                         fprintf(stderr, "no required data! in <%s> at line %d\n", f_name, line);
6767                 else
6768                         fprintf(stderr, "no required data!\n");
6769                 return(-1);
6770         }
6771
6772         return 0;
6773 }
6774                                                           
6775 // 2, parse the arguments and process the command line
6776 // no checks are needed here, because already do in parse_check
6777 // it return a pointer to info needed for make output, or NULL if errors
6778 ///////////////////////////////////////////////////////////////////////////////
6779 OUT_INFO_MON *parse_process(int argc, char *argv[], PARAM_INFO_MON *start)
6780 {
6781         int ctr;
6782         int i;
6783         int time_spec;
6784         int found_data;
6785         int req_tm;
6786         int req_ts;
6787         char *p;
6788         char *tmp;
6789         char *o;
6790         PARAM_INFO_MON *info;                   // iterator on this list
6791         OUT_INFO_MON *out_param;                // iterator on this list
6792
6793         if ((out_param = malloc(sizeof(OUT_INFO_MON))) == NULL)
6794         {       fprintf(stderr, "no mem\n");
6795                 return(NULL);
6796         }
6797
6798 #ifdef DEBUG
6799         fprintf(stderr, "parse_process: argc = %d\n", argc);
6800                 for (i = 0; i < argc; i++)
6801                         fprintf(stderr, "argv[%d] = <%s>\n",i, argv[i]);
6802 #endif
6803
6804         for (i = 0; i < NM_MAX_FIELDS; i++)
6805                 out_param->data[i] = NULL;
6806
6807         strcpy(out_param->req_fs, " ");
6808 #ifdef WIN32
6809         strcpy(out_param->req_ls, "\n\r");
6810 #else
6811         strcpy(out_param->req_ls, "\n");
6812 #endif
6813         time_spec = 0;
6814         out_param->req_n = 0;
6815         out_param->req_header = 1;
6816
6817         time_spec = 0;
6818         req_tm = 200;                   /* default wait */
6819         req_ts = 0;     
6820         
6821         ctr = 0; 
6822         i = 0;
6823         while (i < argc)
6824         {
6825                 p = argv[i];
6826                 if (*p == '-')
6827                 {                       // should be one of the short option
6828                         if (strcmp(argv[i], "-fs") == 0)
6829                         {               // field separator, next arg should be a string
6830                                 if (((i+1) < argc) && (strlen(argv[i+1]) < 10))
6831                                 {       i++;
6832                                         strcpy(out_param->req_fs, argv[i]);
6833                                 }
6834                                 else
6835                                 {       fprintf(stderr, "NEVER BE:-fs: Invalid field separator\n");
6836                                         return(NULL);
6837                                 }
6838                         }
6839                         else if (strcmp(argv[i], "-ls") == 0) 
6840                         {               // line separator, next arg should be a string
6841                                 if (((i+1) < argc) && (strlen(argv[i+1]) < 10))
6842                                 {       i++;
6843                                         strcpy(out_param->req_ls, argv[i]);
6844                                 }
6845                                 else
6846                                 {       fprintf(stderr, "NEVER BE:-ls: Invalid line separator\n");
6847                                         return(NULL);
6848                                 }
6849                         }
6850                         else if (strcmp(argv[i], "-tm") == 0) 
6851                         {               // time separator, next arg should be a millisecond (200-10000)
6852                                 if (time_spec)
6853                                 {       fprintf(stderr, "NEVER BE:-tm, -ts, are mutually exclusive");
6854                                         return(NULL);
6855                                 }
6856
6857                                 if (((i+1) < argc) && (atoi(argv[i+1]) >= 200) && (atoi(argv[i+1]) <= 10000))
6858                                 {       i++;
6859                                         req_tm = atoi(argv[i]);
6860                                         time_spec = 1;
6861                                 }
6862                                 else
6863                                 {       fprintf(stderr, "NEVER BE:-tm: Invalid argument (200-10000 milliseconds)\n");
6864                                         return(NULL);
6865                                 }
6866                         }
6867                         else if (strcmp(argv[i], "-ts") == 0) 
6868                         {               // time separator, next arg should be a seconds (1-3600)
6869                                 if (time_spec)
6870                                 {       fprintf(stderr, "NEVER BE:-tm, -ts, are mutually exclusive");
6871                                         return(NULL);
6872                                 }
6873
6874                                 if (((i+1) < argc) && (atoi(argv[i+1]) >= 1) && (atoi(argv[i+1]) <= 3600))
6875                                 {       i++;
6876                                         req_ts = atoi(argv[i]);
6877                                         time_spec = 1;
6878
6879                                         // delete default
6880                                         req_tm = 0;
6881                                 }
6882                                 else
6883                                 {       fprintf(stderr, "NEVER BE:-ts: Invalid argument (1-3600 seconds)\n");
6884                                         return(NULL);
6885                                 }
6886                         }
6887                         else if (strcmp(argv[i], "-n") == 0) 
6888                         {               // nr of data pump, before stop collection,
6889                                         // next arg should be a int > 0
6890                                 if (((i+1) < argc) && (atoi(argv[i+1]) >= 1) && (atoi(argv[i+1]) <= 99999))
6891                                 {       i++;
6892                                         out_param->req_n = atoi(argv[i]);
6893                                 }
6894                                 else
6895                                 {       fprintf(stderr, "NEVER BE:-n: Invalid argument (1-99999 times)\n");
6896                                         return(NULL);
6897                                 }
6898                         }
6899                         else if (strcmp(argv[i], "-h") == 0) 
6900                         {               // we do NOT want header (default with header)
6901                                 out_param->req_header = 0;
6902                         }
6903                         else if (strcmp(argv[i], "-S") == 0) 
6904                         {               // we have used use specs from a file instead of standard info,
6905                                         // next arg is an existing readable filename
6906                                         // as already parsed correctly, we skip here.
6907                                 i++;
6908                         }
6909                         else if (strcmp(argv[i], "-I") == 0) 
6910                         {               // we have used input from a file instead of command line
6911                                         // next arg is an existing readable filename
6912                                         // as already parsed correctly, we skip here.
6913                                 i++;
6914                         }       
6915                         else
6916                         {       
6917                                 fprintf(stderr, "NEVER BE:Unrecognized option %s\n", argv[i]);
6918                                 return(NULL);
6919                         }
6920                 }
6921                 else
6922                 {                       // should be required data
6923                         tmp = strdup(argv[i]);
6924                         p = strtok(tmp, ":\t\n");
6925                         while (p != NULL)
6926                         {
6927                                 // check if there is an output format specification
6928                                 o = p;
6929                                 while (*o)
6930                                 {
6931                                         o++;
6932                                         if (*o == '-')
6933                                         {       *o = '\0';
6934                                                 o++;
6935                                                 if (strlen(o) == 0)
6936                                                 {
6937                                                         // we have 'minus', so, probably forget format ...
6938
6939                                                         fprintf(stderr,
6940                                                          "NEVER BE:Required data <%s->, without format specifiers\n", p);
6941                                                         return(NULL);
6942                                                 }
6943                                         }
6944                                 }
6945                         
6946                                                         // we check for params
6947                                 found_data = 0;
6948                                 info = start;
6949                                 while (info->next != NULL)
6950                                 {       
6951                                         info = info->next;
6952                                         if (strcmp(p, info->name) == 0)
6953                                         {
6954                                                 if (ctr > NM_MAX_FIELDS)
6955                                                 {
6956                                                         fprintf(stderr, "NEVER BE:too much data field ...");
6957                                                         return(NULL);
6958                                                 }
6959                                                 out_param->data[ctr] = info;
6960                                                 out_param->out_f[ctr] = *o;
6961                                                 found_data = 1;
6962                                                 ctr++;
6963                                                 break;
6964                                         }
6965                                 }
6966                                 
6967                                 if (found_data == 0)
6968                                 {
6969                                         fprintf(stderr,
6970                                                 "NEVER BE:Required data <%s>, not found in info-mon specifications\n", p);
6971                                         return(NULL);
6972                                 }
6973         
6974
6975                                 p = strtok(NULL, ":\t\n");
6976
6977                         } // end while strtok
6978
6979                         // here, we have an array of pointers to required data
6980                         // and an array of output specifiers, from 0 to [ctr-1]
6981
6982                 } // end else '-' (short options)
6983                 
6984                 i++;
6985
6986         } // end while
6987         
6988         if (ctr == 0)
6989         {
6990                 fprintf(stderr, "NEVER BE:no required data!\n");
6991                 return(NULL);
6992         }
6993         
6994         // now, what netmon screen we need to retrieve ?
6995         // we need somewhat were checking is faster, as our goal is lower cicle time
6996
6997         // we can have NM_MAX_SCREEN=254 screens, so we use an array, of unsigned char,
6998         // each char contain number of needed screen, 255 is list terminator
6999         
7000         for (i = 0; i <= NM_MAX_SCREEN; i++)
7001                 out_param->req_screen[i] = 255;
7002
7003         ctr = 0;
7004 #ifdef DEBUG
7005 fprintf(stderr, "Start Required data %s screen %d\n", out_param->data[ctr]->name, out_param->data[ctr]->s_nr);
7006 #endif
7007         while (out_param->data[ctr] != NULL)
7008         {
7009 #ifdef DEBUG
7010 fprintf(stderr, "Required data %s screen %d\n", out_param->data[ctr]->name, out_param->data[ctr]->s_nr);
7011 #endif
7012                 // check if screen already in 
7013                 found_data = 0;
7014                 i = 0;
7015                 while (out_param->req_screen[i] != 255)
7016                 {
7017                         if (out_param->req_screen[i] == out_param->data[ctr]->s_nr)
7018                         {               // already load, skip
7019                                 found_data = 1;
7020                                 break;
7021                         }
7022                         i++;
7023                 }
7024
7025                 if (found_data == 0)
7026                 {       
7027 #ifdef DEBUG
7028 fprintf(stderr, "i = %d, out_param->req_screen[%d] = %d\n", i, i, out_param->data[ctr]->s_nr);
7029 #endif
7030                         out_param->req_screen[i] = out_param->data[ctr]->s_nr;
7031                         i++;
7032                 }
7033
7034                 ctr++;
7035         }
7036
7037 #ifdef DEBUG
7038 i = 0;
7039 while (out_param->req_screen[i] != 255)
7040 {
7041         fprintf(stderr, "Required screen %d\n", out_param->req_screen[i]);
7042         i++;
7043 }
7044 #endif
7045         
7046         if (req_tm)
7047                 out_param->req_wait = req_tm * 1000;
7048         else if (req_ts)
7049                 out_param->req_wait = req_ts * 1000000;
7050         else
7051                 out_param->req_wait = req_tm * 1000;
7052         
7053
7054         return(out_param);
7055 }
7056
7057 int nmd_output(OUT_INFO_MON *out_param)
7058 {
7059         int d;
7060         int len;
7061         int ctr;
7062         int i;
7063         int nr_line;
7064         char *p;
7065         int nr_chr;
7066         int n;
7067         char Screen[NM_MAX_SCREEN_WIDTH];
7068         time_t sec;
7069         struct tm *date_time;
7070
7071         if (out_param->req_header)
7072         {
7073 // print phone help header
7074                 d = 0;
7075                 while (out_param->data[d] != NULL)
7076                 {       len = out_param->data[d]->len;
7077                         if (strlen(out_param->data[d]->name) > len)
7078                                 len = strlen(out_param->data[d]->name);
7079                         if (strlen(out_param->data[d]->mname) > len)
7080                                 len = strlen(out_param->data[d]->mname);
7081                         printf("%*.*s%s", len, len, out_param->data[d]->name, out_param->req_fs);
7082                         d++;
7083                 }
7084                 printf("%s", out_param->req_ls);
7085
7086 // print netmon manual header
7087                 d = 0;
7088                 while (out_param->data[d] != NULL)
7089                 {       len = out_param->data[d]->len;
7090                         if (strlen(out_param->data[d]->name) > len)
7091                                 len = strlen(out_param->data[d]->name);
7092                         if (strlen(out_param->data[d]->mname) > len)
7093                                 len = strlen(out_param->data[d]->mname);
7094                         printf("%*.*s%s", len, len, out_param->data[d]->mname, out_param->req_fs);
7095                         d++;
7096                 }
7097                 printf("%s", out_param->req_ls);
7098                 printf("%s", out_param->req_ls);
7099         }
7100
7101         ctr = 0;
7102         while (!bshutdown)
7103         {
7104 // stop after n data punp
7105
7106                 ctr++;
7107                 if ((out_param->req_n) && (ctr > out_param->req_n))
7108                         break;
7109
7110 //              datapump: for each screen, for each required data, load data info->value
7111
7112                 i = 0;
7113                 while(out_param->req_screen[i] != 255)
7114                 {       
7115                         if (out_param->req_screen[i] == 0)
7116                         {       
7117                                 sec = time(0);
7118                                 date_time = localtime(&sec);
7119                                 sprintf(Screen, "%02d-%02d-%04d\n%02d:%02d:%02d\n",
7120                                         date_time->tm_mday,
7121                                         date_time->tm_mon+1,
7122                                         date_time->tm_year+1900,
7123                                         date_time->tm_hour,
7124                                         date_time->tm_min,
7125                                         date_time->tm_sec);
7126 #ifdef DEBUG
7127                                 fprintf(stderr, "%02d-%02d-%04d\n%02d:%02d:%02d\n",
7128                                         date_time->tm_mday,
7129                                         date_time->tm_mon+1,
7130                                         date_time->tm_year+1900,
7131                                         date_time->tm_hour,
7132                                         date_time->tm_min,
7133                                         date_time->tm_sec);
7134 #endif
7135                         }
7136                         else
7137                         {
7138                                 GSM->NetMonitor(out_param->req_screen[i], Screen);
7139                         }
7140
7141 // we have one screen of data, load those required
7142
7143                         d = 0;
7144                         while (out_param->data[d] != NULL)
7145                         {       
7146                                 if (out_param->data[d]->s_nr == out_param->req_screen[i])
7147                                 {
7148                                         p = Screen;
7149 // goto req y           
7150                                         nr_line = out_param->data[d]->y;
7151                                         while ((*p) && (nr_line))
7152                                         {       
7153                                                 if (*p == '\n')
7154                                                 {       nr_line--;
7155                                                 }
7156                                                 p++;
7157                                         }
7158 #ifdef DEBUG
7159 fprintf(stderr, "\nthis line: %s\n\n", p);
7160 #endif
7161
7162 // goto req x
7163                                         nr_chr = out_param->data[d]->x;
7164                                         while ((*p) && (nr_chr))
7165                                         {       p++;
7166                                                 nr_chr--;
7167                                         }
7168 // this the start of data
7169                                         n = 0;
7170                                         len = out_param->data[d]->len;
7171                                         while ((*p) && (len))
7172                                         {       out_param->data[d]->value[n] = *p;
7173                                                 p++;
7174                                                 n++;
7175                                                 len--;
7176                                         }
7177 // pad with space if shorter than presumed
7178                                         while ((*p) && (len))
7179                                         {       out_param->data[d]->value[n] = ' ';
7180                                                 n++;
7181                                                 len--;
7182                                         }
7183
7184                                         out_param->data[d]->value[n] = '\0';
7185                                 }
7186
7187                                 d++;    // next screen
7188                         }
7189
7190                         i++;            // next screen
7191                 }
7192
7193 // print row of data
7194                 d = 0;
7195                 while (out_param->data[d] != NULL)
7196                 {       
7197                         len = out_param->data[d]->len;
7198                         if (out_param->req_header)
7199                         {       if (strlen(out_param->data[d]->name) > len)
7200                                         len = strlen(out_param->data[d]->name);
7201                                 if (strlen(out_param->data[d]->mname) > len)
7202                                         len = strlen(out_param->data[d]->mname);
7203                         }
7204 // FIXME check format
7205                         printf("%*.*s%s", len, len, out_param->data[d]->value, out_param->req_fs);
7206                         d++;
7207                 }
7208                 printf("%s", out_param->req_ls);
7209
7210                 usleep(out_param->req_wait);
7211                 
7212         }
7213
7214         printf("%s%s", out_param->req_ls, out_param->req_ls);
7215
7216         return(0);
7217 }
7218
7219 // main func
7220 ///////////////////////////////////////////////////////////////////////////////
7221 int netmonitordata(int argc, char *argv[])
7222 {
7223         char *loc_info = NULL;                  // path to --netmonitordata directory
7224         char *f_name;                           // absolute path of phone info-file
7225         int flag_phone_spec = 0;                // flags, set if used -S option
7226
7227         char model[20] = "phonepar";            // TO DO: PHONE AUTODETECTION
7228 //      char phver[20] = "";
7229
7230         PARAM_INFO_MON *start;                  // pointer to list of parsed phone params
7231         OUT_INFO_MON *out_param;                // pointer to struct of output data
7232
7233         char *f_commands = NULL;                // file containings input line arguments
7234         FILE *commands;                         // Handle for this file
7235         char buf[1024];                         // buffer
7236         char *f_argv[NM_MAX_FIELDS+30];         // space for parameters and cmdline options
7237         int f_argc;
7238         char *p, *tmp;                          // various counter, flags, tmp area ...
7239         int i;
7240         int line;
7241         
7242
7243         fbusinit(NULL);
7244
7245         signal(SIGINT, interrupted);
7246         
7247 // FIXME model, phone_version
7248
7249         // before parsing phone-info-file, we check for user specified phone-info-file
7250
7251         i = 0;
7252         while (i < argc)
7253         {
7254                 if (strcmp(argv[i], "-S") == 0)
7255                 {
7256                         if ((i+1) < argc)
7257                         {
7258                                 flag_phone_spec = 1;
7259                                 loc_info = strdup(argv[i+1]);
7260                                 break;
7261                         }
7262                         else
7263                         {       fprintf(stderr, "option -S require an argument ...\n");
7264                                 return -1;
7265                         }
7266                 }
7267
7268                 i++;
7269         }
7270         
7271         if (loc_info != NULL)
7272         {       f_name = strdup(loc_info);
7273         }
7274         else                            // we use standard file specification
7275         {
7276                 if ((tmp = getenv("INFOMONPATH")) == NULL)
7277                 {       loc_info = strdup(".");
7278                 }
7279                 else
7280                 {       loc_info = strdup(tmp);
7281                 }
7282
7283                 f_name = malloc(strlen(loc_info)+strlen(model)+10); 
7284                 sprintf(f_name, "%s/%s", loc_info, model);
7285         }
7286
7287
7288 #ifdef DEBUG
7289 //      fprintf(stderr, "Loc_info <%s> model <%s> version <%s>\n", loc_info, model, phver);
7290         fprintf(stderr, "Info file: <%s>\n", f_name);
7291 #endif
7292         if ((start = get_mon_param_info(f_name, NULL)) == NULL)
7293                 return(-1);             
7294
7295         // option -I give us the possibility of specify a filename,
7296         // containing a "sequence" of command line args.
7297         // if you specify this option, you can use (on command line) only -S option.
7298         // other options may be specified inside the input-file.
7299         // contents of this file as the same sintax as the command line,
7300         // except it must not contain "--netmonitordata" or "-I" or "-S" options 
7301         ///////////////////////////////////////////////////////////////////////
7302
7303         i = 0;
7304         while (i < argc)
7305         {
7306                 if (strcmp(argv[i], "-I") == 0)
7307                 {
7308                         if ((i+1) < argc)
7309                         {
7310                                 if ((argc == 2) || ((argc == 4) && flag_phone_spec == 1))
7311                                 {       f_commands = strdup(argv[i+1]);
7312                                 }
7313                                 else
7314                                 {       fprintf(stderr, "option -I accept only additional -S option.\n");
7315                                         return -1;
7316                                 }
7317
7318                                 break;
7319                         }
7320                         else
7321                         {       fprintf(stderr, "option -I require an argument ...\n");
7322                                 return -1;
7323                         }
7324                 }
7325
7326                 i++;
7327         }
7328         
7329         // before all, we check all command line
7330         
7331         if (f_commands != NULL)
7332         {       
7333 #ifdef DEBUG
7334                 fprintf(stderr, "netmonitordata(check): commands from <%s>\n", f_commands);
7335 #endif
7336                 // for each line
7337                 // do
7338                 //      read line, make array f_argv, and counter f_argc
7339                 //      parse & check args, so errors are checked before real processing
7340                 //                             (-I option here is ignored)
7341                 //                             (-S option can be here, and it is used)
7342                 // done
7343
7344                 if ((commands = fopen(f_commands, "r")) == NULL)
7345                 {       fprintf(stderr, "Can' t open file commands input :<%s>n", f_commands);
7346                         return(-1);
7347                 }
7348         
7349 // FIXME line may be be splitted
7350                 line = 0;
7351                 while (fgets(buf, 1024, commands) != NULL)
7352                 {       
7353                         p = buf;
7354                         line++;
7355
7356                         // Truncate from '#' at right of comments
7357                         if ((tmp = strchr(p, '#')) != NULL)
7358                                 *tmp = '\0';
7359
7360                         // Strip leading, trailing whitespace
7361                         while(isspace((int) *p))
7362                                 p++;
7363
7364                         while((strlen(p) > 0) && isspace((int) p[strlen(p) - 1]))
7365                                 p[strlen(p) - 1] = '\0';
7366         
7367                         // Ignore blank lines
7368                         if ((*p == '\n') || (*p == '\0'))
7369                                 continue;
7370                         
7371 #ifdef DEBUG
7372 fprintf(stderr, "netmonitordata(check): row <%s>\n", p);
7373 #endif
7374                         // make args
7375                         f_argc = 0;
7376
7377                         p = strtok(p, " \t");
7378                         do
7379                         {       f_argv[f_argc++] = strdup(p);
7380 #ifdef DEBUG
7381 fprintf(stderr, "netmonitordata(check): token <%s>\n", p);
7382 #endif
7383                                 p = strtok(NULL, " \t");                // OK p,  (NULL)
7384                         }
7385                         while ((p != NULL) && (*p));
7386         
7387                         // here we have f_argc, f_argv, this line is OK
7388                 
7389                         if (parse_check(f_argc, f_argv, start, f_commands, line) != 0)
7390                         {       free_nm_info(start);
7391                                 return(-1);
7392                         }
7393                 }
7394         
7395                 fclose(commands);
7396         }
7397         else    // as above, but we have only command line, argv, argc.
7398         {
7399                 if (parse_check(argc, argv, start, NULL, 0) != 0)
7400                 {       free_nm_info(start);
7401                         return(-1);
7402                 }
7403         }
7404         
7405         // here, all commands line are checked, and are correct
7406
7407         if (f_commands != NULL)
7408         {       
7409 #ifdef DEBUG
7410                 fprintf(stderr, "netmonitordata(process): commands from <%s>\n", f_commands);
7411 #endif
7412
7413                 // for each line
7414                 // do
7415                 //      read line, make array f_argv, and counter f_argc
7416                 //      parse_process argument,   (-I option here is ignored)
7417                 //                                (-S option can be here, and it is used)
7418                 //      (make header                    // these are in nmd_output();
7419                 //       loop
7420                 //              get net-mon-info 
7421                 //              make output
7422                 //       done)
7423                 // done
7424
7425                 if ((commands = fopen(f_commands, "r")) == NULL)
7426                 {       fprintf(stderr, "Can' t open file commands input :<%s>n", f_commands);
7427                         return(-1);
7428                 }
7429         
7430 // FIXME line may be be splitted
7431                 while (fgets(buf, 1024, commands) != NULL)
7432                 {       
7433                         p = buf;
7434
7435                         // Truncate from '#' at right of comments
7436                         if ((tmp = strchr(p, '#')) != NULL)
7437                                 *tmp = '\0';
7438
7439                         // Strip leading, trailing whitespace
7440                         while(isspace((int) *p))
7441                                 p++;
7442
7443                         while((strlen(p) > 0) && isspace((int) p[strlen(p) - 1]))
7444                                 p[strlen(p) - 1] = '\0';
7445         
7446                         // Ignore blank lines
7447                         if ((*p == '\n') || (*p == '\0'))
7448                                 continue;
7449                         
7450                         // make args
7451
7452                         f_argc = 0;
7453                         p = strtok(p, " \t");
7454                         do
7455                         {       f_argv[f_argc++] = strdup(p);
7456                                 p = strtok(NULL, " \t");                // OK p,  (NULL)
7457                         }
7458                         while ((p != NULL) && (*p));
7459         
7460                         // here we have f_argc, f_argv, this line is OK
7461                 
7462                         if ((out_param = parse_process(f_argc, f_argv, start)) == NULL)
7463                         {       free_nm_info(start);
7464                                 return(-1);     /* NEVER BE */
7465                         }
7466                 
7467                         // here, command line has no error ...
7468
7469                         nmd_output(out_param);
7470
7471                         free(out_param);
7472                 }
7473         
7474                 fclose(commands);
7475         }
7476         else    // as above, but we have only command line, argv, argc.
7477         {
7478                 if ((out_param = parse_process(argc, argv, start)) == NULL)
7479                 {       free_nm_info(start);
7480                         return(-1);     /* NEVER BE */
7481                 }
7482                 nmd_output(out_param);
7483
7484                 free(out_param);
7485         }
7486         GSM->Terminate();
7487
7488         free(loc_info);
7489         free(f_name);
7490
7491 /* I analised this source and this should be done. But when compile with VC6 */
7492 /* I have error. So, commented... MW */
7493 #ifndef VC6
7494         free_nm_info(start);
7495 #endif
7496
7497         return(0);
7498 }
7499
7500
7501 // used by nm_collect()
7502 ///////////////////////////////////////////////////////////////////////////////
7503 char *rowScreen(char *s)
7504 {
7505         char *p;
7506         
7507         // make Screen in one row
7508         p = s;
7509         while(*p)
7510         {
7511             if (*p == '\n')
7512                         *p = ' ';
7513             p++;
7514         }
7515
7516         return(s);
7517 }
7518
7519 void printtime(void)
7520 {
7521
7522   struct mydate {
7523     int Year;          /* The complete year specification - e.g. 1999. Y2K :-) */
7524     int Month;         /* January = 1 */
7525     int Day;
7526     int Hour;
7527     int Minute;
7528     int Second;
7529     int Timezone;      /* The difference between local time and GMT */
7530   } Date;
7531
7532   struct tm *now;
7533   time_t nowh;
7534   nowh=time(NULL);
7535   now=localtime(&nowh);
7536
7537   Date.Year = now->tm_year;
7538   Date.Month = now->tm_mon+1;
7539   Date.Day = now->tm_mday;
7540   Date.Hour = now->tm_hour;
7541   Date.Minute = now->tm_min;
7542   Date.Second = now->tm_sec;
7543
7544   /* I have 100 (for 2000) Year now :-) */
7545   if (Date.Year>99 && Date.Year<1900) {
7546     Date.Year=Date.Year+1900;
7547   }
7548
7549   printf("%d:%d:%d:%d:%d:%d      ",Date.Day,Date.Month,Date.Year,Date.Hour,Date.Minute,Date.Second);
7550
7551 }
7552
7553 // like netmonitor(), but print in one row, 1, 2 or 3 screen, every ~0.3 s
7554 ///////////////////////////////////////////////////////////////////////////////
7555 int nm_collect(int argc, char *argv[])
7556 {
7557         int mode[MAX_NM_COLLECT];
7558         char Screen[NM_MAX_SCREEN_WIDTH];
7559         int i;
7560
7561         for (i=0;i<argc;i++) {
7562             argc > i ? (mode[i] = atoi(argv[i])): (mode[i] = 0);
7563         }
7564
7565         for (i=0;i<argc;i++) {
7566             if (mode[i]==0 && strcmp(argv[i],"-d")) {
7567                 fprintf(stderr, "Wrong %i parameter (not number and not -d)\n",i);
7568                 return(-1);
7569             }
7570         }
7571
7572         signal(SIGINT, interrupted);
7573
7574         fbusinit(NULL);
7575
7576         // end on CTRL-C
7577         while (!bshutdown) 
7578         {
7579                 for (i=0;i<argc;i++) {
7580                   if (!strcmp(argv[i],"-d")) {
7581                      printtime();
7582                      break;
7583                   }
7584                 }
7585                 
7586                 for (i=0;i<argc;i++) {
7587                   if (mode[i]!=0)
7588                   {
7589                         GSM->NetMonitor(mode[i], Screen);
7590                         printf("%s::", rowScreen(Screen));
7591                   }
7592                 }
7593                 
7594                 printf("\n\n");
7595
7596                 usleep(150000);
7597         }
7598
7599         GSM->Terminate();
7600
7601         return 0;
7602 }
7603
7604 #ifdef DEBUG
7605 int sniff(int argc, char *argv[])
7606 {
7607   /* base model comes from gnokiirc */
7608   strcat(model,"sniff");
7609   
7610   if (argc>0) strcpy(Port,argv[0]);
7611     
7612   /* Initialise the GSM interface. */
7613   fbusinit(NULL);
7614
7615   /* Loop here indefinitely - allows you to see messages from GSM code in
7616      response to unknown messages etc. The loops ends after pressing the
7617      Ctrl+C. */
7618   while (!bshutdown) {
7619     sleep(1);
7620   }
7621
7622   GSM->Terminate();    
7623
7624   return 0;
7625
7626 }
7627
7628 int decodefile(int argc, char *argv[])
7629 {
7630  FILE *infile;
7631  unsigned char in_buffer[255];
7632  int nr_read = 0;
7633  int i = 0;
7634
7635   /* base model comes from gnokiirc */
7636   strcat(model,"decode");
7637
7638  /* Initialise the GSM interface. */
7639  fbusinit(NULL);
7640
7641  printf ("open InPutFile: %s\n", argv[0]);
7642  if ( (infile = fopen( argv[0], "rb")) == NULL ) {
7643    printf ("Failed to open InPutFile: %s\n", argv[0]);
7644    exit (1); }
7645
7646  while ( (nr_read = fread(in_buffer, 1, 16, infile)) > 0 ) {
7647   for (i=0; i < nr_read; i++)
7648      Protocol->StateMachine(in_buffer[i]);
7649   }
7650
7651    return 0;
7652 }
7653
7654 #endif
7655
7656 int getringtone(int argc, char *argv[])
7657 {
7658   GSM_BinRingtone ringtone;
7659   GSM_Error error;
7660   GSM_Ringtone SMringtone;
7661
7662   int i;
7663   
7664   char model[64];
7665
7666   FILE *file;
7667
7668   ringtone.location=1;
7669   if (argc>1) ringtone.location=atoi(argv[1]);
7670
7671   /* Initialise the GSM interface. */
7672   fbusinit(NULL);
7673
7674   error=GSM->GetBinRingtone(&ringtone);
7675
7676   while (GSM->GetModel(model)  != GE_NONE)
7677     sleep(1);
7678
7679   GSM->Terminate();
7680
7681   fprintf(stdout, _("Downloaded ringtone, location %i: "),ringtone.location);
7682   
7683   switch (error) {
7684     case GE_NONE:
7685       fprintf(stdout, _("get succeeded!\n"));
7686       fprintf(stdout, _("Name: %s (binary format)\n"),ringtone.name);
7687       break;
7688     case GE_INVALIDRINGLOCATION:
7689       fprintf(stdout, _("invalid location %i!\n"),ringtone.location);
7690       break;
7691     case GE_UNKNOWNMODEL:
7692     
7693       /* In 3310 we have normal "Smart Messaging" format */
7694       if (GetModelFeature (FN_RINGTONES)==F_RING_SM) {
7695       
7696         i=7;
7697         if (ringtone.frame[9]==0x4a && ringtone.frame[10]==0x3a) i=8;
7698         ringtone.frame[i]=0x02;
7699         
7700         GSM_UnPackRingtone(&SMringtone, ringtone.frame+i, ringtone.length-i);
7701
7702         fprintf(stdout, _("Name: %s (normal format)\n"),SMringtone.name);
7703
7704         GSM_SaveRingtoneFileOnConsole(argv[0], &SMringtone);
7705         
7706         return 0;
7707       }
7708
7709       fprintf(stdout, _("mygnokii doesn't know format for this model!\n"));
7710       break;
7711     case GE_NOTIMPLEMENTED:
7712       fprintf(stdout, _("not implemented for this model!\n"));
7713       break;
7714     default:
7715       fprintf(stdout, _("not supported by this model!\n"));
7716       break;
7717   }
7718   
7719   if (error!=GE_NONE)
7720     return(-1);
7721   
7722   file = fopen(argv[0], "wb");
7723       
7724   if (!file)
7725     return(GE_CANTOPENFILE);
7726
7727   fwrite(ringtone.frame, 1, ringtone.length, file);     
7728   
7729   fclose(file);
7730   
7731   return 0;
7732
7733 }
7734
7735 int binringtoneconvert(int argc, char *argv[])
7736 {
7737   GSM_BinRingtone ringtone;
7738   
7739   int i,j,z;
7740   bool isok;
7741   int deflen=7,m,w;
7742   bool pause;
7743
7744   FILE *file;
7745   
7746 //{ "c", "c#", "d", "d#", "e",  "f", "f#", "g", "g#", "a", "a#", "h" };
7747   int binary_notes[12] =
7748   { 0,    1,    2,   3,    4,   6,   7,    8,   9,    10,  11 ,   12};
7749
7750   if (GSM_ReadBinRingtoneFile(argv[0],&ringtone)!=GE_NONE) {
7751     fprintf(stdout,_("Failed to read %s file!\n"),argv[0]);
7752     return -1;
7753   }
7754
7755   file = fopen(argv[1], "wb");
7756       
7757   if (!file)
7758     return(GE_CANTOPENFILE);
7759
7760   i=5;
7761   while (true) {
7762     if (ringtone.frame[i]==0) break;
7763     fprintf(file,_("%c"),ringtone.frame[i]);
7764     i++;
7765   }
7766
7767   fprintf(file,_(":d=32,o=5,b=300:"));
7768     
7769   i=i+5;j=0;z=0;
7770   while (true) {
7771     if (ringtone.frame[i]!=j) {
7772       if (j!=0) {
7773         isok=false;
7774         if (j==64) {
7775           j=255;//Pause
7776           isok=true;
7777         }
7778         if (!isok && j>=114 && j<=125) {
7779           j=14*3+binary_notes[j-114];
7780           isok=true;
7781         }
7782         if (!isok && j>=126 && j<=137) {
7783           j=14*1+binary_notes[j-126];
7784           isok=true;
7785         }
7786         if (!isok && j>=138 && j<=149) {
7787           j=14*2+binary_notes[j-138];
7788           isok=true;
7789         }
7790         if (!isok && j>=150 && j<=161) {
7791           j=14*4+binary_notes[j-150];
7792           isok=true;
7793         }
7794         if (!isok) {
7795           if (j!=10) { 
7796             fprintf(stdout,_("Unknown block in binary ringtone %i %i\n"),j,z);
7797           }
7798         } else {
7799           w=deflen;
7800           for (m=0;m<6;m++) {
7801             w=w*2;
7802             if (w>z && (w/2)<=z) {
7803               switch (m) {
7804                 case 1:fprintf(file,_("16"));break;
7805                 case 2:fprintf(file,_("8"));break;
7806                 case 3:fprintf(file,_("4"));break;
7807                 case 4:fprintf(file,_("2"));break;
7808                 case 5:fprintf(file,_("1"));break;
7809               }
7810               break;
7811             }
7812           }
7813           if (z>w) fprintf(file,_("1"));
7814           pause=false;
7815           switch (GSM_GetNote(j)) {
7816             case Note_C  :fprintf(file,_("c"));break;
7817             case Note_Cis:fprintf(file,_("c#"));break;
7818             case Note_D  :fprintf(file,_("d"));break;
7819             case Note_Dis:fprintf(file,_("d#"));break;
7820             case Note_E  :fprintf(file,_("e"));break;
7821             case Note_F  :fprintf(file,_("f"));break;
7822             case Note_Fis:fprintf(file,_("f#"));break;
7823             case Note_G  :fprintf(file,_("g"));break;
7824             case Note_Gis:fprintf(file,_("g#"));break;
7825             case Note_A  :fprintf(file,_("a"));break;
7826             case Note_Ais:fprintf(file,_("a#"));break;
7827             case Note_H  :fprintf(file,_("h"));break;
7828             default      :pause=true;fprintf(file,_("p"));break; //Pause ?
7829           }
7830           w=deflen*1.5;
7831           for (m=0;m<6;m++) {
7832             w=w*2;
7833             if (w>z && (w/2)<=z) {
7834               fprintf(file,_("."));
7835               break;
7836             }
7837           }
7838           if ((j/14)!=1 && !pause) fprintf(file,_("%i"),j/14);
7839           fprintf(file,_(","));
7840         }
7841       }
7842       j=ringtone.frame[i];
7843       z=ringtone.frame[i+1];
7844     } else {
7845       z=z+ringtone.frame[i+1];
7846     }
7847     i=i+2;
7848     if (i>=ringtone.length) break;
7849   }
7850
7851   fclose(file);
7852   
7853   return 0;
7854
7855 }
7856
7857 int renamesmsc(int argc, char *argv[])
7858 {
7859   GSM_MessageCenter MessageCenter;
7860
7861   MessageCenter.No=atoi(argv[0]);
7862
7863   /* Initialise the GSM interface. */
7864   fbusinit(NULL);
7865
7866   if (GSM->GetSMSCenter(&MessageCenter) == GE_NONE) {
7867     fprintf(stdout,_("SMSC number %i get OK\n"),MessageCenter.No);  
7868   } else {
7869     GSM->Terminate();
7870     fprintf(stdout,_("Error getting SMSC number %i\n"),MessageCenter.No);
7871     return 0;  
7872   }
7873
7874   strncpy(MessageCenter.Name,argv[1],10);
7875
7876   if (GSM->SetSMSCenter(&MessageCenter) == GE_NONE) {
7877     fprintf(stdout,_("SMSC number %i set OK (renamed to \"%s\")\n"),MessageCenter.No,MessageCenter.Name);
7878   } else {
7879     GSM->Terminate();
7880     fprintf(stdout,_("Error setting SMSC number %i\n"),MessageCenter.No);
7881     return 0;  
7882   }
7883   
7884   GSM->Terminate();
7885
7886   return 0;
7887 }
7888
7889 #endif /* UCLINUX */
7890
7891 /*
7892  * Returns number of sostituited characters.
7893  * ... may be useful one day ??
7894  */
7895 static int semicolon_pipe_substitution( GSM_PhonebookEntry *pentry, unsigned int direction )
7896         /* direction = 0 : after reading phone memory (
7897          *             1 : writing phone memory
7898          */
7899 {
7900         register int i;
7901         register int count=0;
7902         char charfrom, charto;
7903
7904         charfrom= (direction==0) ? ';' : '|';
7905         charto  = (direction==0) ? '|' : ';';
7906
7907         count+=str_substch(pentry->Name, charfrom, charto );
7908         count+=str_substch(pentry->Number, charfrom, charto );
7909
7910         for( i = 0; i < pentry->SubEntriesCount; i++ )
7911         {
7912                 if( pentry->SubEntries[i].EntryType != GSM_Date )
7913                                 count+=str_substch(pentry->SubEntries[i].data.Number ,charfrom,charto);
7914         }
7915
7916         return( count );
7917 }
7918
7919 int str_substch( char *str, const char toric, const char sost )
7920 {
7921         unsigned int ct;
7922         int i_sost=0;
7923          
7924                 for( ct = 0; ct < strlen(str); ct++ )
7925                         if( str[ct] == (unsigned char) toric )
7926                         { str[ct] = sost; i_sost++; }
7927                  
7928         return( i_sost );
7929 }                                                                               
7930
7931 #ifndef UCLINUX
7932
7933 extern GSM_Error N6110_EnableExtendedCommands (unsigned char status);
7934
7935 /* Allows to set simlock state.
7936    With older phone (older 51xx, 61xx) can open them, with older
7937    and newer should be able to close them */
7938 /* DO NOT TRY, IF DON'T WANT, WHAT YOU DO !!!!!!!!!! */
7939 int setsimlock()
7940 {
7941   GSM_AllSimlocks siml;
7942
7943   unsigned char closebuffer[20]=
7944                              { 0x00, 0x01, 0x82, 0x01,
7945                                0x00,                         /* which simlock */
7946                                0x00, 0x00,
7947                                0x00, 0x00, 0x00,             /* lock 1 info */
7948                                0x00, 0x00, 0x00, 0x00, 0x00, /* lock 4 info */
7949                                0x00, 0x00,                   /* lock 2 info */
7950                                0x00, 0x00,                   /* lock 3 info */
7951                                0x00};
7952   unsigned char openbuffer[10]= { 0x00, 0x01, 0x81, 0x01,
7953                                   0x00, /* lock number */
7954                                   0x10, 0x10, 0x10, 0x10, 0x10 };
7955   unsigned char openbuffer0[10]= {0x00, 0x01, 0x02, 0x03, 0x1f, 0x11, 0x01, 0x01, 0x10, 0x00 };
7956
7957   unsigned char info[120];
7958   int i,j;
7959   
7960   /* Initialise the code for the GSM interface. */     
7961   fbusinit(NULL);
7962   if (strstr(GSM_Info->FBUSModels, "3310") == NULL)
7963   {
7964     fprintf(stderr,("Not supported\n"));
7965     GSM->Terminate();
7966     return -1;
7967   }
7968   N6110_EnableExtendedCommands(0x02);
7969   /* Initial info */
7970   if (GSM->SimlockInfo(&siml)!=GE_NONE) {
7971     fprintf(stderr,_("Error getting simlock info\n"));GSM->Terminate();return -1;
7972   }
7973   /* Opening all locks (we must check, if we can open them) */
7974   NULL_SendMessageSequence(50, &CurrentMagicError, 10, 0x40,openbuffer0);
7975   openbuffer[4]=1;NULL_SendMessageSequence(50, &CurrentMagicError, 10, 0x40,openbuffer);
7976   openbuffer[4]=2;NULL_SendMessageSequence(50, &CurrentMagicError, 10, 0x40,openbuffer);
7977   openbuffer[4]=4;NULL_SendMessageSequence(50, &CurrentMagicError, 10, 0x40,openbuffer);
7978   openbuffer[4]=8;NULL_SendMessageSequence(50, &CurrentMagicError, 10, 0x40,openbuffer);
7979   if (GSM->SimlockInfo(&siml)!=GE_NONE) {
7980     fprintf(stderr,_("Error getting simlock info\n"));GSM->Terminate();return -1;
7981   }
7982   for (i=0;i<4;i++) {
7983     if (siml.simlocks[i].enabled) {
7984       fprintf(stderr,_("Can not open simlock %i\n"),i+1);GSM->Terminate();return -1;
7985     }
7986   }
7987   /* Making frame for closing simlocks */
7988   strcpy(info,"00101");
7989   j=0;i=7;
7990   while (j!=strlen(info)) {
7991     if (j+2<=strlen(info)) {
7992       closebuffer[i]=((info[j] & 0x0f)<<4) | (info[j+1] & 0x0f);j=j+2;
7993     } else {
7994       closebuffer[i]=(info[j] & 0x0f) << 4;j++;
7995     }i++;
7996   }
7997   strcpy(info,"0000");j=0;i=15;
7998   while (j!=strlen(info)) {
7999     if (j+2<=strlen(info)) {
8000       closebuffer[i]=((info[j] & 0x0f)<<4) | (info[j+1] & 0x0f);j=j+2;
8001     } else {
8002       closebuffer[i]=(info[j] & 0x0f) << 4;j++;
8003     }i++;
8004   }
8005   strcpy(info,"0000");j=0;i=17;
8006   while (j!=strlen(info)) {
8007     if (j+2<=strlen(info)) {
8008       closebuffer[i]=((info[j] & 0x0f)<<4) | (info[j+1] & 0x0f);j=j+2;
8009     } else {
8010       closebuffer[i]=(info[j] & 0x0f) << 4;j++;
8011     }i++;
8012   }
8013   strcpy(info,"0000000001");j=0;i=9;
8014   while (j!=strlen(info)) {
8015     if (j+2<=strlen(info)) {
8016       if (j==0) {
8017         closebuffer[i]=closebuffer[i] | (info[j] & 0x0f);j++;
8018       } else {
8019         closebuffer[i]=((info[j] & 0x0f)<<4) | (info[j+1] & 0x0f);j=j+2;
8020       }
8021     } else {
8022       closebuffer[i]=(info[j] & 0x0f) << 4;j++;
8023     }i++;
8024   }  
8025   /* Closing simlock with given values */
8026   closebuffer[4]=1+2+4+8;
8027   NULL_SendMessageSequence(50, &CurrentMagicError, 20, 0x40,closebuffer);  
8028   /* Opening all locks */
8029   NULL_SendMessageSequence(50, &CurrentMagicError, 10, 0x40,openbuffer0);
8030   openbuffer[4]=1;NULL_SendMessageSequence(50, &CurrentMagicError, 10, 0x40,openbuffer);
8031   openbuffer[4]=2;NULL_SendMessageSequence(50, &CurrentMagicError, 10, 0x40,openbuffer);
8032   openbuffer[4]=4;NULL_SendMessageSequence(50, &CurrentMagicError, 10, 0x40,openbuffer);
8033   openbuffer[4]=8;NULL_SendMessageSequence(50, &CurrentMagicError, 10, 0x40,openbuffer);
8034   GSM->Reset(0x03);
8035   GSM->Terminate();
8036   return 0;
8037 }
8038
8039 int simlockinfo()
8040 {
8041   GSM_AllSimlocks siml;
8042   char s[7];
8043
8044   /* Initialise the code for the GSM interface. */     
8045   fbusinit(NULL);
8046
8047   if (GSM->SimlockInfo(&siml)!=GE_NONE) fprintf(stderr,_("Error\n"));
8048
8049   fprintf(stdout,_("MCC + MNC : %s      ("),siml.simlocks[0].data);
8050   if (siml.simlocks[0].enabled) fprintf(stdout,_("CLOSED"));
8051                            else fprintf(stdout,_("opened"));
8052   if (siml.simlocks[0].factory) fprintf(stdout,_(") (factory"));
8053                            else fprintf(stdout,_(")    (user"));
8054   fprintf(stdout,_(") (counter %i"),siml.simlocks[0].counter);
8055
8056   s[0]=siml.simlocks[0].data[0];
8057   s[1]=siml.simlocks[0].data[1];
8058   s[2]=siml.simlocks[0].data[2];
8059   s[3]=' ';
8060   s[4]=siml.simlocks[0].data[3];
8061   s[5]=siml.simlocks[0].data[4];
8062   s[6]=0;
8063
8064   if (strcmp(GSM_GetNetworkName(s),"unknown"))
8065     fprintf(stdout,_(") (network \"%s\""),GSM_GetNetworkName(s));
8066
8067   fprintf(stdout,_(")\n"));
8068
8069   fprintf(stdout,_("GID1      : %s       ("),siml.simlocks[1].data);
8070   if (siml.simlocks[1].enabled) fprintf(stdout,_("CLOSED"));
8071                            else fprintf(stdout,_("opened"));
8072   if (siml.simlocks[1].factory) fprintf(stdout,_(") (factory"));
8073                            else fprintf(stdout,_(")    (user"));
8074   fprintf(stdout,_(") (counter %i"),siml.simlocks[1].counter);
8075   fprintf(stdout,_(")\n"));
8076
8077   fprintf(stdout,_("GID2      : %s       ("),siml.simlocks[2].data);
8078   if (siml.simlocks[2].enabled) fprintf(stdout,_("CLOSED"));
8079                            else fprintf(stdout,_("opened"));
8080   if (siml.simlocks[2].factory) fprintf(stdout,_(") (factory"));
8081                            else fprintf(stdout,_(")    (user"));
8082   fprintf(stdout,_(") (counter %i"),siml.simlocks[2].counter);
8083   fprintf(stdout,_(")\n"));
8084
8085   fprintf(stdout,_("MSIN      : %s ("),siml.simlocks[3].data);
8086   if (siml.simlocks[3].enabled) fprintf(stdout,_("CLOSED"));
8087                            else fprintf(stdout,_("opened"));
8088   if (siml.simlocks[3].factory) fprintf(stdout,_(") (factory"));
8089                            else fprintf(stdout,_(")    (user"));
8090   fprintf(stdout,_(") (counter %i"),siml.simlocks[3].counter);
8091   fprintf(stdout,_(")\n"));
8092
8093   GSM->Terminate();
8094
8095   return 0;
8096 }
8097
8098 /* Getting EEPROM from older phones */
8099 /* Tested with N5110 5.07, 6150 5.22 */
8100 int geteeprom()
8101 {
8102   int i=0x40;
8103
8104   unsigned char buffer[1000]={ 0x00, 0x01, 0xd4, 0x02, 0x00, 0xa0, 
8105                                0x00, 0x00, /* location Lo and Hi */
8106                                0x10 };     /* how many bytes */
8107
8108   strcpy(Connection,"mbus");
8109   fprintf(stderr,_("Switching connection type to MBUS\n"));
8110
8111   strcpy(model,"5110");  
8112   
8113   /* Initialise the code for the GSM interface. */     
8114   fbusinit(NULL);
8115
8116   if (strstr(GSM_Info->FBUSModels, "3310") == NULL)
8117   {
8118     fprintf(stderr,("Not supported\n"));
8119     GSM->Terminate();
8120     return -1;
8121   }
8122
8123   for (i=0;i<64;i++) {
8124     fprintf(stdout,_("%c"),0xff);
8125   }
8126   
8127   while (i<300000) {
8128     buffer[6] = i/256;
8129     buffer[7] = i%256;
8130     
8131     if ((i/256)!=((i-1)/256)) fprintf(stderr,_("."));
8132     
8133     if (NULL_SendMessageSequence(50, &CurrentMagicError, 9, 0x40,buffer)!=GE_NONE)        break;
8134
8135     i=i+0x10;
8136   }
8137
8138   fprintf(stderr,_("\n"));
8139   
8140   GSM->Terminate();
8141
8142   return 0;
8143 }
8144
8145 int getsmsfolders()
8146 {
8147   GSM_SMSFolders folders;
8148   GSM_Error error;
8149
8150   int i;
8151     
8152   /* Initialise the code for the GSM interface. */     
8153   fbusinit(NULL);
8154
8155   folders.number = 0;
8156
8157   error=GSM->GetSMSFolders(&folders);
8158   
8159   GSM->Terminate();
8160
8161   if (error!=GE_NONE && !folders.number) {
8162     fprintf(stdout,_("Error!\n"));
8163     return -1;
8164   }
8165   
8166   for (i=0;i<folders.number;i++) {
8167       fprintf(stdout,_("%i. %s\n"),i+1,folders.Folder[i].Name);
8168   }
8169   
8170   return 0;
8171 }
8172
8173 int resetphonesettings()
8174 {
8175   /* Initialise the code for the GSM interface. */     
8176   fbusinit(NULL);
8177
8178   GSM->ResetPhoneSettings();
8179
8180   GSM->Reset(0x03);  
8181   
8182   GSM->Terminate();
8183
8184   return 0;
8185 }
8186
8187 /* Checked on 3310 4.02 and doesn't work.
8188    Possible reasons: SMSC has problems (possible), bug in phone firmware
8189    (very possible) or here in code.
8190    I quess, that the second is the most possible - 3310 treat only 3 SMS
8191    as linked (the most often profile needs 4 - 2 and few bytes in 3'th
8192    for screen saver, few bytes for profile name and 1 or 2 sms for ringtone).
8193    When send separate ringtone (see --sendringtone with --profilestyle)
8194    and screen saver (--sendlogo screensaver...), it's received OK.
8195    It's for checking in higher firmware. */
8196 int sendprofile(int argc, char *argv[])
8197 {
8198   GSM_Ringtone ringtone;
8199   GSM_Bitmap bitmap;
8200   GSM_MultiSMSMessage MultiSMS;
8201
8202   int current=0,i,j;
8203
8204   u8 MessageBuffer[140*4];
8205   u16 MessageLength=0;
8206   
8207   char profilename[10+1];
8208   
8209   if (GSM_ReadRingtoneFileOnConsole(argv[2], &ringtone)!=GE_NONE) return(-1);
8210
8211   ringtone.allnotesscale=false;
8212   for (i=0;i<argc;i++)
8213     if (!strcmp(argv[i],"--scale")) ringtone.allnotesscale=true;
8214
8215   /* The fourth argument is the bitmap file. */
8216   if (GSM_ReadBitmapFileOnConsole(argv[3], &bitmap)!=GE_NONE) return -1;
8217
8218   GSM_ResizeBitmap(&bitmap,GSM_PictureImage);
8219
8220   strncpy(profilename,argv[1],10);
8221
8222   MessageBuffer[MessageLength++]=0x30;               //SM version. Here 3.0
8223
8224   MessageBuffer[MessageLength++]=SM30_PROFILENAME;   //ID for profile name
8225   MessageBuffer[MessageLength++]=0x00;               //length hi  
8226   MessageBuffer[MessageLength++]=strlen(profilename);//length lo
8227   
8228   EncodeUnicode (MessageBuffer+MessageLength,profilename ,strlen(profilename));
8229   MessageLength=MessageLength+2*strlen(profilename);
8230
8231   MessageBuffer[MessageLength++]=SM30_RINGTONE; //ID for ringtone
8232   i=MessageLength;
8233   MessageBuffer[MessageLength++]=0x01;          //length hi
8234   MessageBuffer[MessageLength++]=0x00;          //length lo
8235
8236   j=SM30_MAX_RINGTONE_FRAME_LENGTH;
8237   current=GSM_PackRingtone(&ringtone, MessageBuffer+MessageLength, &j);
8238   MessageLength=MessageLength+j;
8239
8240   if (current!=ringtone.NrNotes) {
8241     if (current>FB61_MAX_RINGTONE_NOTES) {
8242       fprintf(stderr,_("Warning: due to phone limitation"));
8243     } else {
8244       fprintf(stderr,_("Warning: ringtone was too long to be saved into SMS,"));
8245     }
8246     fprintf(stderr, _(" only %i first notes were packed (%i cut)\n"),current,ringtone.NrNotes-current);
8247   }
8248     
8249   MessageBuffer[i]=(j)/256;
8250   MessageBuffer[i+1]=(j)%256;
8251
8252   MessageBuffer[MessageLength++]=SM30_SCREENSAVER; //ID for OTA screen saver
8253   MessageBuffer[MessageLength++]=0x01;             //length hi
8254   MessageBuffer[MessageLength++]=0x00;             //length lo
8255   MessageBuffer[MessageLength++]=0x00;
8256   MessageBuffer[MessageLength++]=bitmap.width;
8257   MessageBuffer[MessageLength++]=bitmap.height;   
8258   MessageBuffer[MessageLength++]=0x01;    
8259
8260   memcpy(MessageBuffer+MessageLength,bitmap.bitmap,bitmap.size);
8261   MessageLength=MessageLength+bitmap.size;
8262
8263   GSM_MakeMultiPartSMS2(&MultiSMS,MessageBuffer,MessageLength, GSM_ProfileUDH, GSM_Coding_Default);
8264
8265   optind = 4;
8266
8267   /* Initialise the GSM interface. */
8268   fbusinit(NULL);
8269
8270   for (i=0;i<MultiSMS.number;i++)
8271     strcpy(MultiSMS.SMS[i].Destination,argv[0]);
8272
8273   return GSM_SaveMultiPartSMSOnConsole(&MultiSMS, optind,argc,argv,false,false,false,false);
8274 }
8275
8276 int showbitmap(int argc, char *argv[])
8277 {
8278   GSM_Bitmap bitmap;
8279
8280   if (GSM_ReadBitmapFileOnConsole(argv[0], &bitmap)!=GE_NONE) return(-1);
8281
8282   GSM_PrintBitmap(&bitmap);
8283
8284   return 0;
8285 }
8286
8287 int getwapsettings(int argc, char *argv[])
8288 {
8289   GSM_WAPSettings settings;
8290   GSM_Error error;
8291
8292   settings.location=atoi(argv[0]);
8293   
8294   /* Initialise the GSM interface. */
8295   fbusinit(NULL);
8296
8297   error=GSM->GetWAPSettings(&settings);
8298   
8299   switch (error) {
8300     case GE_NONE:
8301       fprintf(stdout,_("%s."),argv[0]);
8302       if (!(strcmp(settings.title,""))) fprintf(stdout,_("Set %s\n"),argv[0]);
8303                                    else fprintf(stdout,_("%s\n"),settings.title);
8304       fprintf(stdout,_("Homepage: %s\n"),settings.homepage);
8305       if (settings.iscontinuous) fprintf(stdout,_("Connection type: continuous\n"));
8306                             else fprintf(stdout,_("Connection type: temporary\n"));
8307       if (settings.issecurity) fprintf(stdout,_("Connection security: on\n"));
8308                           else fprintf(stdout,_("Connection security: off\n"));
8309       switch (settings.bearer) {
8310         case WAPSETTINGS_BEARER_SMS:
8311           fprintf(stdout,_("Bearer: SMS\n"));
8312           fprintf(stdout,_("Server number: %s\n"),settings.server);
8313           fprintf(stdout,_("Service number: %s\n"),settings.service);
8314           break;
8315         case WAPSETTINGS_BEARER_DATA:
8316           fprintf(stdout,_("Bearer: Data (CSD)\n"));
8317           fprintf(stdout,_("Dial-up number: %s\n"),settings.dialup);
8318           fprintf(stdout,_("IP address: %s\n"),settings.ipaddress);
8319           if (settings.isnormalauthentication) fprintf(stdout,_("Authentication type: normal\n"));
8320                                           else fprintf(stdout,_("Authentication type: secure\n"));  
8321           if (settings.isISDNcall) fprintf(stdout,_("Data call type: ISDN\n"));
8322                               else fprintf(stdout,_("Data call type: analogue\n"));  
8323           if (settings.isspeed14400) fprintf(stdout,_("Data call speed: 14400\n"));
8324                                 else fprintf(stdout,_("Data call speed: 9600\n"));  
8325           fprintf(stdout,_("User name: %s\n"),settings.user);
8326           fprintf(stdout,_("Password: %s\n"),settings.password);
8327           break;
8328         case WAPSETTINGS_BEARER_USSD:
8329           fprintf(stdout,_("Bearer: USSD\n"));
8330           fprintf(stdout,_("Service code: %s\n"),settings.code);
8331           if (settings.isIP) fprintf(stdout,_("Address type: IP address\nIPaddress: %s\n"),settings.service);
8332                         else fprintf(stdout,_("Address type: service number\nService number: %s\n"),settings.service);
8333           break;
8334       }
8335       break;
8336     default:
8337       fprintf(stderr,_("%s\n"),print_error(error));
8338   }
8339
8340   GSM->Terminate();    
8341
8342   return 0;
8343
8344 }
8345
8346 /* Not full done now */
8347 int savewapsettings(int argc, char *argv[])
8348 {
8349   GSM_WAPSettings settings;
8350   GSM_MultiSMSMessage MultiSMS;
8351   GSM_Error error;
8352   int w;
8353
8354   settings.location=atoi(argv[0]);
8355   
8356   /* Initialise the GSM interface. */
8357   fbusinit(NULL);
8358
8359   error=GSM->GetWAPSettings(&settings);
8360 //  strcpy(settings.homepage,"http://OtherSites/");
8361 //  strcpy(settings.title,"Orange");
8362
8363   error=GE_NONE;
8364   
8365   switch (error) {
8366     case GE_NONE:
8367       /* Put settings into SMS structure */
8368       GSM_SaveWAPSettingsToSMS(&MultiSMS,&settings);
8369
8370       for (w=0;w<MultiSMS.number;w++)
8371         strcpy(MultiSMS.SMS[w].Destination,"WAPSettings");
8372
8373       GSM_SaveMultiPartSMSOnConsole(&MultiSMS,1,argc,argv,false,false,false,false);
8374       return 0;
8375
8376       break;
8377     default:
8378       fprintf(stderr,_("%s\n"),print_error(error));
8379   }
8380
8381   GSM->Terminate();    
8382
8383   return 0;
8384 }
8385
8386 int sendwapsettings(int argc, char *argv[])
8387 {
8388   GSM_WAPSettings settings;
8389   GSM_MultiSMSMessage MultiSMS;
8390   GSM_Error error;
8391   int w;
8392
8393   settings.location=atoi(argv[0]);
8394   
8395   /* Initialise the GSM interface. */
8396   fbusinit(NULL);
8397
8398   error=GSM->GetWAPSettings(&settings);
8399 //  strcpy(settings.homepage,"http://OtherSites/");
8400 //  strcpy(settings.title,"Orange");
8401
8402   error=GE_NONE;
8403   
8404   switch (error) {
8405     case GE_NONE:
8406       /* Put settings into SMS structure */
8407       GSM_SaveWAPSettingsToSMS(&MultiSMS,&settings);
8408
8409       for (w=0;w<MultiSMS.number;w++)
8410         strcpy(MultiSMS.SMS[w].Destination,argv[1]);
8411
8412       GSM_SendMultiPartSMSOnConsole(&MultiSMS, 2,argc,argv,false,false,false);
8413
8414       return 0;
8415
8416       break;
8417     default:
8418       fprintf(stderr,_("%s\n"),print_error(error));
8419   }
8420
8421   GSM->Terminate();    
8422
8423   return 0;
8424 }
8425
8426 int getwapbookmark(int argc, char *argv[])
8427 {
8428   GSM_WAPBookmark bookmark;
8429   GSM_Error error;
8430
8431   bookmark.location=atoi(argv[0]);
8432   
8433   /* Initialise the GSM interface. */
8434   fbusinit(NULL);
8435
8436   error=GSM->GetWAPBookmark(&bookmark);
8437   
8438   switch (error) {
8439     case GE_NONE:
8440       if (bookmark.address[0]==0) {
8441         fprintf(stdout,_("Empty bookmark location\n"));
8442       } else {
8443         fprintf(stdout,_("Address: \"%s\"\n"),bookmark.address);
8444         if (bookmark.title[0]==0)
8445           fprintf(stdout,_("Title: \"%s\"\n"),bookmark.address);
8446         else
8447           fprintf(stdout,_("Title: \"%s\"\n"),bookmark.title);
8448       }
8449       break;
8450     default:
8451       fprintf(stderr,_("%s\n"),print_error(error));
8452   }
8453
8454   GSM->Terminate();    
8455
8456   return 0;
8457
8458 }
8459
8460 int setwapbookmark(int argc, char *argv[])
8461 {
8462   GSM_WAPBookmark bookmark;
8463   GSM_Error error;
8464
8465   if (argc == 3)        /* if location given, use it */
8466     bookmark.location=atoi(argv[2]);
8467   else                  /* else use first empty location */
8468     bookmark.location=0xffff;
8469
8470   strcpy(bookmark.title, argv[0]);
8471   strcpy(bookmark.address, argv[1]);
8472
8473   /* Initialise the GSM interface. */
8474   fbusinit(NULL);
8475
8476   error=GSM->SetWAPBookmark(&bookmark);
8477   
8478   switch (error) {
8479     case GE_NONE:
8480       fprintf(stdout,_("No errors\n"));
8481       break;
8482     default:
8483       fprintf(stderr,_("%s\n"),print_error(error));
8484   }
8485
8486   GSM->Terminate();    
8487
8488   return 0;
8489
8490 }
8491
8492 int savewapbookmark(int argc, char *argv[])
8493 {
8494   GSM_WAPBookmark bookmark;
8495   GSM_MultiSMSMessage MultiSMS;
8496   GSM_Error error;
8497   int w;
8498
8499   bookmark.location=atoi(argv[0]);
8500   
8501   /* Initialise the GSM interface. */
8502   fbusinit(NULL);
8503
8504   error=GSM->GetWAPBookmark(&bookmark);
8505
8506 //  strcpy(bookmark.title,"tytulagagagagagagagagagagagagagagagagagagagagagend");
8507 //  strcpy(bookmark.address,"http://jajajajajajajajajajajajagagagagagagagagagagagagagagagagagagagagagpapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapapÂ¥papapapapapapapapagagagagagagagagagagagagagagagagagagagagagagagagagadadadadadadadajdjdjdjdjdjdjdjdjdjdjdjdjdjdjdjdstp");  
8508   error=GE_NONE;
8509
8510   switch (error) {
8511     case GE_NONE:
8512
8513       if (bookmark.address[0]==0) {
8514         fprintf(stdout,_("Empty bookmark location\n"));
8515         GSM->Terminate();   
8516         return 1;
8517       }
8518
8519       /* Put bookmark into SMS structure */
8520       GSM_SaveWAPBookmarkToSMS(&MultiSMS,&bookmark);
8521
8522       for (w=0;w<MultiSMS.number;w++)
8523         strcpy(MultiSMS.SMS[w].Destination,"WAPBookmark");
8524
8525       GSM_SaveMultiPartSMSOnConsole(&MultiSMS, 1,argc,argv,false,false,false,false);
8526       return 0;
8527
8528       break;
8529     default:
8530       fprintf(stderr,_("%s\n"),print_error(error));
8531   }
8532
8533   GSM->Terminate();    
8534
8535   return 0;
8536
8537 }
8538
8539 int sendwapbookmark(int argc, char *argv[])
8540 {
8541   GSM_WAPBookmark bookmark;
8542   GSM_MultiSMSMessage MultiSMS;
8543   GSM_Error error;
8544   int w;
8545
8546   bookmark.location=atoi(argv[0]);
8547   
8548   /* Initialise the GSM interface. */
8549   fbusinit(NULL);
8550
8551   error=GSM->GetWAPBookmark(&bookmark);
8552   
8553   switch (error) {
8554     case GE_NONE:
8555
8556       if (bookmark.address[0]==0) {
8557         fprintf(stdout,_("Empty bookmark location\n"));
8558         GSM->Terminate();   
8559         return 1;
8560       }
8561
8562       /* Put bookmark into SMS structure */
8563       GSM_SaveWAPBookmarkToSMS(&MultiSMS,&bookmark);
8564
8565       for (w=0;w<MultiSMS.number;w++)
8566         strcpy(MultiSMS.SMS[w].Destination,argv[1]);
8567
8568       GSM_SendMultiPartSMSOnConsole(&MultiSMS, 2,argc,argv,false,false,false);
8569       return 0;
8570
8571       break;
8572     default:
8573       fprintf(stderr,_("%s\n"),print_error(error));
8574   }
8575
8576   GSM->Terminate();    
8577
8578   return 0;
8579
8580 }
8581
8582 int savecalendarnote(int argc, char *argv[])
8583 {
8584   GSM_MultiSMSMessage MultiSMS;
8585   int w;
8586   GSM_CalendarNote CalendarNote;
8587   int number;
8588
8589   number=atoi(argv[1]);
8590   
8591   if (number<1) {
8592     fprintf(stdout, _("Number of calendar note must be 1 or higher\n"));
8593     return -1;
8594   }
8595   
8596   switch ( GSM_ReadVCalendarFile(argv[0], &CalendarNote, &number) ) {
8597     case GE_NONE:
8598       break;
8599     case GE_CANTOPENFILE:
8600       fprintf(stdout, _("Failed to open vCalendar file \"%s\"\n"),argv[0]);
8601       return -1;
8602     case GE_TOOSHORT:
8603       fprintf(stdout, _("Number of given calendar note is too high (max=%i)\n"),number);
8604       return(-1);
8605     default:
8606       fprintf(stdout, _("Failed to parse vCalendar file \"%s\"\n"),argv[0]);
8607       return -1;    
8608   }
8609
8610   fbusinit(NULL);
8611
8612   /* Put note into SMS structure */
8613   GSM_SaveCalendarNoteToSMS(&MultiSMS,&CalendarNote);
8614
8615   for (w=0;w<MultiSMS.number;w++)
8616     strcpy(MultiSMS.SMS[w].Destination,"Calendar");
8617
8618   GSM_SaveMultiPartSMSOnConsole(&MultiSMS, 2,argc,argv,false,false,false,false);
8619
8620   return 0;
8621 }
8622
8623 int sendcalendarnote(int argc, char *argv[])
8624 {
8625   GSM_MultiSMSMessage MultiSMS;
8626   int w;
8627   GSM_CalendarNote CalendarNote;
8628   int number;
8629
8630   number=atoi(argv[2]);
8631   
8632   if (number<1) {
8633     fprintf(stdout, _("Number of calendar note must be 1 or higher\n"));
8634     return -1;
8635   }
8636   
8637   switch ( GSM_ReadVCalendarFile(argv[1], &CalendarNote, &number) ) {
8638     case GE_NONE:
8639       break;
8640     case GE_CANTOPENFILE:
8641       fprintf(stdout, _("Failed to open vCalendar file \"%s\"\n"),argv[1]);
8642       return -1;
8643     case GE_TOOSHORT:
8644       fprintf(stdout, _("Number of given calendar note is too high (max=%i)\n"),number);
8645       return(-1);
8646     default:
8647       fprintf(stdout, _("Failed to parse vCalendar file \"%s\"\n"),argv[1]);
8648       return -1;    
8649   }
8650
8651   fbusinit(NULL);
8652
8653   /* Put note into SMS structure */
8654   GSM_SaveCalendarNoteToSMS(&MultiSMS,&CalendarNote);
8655
8656   for (w=0;w<MultiSMS.number;w++)
8657     strcpy(MultiSMS.SMS[w].Destination,argv[0]);
8658
8659   GSM_SendMultiPartSMSOnConsole(&MultiSMS, 3,argc,argv,false,false,false);
8660
8661   return 0;
8662 }
8663
8664 /* Example function for continuous receiving SMS */
8665 /* When phone receives SMS, it's read by mygnokii, ID number is created
8666    and SMS is saved to file. After it it's deleted
8667    Checking many errors is also done */   
8668 int receivesms(int argc, char *argv[])
8669 {
8670   char Dir[500];
8671
8672   GSM_SMSStatus SMSStatus = {0, 0};
8673   GSM_SMSMessage SMS;
8674   int read, location, number;
8675   unsigned char name[50],filename[400];
8676   char nowdate[12]="", nowtime[12]="";
8677   FILE *file;
8678   FILE *logfile;
8679   struct CFG_Header *cfg_info;
8680
8681   /* We do not want to monitor serial line forever - press Ctrl+C to stop the
8682      monitoring mode. */
8683
8684   signal(SIGINT, interrupted);
8685
8686   fprintf (stderr, _("Entering monitor mode (press CTRL+C to break)...\n"));
8687
8688   cfg_info=CFG_FindGnokiirc();
8689
8690   strcpy(Dir,"");
8691   if (cfg_info!=NULL) { 
8692     if (CFG_Get(cfg_info, "receivesms", "path")) {
8693       strcpy(Dir,CFG_Get(cfg_info, "receivesms", "path"));
8694     }
8695   }
8696
8697   fprintf(stderr,_("Path for sms files is \"%s\"\n"),Dir);
8698
8699   fprintf (stderr, _("Initialising GSM interface..."));
8700
8701   /* Initialise the code for the GSM interface. */     
8702   fbusinit(NULL);
8703
8704   fprintf (stderr, _("done\n"));
8705
8706   sleep(1);
8707
8708   /* Loop here indefinitely - allows you to see messages from GSM code in
8709      response to unknown messages etc. The loops ends after pressing the
8710      Ctrl+C. */
8711   while (!bshutdown) {
8712     if (GSM->GetSMSStatus(&SMSStatus) == GE_NONE) {
8713       if (SMSStatus.Number!=0) {
8714
8715         GetMachineDateTime(nowdate, nowtime );
8716         logfile = fopen("log", "a");
8717         if (logfile) {
8718           fprintf(logfile, _("%s %s SMS Messages: UnRead %d, Number %d\n"),
8719              nowdate, nowtime, SMSStatus.UnRead, SMSStatus.Number);
8720           fclose(logfile);
8721         }
8722
8723         read=0;
8724         location=1;
8725
8726         while (!bshutdown) {
8727
8728           SMS.Location=location;
8729           if (GSM->GetSMSMessage(&SMS)==GE_NONE) {
8730             if (SMS.folder==0 || SMS.folder==0x08) { //GST_7110_INBOX
8731
8732               GetMachineDateTime(nowdate, nowtime );
8733               logfile = fopen("log", "a");
8734               if (logfile) {
8735                 fprintf(logfile,_("%s %s SMS on location %i\n"),
8736                   nowdate,nowtime,SMS.MessageNumber);
8737                 fclose(logfile);
8738               }
8739
8740               number=             16*(SMS.MessageText[2] >> 4)+      (SMS.MessageText[2] & 0x0f);
8741               number=number+  256*16*(SMS.MessageText[1] >> 4)+  256*(SMS.MessageText[1] & 0x0f);
8742               number=number+65536*16*(SMS.MessageText[0] >> 4)+65536*(SMS.MessageText[0] & 0x0f);
8743
8744               sprintf( name, "%07i_%02d%02d%02d_%02d%02d%02d.sms", number,
8745                  SMS.Time.Year, SMS.Time.Month, SMS.Time.Day,
8746                  SMS.Time.Hour, SMS.Time.Minute, SMS.Time.Second);
8747
8748               strcpy(filename,Dir);
8749               strcat(filename,name);
8750
8751               logfile = fopen("log", "a");
8752               if (logfile) {
8753                 fprintf(logfile,_("%s %s Name is \"%s\"\n"),nowdate,nowtime,filename);
8754                 fclose(logfile);
8755               }
8756
8757               file = fopen(filename, "rb");
8758               if (!file) {
8759                 file = fopen(filename, "wb");
8760                 if (!file) {
8761                   GetMachineDateTime(nowdate, nowtime );
8762                   fprintf(stderr,_("%s %s ERROR: opening file \"%s\" failed !\n"),nowdate,nowtime,filename);
8763                   logfile = fopen("log", "a");
8764                   if (logfile) {
8765                     fprintf(logfile,_("%s %s ERROR: opening file \"%s\" failed !\n"),nowdate,nowtime,filename);
8766                     fclose(logfile);
8767                   }
8768                 } else {
8769                   fwrite(SMS.MessageText,1,SMS.Length,file);
8770                   fclose(file);
8771                 }
8772               } else {
8773                 fclose(file);
8774   
8775                 GetMachineDateTime(nowdate, nowtime );
8776                 fprintf(stderr,_("%s %s ERROR: file \"%s\" already exist !\n"),nowdate,nowtime,filename);
8777                 logfile = fopen("log", "a");
8778                 if (logfile) { 
8779                   fprintf(logfile,_("%s %s ERROR: file \"%s\" already exist !\n"),nowdate,nowtime,filename);
8780                   fclose(logfile);
8781                 }
8782               }
8783   
8784               SMS.Location=SMS.MessageNumber;
8785               if (GSM->DeleteSMSMessage(&SMS)!=GE_NONE) {
8786                 GetMachineDateTime(nowdate, nowtime );
8787                 fprintf(stderr,_("%s %s ERROR: Deleting SMS location %i failed !\n"),nowdate,nowtime,SMS.MessageNumber);
8788                 logfile = fopen("log", "a");
8789                 if (logfile) {
8790                   fprintf(logfile,_("%s %s ERROR: Deleting SMS location %i failed !\n"),nowdate,nowtime,SMS.MessageNumber);
8791                   fclose(logfile);
8792                 }
8793               }
8794             }
8795             read++;
8796           }
8797           location++;
8798           if (read==SMSStatus.Number) break;
8799         }
8800       }
8801     } else {
8802       GetMachineDateTime(nowdate, nowtime );
8803       fprintf(stderr,_("%s %s ERROR: Can't get SMS status !\n"),nowdate,nowtime);
8804       logfile = fopen("log", "a");
8805       if (logfile) {
8806         fprintf(logfile,_("%s %s ERROR: Can't get SMS status !\n"),nowdate,nowtime);
8807         fclose(logfile);
8808       }
8809     }
8810
8811     sleep(1);
8812   }
8813
8814   fprintf (stderr, _("Leaving monitor mode...\n"));
8815
8816   GSM->Terminate();
8817   
8818   return 0;
8819 }
8820
8821 int divert(int argc, char *argv[])
8822 {
8823         GSM_CallDivert cd;
8824         GSM_Error error;
8825
8826         memset(&cd, 0, sizeof(GSM_CallDivert));
8827
8828              if (!strcmp("register", argv[0])){cd.Operation = GSM_CDV_Register ;} 
8829         else if (!strcmp("enable"  , argv[0])){cd.Operation = GSM_CDV_Enable   ;} 
8830         else if (!strcmp("disable" , argv[0])){cd.Operation = GSM_CDV_Disable  ;}
8831         else if (!strcmp("erasure" , argv[0])){cd.Operation = GSM_CDV_Erasure  ;}
8832         else if (!strcmp("query"   , argv[0])){cd.Operation = GSM_CDV_Query    ;}
8833         else {
8834                 usage();
8835                 exit(-1);
8836         }
8837
8838              if (!strcmp("all"       , argv[1])) {cd.DType = GSM_CDV_AllTypes  ;}
8839         else if (!strcmp("busy"      , argv[1])) {cd.DType = GSM_CDV_Busy      ;}
8840         else if (!strcmp("noans"     , argv[1])) {cd.DType = GSM_CDV_NoAnswer  ;}
8841         else if (!strcmp("outofreach", argv[1])) {cd.DType = GSM_CDV_OutOfReach;}
8842         else {
8843                 usage();
8844                 exit(-1);
8845         }
8846
8847              if (!strcmp("all"  , argv[2])) {cd.CType = GSM_CDV_AllCalls  ;}
8848         else if (!strcmp("voice", argv[2])) {cd.CType = GSM_CDV_VoiceCalls;}
8849         else if (!strcmp("fax"  , argv[2])) {cd.CType = GSM_CDV_FaxCalls  ;}
8850         else if (!strcmp("data" , argv[2])) {cd.CType = GSM_CDV_DataCalls ;}
8851         else {
8852                 usage();
8853                 exit(-1);
8854         }
8855
8856         if (argc>3) strcpy(cd.Number, argv[3]);
8857
8858         if (argc>4) cd.Timeout = atoi(argv[4]);
8859
8860         /* Initialise the code for the GSM interface. */     
8861         fbusinit(NULL);
8862
8863         error=GSM->CallDivert(&cd);
8864
8865         if (error == GE_NONE) {
8866           switch (cd.Operation)
8867           {
8868             case GSM_CDV_Query:
8869               fprintf(stdout, _("Divert type: "));
8870               switch (cd.DType) {
8871                 case GSM_CDV_Busy      :fprintf(stdout, _("when busy"));break;
8872                 case GSM_CDV_NoAnswer  :fprintf(stdout, _("when not answered"));break;
8873                 case GSM_CDV_OutOfReach:fprintf(stdout, _("when phone off or no coverage"));break;
8874                 case GSM_CDV_AllTypes  :fprintf(stdout, _("all call diverts"));break; //?
8875                 default:                fprintf(stdout, _("unknown %i"),cd.DType);break;
8876               }
8877
8878               fprintf(stdout, _("\nCalls type : "));
8879               switch (cd.CType) {
8880                 case GSM_CDV_VoiceCalls: fprintf(stdout, _("voice"));break;
8881                 case GSM_CDV_FaxCalls  : fprintf(stdout, _("fax"));break;
8882                 case GSM_CDV_DataCalls : fprintf(stdout, _("data"));break;
8883                 case GSM_CDV_AllCalls  : fprintf(stdout, _("voice, fax & data"));break;
8884                 default:   fprintf(stdout, _("unknown %i"),cd.CType);break;
8885               }
8886               fprintf(stdout, _("\n"));
8887
8888               if (cd.Enabled) {
8889                 fprintf(stdout, _("Status     : active\n"));
8890                 fprintf(stdout, _("Timeout    : %i seconds\n"),cd.Timeout);
8891                 fprintf(stdout, _("Number     : %s\n"),cd.Number);
8892               } else {
8893                 fprintf(stdout, _("Status     : deactivated\n"));
8894               }
8895
8896               break;
8897             default:
8898               fprintf(stdout,_("Divert done\n"));
8899           }
8900         } else 
8901           fprintf(stderr,_("%s\n"),print_error(error));
8902
8903         GSM->Terminate();
8904
8905         return 0;
8906 }
8907
8908 int savephonebookentry(int argc, char *argv[])
8909 {
8910   GSM_MultiSMSMessage MultiSMS;
8911   GSM_PhonebookEntry entry;
8912   GSM_Error error;
8913   int w;
8914
8915   fbusinit(NULL);
8916
8917   /* Handle command line args that set type, start and end locations. */
8918   if (!GetMemoryTypeID(argv[0], &entry.MemoryType))
8919   {
8920     fprintf(stderr, _("Unknown memory type %s!\n"), argv[0]);
8921     return (-1);
8922   }
8923
8924   entry.Location=atoi(argv[1]);
8925
8926   fbusinit(NULL);
8927
8928   error=GSM->GetMemoryLocation(&entry);
8929
8930   switch (error) {
8931     case GE_NONE:
8932
8933       /* Put entry into SMS structure */
8934 #ifndef UCLINUX
8935       if (GetModelFeature(FN_PHONEBOOK)==F_PBK71) {
8936         GSM_SavePhonebookEntryToSMS(&MultiSMS,&entry,21);
8937       } else
8938 #endif /* UCLINUX */
8939                                 {
8940         GSM_SavePhonebookEntryToSMS(&MultiSMS,&entry,10);
8941       }
8942
8943       for (w=0;w<MultiSMS.number;w++)
8944         strcpy(MultiSMS.SMS[w].Destination,"Phonebook");
8945
8946       GSM_SaveMultiPartSMSOnConsole(&MultiSMS, 2,argc,argv,false,false,false,false);
8947       break;
8948
8949     default:
8950       fprintf(stdout,_("Error\n"));break;
8951   }
8952
8953   return 0;
8954 }
8955
8956 int sendphonebookentry(int argc, char *argv[])
8957 {
8958   GSM_MultiSMSMessage MultiSMS;
8959   GSM_PhonebookEntry entry;
8960   GSM_Error error;
8961   int w;
8962
8963   fbusinit(NULL);
8964
8965   /* Handle command line args that set type, start and end locations. */
8966   if (!GetMemoryTypeID(argv[1], &entry.MemoryType))
8967   {
8968     fprintf(stderr, _("Unknown memory type %s!\n"), argv[1]);
8969     return (-1);
8970   }
8971
8972   entry.Location=atoi(argv[2]);
8973
8974   fbusinit(NULL);
8975
8976   error=GSM->GetMemoryLocation(&entry);
8977
8978   switch (error) {
8979     case GE_NONE:
8980
8981       /* Put entry into SMS structure */
8982       if (GetModelFeature(FN_PHONEBOOK)==F_PBK71) {
8983         GSM_SavePhonebookEntryToSMS(&MultiSMS,&entry,21);
8984       } else {
8985         GSM_SavePhonebookEntryToSMS(&MultiSMS,&entry,10);
8986       }
8987
8988       for (w=0;w<MultiSMS.number;w++)
8989         strcpy(MultiSMS.SMS[w].Destination,argv[0]);
8990
8991       GSM_SendMultiPartSMSOnConsole(&MultiSMS, 3,argc,argv,false,false,false);
8992
8993       break;
8994
8995     default:
8996       fprintf(stdout,_("Error\n"));break;
8997   }
8998
8999   return 0;
9000 }
9001
9002 #endif /* UCLINUX */