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