XMLOBJ = lib/tinyxml/tinystr.o lib/tinyxml/tinyxml.o lib/tinyxml/tinyxmlerror.o lib/tinyxml/tinyxmlparser.o
ALLOBJ = pnd_conf.o pnd_container.o pnd_discovery.o pnd_pxml.o pnd_notify.o pnd_locate.o pnd_tinyxml.o pnd_pndfiles.o pnd_apps.o pnd_utility.o pnd_desktop.o pnd_io_gpio.o pnd_logger.o
-all: ${SOLIB} ${LIB} conftest discotest notifytest pndnotifyd rawpxmltest pndvalidator loggertest pnd_run pndevmapperd
+all: ${SOLIB} ${LIB} conftest discotest notifytest pndnotifyd rawpxmltest pndvalidator loggertest pnd_run pndevmapperd pnd_info
clean:
- ${RM} -f ${ALLOBJ} ${XMLOBJ} ${LIB} ${SOLIB1} locatetest.o bin/locatetest conftest.o bin/conftest discotest.o bin/discotest loggertest.o bin/loggertest bin/notifytest notifytest.o bin/rawpxmltest rawpxmltest.o bin/pnd_run pnd_run.o bin/pndevmapperd pndevmapperd.o bin/pndnotifyd pndnotifyd.o ${SOLIB} testdata/dotdesktop/*.desktop testdata/menu/*.desktop testdata/apps/*.pnd testdata/dotdesktop/*.png deployment/usr/lib/libpnd* deployment/usr/bin/pndnotifyd deployment/usr/bin/pnd_run deployment/usr/pandora/scripts/* deployment/etc/sudoers deployment/etc/init.d/pndnotifyd bin/pndvalidator pndvalidator.o deployment/usr/bin/pndevmapperd testdata/menuicons/*
+ ${RM} -f ${ALLOBJ} ${XMLOBJ} ${LIB} ${SOLIB1} locatetest.o bin/locatetest conftest.o bin/conftest discotest.o bin/discotest loggertest.o bin/loggertest bin/notifytest notifytest.o bin/rawpxmltest rawpxmltest.o bin/pnd_run pnd_run.o pnd_info.o bin/pnd_info bin/pndevmapperd pndevmapperd.o bin/pndnotifyd pndnotifyd.o ${SOLIB} testdata/dotdesktop/*.desktop testdata/menu/*.desktop testdata/apps/*.pnd testdata/dotdesktop/*.png deployment/usr/lib/libpnd* deployment/usr/bin/pndnotifyd deployment/usr/bin/pnd_run deployment/usr/bin/pnd_info deployment/usr/pandora/scripts/* deployment/etc/sudoers deployment/etc/init.d/pndnotifyd bin/pndvalidator pndvalidator.o deployment/usr/bin/pndevmapperd testdata/menuicons/*
${RM} -rf deployment/media
find . -name "*~*" -exec rm {} \; -print
pnd_run: pnd_run.o ${SOLIB1}
${CC} -lstdc++ -o bin/pnd_run pnd_run.o ${SOLIB1}
+pnd_info: pnd_info.o ${SOLIB1}
+ ${CC} -lstdc++ -o bin/pnd_info pnd_info.o ${SOLIB1}
+
pndevmapperd: pndevmapperd.o ${SOLIB1}
${CC} -lstdc++ -o bin/pndevmapperd pndevmapperd.o ${SOLIB1}
cp libpnd* deployment/usr/lib
cp bin/pndnotifyd deployment/usr/bin
cp bin/pnd_run deployment/usr/bin
+ cp bin/pnd_info deployment/usr/bin
cp testdata/scripts/* deployment/usr/pandora/scripts
cp bin/pndevmapperd deployment/usr/bin
# copy in freebee .pnd apps to /usr/pandora/apps
--- /dev/null
+
+#include <stdio.h> /* for printf, NULL */
+#include <stdlib.h> /* for free */
+#include <string.h> /* for strdup */
+
+#include "pnd_conf.h"
+#include "pnd_container.h"
+#include "pnd_apps.h"
+#include "pnd_discovery.h"
+#include "pnd_locate.h"
+#include "pnd_pndfiles.h"
+#include "pnd_pxml.h"
+
+static void usage ( char *argv[] ) {
+ printf ( "%s\tObtain a description, install guide or other info about a pnd-file\n", argv [ 0 ] );
+ printf ( "\n" );
+ printf ( "%s path-to-pndfile [section] [section-2...]\n", argv [ 0 ] );
+ printf ( "\n" );
+ printf ( "section\tOptional. If not specified, general description is shown. (Section 'description')\n" );
+ printf ( "\tIf present, show the named section of the PXML -- such as to obtain install instructions etc.\n" );
+ printf ( "pndfile\tRequired. Full path to the pnd-file to execute.\n" );
+ return;
+}
+
+#define SECTIONMAX 100
+
+int main ( int argc, char *argv[] ) {
+ char *pndfile = NULL;
+ char *section [ SECTIONMAX ];
+ unsigned char sections = 0;
+ int i;
+
+ for ( i = 1; i < argc; i++ ) {
+
+ if ( ! pndfile ) {
+ pndfile = argv [ i ];
+ continue;
+ }
+
+ section [ sections++ ] = argv [ i ];
+
+ if ( sections == SECTIONMAX ) {
+ break;
+ }
+
+ } // for args
+
+ if ( ! pndfile ) {
+ usage ( argv );
+ exit ( 0 );
+ }
+
+ if ( ! sections ) {
+ section [ sections++ ] = "description";
+ }
+
+ // summary
+ printf ( "Pndfile\t%s\n", pndfile );
+ printf ( "Sections to include:\n" );
+ for ( i = 0; i < sections; i++ ) {
+ printf ( "- %s\n", section [ i ] );
+ } // for
+ printf ( "\n" );
+
+ // pull PXML
+ unsigned int pxmlbuflen = 96 * 1024; // lame, need to calculate it
+ char *pxmlbuf = malloc ( pxmlbuflen );
+ if ( ! pxmlbuf ) {
+ printf ( "ERROR: RAM exhausted!\n" );
+ exit ( 0 );
+ }
+ memset ( pxmlbuf, '\0', pxmlbuflen );
+
+ FILE *f = fopen ( pndfile, "r" );
+ if ( ! f ) {
+ printf ( "ERROR: Couldn't open pndfile %s!\n", pndfile );
+ exit ( 0 );
+ }
+
+ pnd_pxml_handle h = NULL;
+ if ( pnd_pnd_seek_pxml ( f ) ) {
+ if ( pnd_pnd_accrue_pxml ( f, pxmlbuf, pxmlbuflen ) ) {
+ h = pnd_pxml_fetch_buffer ( "pnd_run", pxmlbuf );
+ }
+ }
+
+ fclose ( f );
+
+ if ( ! h ) {
+ printf ( "ERROR: Couldn't pull PXML.xml from the pndfile.\n" );
+ exit ( 0 );
+ }
+
+ // display sections
+ for ( i = 0; i < sections; i++ ) {
+ char *t;
+
+ if ( strcasecmp ( section [ i ], "description" ) == 0 ) {
+
+ printf ( "Section: %s\n", section [ i ] );
+
+ if ( ( t = pnd_pxml_get_description_en ( h ) ) ) {
+ printf ( "%s\n", t );
+ } else {
+ printf ( "Not supplied by PXML.xml in the pnd-file\n" );
+ }
+
+ }
+
+ } // for
+
+ return ( 0 );
+} // main
#include <fcntl.h> // for open(2)
#include <errno.h> // for errno
#include <time.h> // for time(2)
+#include <ctype.h> // for isdigit
#include <linux/input.h> // for keys
//#include "../../kernel-rip/input.h" // for keys
#include "pnd_pndfiles.h"
#include "pnd_pxml.h"
#include "pnd_logger.h"
+#include "pnd_utility.h"
+#include "pnd_notify.h"
// daemon and logging
//
static void usage ( char *argv[] ) {
printf ( "%s [-d]\n", argv [ 0 ] );
printf ( "-d\tDaemon mode; detach from terminal, chdir to /tmp, suppress output. Optional.\n" );
+ printf ( "-l#\tLog-it; -l is 0-and-up (or all), and -l2 means 2-and-up (not all); l[0-3] for now. Log goes to /tmp/pndevmapperd.log\n" );
printf ( "Signal: HUP the process to force reload of configuration and reset the notifier watch paths\n" );
return;
}
int main ( int argc, char *argv[] ) {
int i;
+ int logall = -1; // -1 means normal logging rules; >=0 means log all!
for ( i = 1; i < argc; i++ ) {
if ( argv [ i ][ 0 ] == '-' && argv [ i ][ 1 ] == 'd' ) {
//printf ( "Going daemon mode. Silent running.\n" );
g_daemon_mode = 1;
+ } else if ( argv [ i ][ 0 ] == '-' && argv [ i ][ 1 ] == 'l' ) {
+
+ if ( isdigit ( argv [ i ][ 2 ] ) ) {
+ unsigned char x = atoi ( argv [ i ] + 2 );
+ if ( x >= 0 &&
+ x < pndn_none )
+ {
+ logall = x;
+ }
+ } else {
+ logall = 0;
+ }
} else {
usage ( argv );
exit ( 0 );
/* enable logging?
*/
- if ( g_daemon_mode ) {
- // nada
+ pnd_log_set_pretext ( "pndevmapperd" );
+ pnd_log_set_flush ( 1 );
+
+ if ( logall == -1 ) {
+ // standard logging; non-daemon versus daemon
+
+ if ( g_daemon_mode ) {
+ // nada
+ } else {
+ pnd_log_set_filter ( pndn_rem );
+ pnd_log_to_stdout();
+ }
+
} else {
- pnd_log_set_filter ( pndn_rem );
- pnd_log_set_pretext ( "pndevmapperd" );
- pnd_log_to_stdout();
- pnd_log ( pndn_rem, "log level starting as %u", pnd_log_get_filter() );
- }
+ FILE *f;
+
+ f = fopen ( "/tmp/pndevmapperd.log", "w" );
+
+ if ( f ) {
+ pnd_log_set_filter ( logall );
+ pnd_log_to_stream ( f );
+ pnd_log ( pndn_rem, "logall mode - logging to /tmp/pndevmapperd.log\n" );
+ }
+
+ if ( logall == pndn_debug ) {
+ pnd_log_set_buried_logging ( 1 ); // log the shit out of it
+ pnd_log ( pndn_rem, "logall mode 0 - turned on buried logging\n" );
+ }
+
+ } // logall
+
+ pnd_log ( pndn_rem, "%s built %s %s", argv [ 0 ], __DATE__, __TIME__ );
+
+ pnd_log ( pndn_rem, "log level starting as %u", pnd_log_get_filter() );
// basic daemon set up
if ( g_daemon_mode ) {
} // set up daemon
+ /* hmm, seems to not like working right after boot.. do we depend on another daemon or
+ * on giving kernel time to init something, or ... wtf?
+ * -- lets give the system some time to wake up
+ */
+ { // delay
+
+ // this one works for pndnotifyd, which actually needs INOTIFYH..
+ //
+
+ // check if inotify is awake yet; if not, try waiting for awhile to see if it does
+ pnd_log ( pndn_rem, "Starting INOTIFY test; should be instant, but may take awhile...\n" );
+
+ if ( ! pnd_notify_wait_until_ready ( 120 /* seconds */ ) ) {
+ pnd_log ( pndn_error, "ERROR: INOTIFY refuses to be useful and quite awhile has passed. Bailing out.\n" );
+ return ( -1 );
+ }
+
+ pnd_log ( pndn_rem, "INOTIFY seems to be useful, whew.\n" );
+
+ // pndnotifyd also waits for user to log in .. pretty excessive, especially since
+ // what if user wants to close the lid while at the log in screen? for now play the
+ // odds as thats pretty unliekly usage scenariom but is clearly not acceptible :/
+ //
+
+ // wait for a user to be logged in - we should probably get hupped when a user logs in, so we can handle
+ // log-out and back in again, with SDs popping in and out between..
+ pnd_log ( pndn_rem, "Checking to see if a user is logged in\n" );
+ char tmp_username [ 128 ];
+ while ( 1 ) {
+ if ( pnd_check_login ( tmp_username, 127 ) ) {
+ break;
+ }
+ pnd_log ( pndn_debug, " No one logged in yet .. spinning.\n" );
+ sleep ( 2 );
+ } // spin
+ pnd_log ( pndn_rem, "Looks like user '%s' is in, continue.\n", tmp_username );
+
+ } // delay
+
/* inhale config or die trying
*/
char *configpath;
char *run_script; // name of pnd_run.sh script from config
char *pndrun; // full path to located pnd_run.sh
char *pndhup = NULL; // full path to located pnd_hup.sh
+// default username
+char g_username [ 128 ]; // since we have to wait for login (!!), store username here
// notifier handle
pnd_notify_handle nh = 0;
// behaviour
unsigned char scanonlaunch = 1;
unsigned int interval_secs = 5;
+ int logall = -1; // -1 means normal logging rules; >=0 means log all!
// misc
int i;
interval_secs = atoi ( argv [ i ] );
} else if ( argv [ i ][ 0 ] == '-' && argv [ i ][ 1 ] == 'n' ) {
scanonlaunch = 0;
+ } else if ( argv [ i ][ 0 ] == '-' && argv [ i ][ 1 ] == 'l' ) {
+
+ if ( isdigit ( argv [ i ][ 2 ] ) ) {
+ unsigned char x = atoi ( argv [ i ] + 2 );
+ if ( x >= 0 &&
+ x < pndn_none )
+ {
+ logall = x;
+ }
+ } else {
+ logall = 0;
+ }
+
} else {
printf ( "%s [-d] [##]\n", argv [ 0 ] );
printf ( "-d\tDaemon mode; detach from terminal, chdir to /tmp, suppress output. Optional.\n" );
printf ( "-n\tDo not scan on launch; default is to run a scan for apps when %s is invoked.\n", argv [ 0 ] );
+ printf ( "-l#\tLog-it; -l is 0-and-up (or all), and -l2 means 2-and-up (not all); l[0-3] for now. Log goes to /tmp/pndnotifyd.log\n" );
printf ( "##\tA numeric value is interpreted as number of seconds between checking for filesystem changes. Default %u.\n",
interval_secs );
printf ( "Signal: HUP the process to force reload of configuration and reset the notifier watch paths\n" );
/* enable logging?
*/
- if ( g_daemon_mode ) {
- // nada
+ pnd_log_set_pretext ( "pndnotifyd" );
+ pnd_log_set_flush ( 1 );
+
+ if ( logall == -1 ) {
+ // standard logging; non-daemon versus daemon
+
+ if ( g_daemon_mode ) {
+ // nada
+ } else {
+ pnd_log_set_filter ( pndn_rem );
+ pnd_log_to_stdout();
+ }
+
} else {
- pnd_log_set_filter ( pndn_rem );
- pnd_log_set_pretext ( "pndnotifyd" );
- pnd_log_to_stdout();
- pnd_log_set_flush ( 1 );
- pnd_log ( pndn_rem, "log level starting as %u", pnd_log_get_filter() );
- }
+ FILE *f;
+
+ f = fopen ( "/tmp/pndnotifyd.log", "w" );
+
+ if ( f ) {
+ pnd_log_set_filter ( logall );
+ pnd_log_to_stream ( f );
+ pnd_log ( pndn_rem, "logall mode - logging to /tmp/pndnotifyd.log\n" );
+ }
+
+ if ( logall == pndn_debug ) {
+ pnd_log_set_buried_logging ( 1 ); // log the shit out of it
+ pnd_log ( pndn_rem, "logall mode 0 - turned on buried logging\n" );
+ }
+
+ } // logall
+
+ pnd_log ( pndn_rem, "%s built %s %s", argv [ 0 ], __DATE__, __TIME__ );
+
+ pnd_log ( pndn_rem, "log level starting as %u", pnd_log_get_filter() );
pnd_log ( pndn_rem, "Interval between checks is %u seconds\n", interval_secs );
// wait for a user to be logged in - we should probably get hupped when a user logs in, so we can handle
// log-out and back in again, with SDs popping in and out between..
pnd_log ( pndn_rem, "Checking to see if a user is logged in\n" );
- char tmp_username [ 128 ];
while ( 1 ) {
- if ( pnd_check_login ( tmp_username, 127 ) ) {
+ if ( pnd_check_login ( g_username, 127 ) ) {
break;
}
pnd_log ( pndn_debug, " No one logged in yet .. spinning.\n" );
sleep ( 2 );
} // spin
- pnd_log ( pndn_rem, "Looks like user '%s' is in, continue.\n", tmp_username );
+ pnd_log ( pndn_rem, "Looks like user '%s' is in, continue.\n", g_username );
/* parse configs
*/
if ( scanonlaunch ||
pnd_notify_rediscover_p ( nh ) )
{
+
+ if ( time ( NULL ) - createtime <= 2 ) {
+ pnd_log ( pndn_rem, "Rediscovery request comes to soon after previous discovery; skipping.\n" );
+ sleep ( interval_secs );
+ continue;
+ }
+
createtime = time ( NULL ); // all 'new' .destops are created at or after this time; prev are old.
// if this was a forced scan, lets not do that next iteration
}
if ( pnd_conf_get_as_int ( apph, PNDNOTIFYD_LOGLEVEL ) != PND_CONF_BADNUM ) {
- pnd_log_set_filter ( pnd_conf_get_as_int ( apph, PNDNOTIFYD_LOGLEVEL ) );
- pnd_log ( pndn_rem, "config file causes loglevel to change to %u", pnd_log_get_filter() );
+ if ( pnd_log_do_buried_logging() == 0 ) {
+ pnd_log_set_filter ( pnd_conf_get_as_int ( apph, PNDNOTIFYD_LOGLEVEL ) );
+ pnd_log ( pndn_rem, "config file causes loglevel to change to %u", pnd_log_get_filter() );
+ } else {
+ pnd_log ( pndn_rem, "-l command line suppresses log level change in config file\n" );
+ }
}
} else {
* the user is formally logged in
*/
pnd_log ( pndn_rem, "Setting a default $HOME to non-root user\n" );
- {
+
+ // first, try to see if known-username maps to a homedir; if so, just use that!
+ // otherwise, pick first non-root homedir and assume .. or we start blaring .desktops
+ // out to all users like idiots
+ unsigned char got_user_homedir = 0;
+
+ if ( g_username [ 0 ] ) {
+ struct stat homedir;
+ char path [ PATH_MAX ];
+
+ sprintf ( path, "/home/%s", g_username );
+
+ // does this made up path exist?
+ if ( stat ( path, &homedir ) == 0 ) {
+
+ // and its a dir?
+ if ( S_ISDIR(homedir.st_mode) ) {
+ pnd_log ( pndn_rem, " User [%s] matches path [%s], going with '%s'\n", g_username, path, path );
+ setenv ( "HOME", path, 1 /* overwrite */ );
+ got_user_homedir = 1;
+ } // and its a dir?
+
+ } // guessing a homedirname..
+
+ } // got a username?
+
+ // if guessing a path was no good, just try finding one
+ if ( got_user_homedir == 0 ) {
DIR *dir;
if ( ( dir = opendir ( "/home" ) ) ) {
struct dirent *dirent;
while ( ( dirent = readdir ( dir ) ) ) {
- pnd_log ( pndn_rem, " Found user homedir '%s'\n", dirent -> d_name );
+ pnd_log ( pndn_rem, " Scanning user homedir '%s'\n", dirent -> d_name );
// file is a .desktop?
if ( dirent -> d_name [ 0 ] == '.' ) {
pnd_log ( pndn_rem, "ERROR: Error creating .desktop file for app: %s\n", pnd_box_get_key ( d ) );
}
+ // does this object request any mkdir's?
+ if ( d -> mkdir_sp ) {
+
+ // it would appear it does! but we have to carefully validate these suckers
+ pnd_log ( pndn_rem, " App %s requests mkdir: %s\n", d -> object_path, d -> mkdir_sp );
+
+ // for each mkdir requested path, do it...
+ char *searchpath = d -> mkdir_sp;
+
+ SEARCHCHUNK_PRE
+ {
+ /* "buffer" now holds each chunk of the searchpath, expanded */
+
+ // WARN: This whole concept could be flawed; what if they represent '..' in some other obscure way (unicode?)
+ // and we end up allowing mkdir's all over the place? The risk really is limited -- once the pnd is here,
+ // if the user _runs it_, it can go nuts, so creating a few dirs isn't all that dangerous...
+ // HMRF :/
+ // Perhaps I should have a config setting for pndnotifyd to suppress this whole mkdir behaviour?
+
+ // if not containing ".." we allow it
+ if ( strstr ( buffer, ".." ) == NULL ) {
+
+ // determine mountpoint for the file
+ // - we could deduce this from the path (somewhat risky if we assume leading /media/mmcblk1p1 type notation .. could
+ // be other distributions entirely
+ // - better to scan through mount-list and figure it out.. *sucks*
+ char mountpoint [ PATH_MAX ];
+ if ( pnd_determine_mountpoint ( d -> object_path, mountpoint, PATH_MAX - strlen ( buffer ) - 1 ) == 1 ) {
+
+ strcat ( mountpoint, "/" );
+ strcat ( mountpoint, buffer );
+
+ struct stat t;
+ if ( stat ( mountpoint, &t ) == 0 ) {
+ pnd_log ( pndn_rem, " Skipping existing mkdir: %s\n", mountpoint );
+ } else {
+ pnd_log ( pndn_rem, " Attempting create of non-existant path: %s\n", mountpoint );
+ mkdir ( mountpoint, 0777 );
+ }
+
+ } // if figured out the mountpoint
+
+ } // if valid path
+
+ }
+ SEARCHCHUNK_POST
+
+ } // mkdir request
+
// next!
d = pnd_box_get_next ( d );
{
pnd_box_handle applist;
+ pnd_log ( pndn_rem, "perform discovery - apps: %s, overrides: %s\n", appspath, overridespath );
+ pnd_log ( pndn_rem, " - emit desktop: %s, icons: %s\n", emitdesktoppath, emiticonpath );
+
// attempt to auto-discover applications in the given path
applist = pnd_disco_search ( appspath, overridespath );
}
}
if ( source_libpnd ) {
-#if 0
- pnd_log ( pndn_rem,
+#if 1
+ pnd_log ( pndn_debug,
"File '%s' appears to have been created by libpnd so candidate for delete: %u\n", buffer, source_libpnd );
#endif
} else {
#if 0
- pnd_log ( pndn_rem, "File '%s' appears NOT to have been created by libpnd, so leave it alone\n", buffer );
+ pnd_log ( pndn_debug, "File '%s' appears NOT to have been created by libpnd, so leave it alone\n", buffer );
#endif
continue; // skip deleting it
}
// file is 'new'?
if ( stat ( buffer, &dirs ) == 0 ) {
if ( dirs.st_mtime >= createtime ) {
-#if 0
- pnd_log ( pndn_rem, "File '%s' seems 'new', so leave it alone.\n", buffer );
+#if 1
+ pnd_log ( pndn_debug, "File '%s' seems 'new', so leave it alone.\n", buffer );
#endif
continue; // skip deleting it
}
char *alt_category2;
char *preview_pic1;
char *preview_pic2;
+ char *mkdir_sp;
} pnd_disco_t;
void pnd_disco_destroy ( pnd_disco_t *p ); // a function name that simply could not be avoided
// how many targets can be opened, entirely? this is a compile time limit, for sanity.
unsigned char pnd_log_max_targets ( void );
+// tell buried lib functions to do some logging here; ie: since not all API's have a 'options' type flag where we could
+// add a hint to begin logging, they can just ask the logger if they need to do it
+#define PND_LOG_DEFAULT 0 // level 0 is by default the 'debug' level, with anything higher non-debug; only used for buried logging
+void pnd_log_set_buried_logging ( unsigned char yesno ); // set 1 for 'yes', 0 for 'no'
+unsigned char pnd_log_do_buried_logging ( void ); // return 1 for 'yes'
+
#ifdef __cplusplus
} /* "C" */
#endif
char *pnd_pxml_get_clockspeed ( pnd_pxml_handle h );
char *pnd_pxml_get_background ( pnd_pxml_handle h );
char *pnd_pxml_get_startdir ( pnd_pxml_handle h );
+char *pnd_pxml_get_mkdir ( pnd_pxml_handle h );
// for 'set' functions, pass NULL value to delete existing value without setting new one
void pnd_pxml_set_app_name ( pnd_pxml_handle h, char *v );
char *exec_no_x11;
char *package_name;
char *package_release_date;
+ char *mkdir_sp; // a colon separated list of paths to be mkdir'd (silently fail) when pnd is autodiscovered. path is always relative to the root of the hosting device.
} pnd_pxml_t;
#define PND_PXML_ATTRNAME_PACKAGE_NAME "name"
#define PND_PXML_ATTRNAME_PACKAGE_DATE "released"
+/* <mkdir>
+ * <dir path="..." />
+ * </mkdir>
+ */
+#define PND_PXML_NODENAME_MKDIR "mkdir"
+#define PND_PXML_ENAME_MKDIR "dir"
+#define PND_PXML_ATTRNAME_MKDIRPATH "path"
+
#ifdef __cplusplus
} // extern "C"
#endif
// NOTE: Does _NOT_ automatically pick up PXML-overrides; you can call that function if you want
pnd_pxml_handle pnd_pxml_get_by_path ( char *fullpath );
+// determine_mountpoint() will examine a path, and return the mountpoint that this path
+// is sitting on; returns 1 on success, meaning the target was populated.
+// consider for a similar effect: df /home -> look at "Mounted on"
+unsigned char pnd_determine_mountpoint ( char *fullpath, char *r_mountpoint, unsigned char mountpoint_len );
+
#ifdef __cplusplus
} /* "C" */
#endif
temp = pnd_conf_get_as_char ( ch, PND_CONF_KEY );
- if ( searchpath ) {
+ if ( temp ) {
searchpath = strdup ( temp );
} else {
searchpath = strdup ( PND_CONF_SEARCHPATH );
#include "pnd_pathiter.h"
#include "pnd_apps.h"
#include "pnd_pndfiles.h"
+#include "pnd_logger.h"
// need these 'globals' due to the way nftw and ftw work :/
static pnd_box_handle disco_box;
if ( p -> alt_category ) { free ( p -> alt_category ); }
if ( p -> alt_category1 ) { free ( p -> alt_category1 ); }
if ( p -> alt_category2 ) { free ( p -> alt_category2 ); }
+ if ( p -> mkdir_sp ) { free ( p -> mkdir_sp ); }
return;
}
unsigned char valid = pnd_object_type_unknown;
pnd_pxml_handle pxmlh = 0;
unsigned int pxml_close_pos = 0;
+ unsigned char logit = pnd_log_do_buried_logging();
- //printf ( "disco root callback encountered '%s'\n", fpath );
+ if ( logit ) {
+ pnd_log ( PND_LOG_DEFAULT, "disco callback encountered '%s'\n", fpath );
+ }
// PXML.xml is a possible application candidate (and not a dir named PXML.xml :)
if ( typeflag & FTW_D ) {
- //printf ( " .. is dir, skipping\n" );
+ if ( logit ) {
+ pnd_log ( PND_LOG_DEFAULT, " .. is dir, skipping\n" );
+ }
return ( 0 ); // skip directories and other non-regular files
}
// if not a file of interest, just keep looking until we run out
if ( ! valid ) {
- //printf ( " .. bad filename, skipping\n" );
+ if ( logit ) {
+ pnd_log ( PND_LOG_DEFAULT, " .. bad filename, skipping\n" );
+ }
return ( 0 );
}
if ( ( z = pnd_pxml_get_previewpic2 ( pxmlh ) ) ) {
p -> preview_pic2 = strdup ( z );
}
+ // mkdirs
+ if ( pnd_pxml_get_mkdir ( pxmlh ) ) {
+ p -> mkdir_sp = strdup ( pnd_pxml_get_mkdir ( pxmlh ) );
+ }
} else {
//printf ( "Invalid PXML; skipping.\n" );
#include <stdarg.h> // va-args
#include <stdlib.h> // malloc/free
#include <string.h> // strdup
+#include <time.h>
#include "pnd_logger.h"
-char *log_pretext = NULL;
-unsigned char log_filterlevel = 0;
-unsigned char log_flushafter = 0;
+static char *log_pretext = NULL;
+static unsigned char log_filterlevel = 0;
+static unsigned char log_flushafter = 0;
+static time_t log_first = 0;
typedef enum {
pndl_nil = 0,
return ( PND_LOG_MAX );
}
-void pnd_log_emit ( char *message ) {
+static void pnd_log_emit ( unsigned char level, char *message ) {
unsigned char i;
// iterate across targets and attempt to emit
break;
case pndl_stream:
+ // pretext
if ( log_pretext ) {
- fprintf ( log_targets [ i ].stream, "%s\t", log_pretext );
+ fprintf ( log_targets [ i ].stream, "%s ", log_pretext );
}
+ // log level
+ fprintf ( log_targets [ i ].stream, "%u %u\t", level, (unsigned int) (time ( NULL ) - log_first) );
+ // message
if ( message ) {
fprintf ( log_targets [ i ].stream, "%s", message );
if ( strchr ( message, '\n' ) == NULL ) {
unsigned char pnd_log ( unsigned char level, char *fmt, ... ) {
+ if ( log_first == 0 ) {
+ log_first = time ( NULL );
+ }
+
if ( level == PND_LOG_FORCE ) {
// always proceed
} else if ( level < log_filterlevel ) {
/* If that worked, return the string. */
if ( n > -1 && n < size ) {
- pnd_log_emit ( p );
+ pnd_log_emit ( level, p );
break;
}
return ( 1 );
}
+
+
+static unsigned char _do_buried_logging = 0;
+void pnd_log_set_buried_logging ( unsigned char yesno ) {
+ _do_buried_logging = yesno;
+ return;
+}
+
+unsigned char pnd_log_do_buried_logging ( void ) {
+ if ( _do_buried_logging == 1 ) {
+ return ( 1 );
+ }
+ return ( 0 );
+}
return ( 0 ); // nothing, or overflow, or .. whatever.
}
- unsigned int i;
+ unsigned int i = 0;
struct inotify_event *e;
while ( i < actuallen ) {
#if 1 // globbing is performed
+// only iterates actual existing paths; if you want to return
+// non-matching paths, see below
+
#define SEARCHPATH_PRE \
char *end, *colon; \
char *head = searchpath; \
\
} // while
+
+// the following will return even non-matching chunks, but is not doing wordexp() expansion on it
+
+#define SEARCHCHUNK_PRE \
+ char *end, *colon; \
+ char *head = searchpath; \
+ char chunk [ FILENAME_MAX ]; \
+ \
+ /*fprintf ( stderr, "sp %s\n", searchpath );*/ \
+ \
+ while ( 1 ) { \
+ colon = strchr ( head, ':' ); \
+ end = strchr ( head, '\0' ); \
+ \
+ if ( colon && colon < end ) { \
+ memset ( chunk, '\0', FILENAME_MAX ); \
+ strncpy ( chunk, head, colon - head ); \
+ } else { \
+ strncpy ( chunk, head, FILENAME_MAX - 1 ); \
+ } \
+ \
+ /*fprintf ( stderr, "-> %s\n", chunk ); */ \
+ \
+ char buffer [ FILENAME_MAX ]; \
+ \
+ strcpy ( buffer, chunk ); \
+ /*fprintf ( stderr, "glob %s\n", buffer );*/ \
+ { /* user code */
+
+#define SEARCHCHUNK_POST \
+ } /* user code */ \
+ /* next search path */ \
+ if ( colon && colon < end ) { \
+ head = colon + 1; \
+ } else { \
+ break; /* done! */ \
+ } \
+ \
+ } // while
+
+
#endif // globbing is done
pnd_pxml_t *p = (pnd_pxml_t*) h;
return ( p -> startdir );
}
+
+char *pnd_pxml_get_mkdir ( pnd_pxml_handle h ) {
+ pnd_pxml_t *p = (pnd_pxml_t*) h;
+ return ( p -> mkdir_sp );
+}
app -> package_release_date = pnd_pxml_get_attribute ( pElem, PND_PXML_ATTRNAME_PACKAGE_DATE );
}
+ // mkdir request
+ if ( (pElem = hRoot.FirstChild(PND_PXML_NODENAME_MKDIR).Element()) ) {
+
+ // seek <dir>
+ if ( (pElem = pElem->FirstChildElement(PND_PXML_ENAME_MKDIR)) ) {
+ char *t;
+
+ if ( ( t = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_MKDIRPATH) ) ) {
+ // first <dir>, so just replace it wholesale; we use strdup so we can free() easily later, consistently. Mmm, leak seems imminent.
+ app -> mkdir_sp = strdup ( t );
+ }
+
+ while ( ( pElem = pElem -> NextSiblingElement ( PND_PXML_ENAME_MKDIR ) ) ) {
+
+ if ( ( t = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_MKDIRPATH) ) ) {
+ char *foo = (char*) malloc ( strlen ( app -> mkdir_sp ) + strlen ( t ) + 1 /*:*/ + 1 /*\0*/ );
+
+ if ( foo ) {
+ sprintf ( foo, "%s:%s", app -> mkdir_sp, t );
+ free ( app -> mkdir_sp );
+ app -> mkdir_sp = foo;
+ } // assuming we got ram, lets cat it all together
+
+ } // got another elem?
+
+ } // while
+
+ } // found a <dir>
+
+#if 0
+ if ( app -> mkdir_sp ) {
+ printf ( "mkdir: %s\n", app -> mkdir_sp );
+ }
+#endif
+
+ } // mkdir
+
return (1);
}
#include <utmp.h> /* for expand-tilde below; see commentary for this about-turn */
#include <sys/types.h> /* ditto */
#include <pwd.h> /* ditto */
+#include <sys/stat.h> /* for fstat */
+#include <dirent.h> /* for opendir */
#include "pnd_pxml.h"
#include "pnd_container.h"
char *s = freeable_buffer;
char *home = getenv ( "HOME" );
- printf ( "DEBUG: expand tilde IN: '%s'\n", freeable_buffer );
- printf ( "DEBUG: $HOME was %s\n", home );
+ //printf ( "DEBUG: expand tilde IN: '%s'\n", freeable_buffer );
+ //printf ( "DEBUG: $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
florp = strdup ( pw -> pw_dir );
home = florp;
- printf ( " DEBUG: home (for %s) is %s (from %u)\n", b.ut_user, home, b.ut_type );
+ //printf ( " DEBUG: home (for %s) is %s (from %u)\n", b.ut_user, home, b.ut_type );
} // passwd entry matches the utmp entry
return ( s ); // can't succeed
}
- printf ( "DEBUG: entering while (%s) with home (%s)\n", s, home );
+ //printf ( "DEBUG: entering while (%s) with home (%s)\n", s, home );
while ( ( p = strchr ( s, '~' ) ) ) {
- printf ( "DEBUG: within while (%s)\n", s );
+ //printf ( "DEBUG: within while (%s)\n", s );
char *temp = malloc ( strlen ( s ) + strlen ( home ) + 1 );
memset ( temp, '\0', strlen ( s ) + strlen ( home ) + 1 );
// copy in stuff prior to ~
s = temp;
} // while finding matches
- printf ( "DEBUG: expand tilde OUT: '%s'\n", s );
+ //printf ( "DEBUG: expand tilde OUT: '%s'\n", s );
return ( s );
}
return ( pxmlh );
}
+
+unsigned char pnd_determine_mountpoint ( char *fullpath, char *r_mountpoint, unsigned char mountpoint_len ) {
+
+ // just cheap it, and call df like an idiot.
+
+ // Filesystem 1K-blocks Used Available Use% Mounted on
+
+ char cmd [ PATH_MAX ];
+ FILE *p;
+ char inbuf [ PATH_MAX ];
+
+ sprintf ( cmd, "/bin/df %s 2>/dev/null", fullpath );
+
+ if ( ( p = popen ( cmd, "r" ) ) ) {
+
+ // ignore title line; we really shoudl analyze it to figure out which column, but we make assumptions..
+ fgets ( inbuf, PATH_MAX, p );
+
+ if ( ! fgets ( inbuf, PATH_MAX, p ) ) {
+ pclose ( p );
+ return ( 0 );
+ }
+
+ pclose ( p );
+
+ // by now, good
+ char crap [ PATH_MAX ];
+ char mount [ PATH_MAX ];
+ if ( sscanf ( inbuf, "%s %s %s %s %s %s", crap, crap, crap, crap, crap, mount ) != 6 ) {
+ return ( 0 );
+ }
+
+ if ( strlen ( mount ) < mountpoint_len ) {
+ strcpy ( r_mountpoint, mount );
+ return ( 1 );
+ }
+
+ } // if popen
+
+ return ( 0 );
+
+#if 0
+ struct stat fooby;
+
+ // can we even stat this file?
+ if ( stat ( fullpath, &fooby ) == 0 ) {
+ //dev_t st_dev; /* ID of device containing file */
+ //dev_t st_rdev; /* device ID (if special file) */
+
+ dev_t mount = fooby.st_dev;
+
+ DIR *d = opendir ( "/dev" );
+
+ if ( d ) {
+ struct dirent *de;
+ char path [ FILENAME_MAX ];
+
+ while ( de = readdir ( d ) ) {
+ sprintf ( path, "/dev/%s", de -> d_name );
+
+ if ( stat ( path, &fooby ) == 0 ) {
+
+ // finally, if we find the same major/minor pair in /dev, as we found for the target file, it means we found the right device
+ if ( fooby.st_rdev == mount ) {
+ printf ( "Device: %s\n", path );
+ }
+
+ } // if
+
+ } // while
+
+ } // opened /dev?
+
+ } // stat
+#endif
+
+ return ( 0 );
+}
if ( d -> preview_pic2 ) {
printf ( " Preview Pic 2: %s\n", d -> preview_pic2 );
}
+ if ( d -> mkdir_sp ) {
+ printf ( " mkdir requests: %s\n", d -> mkdir_sp );
+ }
if ( do_icon ) {
if ( pnd_emit_icon ( "./testdata/dotdesktop", d ) ) {
<author name="EvilDragon" website="http://www.openpandora.org"/><!--Optional email and website, name required-->
+ <mkdir>
+ <dir path="common/mydir1"/>
+ <dir path="common/mydir2"/>
+ </mkdir>
+
<version major="1" minor="1" release="1" build="2"/><!--This program's version-->
<osversion major="1" minor="0" release="0" build="0"/><!--The minimum OS version required-->