pass_persist.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:22k
源码类别:

SNMP编程

开发平台:

Unix_Linux

  1. #include <net-snmp/net-snmp-config.h>
  2. #if HAVE_IO_H
  3. #include <io.h>
  4. #endif
  5. #if HAVE_STDLIB_H
  6. #include <stdlib.h>
  7. #endif
  8. #if HAVE_STRING_H
  9. #include <string.h>
  10. #else
  11. #include <strings.h>
  12. #endif
  13. #if HAVE_UNISTD_H
  14. #include <unistd.h>
  15. #endif
  16. #include <ctype.h>
  17. #include <sys/types.h>
  18. #if HAVE_NETINET_IN_H
  19. #include <netinet/in.h>
  20. #endif
  21. #if HAVE_SYS_WAIT_H
  22. # include <sys/wait.h>
  23. #endif
  24. #if HAVE_WINSOCK_H
  25. #include <winsock.h>
  26. #endif
  27. #if HAVE_DMALLOC_H
  28. #include <dmalloc.h>
  29. #endif
  30. #include <signal.h>
  31. #include <errno.h>
  32. #include <net-snmp/net-snmp-includes.h>
  33. #include <net-snmp/agent/net-snmp-agent-includes.h>
  34. #include "struct.h"
  35. #include "pass_persist.h"
  36. #include "extensible.h"
  37. #include "util_funcs.h"
  38. struct extensible *persistpassthrus = NULL;
  39. int             numpersistpassthrus = 0;
  40. struct persist_pipe_type {
  41.     FILE           *fIn, *fOut;
  42.     int             fdIn, fdOut;
  43.     int             pid;
  44. }              *persist_pipes = (struct persist_pipe_type *) NULL;
  45. static int      init_persist_pipes(void);
  46. static void     close_persist_pipe(int iindex);
  47. static int      open_persist_pipe(int iindex, char *command);
  48. static void     destruct_persist_pipes(void);
  49. static int      write_persist_pipe(int iindex, const char *data);
  50. /*
  51.  * These are defined in pass.c 
  52.  */
  53. extern int      asc2bin(char *p);
  54. extern int      bin2asc(char *p, size_t n);
  55. extern int      snmp_oid_min_compare(const oid *, size_t, const oid *,
  56.                                      size_t);
  57. /*
  58.  * the relocatable extensible commands variables 
  59.  */
  60. struct variable2 extensible_persist_passthru_variables[] = {
  61.     /*
  62.      * bogus entry.  Only some of it is actually used. 
  63.      */
  64.     {MIBINDEX, ASN_INTEGER, RWRITE, var_extensible_pass_persist, 0,
  65.      {MIBINDEX}},
  66. };
  67. void
  68. init_pass_persist(void)
  69. {
  70.     snmpd_register_config_handler("pass_persist",
  71.                                   pass_persist_parse_config,
  72.                                   pass_persist_free_config,
  73.                                   "miboid program");
  74. }
  75. void
  76. pass_persist_parse_config(const char *token, char *cptr)
  77. {
  78.     struct extensible **ppass = &persistpassthrus, **etmp, *ptmp;
  79.     char           *tcptr;
  80.     int             i;
  81.     if (*cptr == '.')
  82.         cptr++;
  83.     if (!isdigit(*cptr)) {
  84.         config_perror("second token is not a OID");
  85.         return;
  86.     }
  87.     numpersistpassthrus++;
  88.     while (*ppass != NULL)
  89.         ppass = &((*ppass)->next);
  90.     (*ppass) = (struct extensible *) malloc(sizeof(struct extensible));
  91.     if (*ppass == NULL)
  92.         return;
  93.     (*ppass)->type = PASSTHRU_PERSIST;
  94.     (*ppass)->miblen = parse_miboid(cptr, (*ppass)->miboid);
  95.     while (isdigit(*cptr) || *cptr == '.')
  96.         cptr++;
  97.     /*
  98.      * name 
  99.      */
  100.     cptr = skip_white(cptr);
  101.     if (cptr == NULL) {
  102.         config_perror("No command specified on pass_persist line");
  103.         (*ppass)->command[0] = 0;
  104.     } else {
  105.         for (tcptr = cptr; *tcptr != 0 && *tcptr != '#' && *tcptr != ';';
  106.              tcptr++);
  107.         strncpy((*ppass)->command, cptr, tcptr - cptr);
  108.         (*ppass)->command[tcptr - cptr] = 0;
  109.     }
  110.     strncpy((*ppass)->name, (*ppass)->command, sizeof((*ppass)->name));
  111.     (*ppass)->name[ sizeof((*ppass)->name)-1 ] = 0;
  112.     (*ppass)->next = NULL;
  113.     register_mib("pass_persist",
  114.                  (struct variable *) extensible_persist_passthru_variables,
  115.                  sizeof(struct variable2), 1, (*ppass)->miboid,
  116.                  (*ppass)->miblen);
  117.     /*
  118.      * argggg -- pasthrus must be sorted 
  119.      */
  120.     if (numpersistpassthrus > 1) {
  121.         etmp = (struct extensible **)
  122.             malloc(((sizeof(struct extensible *)) * numpersistpassthrus));
  123.         if (etmp == NULL)
  124.             return;
  125.         for (i = 0, ptmp = (struct extensible *) persistpassthrus;
  126.              i < numpersistpassthrus && ptmp != 0; i++, ptmp = ptmp->next)
  127.             etmp[i] = ptmp;
  128.         qsort(etmp, numpersistpassthrus, sizeof(struct extensible *),
  129.               pass_persist_compare);
  130.         persistpassthrus = (struct extensible *) etmp[0];
  131.         ptmp = (struct extensible *) etmp[0];
  132.         for (i = 0; i < numpersistpassthrus - 1; i++) {
  133.             ptmp->next = etmp[i + 1];
  134.             ptmp = ptmp->next;
  135.         }
  136.         ptmp->next = NULL;
  137.         free(etmp);
  138.     }
  139. }
  140. void
  141. pass_persist_free_config(void)
  142. {
  143.     struct extensible *etmp, *etmp2;
  144.     /*
  145.      * Close any open pipes to any programs 
  146.      */
  147.     destruct_persist_pipes();
  148.     for (etmp = persistpassthrus; etmp != NULL;) {
  149.         etmp2 = etmp;
  150.         etmp = etmp->next;
  151.         unregister_mib(etmp2->miboid, etmp2->miblen);
  152.         free(etmp2);
  153.     }
  154.     persistpassthrus = NULL;
  155.     numpersistpassthrus = 0;
  156. }
  157. u_char         *
  158. var_extensible_pass_persist(struct variable *vp,
  159.                             oid * name,
  160.                             size_t * length,
  161.                             int exact,
  162.                             size_t * var_len, WriteMethod ** write_method)
  163. {
  164.     oid             newname[MAX_OID_LEN];
  165.     int             i, rtest, newlen;
  166.     static long     long_ret;
  167.     char            buf[SNMP_MAXBUF];
  168.     static char     buf2[SNMP_MAXBUF];
  169.     static oid      objid[MAX_OID_LEN];
  170.     struct extensible *persistpassthru;
  171.     FILE           *file;
  172.     /*
  173.      * Make sure that our basic pipe structure is malloced 
  174.      */
  175.     init_persist_pipes();
  176.     long_ret = *length;
  177.     for (i = 1; i <= numpersistpassthrus; i++) {
  178.         persistpassthru = get_exten_instance(persistpassthrus, i);
  179.         rtest = snmp_oid_min_compare(name, *length,
  180.                                      persistpassthru->miboid,
  181.                                      persistpassthru->miblen);
  182.         if ((exact && rtest == 0) || (!exact && rtest <= 0)) {
  183.             /*
  184.              * setup args 
  185.              */
  186.             if (persistpassthru->miblen >= *length || rtest < 0)
  187.                 sprint_mib_oid(buf, persistpassthru->miboid,
  188.                                persistpassthru->miblen);
  189.             else
  190.                 sprint_mib_oid(buf, name, *length);
  191.             /*
  192.              * Open our pipe if necessary 
  193.              */
  194.             if (!open_persist_pipe(i, persistpassthru->name)) {
  195.                 return (NULL);
  196.             }
  197.             if (exact)
  198.                 snprintf(persistpassthru->command,
  199.                   sizeof(persistpassthru->command), "getn%sn", buf);
  200.             else
  201.                 snprintf(persistpassthru->command,
  202.                   sizeof(persistpassthru->command), "getnextn%sn", buf);
  203.             persistpassthru->command[ sizeof(persistpassthru->command)-1 ] = 0;
  204.             DEBUGMSGTL(("ucd-snmp/pass_persist",
  205.                         "persistpass-sending:n%s",
  206.                         persistpassthru->command));
  207.             if (!write_persist_pipe(i, persistpassthru->command)) {
  208.                 *var_len = 0;
  209.                 /*
  210.                  * close_persist_pipes is called in write_persist_pipe 
  211.                  */
  212.                 return (NULL);
  213.             }
  214.             /*
  215.              * valid call.  Exec and get output 
  216.              */
  217.             if ((file = persist_pipes[i].fIn)) {
  218.                 if (fgets(buf, sizeof(buf), file) == NULL) {
  219.                     *var_len = 0;
  220.                     close_persist_pipe(i);
  221.                     return (NULL);
  222.                 }
  223.                 /*
  224.                  * persistant scripts return "NONEn" on invalid items 
  225.                  */
  226.                 if (!strncmp(buf, "NONE", 4)) {
  227.                     if (exact) {
  228.                         *var_len = 0;
  229.                         return (NULL);
  230.                     }
  231.                     continue;
  232.                 }
  233.                 newlen = parse_miboid(buf, newname);
  234.                 /*
  235.                  * its good, so copy onto name/length 
  236.                  */
  237.                 memcpy((char *) name, (char *) newname,
  238.                        (int) newlen * sizeof(oid));
  239.                 *length = newlen;
  240.                 /*
  241.                  * set up return pointer for setable stuff 
  242.                  */
  243.                 *write_method = setPassPersist;
  244.                 if (newlen == 0 || fgets(buf, sizeof(buf), file) == NULL
  245.                     || fgets(buf2, sizeof(buf2), file) == NULL) {
  246.                     *var_len = 0;
  247.                     close_persist_pipe(i);
  248.                     return (NULL);
  249.                 }
  250.                 /*
  251.                  * buf contains the return type, and buf2 contains the data 
  252.                  */
  253.                 if (!strncasecmp(buf, "string", 6)) {
  254.                     buf2[strlen(buf2) - 1] = 0; /* zap the linefeed */
  255.                     *var_len = strlen(buf2);
  256.                     vp->type = ASN_OCTET_STR;
  257.                     return ((unsigned char *) buf2);
  258.                 } else if (!strncasecmp(buf, "integer", 7)) {
  259.                     *var_len = sizeof(long_ret);
  260.                     long_ret = strtol(buf2, NULL, 10);
  261.                     vp->type = ASN_INTEGER;
  262.                     return ((unsigned char *) &long_ret);
  263.                 } else if (!strncasecmp(buf, "unsigned", 8)) {
  264.                     *var_len = sizeof(long_ret);
  265.                     long_ret = strtoul(buf2, NULL, 10);
  266.                     vp->type = ASN_UNSIGNED;
  267.                     return ((unsigned char *) &long_ret);
  268.                 } else if (!strncasecmp(buf, "counter", 7)) {
  269.                     *var_len = sizeof(long_ret);
  270.                     long_ret = strtoul(buf2, NULL, 10);
  271.                     vp->type = ASN_COUNTER;
  272.                     return ((unsigned char *) &long_ret);
  273.                 } else if (!strncasecmp(buf, "octet", 5)) {
  274.                     *var_len = asc2bin(buf2);
  275.                     vp->type = ASN_OCTET_STR;
  276.                     return ((unsigned char *) buf2);
  277.                 } else if (!strncasecmp(buf, "opaque", 6)) {
  278.                     *var_len = asc2bin(buf2);
  279.                     vp->type = ASN_OPAQUE;
  280.                     return ((unsigned char *) buf2);
  281.                 } else if (!strncasecmp(buf, "gauge", 5)) {
  282.                     *var_len = sizeof(long_ret);
  283.                     long_ret = strtoul(buf2, NULL, 10);
  284.                     vp->type = ASN_GAUGE;
  285.                     return ((unsigned char *) &long_ret);
  286.                 } else if (!strncasecmp(buf, "objectid", 8)) {
  287.                     newlen = parse_miboid(buf2, objid);
  288.                     *var_len = newlen * sizeof(oid);
  289.                     vp->type = ASN_OBJECT_ID;
  290.                     return ((unsigned char *) objid);
  291.                 } else if (!strncasecmp(buf, "timetick", 8)) {
  292.                     *var_len = sizeof(long_ret);
  293.                     long_ret = strtoul(buf2, NULL, 10);
  294.                     vp->type = ASN_TIMETICKS;
  295.                     return ((unsigned char *) &long_ret);
  296.                 } else if (!strncasecmp(buf, "ipaddress", 9)) {
  297.                     newlen = parse_miboid(buf2, objid);
  298.                     if (newlen != 4) {
  299.                         snmp_log(LOG_ERR,
  300.                                  "invalid ipaddress returned:  %sn",
  301.                                  buf2);
  302.                         *var_len = 0;
  303.                         return (NULL);
  304.                     }
  305.                     long_ret =
  306.                         (objid[0] << (8 * 3)) + (objid[1] << (8 * 2)) +
  307.                         (objid[2] << 8) + objid[3];
  308.                     long_ret = htonl(long_ret);
  309.                     *var_len = sizeof(long_ret);
  310.                     vp->type = ASN_IPADDRESS;
  311.                     return ((unsigned char *) &long_ret);
  312.                 }
  313.             }
  314.             *var_len = 0;
  315.             return (NULL);
  316.         }
  317.     }
  318.     if (var_len)
  319.         *var_len = 0;
  320.     *write_method = NULL;
  321.     return (NULL);
  322. }
  323. int
  324. setPassPersist(int action,
  325.                u_char * var_val,
  326.                u_char var_val_type,
  327.                size_t var_val_len,
  328.                u_char * statP, oid * name, size_t name_len)
  329. {
  330.     int             i, rtest;
  331.     struct extensible *persistpassthru;
  332.     char            buf[SNMP_MAXBUF], buf2[SNMP_MAXBUF];
  333.     long            tmp;
  334.     unsigned long   utmp;
  335.     /*
  336.      * Make sure that our basic pipe structure is malloced 
  337.      */
  338.     init_persist_pipes();
  339.     for (i = 1; i <= numpersistpassthrus; i++) {
  340.         persistpassthru = get_exten_instance(persistpassthrus, i);
  341.         rtest = snmp_oid_min_compare(name, name_len,
  342.                                      persistpassthru->miboid,
  343.                                      persistpassthru->miblen);
  344.         if (rtest <= 0) {
  345.             if (action != ACTION)
  346.                 return SNMP_ERR_NOERROR;
  347.             /*
  348.              * setup args 
  349.              */
  350.             if (persistpassthru->miblen >= name_len || rtest < 0)
  351.                 sprint_mib_oid(buf, persistpassthru->miboid,
  352.                                persistpassthru->miblen);
  353.             else
  354.                 sprint_mib_oid(buf, name, name_len);
  355.             snprintf(persistpassthru->command,
  356.                      sizeof(persistpassthru->command), "setn%sn", buf);
  357.             persistpassthru->command[ sizeof(persistpassthru->command)-1 ] = 0;
  358.             switch (var_val_type) {
  359.             case ASN_INTEGER:
  360.             case ASN_COUNTER:
  361.             case ASN_GAUGE:
  362.             case ASN_TIMETICKS:
  363.                 tmp = *((long *) var_val);
  364.                 switch (var_val_type) {
  365.                 case ASN_INTEGER:
  366.                     sprintf(buf, "integer %dn", (int) tmp);
  367.                     break;
  368.                 case ASN_COUNTER:
  369.                     sprintf(buf, "counter %dn", (int) tmp);
  370.                     break;
  371.                 case ASN_GAUGE:
  372.                     sprintf(buf, "gauge %dn", (int) tmp);
  373.                     break;
  374.                 case ASN_TIMETICKS:
  375.                     sprintf(buf, "timeticks %dn", (int) tmp);
  376.                     break;
  377.                 }
  378.                 break;
  379.             case ASN_IPADDRESS:
  380.                 utmp = *((u_long *) var_val);
  381.                 utmp = ntohl(utmp);
  382.                 sprintf(buf, "ipaddress %d.%d.%d.%dn",
  383.                         (int) ((utmp & 0xff000000) >> (8 * 3)),
  384.                         (int) ((utmp & 0xff0000) >> (8 * 2)),
  385.                         (int) ((utmp & 0xff00) >> (8)),
  386.                         (int) ((utmp & 0xff)));
  387.                 break;
  388.             case ASN_OCTET_STR:
  389.                 memcpy(buf2, var_val, var_val_len);
  390.                 if (var_val_len == 0)
  391.                     sprintf(buf, "string ""n");
  392.                 else if (bin2asc(buf2, var_val_len) == (int) var_val_len)
  393.                     snprintf(buf, sizeof(buf), "string "%s"n", buf2);
  394.                 else
  395.                     snprintf(buf, sizeof(buf), "octet "%s"n", buf2);
  396.                 buf[ sizeof(buf)-1 ] = 0;
  397.                 break;
  398.             case ASN_OBJECT_ID:
  399.                 sprint_mib_oid(buf2, (oid *) var_val, var_val_len);
  400.                 snprintf(buf, sizeof(buf), "objectid "%s"n", buf2);
  401.                 buf[ sizeof(buf)-1 ] = 0;
  402.                 break;
  403.             }
  404.             strncat(persistpassthru->command, buf,
  405.                     sizeof(persistpassthru->command) -
  406.                     strlen(persistpassthru->command) - 2);
  407.             persistpassthru->command[ sizeof(persistpassthru->command)-2 ] = 'n';
  408.             persistpassthru->command[ sizeof(persistpassthru->command)-1 ] = 0;
  409.             if (!open_persist_pipe(i, persistpassthru->name)) {
  410.                 return SNMP_ERR_NOTWRITABLE;
  411.             }
  412.             DEBUGMSGTL(("ucd-snmp/pass_persist",
  413.                         "persistpass-writing:  %sn",
  414.                         persistpassthru->command));
  415.             if (!write_persist_pipe(i, persistpassthru->command)) {
  416.                 close_persist_pipe(i);
  417.                 return SNMP_ERR_NOTWRITABLE;
  418.             }
  419.             if (fgets(buf, sizeof(buf), persist_pipes[i].fIn) == NULL) {
  420.                 close_persist_pipe(i);
  421.                 return SNMP_ERR_NOTWRITABLE;
  422.             }
  423.             if (!strncasecmp(buf, "not-writable", 12)) {
  424.                 return SNMP_ERR_NOTWRITABLE;
  425.             } else if (!strncasecmp(buf, "wrong-type", 10)) {
  426.                 return SNMP_ERR_WRONGTYPE;
  427.             }
  428.             return SNMP_ERR_NOERROR;
  429.         }
  430.     }
  431.     if (snmp_get_do_debugging()) {
  432.         sprint_mib_oid(buf2, name, name_len);
  433.         DEBUGMSGTL(("ucd-snmp/pass_persist", "persistpass-notfound:  %sn",
  434.                     buf2));
  435.     }
  436.     return SNMP_ERR_NOSUCHNAME;
  437. }
  438. int
  439. pass_persist_compare(const void *a, const void *b)
  440. {
  441.     const struct extensible *const *ap, *const *bp;
  442.     ap = (const struct extensible * const *) a;
  443.     bp = (const struct extensible * const *) b;
  444.     return snmp_oid_compare((*ap)->miboid, (*ap)->miblen, (*bp)->miboid,
  445.                             (*bp)->miblen);
  446. }
  447. /*
  448.  * Initialize our persistant pipes
  449.  *   - Returns 1 on success, 0 on failure.
  450.  *   - Initializes all FILE pointers to NULL to indicate "closed"
  451.  */
  452. static int
  453. init_persist_pipes(void)
  454. {
  455.     int             i;
  456.     /*
  457.      * if we are already taken care of, just return 
  458.      */
  459.     if (persist_pipes) {
  460.         return persist_pipes ? 1 : 0;
  461.     }
  462.     /*
  463.      * Otherwise malloc and initialize 
  464.      */
  465.     persist_pipes = (struct persist_pipe_type *)
  466.         malloc(sizeof(struct persist_pipe_type) *
  467.                (numpersistpassthrus + 1));
  468.     if (persist_pipes) {
  469.         for (i = 0; i <= numpersistpassthrus; i++) {
  470.             persist_pipes[i].fIn = persist_pipes[i].fOut = (FILE *) 0;
  471.             persist_pipes[i].fdIn = persist_pipes[i].fdOut = -1;
  472.             persist_pipes[i].pid = -1;
  473.         }
  474.     }
  475.     return persist_pipes ? 1 : 0;
  476. }
  477. /*
  478.  * Destruct our persistant pipes
  479.  *
  480.  */
  481. static void
  482. destruct_persist_pipes(void)
  483. {
  484.     int             i;
  485.     /*
  486.      * Return if there are no pipes 
  487.      */
  488.     if (!persist_pipes) {
  489.         return;
  490.     }
  491.     for (i = 0; i <= numpersistpassthrus; i++) {
  492.         close_persist_pipe(i);
  493.     }
  494.     free(persist_pipes);
  495.     persist_pipes = (struct persist_pipe_type *) 0;
  496. }
  497. /*
  498.  * returns 0 on failure, 1 on success 
  499.  */
  500. static int
  501. open_persist_pipe(int iindex, char *command)
  502. {
  503.     static int      recurse = 0;        /* used to allow one level of recursion */
  504.     DEBUGMSGTL(("ucd-snmp/pass_persist", "open_persist_pipe(%d,'%s')n",
  505.                 iindex, command));
  506.     /*
  507.      * Open if it's not already open 
  508.      */
  509.     if (persist_pipes[iindex].pid == -1) {
  510.         int             fdIn, fdOut, pid;
  511.         /*
  512.          * Did we fail? 
  513.          */
  514.         if ((0 == get_exec_pipes(command, &fdIn, &fdOut, &pid)) ||
  515.             (pid == -1)) {
  516.             DEBUGMSGTL(("ucd-snmp/pass_persist",
  517.                         "open_persist_pipe: pid == -1n"));
  518.             recurse = 0;
  519.             return 0;
  520.         }
  521.         /*
  522.          * If not, fill out our structure 
  523.          */
  524.         persist_pipes[iindex].pid = pid;
  525.         persist_pipes[iindex].fdIn = fdIn;
  526.         persist_pipes[iindex].fdOut = fdOut;
  527.         persist_pipes[iindex].fIn = fdopen(fdIn, "r");
  528.         persist_pipes[iindex].fOut = fdopen(fdOut, "w");
  529.         /*
  530.          * Setup our -non-buffered-io- 
  531.          */
  532.         setbuf(persist_pipes[iindex].fOut, (char *) 0);
  533.     }
  534.     /*
  535.      * Send test packet always so we can self-catch 
  536.      */
  537.     {
  538.         char            buf[SNMP_MAXBUF];
  539.         /*
  540.          * Should catch SIGPIPE around this call! 
  541.          */
  542.         if (!write_persist_pipe(iindex, "PINGn")) {
  543.             DEBUGMSGTL(("ucd-snmp/pass_persist",
  544.                         "open_persist_pipe: Error writing PINGn"));
  545.             close_persist_pipe(iindex);
  546.             /*
  547.              * Recurse one time if we get a SIGPIPE 
  548.              */
  549.             if (!recurse) {
  550.                 recurse = 1;
  551.                 return open_persist_pipe(iindex, command);
  552.             }
  553.             recurse = 0;
  554.             return 0;
  555.         }
  556.         if (fgets(buf, sizeof(buf), persist_pipes[iindex].fIn) == NULL) {
  557.             DEBUGMSGTL(("ucd-snmp/pass_persist",
  558.                         "open_persist_pipe: Error reading for PONGn"));
  559.             close_persist_pipe(iindex);
  560.             recurse = 0;
  561.             return 0;
  562.         }
  563.         if (strncmp(buf, "PONG", 4)) {
  564.             DEBUGMSGTL(("ucd-snmp/pass_persist",
  565.                         "open_persist_pipe: PONG not received!n"));
  566.             close_persist_pipe(iindex);
  567.             recurse = 0;
  568.             return 0;
  569.         }
  570.     }
  571.     recurse = 0;
  572.     return 1;
  573. }
  574. #if STRUCT_SIGACTION_HAS_SA_SIGACTION
  575. /*
  576.  * Generic handler 
  577.  */
  578. void
  579. sigpipe_handler(int sig, siginfo_t * sip, void *uap)
  580. {
  581.     return;
  582. }
  583. #endif
  584. static int
  585. write_persist_pipe(int iindex, const char *data)
  586. {
  587. #if HAVE_SIGNAL
  588.     struct sigaction sa, osa;
  589.     int             wret = 0, werrno = 0;
  590.     /*
  591.      * Don't write to a non-existant process 
  592.      */
  593.     if (persist_pipes[iindex].pid == -1) {
  594.         return 0;
  595.     }
  596.     /*
  597.      * Setup our signal action to catch SIGPIPEs 
  598.      */
  599.     sa.sa_handler = NULL;
  600. #if STRUCT_SIGACTION_HAS_SA_SIGACTION
  601.     sa.sa_sigaction = &sigpipe_handler;
  602. #endif
  603.     sigemptyset(&sa.sa_mask);
  604.     sa.sa_flags = 0;
  605.     if (sigaction(SIGPIPE, &sa, &osa)) {
  606.         DEBUGMSGTL(("ucd-snmp/pass_persist",
  607.                     "write_persist_pipe: sigaction failed: %d", errno));
  608.     }
  609.     /*
  610.      * Do the write 
  611.      */
  612.     wret = write(persist_pipes[iindex].fdOut, data, strlen(data));
  613.     werrno = errno;
  614.     /*
  615.      * Reset the signal handler 
  616.      */
  617.     sigaction(SIGPIPE, &osa, (struct sigaction *) 0);
  618.     if (wret < 0) {
  619.         if (werrno != EINTR) {
  620.             DEBUGMSGTL(("ucd-snmp/pass_persist",
  621.                         "write_persist_pipe: write returned unknown error %dn",
  622.                         errno));
  623.         }
  624.         close_persist_pipe(iindex);
  625.         return 0;
  626.     }
  627. #endif                          /* HAVE_SIGNAL */
  628.     return 1;
  629. }
  630. static void
  631. close_persist_pipe(int iindex)
  632. {
  633.     /*
  634.      * Check and nix every item 
  635.      */
  636.     if (persist_pipes[iindex].fOut) {
  637.         fclose(persist_pipes[iindex].fOut);
  638.         persist_pipes[iindex].fOut = (FILE *) 0;
  639.     }
  640.     if (persist_pipes[iindex].fdOut != -1) {
  641.         close(persist_pipes[iindex].fdOut);
  642.         persist_pipes[iindex].fdOut = -1;
  643.     }
  644.     if (persist_pipes[iindex].fIn) {
  645.         fclose(persist_pipes[iindex].fIn);
  646.         persist_pipes[iindex].fIn = (FILE *) 0;
  647.     }
  648.     if (persist_pipes[iindex].fdIn != -1) {
  649.         close(persist_pipes[iindex].fdIn);
  650.         persist_pipes[iindex].fdIn = -1;
  651.     }
  652.     if (persist_pipes[iindex].pid != -1) {
  653. #if HAVE_SYS_WAIT_H
  654.         waitpid(persist_pipes[iindex].pid, 0, 0);
  655. #endif
  656.         persist_pipes[iindex].pid = -1;
  657.     }
  658. }