I finally bit the bullet and dug into the cfagent source code -- and I
not only survived, but came back with a neat little globbing method for
import stanzas, along with a test case.

Caveats:
* I have no idea how portable this whole thing is.  glob() is supposed to be
POSIX.2, and I've only used the basic features, but who knows what craziness
is out there in the wide world.

* I haven't totally thought-through the security implications of this change
yet.  IMAO, if you let untrusted users drop files into your directories,
you deserve what you get, but I'm happy enough to accept that not everyone
is as brutal as I am.

glob_import.patch is the patch itself, against parse.c.  glob_import.test is
a shell script which, if run in the root directory of a built source tree,
will test the globbing functionality.  I like tests.  <grin>

Patch is GPL v2 licenced.  If there are any problems with the patch, please
let me know, otherwise I look forward to seeing it in an upcoming release of
cfengine.

- Matt
--- cfengine-2.1.15/src/parse.c 2005-05-29 20:34:15.000000000 +1000
+++ cfengine-2.1.15.mpalmer/src/parse.c 2005-12-28 19:33:06.000000000 +1100
@@ -37,6 +37,7 @@
 
 #define INET
 
+#include <glob.h>
 #include <stdio.h>
 #include "cf.defs.h"
 #include "cf.extern.h"
@@ -1012,7 +1013,11 @@
 
 void ParseFile(char *filename,char *env)
 
-{ FILE *save_yyin = yyin;
+{
+FILE *save_yyin = yyin;
+glob_t globbuf;
+int i;
+char *curfile;
  
 signal(SIGALRM,(void *)TimeOut);
 alarm(RPCTIMEOUT);
@@ -1022,8 +1027,14 @@
    FatalError("Security exception");
    }
  
-if ((yyin = fopen(filename,"r")) == NULL)      /* Open root file */
-   {
+/* mpalmer: Extension to use glob() to allow a globbed list of files
+ * to be processed.  Usual shell globbing rules apply -- *, ?, etc.
+ */
+if (glob(filename, 0, NULL, &globbuf))
+{
+   /* Something went wrong with the glob().  Frankly, I don't really care
+    * what.
+    */
    printf("%s: Can't open file %s\n",VPREFIX,filename);
 
    if (env == NULL)
@@ -1036,31 +1047,52 @@
       }
    
    exit (1);
+}
+
+for (i = 0; i < globbuf.gl_pathc; i++)
+{
+   curfile = globbuf.gl_pathv[i];
+   if ((yyin = fopen(curfile, "r")) == NULL)
+   {
+      printf("%s: Can't open file %s\n",VPREFIX, curfile);
+
+      if (env == NULL)
+         {
+         printf("%s: (%s is set to <nothing>)\n",VPREFIX,CF_INPUTSVAR);
+         }
+      else
+         {
+         printf("%s: (%s is set to %s)\n",VPREFIX,CF_INPUTSVAR,env);
+         }
+   
+      exit (1);
    }
- 
-strcpy(VCURRENTFILE,filename);
 
-Debug("\n##########################################################################\n");
 
-Debug("# BEGIN PARSING %s\n",VCURRENTFILE);
-Debug("##########################################################################\n\n");
 
+   strcpy(VCURRENTFILE,curfile);
+
+   
Debug("\n##########################################################################\n");
 
+   Debug("# BEGIN PARSING %s\n",VCURRENTFILE);
+   
Debug("##########################################################################\n\n");
 
  
-LINENUMBER=1;
+   LINENUMBER=1;
  
-while (!feof(yyin))
-   { 
-   yyparse();
+   while (!feof(yyin))
+      { 
+      yyparse();
    
-   if (ferror(yyin))  /* abortable */
-      {
-      printf("%s: Error reading %s\n",VPREFIX,VCURRENTFILE);
-      perror("cfengine");
-      exit(1);
+      if (ferror(yyin))  /* abortable */
+         {
+         printf("%s: Error reading %s\n",VPREFIX,VCURRENTFILE);
+         perror("cfengine");
+         exit(1);
+         }
       }
-   }
  
-fclose (yyin);
-yyin = save_yyin;
+   fclose (yyin);
+   yyin = save_yyin;
+}
  
+globfree(&globbuf);
 alarm(0);
 signal(SIGALRM,SIG_DFL);
 InstallPending(ACTION);
#!/bin/sh

expected="cfengine::/bin/echo 1: 1
cfengine::/bin/echo 2: 2"

WORKDIR=$(mktemp -d)

cat <<EOF >$WORKDIR/cfagent.conf
control:
        actionsequence = ( shellcommands )

import:
        glob/cf.*
EOF

cat <<EOF >$WORKDIR/cf.notrun
shellcommands:
        "/bin/echo notrun"
EOF

mkdir $WORKDIR/glob
cat <<EOF >$WORKDIR/glob/notrun
shellcommands:
        "/bin/echo glob/notrun"
EOF

cat <<EOF >$WORKDIR/glob/cf.1
shellcommands:
        "/bin/echo 1"
EOF

cat <<EOF >$WORKDIR/glob/cf.2
shellcommands:
        "/bin/echo 2"
EOF

actual=$(CFINPUTS=$WORKDIR src/cfagent -K 2>&1)

if [ "$actual" != "$expected" ]; then
        echo "TEST FAILURE!  expected:"
        echo $expected
        echo "actual:"
        echo $actual
        echo "============================================================="
else
        echo "Test passed."
fi

rm -rf $WORKDIR
_______________________________________________
Help-cfengine mailing list
Help-cfengine@gnu.org
http://lists.gnu.org/mailman/listinfo/help-cfengine

Reply via email to