Implemented renicing (-20) in gnokiid mode
[gnokii.git] / gnokii / gnokii.c
index 82b2b8b..1cbe8fe 100644 (file)
@@ -20,6 +20,8 @@
 #include <ctype.h>
 #include <time.h>
 #include <sys/stat.h>
+#include <limits.h>
+#include <errno.h>
 
 #ifdef UCLINUX
 /* <getopt.h> or "getopt.h" would include insufficient getopt.h from uClinux */
@@ -97,9 +99,9 @@ char *SynchronizeTime; /* If we set date and time from computer to phone (from .
 #endif /* UCLINUX */
 static char *BinDir;          /* Binaries directory from .gnokiirc file - not used here yet */
 
-#ifdef DEBUG
+#ifndef UCLINUX
 static GSM_SMSMessage SMS[4];
-#endif
+#endif /* UCLINUX */
   
 #ifndef UCLINUX
 
@@ -560,8 +562,6 @@ int GSM_SendMultiPartSMSOnConsole(GSM_MultiSMSMessage *MultiSMS, int argnum, int
   return 0;
 }
 
-#endif /* UCLINUX */
-
 static int GSM_SaveMultiPartSMSOnConsole(GSM_MultiSMSMessage *MultiSMS, int argnum, int argc, char *argv[],
                                   bool inter, bool unicode, bool profile, bool scale) {
 
@@ -688,8 +688,6 @@ static int GSM_SaveMultiPartSMSOnConsole(GSM_MultiSMSMessage *MultiSMS, int argn
   return 0;
 }
 
-#ifndef UCLINUX
-
 void GSM_PlayRingtoneOnConsole(GSM_Ringtone *ringtone)
 {
   int i;
@@ -737,8 +735,17 @@ static int usage(void)
   ));
 #endif /* UCLINUX */
 
+#ifndef UCLINUX
   fprintf(stdout, _(
 "          gnokii --getmemory memory_type [start [end]] [-short|-v30|-v21|-v]\n"
+  ));
+#else /* UCLINUX */
+  fprintf(stdout, _(
+"          gnokii --getmemory memory_type [start [end]] [-short]\n"
+  ));
+#endif /* UCLINUX */
+
+  fprintf(stdout, _(
 "          gnokii --writephonebook [-i]\n"
   ));
 
@@ -747,17 +754,9 @@ static int usage(void)
 "          gnokii --sendphonebookentry destination memory_type location\n"
 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
 "                 [-s] [-v n] [-d]\n"
-  ));
-#endif /* UCLINUX */
-
-  fprintf(stdout, _(
 "          gnokii --savephonebookentry memory_type location\n"
 "                 [--smsc message_center_number] [--smscno message_center_index]\n"
 "                 [-r] [-i] [-s] [-a] [--name name]\n"
-  ));
-
-#ifndef UCLINUX
-  fprintf(stdout, _(
 "          gnokii --getvoicemailbox\n"
   ));
 #endif /* UCLINUX */
@@ -951,7 +950,7 @@ static int usage(void)
 
 #ifdef UCLINUX
   fprintf(stdout, _(
-"          gnokii --gnokiid [--debug]\n"
+"          gnokii --gnokiid [--debug] [<child to run> [<child args>...]]\n"
   ));
 #endif
 
@@ -1085,9 +1084,7 @@ int main(int argc, char *argv[])
     { "sendcalendarnote",   required_argument, NULL, OPT_SENDCALENDARNOTE },
     { "savecalendarnote",   required_argument, NULL, OPT_SAVECALENDARNOTE },
     { "sendphonebookentry", required_argument, NULL, OPT_SENDPHONEBOOKENTRY},
-#endif /* UCLINUX */
     { "savephonebookentry", required_argument, NULL, OPT_SAVEPHONEBOOKENTRY},
-#ifndef UCLINUX
     { "deletecalendarnote", required_argument, NULL, OPT_DELCALENDARNOTE  },// Delete calendar note mode    
 #endif /* UCLINUX */
     { "getmemory",          required_argument, NULL, OPT_GETMEMORY        },// Get memory mode
@@ -1237,12 +1234,14 @@ int main(int argc, char *argv[])
 #endif /* UCLINUX */
 
 #ifdef UCLINUX
-    { OPT_GNOKIID,           0, 1, 0 },
+    { OPT_GNOKIID,           0, INT_MAX, 0 },
 #endif /* UCLINUX */
 
     { 0, 0, 0, 0 },
   };
 
