Numerous fixes and changes
[pandora-libraries.git] / lib / pnd_utility.c
index 33f672e..b7e146f 100644 (file)
@@ -1,9 +1,19 @@
 
 #include <stdio.h> /* for FILE etc */
 #include <stdlib.h> /* for malloc */
+#define __USE_GNU /* for strcasestr */
 #include <string.h> /* for making ftw.h happy */
+#include <unistd.h> /* for fork exec */
 
+#include <utmp.h> /* for expand-tilde below; see commentary for this about-turn */
+#include <sys/types.h> /* ditto */
+#include <pwd.h> /* ditto */
+
+#include "pnd_pxml.h"
+#include "pnd_container.h"
 #include "pnd_utility.h"
+#include "pnd_pndfiles.h"
+#include "pnd_discovery.h"
 
 // a generalized variable-substitution routine might be nice; for now we need a quick tilde one,
 // so here goes. Brute force ftw!
@@ -12,6 +22,61 @@ char *pnd_expand_tilde ( char *freeable_buffer ) {
   char *s = freeable_buffer;
   char *home = getenv ( "HOME" );
 
+  //printf ( "expand tilde IN: '%s'\n", freeable_buffer );
+  //printf ( "  home was %s\n", home );
+
+  // well, as pndnotifyd (etc) may be running as _root_, while the user is logged in
+  // as 'pandora' or god knows what, this could be problematic. Other parts of the lib
+  // use wordexp() for shell-like expansion, but this funciton is (at least) used by
+  // pndnotifyd for determination of the .desktop emit path, so we need ~ to expand
+  // to the _actual user_ rather than root's homedir. Rather than run 'users' or 'who'
+  // or the like, we'll just cut to the chase..
+  ///////
+  {
+    FILE *f;
+    struct utmp b;
+    static char *florp = NULL;
+    struct passwd *pw;
+
+    f = fopen ( "/var/run/utmp", "r" );
+
+    if ( f ) {
+
+      while ( fread ( &b, sizeof(struct utmp), 1, f ) == 1 ) {
+
+       if ( b.ut_type == USER_PROCESS ) {
+
+         // ut_user contains the username ..
+         // now we need to find the path to that account.
+         while ( ( pw = getpwent() ) ) {
+
+           if ( strcmp ( pw -> pw_name, b.ut_user ) == 0 ) {
+
+             // aight, we've got a logged in user and have matched it to
+             // passwd entry, so can construct the appropriate path
+
+             if ( florp ) {
+               free ( florp );
+             }
+             florp = strdup ( pw -> pw_dir );
+
+             home = florp;
+             //printf ( "  home is %s (from %u)\n", home, b.ut_type );
+
+           } // passwd entry matches the utmp entry
+
+         } // while iteratin across passwd entries
+         endpwent();
+
+       } // utmp entry is for a user login
+
+      } // while
+      fclose ( f );
+    } // opened?
+
+  }
+  ///////
+
   if ( ! home ) {
     return ( s ); // can't succeed
   }
@@ -30,5 +95,85 @@ char *pnd_expand_tilde ( char *freeable_buffer ) {
     s = temp;
   } // while finding matches
 
+  //printf ( "expand tilde OUT: '%s'\n", s );
+
   return ( s );
 }
+
+void pnd_exec_no_wait_1 ( char *fullpath, char *arg1 ) {
+  int i;
+
+  if ( ( i = fork() ) < 0 ) {
+    printf ( "ERROR: Couldn't fork()\n" );
+    return;
+  }
+
+  if ( i ) {
+    return; // parent process, don't care
+  }
+
+  // child process, do something
+  if ( arg1 ) {
+    execl ( fullpath, fullpath, arg1, (char*) NULL );
+  } else {
+    execl ( fullpath, fullpath, (char*) NULL );
+  }
+
+  // getting here is an error
+  //printf ( "Error attempting to run %s\n", fullpath );
+
+  return;
+}
+
+pnd_pxml_handle pnd_pxml_get_by_path ( char *fullpath ) {
+  unsigned char valid = pnd_object_type_unknown;
+  pnd_pxml_handle pxmlh = 0;
+
+  // WARN: this is way too close to callback in pnd_disco .. should be refactored!
+
+  if ( strcasestr ( fullpath, PXML_FILENAME ) ) {
+    valid = pnd_object_type_directory;
+  } else if ( strcasestr ( fullpath, PND_PACKAGE_FILEEXT "\0" ) ) {
+    valid = pnd_object_type_pnd;
+  }
+
+  // if not a file of interest, just keep looking until we run out
+  if ( ! valid ) {
+    return ( 0 );
+  }
+
+  // potentially a valid application
+  if ( valid == pnd_object_type_directory ) {
+    pxmlh = pnd_pxml_fetch ( (char*) fullpath );
+
+  } else if ( valid == pnd_object_type_pnd ) {
+    FILE *f;
+    char pxmlbuf [ 32 * 1024 ]; // TBD: assuming 32k pxml accrual buffer is a little lame
+
+    // open it up..
+    f = fopen ( fullpath, "r" );
+
+    // try to locate the PXML portion
+    if ( ! pnd_pnd_seek_pxml ( f ) ) {
+      fclose ( f );
+      return ( 0 ); // pnd or not, but not to spec. Pwn'd the pnd?
+    }
+
+    // accrue it into a buffer
+    if ( ! pnd_pnd_accrue_pxml ( f, pxmlbuf, 32 * 1024 ) ) {
+      fclose ( f );
+      return ( 0 );
+    }
+
+    // by now, we have <PXML> .. </PXML>, try to parse..
+    pxmlh = pnd_pxml_fetch_buffer ( (char*) fullpath, pxmlbuf );
+
+    // done with file
+    fclose ( f );
+
+  }
+
+  // ..
+
+  return ( pxmlh );
+}