dnxPlugin.c

Go to the documentation of this file.
00001 /*--------------------------------------------------------------------------
00002 
00003    Copyright (c) 2006-2007, Intellectual Reserve, Inc. All rights reserved.
00004 
00005    This program is free software; you can redistribute it and/or modify
00006    it under the terms of the GNU General Public License version 2 as
00007    published by the Free Software Foundation.
00008 
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012    GNU General Public License for more details.
00013 
00014    You should have received a copy of the GNU General Public License
00015    along with this program; if not, write to the Free Software
00016    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018   --------------------------------------------------------------------------*/
00019 
00029 #include "dnxPlugin.h"
00030 
00031 #include "dnxError.h"
00032 #include "dnxDebug.h"
00033 #include "pfopen.h"
00034 
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <ctype.h>
00038 #include <string.h>
00039 #include <time.h>
00040 #include <errno.h>
00041 #include <unistd.h>
00042 #include <sys/types.h>
00043 #include <signal.h>
00044 
00045 #define USE_POLL     // use poll instead of select for descriptor multiplexing
00046 
00047 #ifdef USE_POLL
00048 # include <poll.h>
00049 # define MPLEXER "poll"
00050 #else
00051 # include <sys/select.h>
00052 # define MPLEXER "select"
00053 #endif
00054 
00055 #define elemcount(x) (sizeof(x)/sizeof(*(x)))
00056 
00057 #define MAX_PLUGIN_PREFIX     1024  
00058 #define MAX_PLUGIN_PATH       2048  
00059 #define DNX_MAX_ARGV          256   
00060 #define MAX_INPUT_BUFFER      1024  
00061 #define DNX_MAX_PLUGIN_NAME   255   
00062 
00063 
00064 typedef struct iDnxModule
00065 {
00066    char * path;               
00067    void * handle;             
00068    int (* init)(void);        
00069    int (* deinit)(void);      
00070    struct iDnxModule * next;  
00071    struct iDnxModule * prev;  
00072 } iDnxModule;
00073 
00075 typedef struct iDnxPlugin
00076 {
00077    char * name;               
00078    int (* func)(int argc, char ** argv);
00080    iDnxModule * parent;       
00081    struct iDnxPlugin * next;  
00082    struct iDnxPlugin * prev;  
00083 } iDnxPlugin;
00084 
00086 typedef struct { int unused; } DnxPlugin;
00087 
00089 typedef struct { int unused; } DnxModule;
00090 
00091 static iDnxModule * gModules; 
00092 static iDnxPlugin * gPlugins; 
00093 static char * gPluginPath;    
00094 static int gInitialized = 0;  
00095 
00096 // HACK: The NRPE module is hardwired for now...
00097 #ifdef USE_NRPE_MODULE
00098 extern int mod_nrpe(int argc, char ** argv, char * resData);
00099 #endif
00100 
00101 /*--------------------------------------------------------------------------
00102                               IMPLEMENTATION
00103   --------------------------------------------------------------------------*/
00104 
00117 static char * dnxFgets(char * data, int size, FILE * fp, int timeout)
00118 {
00119    struct timeval tv;
00120    fd_set fd_read;
00121    int count, fdmax;
00122 
00123    assert(data && size > 0 && fp && timeout > 0);
00124 
00125    data[0] = 0;
00126 
00127    // retrieve file descriptor
00128    fdmax = fileno(fp);
00129 
00130    // setup select
00131    FD_ZERO(&fd_read);
00132    FD_SET(fdmax, &fd_read);
00133 
00134    // setup read timeout on pipe
00135    tv.tv_sec  = timeout;
00136    tv.tv_usec = 0L;
00137 
00138    // wait for some data to show up on the pipe
00139    if ((count = select(fdmax + 1, &fd_read, 0, 0, &tv)) < 0)
00140       return 0;      // select error
00141    else if (count == 0)
00142       return 0;      // plugin timeout
00143 
00144    return fgets(data, size, fp);
00145 }
00146 
00147 //----------------------------------------------------------------------------
00148 
00159 static void strip(char * buf)
00160 {
00161    register char * cp, * ep;
00162    assert(buf);
00163    ep = buf + strlen(buf);
00164    while (ep > buf && !isspace(ep[-1])) ep--;
00165    *ep = 0;                      // terminate at last space (or existing null)
00166    cp = buf;
00167    while (isspace(*cp)) cp++;
00168    memmove(buf, cp, ep - cp);    // move zero or more characters
00169 }
00170 
00171 //----------------------------------------------------------------------------
00172 
00183 static int dnxPluginRegister(char * szPlugin, char * szErrMsg)
00184 {
00185    assert(gInitialized);
00186    return DNX_OK;
00187 }
00188 
00189 //----------------------------------------------------------------------------
00190 
00199 static int dnxPluginLoad(DnxModule * module)
00200 {
00201    iDnxModule * imod = (iDnxModule *)module;
00202    assert(gInitialized);
00203    assert(module);
00204    return DNX_OK;
00205 }
00206 
00207 //----------------------------------------------------------------------------
00208 
00215 static void dnxPluginUnload(DnxModule * module)
00216 {
00217    iDnxPlugin * imod = (iDnxPlugin *)module;
00218    assert(gInitialized);
00219    assert(module);
00220 }
00221 
00222 //----------------------------------------------------------------------------
00223 
00232 static int dnxPluginBaseName(char * command, char * baseName, int maxData)
00233 {
00234    char * cp, * ep, * base;
00235    int len;
00236 
00237    // skip leading whitespace
00238    for (cp = command; *cp && *cp <= ' '; cp++)
00239       ;
00240 
00241    if (!*cp) return DNX_ERR_INVALID; // no basename - string is empty
00242 
00243    // determine end of token
00244    for (ep=cp; *ep && *ep > ' '; ep++);
00245    if (ep == cp)
00246       return DNX_ERR_INVALID; // no basename - string is empty
00247 
00248    // determine start of base name within this token
00249    for (base = (ep-1); base > cp && *base != '/'; base--);
00250    if (base == (ep-1))
00251       return DNX_ERR_INVALID; // no basename - token ends with '/'
00252    if (*base == '/')
00253       cp = base+1;
00254 
00255    // validate base name length
00256    if ((len = (ep - cp)) > maxData)
00257       return DNX_ERR_MEMORY;  // insufficient room for base name
00258 
00259    memcpy(baseName, cp, len);
00260    baseName[len] = 0;
00261 
00262    return DNX_OK;
00263 }
00264 
00265 //----------------------------------------------------------------------------
00266 
00275 static int dnxPluginLocate(char * command, DnxPlugin ** plugin)
00276 {
00277    char baseName[DNX_MAX_PLUGIN_NAME + 1];
00278    int ret;
00279 
00280    assert(gInitialized);
00281    assert(command && plugin);
00282 
00283    // isolate the plugin base name
00284    if ((ret = dnxPluginBaseName(command, baseName, DNX_MAX_PLUGIN_NAME)) != DNX_OK)
00285       return ret;
00286 
00289    // HACK: Hardwired to only find the check_nrpe plugin
00290 #ifdef USE_NRPE_MODULE
00291    return (strcmp(baseName, "check_nrpe") ? DNX_ERR_NOTFOUND : DNX_OK);
00292 #else
00293    return DNX_ERR_NOTFOUND;
00294 #endif
00295 }
00296 
00297 //----------------------------------------------------------------------------
00298 
00313 static int dnxPluginVector(char * command, int * argc, char ** argv, int maxargs)
00314 {
00315    char * cp, * ep;
00316    int idx = 0;
00317    int ret = DNX_OK;
00318 
00319    assert(command && argc && argv && maxargs > 0);
00320 
00321    // loop through the command string
00322    ep = command;
00323    while (idx < maxargs)
00324    {
00325       // find beginning of the next token
00326       for (cp=ep; *cp && *cp <= ' '; cp++);
00327       if (!*cp)
00328          break;   // No more tokens
00329 
00330       // search for end of token
00331       for (ep=cp; *ep && *ep > ' '; ep++);
00332       if (ep == cp)
00333          break;   // No more tokens
00334 
00335       // add this token to the arg vector array
00336       if ((argv[idx] = (char *)xmalloc((ep-cp)+1)) == 0)
00337       {
00338          ret = DNX_ERR_MEMORY;
00339          break;
00340       }
00341       memcpy(argv[idx], cp, (ep-cp));
00342       argv[idx][ep-cp] = 0;
00343 
00344       idx++;   // Increment arg vector index
00345    }
00346 
00347    // append null arg vector
00348    argv[idx] = 0;
00349 
00350    *argc = idx;   // aet the arg vector total
00351 
00352    return ret;
00353 }
00354 
00355 //----------------------------------------------------------------------------
00356 
00370 static void dnxPluginInternal(DnxPlugin * plugin, char * command, int * resCode,
00371       char * resData, int maxData, int timeout, char * myaddr)
00372 {
00373    char temp_buffer[MAX_INPUT_BUFFER + 1];
00374    char * argv[DNX_MAX_ARGV];
00375    int argc, len, ret;
00376 
00377    assert(gInitialized);
00378 
00381    assert(command && resCode && resData && maxData > 1 && timeout >= 0);
00382 
00383    // clear the result data buffer
00384    *resData = 0;
00385 
00386    // break-up command string into vectors
00387    if ((ret = dnxPluginVector(command, &argc, argv, DNX_MAX_ARGV)) != DNX_OK)
00388    {
00389       *resCode = DNX_PLUGIN_RESULT_UNKNOWN;
00390       resData += sprintf(resData, "(DNX: Vectorize command-line failed!)");
00391       if (myaddr)
00392          sprintf(resData, " (dnx node %s)", myaddr);
00393       return;
00394    }
00395 
00398    // HACK: Only works with static check_nrpe plugin for the moment
00399 #ifdef USE_NRPE_MODULE
00400    *resCode = mod_nrpe(argc, argv, resData);
00401 #else
00402    {
00403       *resCode = DNX_PLUGIN_RESULT_UNKNOWN;
00404       resData += sprintf(resData, "(DNX: Internal NRPE modules unavailable!)");
00405       if (myaddr)
00406          sprintf(resData, " (dnx node %s)", myaddr);
00407    }
00408 #endif
00409 
00410    // check for no output condition
00411    if (!resData[0])
00412    {
00413 
00414       resData += sprintf(resData, "(No output!)");
00415       if (myaddr)
00416          sprintf(resData, " (dnx node %s)", myaddr);
00417    }
00418 
00419    // test for exception conditions:
00420    temp_buffer[0] = 0;
00421 
00422    // test for out-of-range plugin exit code
00423    if (*resCode < DNX_PLUGIN_RESULT_OK || *resCode > DNX_PLUGIN_RESULT_UNKNOWN)
00424    {
00425       len = strlen(temp_buffer);
00426       sprintf(temp_buffer+len, "[EC %d]", ((*resCode < 256) ? *resCode : (*resCode >> 8)));
00427       *resCode = DNX_PLUGIN_RESULT_UNKNOWN;
00428    }
00429 
00430    // prepend any error condition messages to the plugin output
00431    if (temp_buffer[0])
00432    {
00433       strncat(temp_buffer, resData, MAX_INPUT_BUFFER);
00434       temp_buffer[MAX_INPUT_BUFFER] = 0;
00435       strncpy(resData, temp_buffer, maxData);
00436       resData[maxData-1] = 0;
00437    }
00438 }
00439 
00440 //----------------------------------------------------------------------------
00441 
00455 static void dnxPluginExternal(char * command, int * resCode, char * resData, 
00456       int maxData, int timeout, char * myaddr)
00457 {
00458    char temp_buffer[MAX_INPUT_BUFFER + 1];
00459    char temp_cmd[MAX_PLUGIN_PATH + 1];
00460    char * plugin, * cp, * bp, * ep;
00461    int p_out, p_err, count, len, isErrOutput = 0;
00462    time_t start_time;
00463    PFILE * pf;
00464    cp = 0;
00465 
00466 #ifdef USE_POLL
00467    struct pollfd fds[2];
00468 #else
00469    int fdmax;
00470    struct timeval tv;
00471    fd_set fd_read;
00472 #endif
00473 
00474    assert(gInitialized);
00475    assert(command && resCode && resData && maxData > 1);
00476 
00477    // initialize plugin output buffer
00478    *resData = 0;
00479 
00480    // find non-whitespace beginning of command string
00481    for (cp = command; *cp && *cp <= ' '; cp++)
00482       ;
00483 
00484    if (!*cp)
00485    {
00486       *resCode = DNX_PLUGIN_RESULT_UNKNOWN;
00487       resData += sprintf(resData, "(DNX: Empty check command-line!)");
00488       if (myaddr)
00489          sprintf(resData, " (dnx node %s)", myaddr);
00490       return;
00491    }
00492 
00493    // see if we are restricting plugin path
00494    if (gPluginPath)
00495    {
00496       // find end of plugin base name
00497       for (bp = ep = cp; *ep && *ep > ' '; ep++)
00498          if (*ep == '/')
00499             bp = ep + 1;
00500 
00501       if (bp == ep)
00502       {
00503          *resCode = DNX_PLUGIN_RESULT_UNKNOWN;
00504          resData += sprintf(resData, "(DNX: Invalid check command-line!");
00505          if (myaddr)
00506             sprintf(resData, " (dnx node %s)", myaddr);
00507          return;
00508       }
00509 
00510       // verify that the restructured plugin path doesn't exceed our maximum
00511       if ((len = strlen(gPluginPath) + strlen(bp)) > MAX_PLUGIN_PATH)
00512       {
00513          *resCode = DNX_PLUGIN_RESULT_UNKNOWN;
00514          resData += sprintf(resData, "(DNX: Check command-line exceeds max size!)");
00515          if (myaddr)
00516             sprintf(resData, " (dnx node %s)", myaddr);
00517          return;
00518       }
00519 
00520       // construct controlled plugin path
00521       strcpy(temp_cmd, gPluginPath);
00522       strcat(temp_cmd, bp);
00523       plugin = temp_cmd;
00524    }
00525    else
00526       plugin = cp;
00527 
00528    // execute the plugin check command
00529    if ((pf = pfopen(plugin, "r")) == 0)
00530    {
00531       *resCode = DNX_PLUGIN_RESULT_UNKNOWN;
00532       resData += sprintf(resData, "(DNX: pfopen failed, %s!)", strerror(errno));
00533       if (myaddr)
00534          sprintf(resData, " (dnx node %s)", myaddr);
00535       return;
00536    }
00537 
00538    // retrieve file descriptors for pipe's stdout/stderr
00539    p_out = fileno(PF_OUT(pf));
00540    p_err = fileno(PF_ERR(pf));
00541 
00542    // used for computing remaining time on pipe reads
00543    time(&start_time);
00544 
00545 #ifdef USE_POLL
00546    fds[0].fd = p_out;
00547    fds[1].fd = p_err;
00548    fds[0].events = fds[1].events = POLLIN;
00549 
00550    if ((count = poll(fds, elemcount(fds), timeout * 1000)) < 0)
00551 #else // !USE_POLL (instead use select)
00552    // compute highest descriptor, plus one
00553    fdmax = ((p_out > p_err) ? p_out : p_err) + 1;
00554 
00555    // setup select on pipe's stdout and stderr
00556    FD_ZERO(&fd_read);
00557    FD_SET(p_out, &fd_read);
00558    FD_SET(p_err, &fd_read);
00559 
00560    // setup read timeout on pipe
00561    tv.tv_sec  = timeout;
00562    tv.tv_usec = 0L;
00563 
00564    // wait for some data to show up on the pipe
00565    // @todo We can't count on only a single select call here.
00566    if ((count = select(fdmax, &fd_read, 0, 0, &tv)) < 0)
00567 #endif   // USE_POLL
00568    {
00569       // poll/select error
00570       *resCode = DNX_PLUGIN_RESULT_UNKNOWN;
00571       resData += sprintf(resData, 
00572             "(DNX: " MPLEXER " failed on pipe, %s!)", strerror(errno));
00573       if (myaddr) sprintf(resData, " (dnx node %s)", myaddr);
00574 
00575       pfkill(pf, SIGTERM);
00576       pfclose(pf);
00577 
00578       return;
00579    }
00580 
00581    if (count == 0)
00582    {
00583       // plugin timeout
00584       *resCode = DNX_PLUGIN_RESULT_CRITICAL;
00585       resData += sprintf(resData, "(DNX: Plugin Timed Out)");
00586       if (myaddr) sprintf(resData, " (dnx node %s)", myaddr);
00587 
00588       // could be hanging for any number of reasons; ensure we really kill it
00589       pfkill(pf, SIGTERM);
00590       sleep(1);
00591       pfkill(pf, SIGKILL);
00592       pfclose(pf);
00593 
00594       return;
00595    }
00596 
00597    // data is available on the pipe, so now we read it.
00598 #ifdef USE_POLL
00599    if (fds[0].revents & POLLIN)     // first, check stdout
00600 #else
00601    if (FD_ISSET(p_out, &fd_read))   // first, check stdout
00602 #endif
00603    {
00604       // consume plugin's stdout
00605       while (!resData[0] && fgets(resData, maxData, PF_OUT(pf)) != 0)
00606          strip(resData);
00607       while(fgets(temp_buffer, MAX_INPUT_BUFFER, PF_OUT(pf)));
00608    }
00609 
00610 #ifdef USE_POLL
00611    if (!resData[0] && (fds[1].revents & POLLIN))   // if nothing on stdout, check stderr
00612 #else
00613    if (!resData[0] && FD_ISSET(p_err, &fd_read))   // if nothing on stdout, check stderr
00614 #endif
00615    {
00616       // consume plugin's stderr
00617       while (!resData[0] && fgets(resData, maxData, PF_ERR(pf)) != 0)
00618          strip(resData);
00619       while(fgets(temp_buffer, MAX_INPUT_BUFFER, PF_ERR(pf)));
00620 
00621       isErrOutput = 1;
00622    }
00623 
00624    // check for no output condition
00625    if (!resData[0])
00626    {
00627       resData += sprintf(resData, "(No output!)");
00628       if (myaddr)
00629          sprintf(resData, " (dnx node %s)", myaddr);
00630       isErrOutput = 0;
00631    }
00632 
00633    // close the pipe and harvest the exit code
00634    *resCode = (pfclose(pf) >> 8);
00635 
00636    // test for exception conditions:
00637    temp_buffer[0] = 0;
00638 
00639    // test for stderr output
00640    if (isErrOutput)
00641    {
00642       // prefix stderr message with [STDERR] disclaimer
00643       strcpy(temp_buffer, "[STDERR]");
00644    }
00645 
00646    // test for out-of-range plugin exit code
00647    if (*resCode < DNX_PLUGIN_RESULT_OK || *resCode > DNX_PLUGIN_RESULT_UNKNOWN)
00648    {
00649       len = strlen(temp_buffer);
00650       sprintf(temp_buffer+len, "[EC %d]", ((*resCode < 256) ? *resCode : (*resCode >> 8)));
00651       *resCode = DNX_PLUGIN_RESULT_UNKNOWN;
00652    }
00653 
00654    // prepend any error condition messages to the plugin output
00655    if (temp_buffer[0])
00656    {
00657       strncat(temp_buffer, resData, MAX_INPUT_BUFFER);
00658       temp_buffer[MAX_INPUT_BUFFER] = 0;
00659       strncpy(resData, temp_buffer, maxData);
00660       resData[maxData - 1] = 0;
00661    }
00662 }
00663 
00664  /*
00665 static void dnxPluginExternal(char * command, int * resCode, char * resData,
00666       int maxData, int timeout, char * myaddr)
00667 {
00668    char temp_buffer[MAX_INPUT_BUFFER + 1];
00669    char temp_cmd[MAX_PLUGIN_PATH + 1];
00670    char * plugin, * cp, * bp, * ep;
00671    struct timeval tv;
00672    PFILE * pf;
00673    fd_set fd_read;
00674    int p_out, p_err;
00675    int count, fdmax;
00676    int len, isErrOutput = 0;
00677    time_t start_time;
00678    cp = 0;
00679 
00680    assert(gInitialized);
00681    assert(command && resCode && resData && maxData > 1);
00682 
00683    // initialize plugin output buffer
00684    *resData = 0;
00685 
00686    // find non-whitespace beginning of command string
00687    for (cp = command; *cp && *cp <= ' '; cp++);
00688 
00689    if (!*cp)
00690    {
00691       cp = resData;
00692       *resCode = DNX_PLUGIN_RESULT_UNKNOWN;
00693       cp += sprintf(cp, "(DNX: Empty check command-line!)");
00694       if (myaddr)
00695          sprintf(cp, " (dnx node %s)", myaddr);
00696       return;
00697    }
00698 
00699    // see if we are restricting plugin path
00700    if (gPluginPath)
00701    {
00702       // find end of plugin base name
00703       for (bp = ep = cp; *ep && *ep > ' '; ep++)
00704          if (*ep == '/')
00705             bp = ep + 1;
00706 
00707       if (bp == ep)
00708       {
00709          cp = resData;
00710          *resCode = DNX_PLUGIN_RESULT_UNKNOWN;
00711          cp += sprintf(cp, "(DNX: Invalid check command-line!");
00712          if (myaddr)
00713             sprintf(cp, " (dnx node %s)", myaddr);
00714          return;
00715       }
00716 
00717       // verify that the restructured plugin path doesn't exceed our maximum
00718       if ((len = strlen(gPluginPath) + strlen(bp)) > MAX_PLUGIN_PATH)
00719       {
00720          cp = resData;
00721          *resCode = DNX_PLUGIN_RESULT_UNKNOWN;
00722          cp += sprintf(cp, "(DNX: Check command-line exceeds max size!)");
00723          if (myaddr)
00724             sprintf(cp, " (dnx node %s)", myaddr);
00725          return;
00726       }
00727 
00728       // construct controlled plugin path
00729       strcpy(temp_cmd, gPluginPath);
00730       strcat(temp_cmd, bp);
00731       plugin = temp_cmd;
00732    }
00733    else
00734       plugin = cp;
00735 
00736    // execute the plugin check command
00737    if ((pf = pfopen(plugin, "r")) == 0)
00738    {
00739       cp = resData;
00740       *resCode = DNX_PLUGIN_RESULT_UNKNOWN;
00741       cp += sprintf(cp, "(DNX: pfopen failed, %s!)", strerror(errno));
00742       if (myaddr)
00743          sprintf(cp, " (dnx node %s)", myaddr);
00744       return;
00745    }
00746 
00747    // retrieve file descriptors for pipe's stdout/stderr
00748    p_out = fileno(PF_OUT(pf));
00749    p_err = fileno(PF_ERR(pf));
00750 
00751    // compute highest descriptor, plus one
00752    fdmax = ((p_out > p_err) ? p_out : p_err) + 1;
00753 
00754    // setup select on pipe's stdout and stderr
00755    FD_ZERO(&fd_read);
00756    FD_SET(p_out, &fd_read);
00757    FD_SET(p_err, &fd_read);
00758 
00759    // setup read timeout on pipe
00760    tv.tv_sec  = timeout;
00761    tv.tv_usec = 0L;
00762 
00763    // used for computing remaining time on pipe reads
00764    time(&start_time);
00765 
00766    // wait for some data to show up on the pipe
00767    // @todo We can't count on only a single select call here.
00768    if ((count = select(fdmax, &fd_read, 0, 0, &tv)) < 0)
00769    {
00770       // select error
00771       cp = resData;
00772       *resCode = DNX_PLUGIN_RESULT_UNKNOWN;
00773       cp += sprintf(cp, "(DNX: select failed on pipe, %s!)", strerror(errno));
00774       if (myaddr)
00775          sprintf(cp, " (dnx node %s)", myaddr);
00776       pfkill(pf, SIGTERM);
00777       pfclose(pf);
00778 
00779       return;
00780    }
00781    else if (count == 0)
00782    {
00783       // plugin timeout
00784       cp = resData;
00785       *resCode = DNX_PLUGIN_RESULT_CRITICAL;
00786       cp += sprintf(cp, "(DNX: Plugin Timed Out)");
00787       if (myaddr)
00788          sprintf(cp, " (dnx node %s)", myaddr);
00789       pfkill(pf, SIGTERM);
00790       pfclose(pf);
00791 
00792       return;
00793    }
00794 
00795    // data is available on the pipe, so now we read it.
00796    if (FD_ISSET(p_out, &fd_read))   // first, check stdout
00797    {
00798       // consume plugin's stdout
00799       while (!resData[0] && fgets(resData, maxData, PF_OUT(pf)) != 0)
00800          strip(resData);
00801       while(fgets(temp_buffer, MAX_INPUT_BUFFER, PF_OUT(pf)));
00802    }
00803 
00804    if (!resData[0] && FD_ISSET(p_err, &fd_read))   // if nothing on stdout, then check stderr
00805    {
00806       // consume plugin's stderr
00807       while (!resData[0] && fgets(resData, maxData, PF_ERR(pf)) != 0)
00808          strip(resData);
00809       while(fgets(temp_buffer, MAX_INPUT_BUFFER, PF_ERR(pf)));
00810 
00811       isErrOutput = 1;
00812    }
00813 
00814    // check for no output condition
00815    if (!resData[0])
00816    {
00817       cp = resData;
00818       cp += sprintf(cp, "(No output!)");
00819       if (myaddr)
00820          sprintf(cp, " (dnx node %s)", myaddr);
00821       isErrOutput = 0;
00822    }
00823 
00824    // close the pipe and harvest the exit code
00825    *resCode = (pfclose(pf) >> 8);
00826 
00827    // test for exception conditions:
00828    temp_buffer[0] = 0;
00829 
00830    // test for stderr output
00831    if (isErrOutput)
00832    {
00833       // prefix stderr message with [STDERR] disclaimer
00834       strcpy(temp_buffer, "[STDERR]");
00835    }
00836 
00837    // test for out-of-range plugin exit code
00838    if (*resCode < DNX_PLUGIN_RESULT_OK || *resCode > DNX_PLUGIN_RESULT_UNKNOWN)
00839    {
00840       len = strlen(temp_buffer);
00841       sprintf(temp_buffer+len, "[EC %d]", ((*resCode < 256) ? *resCode : (*resCode >> 8)));
00842       *resCode = DNX_PLUGIN_RESULT_UNKNOWN;
00843    }
00844 
00845    // prepend any error condition messages to the plugin output
00846    if (temp_buffer[0])
00847    {
00848       strncat(temp_buffer, resData, MAX_INPUT_BUFFER);
00849       temp_buffer[MAX_INPUT_BUFFER] = 0;
00850       strncpy(resData, temp_buffer, maxData);
00851       resData[maxData - 1] = 0;
00852    }
00853 
00854 }
00855 */
00856 
00857 /*--------------------------------------------------------------------------
00858                                  INTERFACE
00859   --------------------------------------------------------------------------*/
00860 
00861 void dnxPluginExecute(char * command, int * resCode, char * resData, int maxData, int timeout, char * myaddr)
00862 {
00863    DnxPlugin * plugin;
00864    int ret;
00865 
00866    assert(gInitialized);
00867    assert(command && resCode && resData && maxData > 1);
00868 
00869    dnxDebug(2, "dnxPluginExecute: Executing %s", command);
00870 
00871    // see if this is an internal or external plugin
00872    if ((ret = dnxPluginLocate(command, &plugin)) == DNX_OK)
00873    {
00874       dnxPluginInternal(plugin, command, resCode, resData,maxData, timeout, myaddr);
00875    }else if (ret == DNX_ERR_NOTFOUND){
00876       dnxPluginExternal(command, resCode, resData,maxData, timeout, myaddr);
00877    }else{
00878        *resCode = DNX_PLUGIN_RESULT_UNKNOWN;
00879       resData += sprintf(resData, "(DNX: Unable to isolate check base name!)");
00880       if (myaddr)
00881          sprintf(resData, " (dnx node %s)", myaddr);
00882    }
00883 }
00884 
00885 //----------------------------------------------------------------------------
00886 
00887 int dnxPluginInit(char * pluginPath)
00888 {
00889    int len, extra = 0;
00890 
00891    assert(!gInitialized);
00892 
00893    // clear private globals
00894    gPluginPath = 0;
00895    gModules = 0;
00896    gPlugins = 0;
00897 
00898    if (pluginPath)
00899    {
00900       if ((len = strlen(pluginPath)) < 1 || len > MAX_PLUGIN_PREFIX)
00901       {
00902          dnxLog("Invalid plugin path.");
00903          return DNX_ERR_INVALID;
00904       }
00905 
00906       // ensure that the plugin path prefix is absolute
00907       if (*pluginPath != '/')
00908       {
00909          dnxLog("Plugin path is not absolute.");
00910          return DNX_ERR_INVALID;
00911       }
00912 
00913       // ensure that plugin path has trailing '/'
00914       extra = (pluginPath[len-1] == '/') ? 0 : 1;
00915       if ((gPluginPath = (char *)xmalloc(len + 1 + extra)) == 0)
00916          return DNX_ERR_MEMORY;
00917       strcpy(gPluginPath, pluginPath);
00918       if (extra)
00919          strcat(gPluginPath, "/");
00920    }
00921 
00922    gInitialized = 1;
00923 
00924    return DNX_OK;
00925 }
00926 
00927 //----------------------------------------------------------------------------
00928 
00929 void dnxPluginRelease(void)
00930 {
00931    assert(gInitialized);
00932 
00933    if (gPluginPath)
00934    {
00935       xfree(gPluginPath);
00936       gPluginPath = 0;
00937    }
00938 
00941    gInitialized = 0;
00942 }
00943 
00944 /*--------------------------------------------------------------------------*/
00945 

Generated on Tue Apr 13 15:48:07 2010 for DNX by  doxygen 1.5.6