+  LIVE;
+
   opterr = 0;
 
   /* For GNU gettext */
@@ -1283,6 +1282,7 @@ int main(int argc, char *argv[])
 
     for(i = 2; i < argc; i++)
       nargv[i-2] = argv[i];
+               nargv[argc-2] = NULL;   /* required by gnokiid() for execv(3) */
        
     if(checkargs(c, gals, nargc)) {
 
@@ -1346,9 +1346,7 @@ int main(int argc, char *argv[])
     case OPT_DELCALENDARNOTE:       rc = deletecalendarnote(optarg);break;
     case OPT_SAVECALENDARNOTE:      rc = savecalendarnote(nargc, nargv);break;
     case OPT_SENDCALENDARNOTE:      rc = sendcalendarnote(nargc, nargv);break;
-#endif /* UCLINUX */
     case OPT_SAVEPHONEBOOKENTRY:    rc = savephonebookentry(nargc, nargv);break;
-#ifndef UCLINUX
     case OPT_SENDPHONEBOOKENTRY:    rc = sendphonebookentry(nargc, nargv);break;
     case OPT_WRITECALENDARNOTE:     rc = writecalendarnote(nargv);  break;
 #endif /* UCLINUX */
@@ -4121,6 +4119,14 @@ int monitormode(int argc, char *argv[])
 
 #ifdef UCLINUX
 
+#define NICE_LEVEL (-20)
+
+static void gnokiid_SIGCHLD(int signo)
+{
+       fprintf (stderr, _("Child process exited, aborting...\n"));
+       exit(2);
+}
+
 static int gnokiid(int argc, char *argv[])
 {
        bool    DebugMode;  /* When true, run in debug mode */
@@ -4134,17 +4140,16 @@ static int gnokiid(int argc, char *argv[])
        DebugMode = false;
        if(argc>0)
        {
-               if( strcmp(argv[0],"--debug" ))
+               if( !strcmp(argv[0],"--debug" ))
                {
-                       usage();
-                       return -1;
-               }
-               else
                        DebugMode = true;
+                       argv++;
+                       argc--;
+               }
        }
 
 #ifdef DEBUG
-  fprintf (stderr, _("Entering gnokiid mode...\n"));
+  fprintf (stderr, _("Initializing gnokiid mode...\n"));
 #endif
 
        if (CFG_ReadConfig(&Model, &Port, &Initlength, &Connection, &BinDir, true) < 0)
@@ -4153,6 +4158,35 @@ static int gnokiid(int argc, char *argv[])
   if (VM_Initialise(Model, Port, Initlength, GCT_FBUS, BinDir, DebugMode, true, ""/*SynchronizeTime*/) == false)
                return (-1);
 
+       if (argc>0) {
+#ifdef DEBUG
+               fprintf (stderr, _("Spawning gnokiid startup child process \"%s\"...\n"), *argv);
+#endif
+               signal(SIGCHLD,gnokiid_SIGCHLD);
+               errno=0;
+               switch (vfork()) {
+                       case -1: /* vfork() failure */
+                               fprintf (stderr, _("vfork() failed! (%s)\n"),strerror(errno));
+                               return -1;
+                       case 0: /* child */
+                               execv(*argv,argv);
+                               fprintf (stderr, _("Spawn of child process failed! (%s)\n"),strerror(errno));
+                               _exit(9);
+                               break;
+                       default: /* parent */
+                               /* PASSTHRU */
+                               break;
+                       }
+               }
+
+#ifdef DEBUG
+  fprintf (stderr, _("Entering gnokiid virtual modem main loop...\n"));
+#endif
+       if (nice(NICE_LEVEL))
+               fprintf (stderr, _("WARNING: nice level change failed (by %d)\n"),NICE_LEVEL);
+
+       VM_ThreadLoop();
+
        VM_Terminate();
 
   return 0;
@@ -4679,6 +4713,7 @@ static int getmemory(int argc, char *argv[])
     fprintf(stderr, _("Unknown memory type %s!\n"), argv[0]);
     return (-1);
   }
+
   GetMemoryTypeString(memory_type_string, &entry.MemoryType);
 
   if (argv[argc-1][0] == '-')
@@ -4726,6 +4761,7 @@ static int getmemory(int argc, char *argv[])
        i_used++;
       else if (do_all)
        break;
+#ifndef UCLINUX
       if (output_opt && !strcmp( output_opt,"-v30")) {
        semicolon_pipe_substitution( &entry, 0 );
         fprintf(stdout,_("%s"),GSM_GetVCARD(&entry,30));
@@ -4741,6 +4777,7 @@ static int getmemory(int argc, char *argv[])
         fprintf(stdout,_("%s"),GSM_GetVCARD(&entry,10));
        formatdone=true;
       } 
