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