Created pnd_desktop.[ch] pair, to contain relocated dotdesktop and icon stuff
authorskeezix <skeezix@flotsam-vm.(none)>
Sat, 7 Mar 2009 06:43:14 +0000 (01:43 -0500)
committerskeezix <skeezix@flotsam-vm.(none)>
Sat, 7 Mar 2009 06:43:14 +0000 (01:43 -0500)
Relocated hup-script config key/default to pnd_desktop
Figured that app searchpath was being misused -- using for both app searchpath and notify searchpath, so
created new config entry for notify searchpath; ie: you might wish to notify on /media so that dirs
created by automount will be detected, but you may not wish to find .pnd files in that path (since it
recurses and would thus find apps on the entire SD card.)

12 files changed:
Makefile
apps/pndnotifyd.c
deployment/etc/pandora/conf/apps
deployment/etc/pandora/conf/desktop
include/pnd_apps.h
include/pnd_desktop.h [new file with mode: 0644]
include/pnd_device.h
lib/pnd_desktop.c [new file with mode: 0644]
lib/pnd_discovery.c
testdata/conf/apps
testdata/conf/desktop
testdata/scripts/pnd_hup.sh [new file with mode: 0755]

index bbb0402..91a9181 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -20,7 +20,7 @@ LIB = libpnd.a
 SOLIB = libpnd.so.1         # canonicle name
 SOLIB1 = libpnd.so.1.0.1    # versioned name
 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
+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
 
 all: ${SOLIB} ${LIB} conftest discotest notifytest locatetest pndnotifyd
 
index 797fb80..b4eb678 100644 (file)
@@ -28,6 +28,7 @@
 #include "pnd_discovery.h"
 #include "pnd_locate.h"
 #include "pnd_utility.h"
+#include "pnd_desktop.h"
 
 // this piece of code was simpler once; but need to grow it a bit and in a rush
 // moving all these to globals rather than refactor the code a bit; tsk tsk..
@@ -42,11 +43,12 @@ char *overridespath;
 // daemon stuff
 char *searchpath = NULL;
 char *dotdesktoppath = NULL;
+char *notifypath = NULL;
 // pnd runscript
-char *run_searchpath;
-char *run_script;
-char *pndrun;
-char *pndhup = NULL;
+char *run_searchpath; // searchpath to find pnd_run.sh
+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
 // notifier handle
 pnd_notify_handle nh = 0;
 
@@ -124,6 +126,7 @@ int main ( int argc, char *argv[] ) {
     printf ( "Apps searchpath is '%s'\n", appspath );
     printf ( "PXML overrides searchpath is '%s'\n", overridespath );
     printf ( ".desktop files emit to '%s'\n", dotdesktoppath );
+    printf ( "Notify searchpath is '%s'\n", notifypath );
   }
 
   /* set up signal handler
@@ -373,6 +376,7 @@ void consume_configuration ( void ) {
   apph = pnd_conf_fetch_by_id ( pnd_conf_apps, configpath );
 
   if ( apph ) {
+
     appspath = pnd_conf_get_as_char ( apph, PND_APPS_KEY );
 
     if ( ! appspath ) {
@@ -385,10 +389,17 @@ void consume_configuration ( void ) {
       overridespath = PND_PXML_OVERRIDE_SEARCHPATH;
     }
 
+    notifypath = pnd_conf_get_as_char ( apph, PND_APPS_NOTIFY_KEY );
+
+    if ( ! notifypath ) {
+      notifypath = PND_APPS_NOTIFYPATH;
+    }
+
   } else {
     // couldn't find a useful app search path so use the default
     appspath = PND_APPS_SEARCHPATH;
     overridespath = PND_PXML_OVERRIDE_SEARCHPATH;
+    notifypath = PND_APPS_NOTIFYPATH;
   }
 
   // attempt to figure out where to drop dotfiles
@@ -434,10 +445,10 @@ void consume_configuration ( void ) {
 
   }
 
-  if ( apph && run_searchpath ) {
+  if ( desktoph && run_searchpath ) {
     char *t;
 
-    if ( ( t = pnd_conf_get_as_char ( apph, PND_PNDHUP_KEY ) ) ) {
+    if ( ( t = pnd_conf_get_as_char ( desktoph, PND_PNDHUP_KEY ) ) ) {
       pndhup = pnd_locate_filename ( run_searchpath, t );
 #if 0 // don't enable this; if no key in config, we don't want to bother hupping
     } else {
@@ -472,7 +483,7 @@ void consume_configuration ( void ) {
 }
 
 void setup_notifications ( void ) {
-  searchpath = appspath;
+  searchpath = notifypath;
 
   // if this is first time through, we can just set it up; for subsequent times
   // through, we need to close existing fd and re-open it, since we're too lame
index cc8659c..7cf038b 100644 (file)
@@ -3,14 +3,17 @@
 # Application configuration
 
 [autodiscovery]
-searchpath     /media:/media/*:/usr/pandora/apps       # path to depth-search for PXMLs
+# searchpath is a list of paths (colon separated) in which to look for PXML.xml or .pnd-file applications
+searchpath     /media/*/pandora/apps:/usr/pandora/apps
+# notifypath is a list of paths to monitor; if anything in those paths changes, the searchpath is rescanned
+notifypath     /media:/media/*/pandora/apps:/usr/pandora/apps:./testdata/app?
 
 # PXMLs may be overridden .. ie: overrides are a subset of PXML, where the values are copied over the full PXML
 [overrides]
+# searchpath to look for PXML overrides (which are named by the unique-id)
 searchpath     ~/pxml-overrides
 
 # [pnd] defines where to locate the pnd support scripts, so the user may override pnd_run.sh without clobbering built in
 [pnd]
 searchpath     /media/*/pandora/scripts:/usr/pandora/scripts
 runscript      pnd_run.sh