+#endif /* UCLINUX */
       if (output_opt && !strcmp(output_opt,"-short")) {
         semicolon_pipe_substitution( &entry, 0 );
         fprintf(stdout, "%s;%s;%s;%d;%d;", entry.Name, entry.Number, memory_type_string, entry.Location, entry.Group);
@@ -5236,20 +5273,29 @@ static int identify( void )
   /* Hopefully is 64 larger as FB38_MAX* / FB61_MAX* */
   char imei[64], model[64], rev[64], manufacturer[64];
 
+  LIVE;
   fbusinit(NULL);
 
+  LIVE;
   while (GSM->GetIMEI(imei)    != GE_NONE) sleep(1);
+  LIVE;
   while (GSM->GetRevision(rev) != GE_NONE) sleep(1);
+  LIVE;
   while (GSM->GetModel(model)  != GE_NONE) sleep(1);
+  LIVE;
 
   strcpy(manufacturer, "(unknown)");
+  LIVE;
   GSM->GetManufacturer(manufacturer);
+  LIVE;
 
   fprintf(stdout, _("IMEI:     %s\n"), imei);
   fprintf(stdout, _("Model:    %s %s (%s)\n"), manufacturer, GetModelName (model), model);
   fprintf(stdout, _("Revision: %s\n"), rev);
 
+  LIVE;
   GSM->Terminate();
+  LIVE;
 
   return 0;
 }
@@ -7755,32 +7801,32 @@ int binringtoneconvert(int argc, char *argv[])
            w=w*2;
            if (w>z && (w/2)<=z) {
              switch (m) {
-               case 1:fprintf(file,_("16"));break;\r
-               case 2:fprintf(file,_("8"));break;\r
-               case 3:fprintf(file,_("4"));break;\r
-               case 4:fprintf(file,_("2"));break;\r
-               case 5:fprintf(file,_("1"));break;\r
+               case 1:fprintf(file,_("16"));break;
+               case 2:fprintf(file,_("8"));break;
+               case 3:fprintf(file,_("4"));break;
+               case 4:fprintf(file,_("2"));break;
+               case 5:fprintf(file,_("1"));break;
              }
              break;
            }
          }
          if (z>w) fprintf(file,_("1"));
          pause=false;
-          switch (GSM_GetNote(j)) {\r
-            case Note_C  :fprintf(file,_("c"));break;\r
-            case Note_Cis:fprintf(file,_("c#"));break;\r
-            case Note_D  :fprintf(file,_("d"));break;\r
-            case Note_Dis:fprintf(file,_("d#"));break;\r
-            case Note_E  :fprintf(file,_("e"));break;\r
-            case Note_F  :fprintf(file,_("f"));break;\r
-            case Note_Fis:fprintf(file,_("f#"));break;\r
-            case Note_G  :fprintf(file,_("g"));break;\r
-            case Note_Gis:fprintf(file,_("g#"));break;\r
-            case Note_A  :fprintf(file,_("a"));break;\r
-            case Note_Ais:fprintf(file,_("a#"));break;\r
-            case Note_H  :fprintf(file,_("h"));break;\r
-            default      :pause=true;fprintf(file,_("p"));break; //Pause ?\r
-          }\r
+          switch (GSM_GetNote(j)) {
+            case Note_C  :fprintf(file,_("c"));break;
+            case Note_Cis:fprintf(file,_("c#"));break;
+            case Note_D  :fprintf(file,_("d"));break;
+            case Note_Dis:fprintf(file,_("d#"));break;
+            case Note_E  :fprintf(file,_("e"));break;
+            case Note_F  :fprintf(file,_("f"));break;
+            case Note_Fis:fprintf(file,_("f#"));break;
+            case Note_G  :fprintf(file,_("g"));break;
+            case Note_Gis:fprintf(file,_("g#"));break;
+            case Note_A  :fprintf(file,_("a"));break;
+            case Note_Ais:fprintf(file,_("a#"));break;
+            case Note_H  :fprintf(file,_("h"));break;
+            default      :pause=true;fprintf(file,_("p"));break; //Pause ?
+          }
          w=deflen*1.5;
          for (m=0;m<6;m++) {
            w=w*2;
@@ -7925,11 +7971,11 @@ int setsimlock()
     fprintf(stderr,_("Error getting simlock info\n"));GSM->Terminate();return -1;
   }
   /* Opening all locks (we must check, if we can open them) */