-hupscript      pnd_hup.sh
index 84199bc..a799351 100644 (file)
@@ -5,3 +5,6 @@
 [dotfiles]
 #dotdesktoppath        /usr/share/applications/        # path for pndnotifyd to spit .desktop files into
 dotdesktoppath ~/.applications/        # path for pndnotifyd to spit .desktop files into
+
+[launcher]
+hupscript      pnd_hup.sh
index af179e0..da192f2 100644 (file)
@@ -6,16 +6,18 @@
 extern "C" {
 #endif
 
-#define PND_APPS_SEARCHPATH "/mnt/sd1/pandora/apps:/mnt/sd2/pandora/apps:./testdata/apps"
+// default application searchpath (and key to look it up in config)
+#define PND_APPS_SEARCHPATH "/media/*/pandora/apps:/usr/pandora/apps"
 #define PND_APPS_KEY "autodiscovery.searchpath"
 
+// default notify searchpath (and key to look it up in config)
+#define PND_APPS_NOTIFYPATH "/media:/media/*/pandora/apps:/usr/pandora/apps"
+#define PND_APPS_NOTIFY_KEY "autodiscovery.notifypath"
+
 #define PND_PNDRUN_SEARCHPATH_KEY "pnd.searchpath"
 #define PND_PNDRUN_KEY "pnd.runscript"
 #define PND_PNDRUN_FILENAME "pnd_run.sh"
-#define PND_PNDRUN_DEFAULT "./testdata/scripts/pnd_run.sh"
-
-#define PND_PNDHUP_KEY "pnd.hupscript"
-#define PND_PNDHUP_FILENAME "pnd_hup.sh"
+#define PND_PNDRUN_DEFAULT "/usr/pandora/scripts/pnd_run.sh"
 
 #define PND_PXML_OVERRIDE_SEARCHPATH "~/pxml-overrides"
 #define PND_PXML_OVERRIDE_KEY "overrides.searchpath"
@@ -24,7 +26,7 @@ extern "C" {
 
 // .desktop support
 #define PND_DOTDESKTOP_KEY "dotfiles.dotdesktoppath"
-#define PND_DOTDESKTOP_DEFAULT "/usr/share/applications"
+#define PND_DOTDESKTOP_DEFAULT "~/.applications"
 
 // apps
 #define PND_DEFAULT_WORKDIR "./"
diff --git a/include/pnd_desktop.h b/include/pnd_desktop.h
new file mode 100644 (file)
index 0000000..7e0b2ee
--- /dev/null
@@ -0,0 +1,28 @@
+
+#ifndef h_pnd_desktop_h
+#define h_pnd_desktop_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define PND_PNDHUP_KEY "launcher.hupscript"
+#define PND_PNDHUP_FILENAME "pnd_hup.sh"
+
+// emit_dotdesktop() will determine a filename and create a FILENAME.desktop file in the targetpath
+// TODO: Copy the icon into this directory as well, if its source is a .pnd or info is in the dico struct
+#define PND_DOTDESKTOP_HEADER "[Desktop Entry]"
+#define PND_DOTDESKTOP_SOURCE "_Source=libpnd"
+unsigned char pnd_emit_dotdesktop ( char *targetpath, char *pndrun, pnd_disco_t *p );
+
+// emit_icon() will attempt to copy the icon from a PXML directory, or from a pnd file if appended,
+// to the given directory; returns 1 on sucess, otherwise is a fail.
+unsigned char pnd_emit_icon ( char *targetpath, pnd_disco_t *p );
+
+
+#ifdef __cplusplus
+} /* "C" */
+#endif
+
+#endif
index 383a66a..b1f021a 100644 (file)
@@ -13,6 +13,15 @@ extern "C" {
 // places to look:
 // http://pandorawiki.org/Kernel_interface
 
+/* for reference, here are some devices of use; most of these should already have
+ * functions below, to avoid you having to code your own.
+ */
+#define PND_DEVICE_PROC_CLOCK "/proc/pandora/cpu_mhz_max"
+#define PND_DEVICE_SYS_BACKLIGHT_BRIGHTNESS "/sys/class/backlight/gpio-backlight/brightness"
+#define PND_DEVICE_FRAMEBUFFER "/dev/fb0"
+#define PND_DEVICE_NUB1 "/dev/input/js1"
+#define PND_DEVICE_NUB1 "/dev/input/js2"
+
 /* utility
  */
 unsigned char pnd_device_open_write_close ( char *name, char *v );
@@ -22,14 +31,12 @@ unsigned char pnd_device_open_read_close ( char *name, char *r_buffer, unsigned
  * WARN: No boundaries are checked, so try to avoid setting clock to 2GHz :)
  * NOTE: get-clock() is not implemented yet.
  */
-#define PND_DEVICE_PROC_CLOCK "/proc/pandora/cpu_mhz_max"
 unsigned char pnd_device_set_clock ( unsigned int c ); // returns >0 on success
 unsigned int pnd_device_get_clock ( void );
 
 // LCD to set on/off
 
 // Backlight control
-#define PND_DEVICE_SYS_BACKLIGHT_BRIGHTNESS "/sys/class/backlight/gpio-backlight/brightness"
 unsigned char pnd_device_set_backlight ( unsigned int v ); // value to set; 0 is off
 unsigned int pnd_device_get_backlight ( void );
 
diff --git a/lib/pnd_desktop.c b/lib/pnd_desktop.c
new file mode 100644 (file)
index 0000000..0868629
--- /dev/null
@@ -0,0 +1,194 @@
+
+#include <stdio.h> /* for FILE etc */
+#include <string.h>
+#include <unistd.h> /* for unlink */
+
+#include "pnd_apps.h"
+#include "pnd_container.h"
+#include "pnd_pxml.h"
+#include "pnd_discovery.h"
+#include "pnd_pndfiles.h"
+
+unsigned char pnd_emit_dotdesktop ( char *targetpath, char *pndrun, pnd_disco_t *p ) {
+  char filename [ FILENAME_MAX ];
+  char buffer [ 1024 ];
+  FILE *f;
+
+  // specification
+  // http://standards.freedesktop.org/desktop-entry-spec
+
+  // validation
+
+  if ( ! p -> unique_id ) {
+    return ( 0 );
+  }
+
+  if ( ! p -> exec ) {
+    return ( 0 );
+  }
+
+  if ( ! targetpath ) {
+    return ( 0 );
+  }
+
+  if ( ! pndrun ) {
+    return ( 0 );
+  }
+
+  // set up
+
+  sprintf ( filename, "%s/%s.desktop", targetpath, p -> unique_id );
+
+  // emit
+
+  //printf ( "EMIT DOTDESKTOP '%s'\n", filename );
+
+  f = fopen ( filename, "w" );
+
+  if ( ! f ) {
+    return ( 0 );
+  }
+
+  fprintf ( f, "%s\n", PND_DOTDESKTOP_HEADER );
+
+  if ( p -> title_en ) {
+    snprintf ( buffer, 1020, "Name=%s\n", p -> title_en );
+    fprintf ( f, "%s", buffer );
+  }
+
+  fprintf ( f, "Type=Application\n" );
+  fprintf ( f, "Version=1.0\n" );
+
+  if ( p -> icon ) {
+    snprintf ( buffer, 1020, "Icon=%s\n", p -> icon );
+    fprintf ( f, "%s", buffer );
+  }
+
+#if 0
+  if ( p -> description_en ) {
+    snprintf ( buffer, 1020, "Comment=%s\n", p -> description_en );
+    fprintf ( f, "%s", buffer );
+  }
+#endif
+
+#if 0 // we let pnd_run.sh handle this
+  if ( p -> startdir ) {
+    snprintf ( buffer, 1020, "Path=%s\n", p -> startdir );
+    fprintf ( f, "%s", buffer );
+  } else {
+    fprintf ( f, "Path=%s\n", PND_DEFAULT_WORKDIR );
+  }
+#endif
+
+  if ( p -> exec ) {
+
+    // basics
+    if ( p -> object_type == pnd_object_type_directory ) {
+      snprintf ( buffer, 1020, "Exec=%s -p %s -e %s -n", pndrun, p -> object_path, p -> exec );
+    } else if ( p -> object_type == pnd_object_type_pnd ) {
+      snprintf ( buffer, 1020, "Exec=%s -p %s/%s -e %s -n", pndrun, p -> object_path, p -> object_filename, p -> exec );
+    }
+
+    // start dir
+    if ( p -> startdir ) {
+      strncat ( buffer, " -s ", 1020 );
+      strncat ( buffer, p -> startdir, 1020 );
+    }
+
+    // newline
+    strncat ( buffer, "\n", 1020 );
+
+    // emit
+    fprintf ( f, "%s", buffer );
+  }
+
+#if 1 // categories
+  fprintf ( f, "%s\n", "Categories=Application;Network;" );
+#endif
+
+  fprintf ( f, "%s\n", PND_DOTDESKTOP_SOURCE ); // should we need to know 'who' created the file during trimming
+
+  fclose ( f );
+
+  return ( 1 );
+}
+
+unsigned char pnd_emit_icon ( char *targetpath, pnd_disco_t *p ) {
+  char buffer [ FILENAME_MAX ]; // target filename
+  char from [ FILENAME_MAX ];   // source filename
+  char bits [ 8 * 1024 ];
+  unsigned int bitlen;
+  FILE *pnd, *target;
+
+  // prelim .. if a pnd file, and no offset found, discovery code didn't locate icon.. so bail.
+  if ( ( p -> object_type == pnd_object_type_pnd ) &&
+       ( ! p -> pnd_icon_pos ) )
+  {
+    return ( 0 ); // discover code didn't find it, so FAIL
+  }
+
+  // determine filename for target
+  sprintf ( buffer, "%s/%s.png", targetpath, p -> unique_id ); // target
+
+  /* first.. open the source file, by type of application:
+   * are we looking through a pnd file or a dir?
+   */
+  if ( p -> object_type == pnd_object_type_directory ) {
+    sprintf ( from, "%s/%s", p -> object_path, p -> icon );
+  } else if ( p -> object_type == pnd_object_type_pnd ) {
+    sprintf ( from, "%s/%s", p -> object_path, p -> object_filename );
+  }
+
+  pnd = fopen ( from, "r" );
+
+  if ( ! pnd ) {
+    return ( 0 );
+  }
+
+  unsigned int len;
+
+  target = fopen ( buffer, "wb" );
+
+  if ( ! target ) {
+    fclose ( pnd );
+    return ( 0 );
+  }
+
+  fseek ( pnd, 0, SEEK_END );
+  len = ftell ( pnd );
+  //fseek ( pnd, 0, SEEK_SET );
+
+  fseek ( pnd, p -> pnd_icon_pos, SEEK_SET );
+
+  len -= p -> pnd_icon_pos;
+
+  while ( len ) {
+
+    if ( len > (8*1024) ) {
+      bitlen = (8*1024);
+    } else {
+      bitlen = len;
+    }
+
+    if ( fread ( bits, bitlen, 1, pnd ) != 1 ) {
+      fclose ( pnd );
+      fclose ( target );
+      unlink ( buffer );
+      return ( 0 );
+    }
+
+    if ( fwrite ( bits, bitlen, 1, target ) != 1 ) {
+      fclose ( pnd );
+      fclose ( target );
+      unlink ( buffer );
+      return ( 0 );
+    }
+
+    len -= bitlen;
+  } // while
+
+  fclose ( pnd );
+  fclose ( target );
+
+  return ( 1 );
+}
index 0013b98..b6d5860 100644 (file)
@@ -237,187 +237,3 @@ pnd_box_handle pnd_disco_search ( char *searchpath, char *overridespath ) {
 
   return ( disco_box );
 }
-
-unsigned char pnd_emit_dotdesktop ( char *targetpath, char *pndrun, pnd_disco_t *p ) {
-  char filename [ FILENAME_MAX ];
-  char buffer [ 1024 ];
-  FILE *f;
-
-  // specification
-  // http://standards.freedesktop.org/desktop-entry-spec
-
-  // validation
-
-  if ( ! p -> unique_id ) {
-    return ( 0 );
-  }
-
-  if ( ! p -> exec ) {
-    return ( 0 );
-  }
-
-  if ( ! targetpath ) {
-    return ( 0 );
-  }
-
-  if ( ! pndrun ) {
-    return ( 0 );
-  }
-
-  // set up
-
-  sprintf ( filename, "%s/%s.desktop", targetpath, p -> unique_id );
-
-  // emit
-
-  //printf ( "EMIT DOTDESKTOP '%s'\n", filename );
-
-  f = fopen ( filename, "w" );
-
-  if ( ! f ) {
-    return ( 0 );
-  }
-
-  fprintf ( f, "%s\n", PND_DOTDESKTOP_HEADER );
-
-  if ( p -> title_en ) {
-    snprintf ( buffer, 1020, "Name=%s\n", p -> title_en );
-    fprintf ( f, "%s", buffer );
-  }
-
-  fprintf ( f, "Type=Application\n" );
-  fprintf ( f, "Version=1.0\n" );
-
-  if ( p -> icon ) {
-    snprintf ( buffer, 1020, "Icon=%s\n", p -> icon );
-    fprintf ( f, "%s", buffer );
-  }
-
-#if 0
-  if ( p -> description_en ) {
-    snprintf ( buffer, 1020, "Comment=%s\n", p -> description_en );
-    fprintf ( f, "%s", buffer );
-  }
-#endif
-
-#if 0 // we let pnd_run.sh handle this
-  if ( p -> startdir ) {
-    snprintf ( buffer, 1020, "Path=%s\n", p -> startdir );
-    fprintf ( f, "%s", buffer );
-  } else {
-    fprintf ( f, "Path=%s\n", PND_DEFAULT_WORKDIR );
-  }
-#endif
-
-  if ( p -> exec ) {
-
-    // basics
-    if ( p -> object_type == pnd_object_type_directory ) {
-      snprintf ( buffer, 1020, "Exec=%s -p %s -e %s -n", pndrun, p -> object_path, p -> exec );
-    } else if ( p -> object_type == pnd_object_type_pnd ) {
-      snprintf ( buffer, 1020, "Exec=%s -p %s/%s -e %s -n", pndrun, p -> object_path, p -> object_filename, p -> exec );
-    }
-
-    // start dir
-    if ( p -> startdir ) {
-      strncat ( buffer, " -s ", 1020 );
-      strncat ( buffer, p -> startdir, 1020 );
-    }
-
-    // newline
-    strncat ( buffer, "\n", 1020 );
-
-    // emit
-    fprintf ( f, "%s", buffer );
-  }
-
-#if 1 // categories
-  fprintf ( f, "%s\n", "Categories=Application;Network;" );
-#endif
-
-  fprintf ( f, "%s\n", PND_DOTDESKTOP_SOURCE ); // should we need to know 'who' created the file during trimming
-
-  fclose ( f );
-
-  return ( 1 );
-}
-
-unsigned char pnd_emit_icon ( char *targetpath, pnd_disco_t *p ) {
-  char buffer [ FILENAME_MAX ]; // target filename
-  char from [ FILENAME_MAX ];   // source filename
-  char bits [ 8 * 1024 ];
-  unsigned int bitlen;
-  FILE *pnd, *target;
-
-  // prelim .. if a pnd file, and no offset found, discovery code didn't locate icon.. so bail.
-  if ( ( p -> object_type == pnd_object_type_pnd ) &&
-       ( ! p -> pnd_icon_pos ) )
-  {
-    return ( 0 ); // discover code didn't find it, so FAIL
-  }
-
-  // determine filename for target
-  sprintf ( buffer, "%s/%s.png", targetpath, p -> unique_id ); // target
-
-  /* first.. open the source file, by type of application:
-   * are we looking through a pnd file or a dir?
-   */
-  if ( p -> object_type == pnd_object_type_directory ) {
-    sprintf ( from, "%s/%s", p -> object_path, p -> icon );
-  } else if ( p -> object_type == pnd_object_type_pnd ) {
-    sprintf ( from, "%s/%s", p -> object_path, p -> object_filename );
-  }
-
-  pnd = fopen ( from, "r" );
-
-  if ( ! pnd ) {
-    return ( 0 );
-  }
-
-  unsigned int len;
-
-  target = fopen ( buffer, "wb" );
-
-  if ( ! target ) {
-    fclose ( pnd );
-    return ( 0 );
-  }
-
-  fseek ( pnd, 0, SEEK_END );
-  len = ftell ( pnd );
-  //fseek ( pnd, 0, SEEK_SET );
-
-  fseek ( pnd, p -> pnd_icon_pos, SEEK_SET );
-
-  len -= p -> pnd_icon_pos;
-
-  while ( len ) {
-
-    if ( len > (8*1024) ) {
-      bitlen = (8*1024);
-    } else {
-      bitlen = len;
-    }
-
-    if ( fread ( bits, bitlen, 1, pnd ) != 1 ) {
-      fclose ( pnd );
-      fclose ( target );
-      unlink ( buffer );
-      return ( 0 );
-    }
-
-    if ( fwrite ( bits, bitlen, 1, target ) != 1 ) {
-      fclose ( pnd );
-      fclose ( target );
-      unlink ( buffer );
-      return ( 0 );
-    }
-
-    len -= bitlen;
-  } // while
-
-  fclose ( pnd );
-  fclose ( target );
-
-  return ( 1 );
-}
index 0f8ff92..46884ee 100644 (file)
@@ -4,6 +4,7 @@
 
 [autodiscovery]
 searchpath     /mnt/sd?/pandora/apps:./testdata/app?   # path to depth-search for PXMLs
+notifypath     /media:/media/*/pandora/apps:./testdata/app?
 
 # PXMLs may be overridden .. ie: overrides are a subset of PXML, where the values are copied over the full PXML
 [overrides]
@@ -13,4 +14,3 @@ searchpath    ~/pxml-overrides:./testdata/apps-override
 [pnd]
 searchpath     /mnt/sd?/pandora/scripts:./testdata/scripts
 runscript      pnd_run.sh
-hupscript      pnd_hup.sh
index c84db94..befc4e1 100644 (file)
@@ -5,3 +5,6 @@
 [dotfiles]
 #dotdesktoppath        ./testdata/dotdesktop   # path for pndnotifyd to spit .desktop files into
 dotdesktoppath ~/.applications         # path for pndnotifyd to spit .desktop files into
+
+[launcher]
+hupscript      pnd_hup.sh
diff --git a/testdata/scripts/pnd_hup.sh b/testdata/scripts/pnd_hup.sh
new file mode 100755 (executable)
index 0000000..c53cf12
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+echo "pnd_hup script"