-  NULL_SendMessageSequence\r(50, &CurrentMagicError, 10, 0x40,openbuffer0);
-  openbuffer[4]=1;NULL_SendMessageSequence\r(50, &CurrentMagicError, 10, 0x40,openbuffer);
-  openbuffer[4]=2;NULL_SendMessageSequence\r(50, &CurrentMagicError, 10, 0x40,openbuffer);
-  openbuffer[4]=4;NULL_SendMessageSequence\r(50, &CurrentMagicError, 10, 0x40,openbuffer);
-  openbuffer[4]=8;NULL_SendMessageSequence\r(50, &CurrentMagicError, 10, 0x40,openbuffer);
+  NULL_SendMessageSequence(50, &CurrentMagicError, 10, 0x40,openbuffer0);
+  openbuffer[4]=1;NULL_SendMessageSequence(50, &CurrentMagicError, 10, 0x40,openbuffer);
+  openbuffer[4]=2;NULL_SendMessageSequence(50, &CurrentMagicError, 10, 0x40,openbuffer);
+  openbuffer[4]=4;NULL_SendMessageSequence(50, &CurrentMagicError, 10, 0x40,openbuffer);
+  openbuffer[4]=8;NULL_SendMessageSequence(50, &CurrentMagicError, 10, 0x40,openbuffer);
   if (GSM->SimlockInfo(&siml)!=GE_NONE) {
     fprintf(stderr,_("Error getting simlock info\n"));GSM->Terminate();return -1;
   }
@@ -7978,13 +8024,13 @@ int setsimlock()
   }  
   /* Closing simlock with given values */
   closebuffer[4]=1+2+4+8;
-  NULL_SendMessageSequence\r(50, &CurrentMagicError, 20, 0x40,closebuffer);  
+  NULL_SendMessageSequence(50, &CurrentMagicError, 20, 0x40,closebuffer);  
   /* Opening all locks */
-  NULL_SendMessageSequence\r(50, &CurrentMagicError, 10, 0x40,openbuffer0);
-  openbuffer[4]=1;NULL_SendMessageSequence\r(50, &CurrentMagicError, 10, 0x40,openbuffer);
-  openbuffer[4]=2;NULL_SendMessageSequence\r(50, &CurrentMagicError, 10, 0x40,openbuffer);
-  openbuffer[4]=4;NULL_SendMessageSequence\r(50, &CurrentMagicError, 10, 0x40,openbuffer);
-  openbuffer[4]=8;NULL_SendMessageSequence\r(50, &CurrentMagicError, 10, 0x40,openbuffer);
+  NULL_SendMessageSequence(50, &CurrentMagicError, 10, 0x40,openbuffer0);
+  openbuffer[4]=1;NULL_SendMessageSequence(50, &CurrentMagicError, 10, 0x40,openbuffer);
+  openbuffer[4]=2;NULL_SendMessageSequence(50, &CurrentMagicError, 10, 0x40,openbuffer);
+  openbuffer[4]=4;NULL_SendMessageSequence(50, &CurrentMagicError, 10, 0x40,openbuffer);
+  openbuffer[4]=8;NULL_SendMessageSequence(50, &CurrentMagicError, 10, 0x40,openbuffer);
   GSM->Reset(0x03);
   GSM->Terminate();
   return 0;
@@ -8084,7 +8130,7 @@ int geteeprom()
     
     if ((i/256)!=((i-1)/256)) fprintf(stderr,_("."));
     
-    if (NULL_SendMessageSequence(50, &CurrentMagicError, 9, 0x40,buffer)!=GE_NONE)\r      break;
+    if (NULL_SendMessageSequence(50, &CurrentMagicError, 9, 0x40,buffer)!=GE_NONE)       break;
 
     i=i+0x10;
   }
@@ -8859,9 +8905,7 @@ int divert(int argc, char *argv[])
        return 0;
 }
 
-#endif /* UCLINUX */
-
-static int savephonebookentry(int argc, char *argv[])
+int savephonebookentry(int argc, char *argv[])
 {
   GSM_MultiSMSMessage MultiSMS;
   GSM_PhonebookEntry entry;
@@ -8909,8 +8953,6 @@ static int savephonebookentry(int argc, char *argv[])
   return 0;
 }
 
-#ifndef UCLINUX
-
 int sendphonebookentry(int argc, char *argv[])
 {
   GSM_MultiSMSMessage MultiSMS;