Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief View print & parse functions to/from UBF style output
0003  *
0004  * @file view_print.c
0005  */
0006 /* -----------------------------------------------------------------------------
0007  * Enduro/X Middleware Platform for Distributed Transaction Processing
0008  * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved.
0009  * Copyright (C) 2017-2023, Mavimax, Ltd. All Rights Reserved.
0010  * This software is released under one of the following licenses:
0011  * AGPL (with Java and Go exceptions) or Mavimax's license for commercial use.
0012  * See LICENSE file for full text.
0013  * -----------------------------------------------------------------------------
0014  * AGPL license:
0015  *
0016  * This program is free software; you can redistribute it and/or modify it under
0017  * the terms of the GNU Affero General Public License, version 3 as published
0018  * by the Free Software Foundation;
0019  *
0020  * This program is distributed in the hope that it will be useful, but WITHOUT ANY
0021  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
0022  * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3
0023  * for more details.
0024  *
0025  * You should have received a copy of the GNU Affero General Public License along 
0026  * with this program; if not, write to the Free Software Foundation, Inc.,
0027  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0028  *
0029  * -----------------------------------------------------------------------------
0030  * A commercial use license is available from Mavimax, Ltd
0031  * contact@mavimax.com
0032  * -----------------------------------------------------------------------------
0033  */
0034 
0035 /* needed for asprintf */
0036 #ifndef _GNU_SOURCE
0037 #define _GNU_SOURCE
0038 #endif
0039 #include <string.h>
0040 #include <stdio.h>
0041 #include <stdlib.h>
0042 #include <memory.h>
0043 #include <errno.h>
0044 #include <dirent.h>
0045 #include <limits.h>
0046 
0047 #include <ndrstandard.h>
0048 #include <ubfview.h>
0049 #include <ndebug.h>
0050 
0051 #include <userlog.h>
0052 #include <view_cmn.h>
0053 #include <atmi_tls.h>
0054 #include <cf.h>
0055 #include "Exfields.h"
0056 #include <exhash.h>
0057 /*---------------------------Externs------------------------------------*/
0058 /*---------------------------Macros-------------------------------------*/
0059 #define OUTPUT_FORMAT_WDATA fmt_wdata, f->cname, p
0060 #define OUTPUT_FORMAT_NDATA fmt_ndata, f->cname
0061 /*---------------------------Enums--------------------------------------*/
0062 /*---------------------------Typedefs-----------------------------------*/
0063 /*---------------------------Globals------------------------------------*/
0064 /*---------------------------Statics------------------------------------*/
0065 /*---------------------------Prototypes---------------------------------*/
0066 
0067 
0068 /**
0069  * Get current occurrence, if field is not register, add new 0 entry to
0070  * the hash
0071  * @return -1 if failed (malloc), >=0 occurrence
0072  */
0073 expublic int ndrx_viewocc_get(ndrx_viewocc_t **hhandle, char *fld)
0074 {
0075     ndrx_viewocc_t *el;
0076     int occ=EXFAIL;
0077     
0078     EXHASH_FIND_STR( (*hhandle), fld, el);
0079     
0080     if (NULL==el)
0081     {
0082         if (NULL==(el = NDRX_FPMALLOC(sizeof(ndrx_viewocc_t), 0)))
0083         {
0084             int err = errno;
0085             UBF_LOG(log_error, "Failed to alloc: %s", strerror(err));
0086             userlog("Failed to alloc: %s", strerror(err));
0087             goto out;
0088         }
0089         
0090         /* set the data and add */
0091         NDRX_STRCPY_SAFE(el->fldnm, fld);
0092         el->occ = 0;
0093         EXHASH_ADD_STR( (*hhandle), fldnm, el);
0094         occ=el->occ;
0095     }
0096     else
0097     {
0098         el->occ++;
0099         occ=el->occ;
0100     }
0101     
0102 out:
0103     return occ;
0104 }
0105 
0106 /**
0107  * free occ counter hash
0108  * @param hhandle hash handle
0109  */
0110 expublic void ndrx_viewocc_free(ndrx_viewocc_t **hhandle)
0111 {
0112     ndrx_viewocc_t * el = NULL;
0113     ndrx_viewocc_t * tmp = NULL;
0114     
0115     EXHASH_ITER(hh, (*hhandle), el, tmp)
0116     {
0117         EXHASH_DEL((*hhandle), el);
0118         NDRX_FPFREE(el);
0119     }
0120 }
0121 
0122 /**
0123  * Read the view data from the data input
0124  * @param cstruct view structure to fill up
0125  * @param view view name to read
0126  * @param inf input stream
0127  * @param p_readf read data from function
0128  * @param dataptr1 RFU
0129  * @param level current read level
0130  * @param p_readbuf_buffered any buffered data returned (i.e. if read from
0131  *  UBF buffer dump
0132  * @return EXSUCCEED/EXFAIL
0133  */
0134 expublic int ndrx_Bvextread (char *cstruct, char *view, FILE *inf,
0135         long (*p_readf)(char *buffer, long bufsz, void *dataptr1), 
0136         void *dataptr1, int level, char **p_readbuf_buffered)
0137 {
0138     int ret=EXSUCCEED;
0139     int line=0;
0140     char *readbuf=NULL;
0141     size_t readbuf_len;
0142     char cname[NDRX_VIEW_CNAME_LEN+1];
0143     char *value=NULL;
0144     size_t value_len;
0145     char flag;
0146     char *p;
0147     char *tok;
0148     int fldtype;
0149     int cpylen;
0150     int len;
0151     char *readbuf_buffered=NULL;
0152     int nr_lead_tabs;
0153     ndrx_viewocc_t *occhash = NULL;
0154     BFLDOCC occ;
0155     ndrx_typedview_t *v = NULL;
0156     ndrx_typedview_field_t *f = NULL;
0157     ndrx_typedview_field_t *fsrc = NULL;
0158     char *copysrcbuf;
0159     BFLDLEN copysrcbuf_len;
0160     
0161     NDRX_USYSBUF_MALLOC_WERR_OUT(readbuf, readbuf_len, ret);
0162     NDRX_USYSBUF_MALLOC_WERR_OUT(value, value_len, ret);
0163     
0164     if (NULL==(v = ndrx_view_get_view(view)))
0165     {
0166         ndrx_Bset_error_fmt(BBADVIEW, "View [%s] not found!", view);
0167         EXFAIL_OUT(ret);
0168     }
0169     
0170     UBF_LOG(log_debug, "Init view [%s] at %p to null", view, cstruct);
0171     
0172     if (EXSUCCEED!=ndrx_Bvsinit(cstruct, view))
0173     {
0174         UBF_LOG(log_error, "Failed to init view [%s] at %p to null", view, cstruct);
0175         EXFAIL_OUT(ret);
0176     }
0177     
0178     /* TODO: Init the view to NULL, so that we can count occurrences 
0179      * Question about initialization of the occurrences, if occurrence
0180      * follows after some other field -> shall be set first or still added
0181      * to last. If added to last, then we need to build a hash list of each
0182      * parsed field to count the occurrences.
0183      * String Hash... of integer
0184      */
0185     
0186     /* Read line by line */
0187     while(1)
0188     {
0189         if (NULL!=p_readf)
0190         {
0191             /* read the data from callback */
0192             ret = (int)p_readf(readbuf, readbuf_len, dataptr1);
0193             
0194             if (0==ret)
0195             {
0196                 /* eof reached */
0197                 break;
0198             }
0199             if (ret < 0)
0200             {
0201                 ndrx_Bset_error_fmt(BEUNIX, "p_readf() user callback failed");
0202                 
0203                 EXFAIL_OUT(ret);
0204             }
0205             ret = EXSUCCEED;
0206         }
0207         else 
0208         {
0209             if (NULL==fgets(readbuf, readbuf_len, inf))
0210             {
0211                 /* terminate the loop */
0212                 /*
0213                  * Check errors on file.
0214                  */
0215                 if (!feof(inf))
0216                 {
0217                    /* some other error happened!?! */
0218                    ndrx_Bset_error_fmt(BEUNIX, "Failed to read from file "
0219                            "with error: [%s]", strerror(errno));
0220                    EXFAIL_OUT(ret);
0221                 }
0222 
0223                 break;
0224             }
0225         }
0226                 
0227         len = strlen(readbuf);
0228         line++;
0229         value[0] = EXEOS;
0230         cname[0] = EXEOS;
0231         p = readbuf;
0232 
0233         if ('#'==p[0])
0234         {
0235             continue; /* <<<< nothing to do - continue */
0236         }
0237 
0238         /* Ignore any newline we get, so that we are backwards compatible
0239          * with original logic
0240          */
0241         if (0==strcmp(p, "\n"))
0242         {
0243             continue; /* <<<< nothing to do - continue */
0244         }
0245         
0246         /* check the leading tabs, to see the current nesting level */
0247         nr_lead_tabs=0;
0248         while (*p=='\t')
0249         {
0250             nr_lead_tabs++;
0251             p++;
0252         }
0253         
0254         /* terminate the function if found less tabs than current level*/
0255         if (nr_lead_tabs < level)
0256         {
0257             UBF_LOG(log_debug, "Found tab level %d current %d, popping up line %d", 
0258                     nr_lead_tabs, level, line);
0259             if (NULL!=p_readbuf_buffered)
0260             {
0261                 /* pass to upper level */
0262                 *p_readbuf_buffered=readbuf;
0263                 readbuf=NULL;
0264             }
0265             /* terminate the read */
0266             goto out;
0267         }
0268         else if (nr_lead_tabs > level)
0269         {
0270             ndrx_Bset_error_fmt(BSYNTAX, "Tab level %d expected %d or less - "
0271                     "invalid data at line %d", nr_lead_tabs, level, line);
0272             EXFAIL_OUT(ret);
0273         }
0274         /* else: it is current level and process ok */
0275         
0276         flag = 0;
0277 
0278         if ('-'==p[0] || '+'==p[0] || '='==p[0])
0279         {
0280             /* Check syntax with flags... */
0281 
0282             flag=p[0];
0283 
0284             if (' '!=p[1])
0285             {
0286                 ndrx_Bset_error_fmt(BSYNTAX, "Space does not follow the flag on "
0287                                             "line %d!", line);
0288                 
0289                 EXFAIL_OUT(ret);
0290             }
0291             else
0292             {
0293                 /* step forward, flag + eos*/
0294                 p+=2;
0295             }
0296         }
0297         
0298         tok = strchr(p, '\t');
0299         if (NULL==tok)
0300         {
0301             ndrx_Bset_error_fmt(BSYNTAX, "No tab on "
0302                                         "line %d!", line);
0303             EXFAIL_OUT(ret);
0304         }
0305         else if (tok==readbuf)
0306         {
0307             ndrx_Bset_error_fmt(BSYNTAX, "Line should not start with tab on "
0308                                         "line %d!", line);
0309             EXFAIL_OUT(ret);
0310         } 
0311         else
0312         {
0313             int tmpl = strlen(p);
0314             /* seems to be ok, remove trailing newline */
0315             
0316             if (p[tmpl-1]!='\n')
0317             {
0318                 /* new line at the end is optional for callbacks... */
0319                 if (NULL==p_readf)
0320                 {
0321                     ndrx_Bset_error_fmt(BSYNTAX, "Line %d does not "
0322                             "terminate with newline!", line);
0323                     EXFAIL_OUT(ret);
0324                 }
0325             }
0326             else
0327             {
0328                 p[tmpl-1]=EXEOS;
0329             }
0330         }
0331 
0332         /* now read field number + value */
0333         cpylen = (tok-p);
0334         /* Copy off field name */
0335         NDRX_STRNCPY_EOS(cname, p, cpylen, sizeof(cname));
0336         
0337         /* Copy off value */
0338         NDRX_STRCPY_SAFE_DST(value, tok+1, value_len);
0339         UBF_LOG(log_debug, "Got [%s]:[%s]", cname, value);
0340 
0341         /* ignore, be backward/forward compatible */
0342         if (NULL==(f = ndrx_view_get_field(v, cname)))
0343         {
0344             UBF_LOG(log_warn, "Field [%s] of view [%s] not found - ignore", 
0345                     cname, view);
0346             continue;
0347         }
0348         
0349         fldtype=f->typecode_full;
0350         
0351         /* get field descriptor... */
0352         occ = ndrx_viewocc_get(&occhash, cname);
0353         
0354         if (EXFAIL==occ)
0355         {
0356             ndrx_Bset_error_fmt(BEUNIX, "malloc failed");
0357             EXFAIL_OUT(ret);
0358         }
0359         
0360         UBF_LOG(log_debug, "field [%s] next occ=%d type=%d", cname, occ, fldtype);
0361         
0362         /* Check field type */
0363         if ((BFLD_STRING == fldtype || BFLD_CARRAY == fldtype || 
0364                 BFLD_CHAR == fldtype) && '='!=flag)
0365         {
0366             if (EXFAIL==ndrx_normalize_string(value, &len))
0367             {
0368                 ndrx_Bset_error_fmt(BSYNTAX, "Cannot normalize value on line %d", 
0369                         line);
0370                 EXFAIL_OUT(ret);
0371             }
0372         }
0373         
0374         /* now about to execute command */
0375         if (0==flag)
0376         {
0377             if (EXSUCCEED!=(ret=ndrx_CBvchg_int(cstruct, v, f, occ, value, len, 
0378                     BFLD_CARRAY)))
0379             {
0380                 EXFAIL_OUT(ret);
0381             }
0382         }
0383         else if ('+'==flag)
0384         {
0385             if (EXSUCCEED!=(ret=ndrx_CBvchg_int(cstruct, v, f, 0, value, len, 
0386                     BFLD_CARRAY)))
0387             {
0388                 EXFAIL_OUT(ret);
0389             }
0390             
0391         }
0392         else if ('-'==flag)
0393         {
0394             if (EXSUCCEED!=(ret=ndrx_Bvselinit_int(v, f,  0, cstruct)))
0395             {
0396                 EXFAIL_OUT(ret);
0397             }
0398         }
0399         else if ('='==flag)
0400         {
0401             /* Resolve field to-field id 
0402              * get ptr & size from field, and BVchg to current field.
0403              */
0404             
0405             if (NULL==(fsrc = ndrx_view_get_field(v, value)))
0406             {
0407                 ndrx_Bset_error_fmt(BNOCNAME, "Source field [%s] of view [%s] not found!", 
0408                         value, v->vname);
0409                 EXFAIL_OUT(ret);
0410             }
0411 
0412             /* copy from src */
0413             copysrcbuf = ndrx_Bvfind_int(cstruct, v, fsrc, 0, &copysrcbuf_len);
0414             
0415             /* normally shall not happen as field is defined and we search
0416              * for 0 occ
0417              */
0418             if (NULL==copysrcbuf)
0419             {
0420                 UBF_LOG(log_error, "Failed to read field [%s] at occ 0", value);
0421                 EXFAIL_OUT(ret);
0422             }
0423             
0424             if (EXSUCCEED!=(ret=ndrx_CBvchg_int(cstruct, v, f, 0, copysrcbuf, 
0425                     copysrcbuf_len, fsrc->typecode_full)))
0426             {
0427                 EXFAIL_OUT(ret);
0428             }
0429         } /* '='==flag */
0430     } /* while */
0431     
0432 out:
0433     
0434     if (NULL!=readbuf_buffered)
0435     {
0436         NDRX_SYSBUF_FREE(readbuf_buffered);
0437     }
0438 
0439     if (NULL!=readbuf)
0440     {
0441         NDRX_SYSBUF_FREE(readbuf);
0442     }
0443 
0444     if (NULL!=value)
0445     {
0446         NDRX_SYSBUF_FREE(value);
0447     }
0448 
0449     if (NULL!=occhash)
0450     {
0451         ndrx_viewocc_free(&occhash);
0452     }
0453 
0454     UBF_LOG(log_debug, "%s: return %d", __func__, ret);
0455     
0456     return ret;
0457 
0458 }
0459 
0460 /**
0461  * Print VIEW data to file pointer 
0462  * Note that only initialized are printed in case if 
0463  * @param cstruct ptr to the view struct (c)
0464  * @param view view name
0465  * @param outf file pointer to which to print
0466  * @param p_writef masking function if any (shared with UBF)
0467  * @param dataptr1 RFU data pointer
0468  * @param level level (front tabs at which to print)
0469  * @return EXSUCCEED/EXFAIL
0470  */
0471 expublic int ndrx_Bvfprint (char *cstruct, char *view, FILE * outf,
0472           ndrx_plugin_tplogprintubf_hook_t p_writef, void *dataptr1, int level)
0473 {
0474     int ret=EXSUCCEED;
0475     BFLDID bfldid;
0476     BFLDLEN  len;
0477     BFLDOCC occ;
0478     char *p;
0479     char *cnv_buf = NULL;
0480     BFLDLEN cnv_len;
0481     char fmt_wdata[256];
0482     char fmt_ndata[256];
0483     int i;
0484     Bvnext_state_t bprint_state;
0485     char *p_view = view;
0486     int temp_len;
0487     
0488     /* Indicators.. */
0489     short *C_count;
0490     short C_count_stor;
0491     unsigned short *L_length; /* will transfer as long */
0492     
0493     ndrx_typedview_t *v;
0494     ndrx_typedview_field_t *f;
0495     
0496     UBF_LOG(log_debug, "%s enter at level %d", __func__, level);
0497     
0498     memset(&bprint_state, 0, sizeof(bprint_state));
0499     
0500     
0501     /* Resolve view descriptor */
0502     if (NULL==(v = ndrx_view_get_view(view)))
0503     {
0504         ndrx_Bset_error_fmt(BBADVIEW, "View [%s] not found!", view);
0505         EXFAIL_OUT(ret);
0506     }
0507     
0508     for (i=0; i<level; i++)
0509     {
0510         fmt_wdata[i]='\t';
0511         fmt_ndata[i]='\t';
0512     }
0513     
0514     fmt_wdata[i]=EXEOS;
0515     fmt_ndata[i]=EXEOS;
0516     
0517     NDRX_STRCAT_S(fmt_wdata, sizeof(fmt_wdata), "%s\t%s\n");
0518     NDRX_STRCAT_S(fmt_ndata, sizeof(fmt_ndata), "%s\t\n");
0519     
0520     bfldid = 0;
0521 
0522     DL_FOREACH(v->fields, f)
0523     {
0524         p_view=NULL;
0525 
0526         if (f->flags & NDRX_VIEW_FLAG_ELEMCNT_IND_C)
0527         {
0528             C_count = (short *)(cstruct+f->count_fld_offset);
0529         }
0530         else
0531         {
0532             C_count_stor=f->count; 
0533             C_count = &C_count_stor;
0534         }
0535         
0536         /* extra check: */
0537         if (*C_count > f->count)
0538         {
0539             UBF_LOG(log_error, "Invalid count for field %s.%s in "
0540                     "view %hd, specified: %hd", v->vname, f->cname, 
0541                     f->count, *C_count);
0542             
0543             ndrx_Bset_error_fmt(BNOCNAME, "Invalid count for field %s.%s in "
0544                     "view %hd, specified: %hd", v->vname, f->cname, 
0545                     f->count, *C_count);
0546             EXFAIL_OUT(ret);
0547         }
0548         
0549         for (occ=0; occ<*C_count; occ++)
0550         {
0551             BFLDLEN dim_size = f->fldsize/f->count;
0552             p = cstruct+f->offset+occ*dim_size;
0553             
0554             /* just increment the field id for view.. */
0555             bfldid++;
0556             
0557             /* get the carray length  */
0558             if (f->flags & NDRX_VIEW_FLAG_LEN_INDICATOR_L)
0559             {
0560                 L_length = (unsigned short *)(cstruct+f->length_fld_offset+
0561                             occ*sizeof(unsigned short));
0562                 len = (BFLDLEN)*L_length;
0563             }
0564             else
0565             {
0566                 len=dim_size;
0567             }
0568             
0569             /* print the field... */
0570             if (BFLD_STRING==f->typecode_full || BFLD_CARRAY==f->typecode_full)
0571             {
0572                 /* For strings we must count off trailing EOS */
0573                 if (BFLD_STRING==f->typecode_full)
0574                 {
0575                     len=strlen(p);
0576                 }
0577 
0578                 temp_len = ndrx_get_nonprintable_char_tmpspace(p, len);
0579 
0580                 if (temp_len!=len) /* for carray we need EOS at end! */
0581                 {
0582                     UBF_LOG(log_debug, "Containing special characters -"
0583                                         " needs to temp buffer for prefixing");
0584                     cnv_buf=NDRX_MALLOC(temp_len+1); /* adding +1 for EOS */
0585                     if (NULL==cnv_buf)
0586                     {
0587                         ndrx_Bset_error_fmt(BMALLOC, "%s: Failed to allocate ",
0588                                 __func__, temp_len+1);
0589                         EXFAIL_OUT(ret);
0590                     }
0591                     
0592                     /* build the printable string */
0593                     ndrx_build_printable_string(cnv_buf, temp_len+1, p, len);
0594                     
0595                     p = cnv_buf;
0596                 }
0597                 else if (BFLD_CARRAY==f->typecode_full) /* we need EOS for carray... */
0598                 {
0599                     cnv_buf=NDRX_MALLOC(temp_len+1); /* adding +1 for EOS */
0600 
0601                     memcpy(cnv_buf, p, temp_len);
0602 
0603                     if (NULL==cnv_buf)
0604                     {
0605                         ndrx_Bset_error_fmt(BMALLOC, "%s: Failed to allocate ", 
0606                                 __func__, temp_len+1);
0607                         EXFAIL_OUT(ret);
0608                     }
0609                     cnv_buf[temp_len] = EXEOS;
0610                     p = cnv_buf;
0611                 }
0612             }
0613             else
0614             {
0615                 cnv_buf=ndrx_Btypcvt(&cnv_len, BFLD_STRING, p, f->typecode_full, len);
0616 
0617                 if (NULL==cnv_buf)
0618                 {
0619                     /* we failed to convert - FAIL! No buffers should be allocated
0620                      * at the moment. */
0621                     break; /* <<< BREAK */
0622                 }
0623                 else
0624                 {
0625                     p=cnv_buf;
0626                 }
0627                 
0628                 /* escape char data... */
0629                 if (BFLD_CHAR==f->typecode_full &&
0630                         (temp_len = ndrx_get_nonprintable_char_tmpspace(p, cnv_len)) &&
0631                         temp_len!=cnv_len)
0632                 {
0633                     UBF_LOG(log_debug, "Containing special characters -"
0634                                     " needs to temp buffer for prefixing");
0635                     cnv_buf=NDRX_MALLOC(temp_len+1); /* adding +1 for EOS */
0636                     if (NULL==cnv_buf)
0637                     {
0638                         ndrx_Bset_error_fmt(BMALLOC, "%s: Failed to allocate ",
0639                                 __func__, temp_len+1);
0640                         EXFAIL_OUT(ret);
0641                     }
0642 
0643                     /* build the printable string */
0644                     ndrx_build_printable_string(cnv_buf, temp_len+1, p, len);
0645                     
0646                     NDRX_FREE(p);
0647                     p = cnv_buf;
0648                 }
0649 
0650                 len=cnv_len;
0651             }
0652             
0653             /* value is kept in p */
0654             if (len>0)
0655             {
0656                 if (NULL!=p_writef)
0657                 {
0658                     char *tmp;
0659                     long tmp_len;
0660                     int do_write = EXFALSE;
0661                     
0662                     NDRX_ASPRINTF(&tmp, &tmp_len, OUTPUT_FORMAT_WDATA);
0663                     
0664                     if (NULL==tmp)
0665                     {
0666                         ndrx_Bset_error_fmt(BMALLOC, "%s: NDRX_ASPRINTF failed", 
0667                                 __func__);
0668                         EXFAIL_OUT(ret);
0669                     }
0670                     
0671                     tmp_len++;
0672                     
0673                     if (EXSUCCEED!=(ret=p_writef(&tmp, tmp_len, dataptr1, &do_write, 
0674                             outf, bfldid)))
0675                     {
0676                         ndrx_Bset_error_fmt(BEINVAL, "%s: p_writef user function "
0677                                 "failed with %d for [%s]", 
0678                                 __func__, ret, tmp);
0679                         NDRX_FREE(tmp);
0680                         EXFAIL_OUT(ret);
0681                     }
0682                     
0683                     if (do_write)
0684                     {
0685                         fprintf(outf, "%s", tmp);
0686                     }
0687                             
0688                     NDRX_FREE(tmp);
0689                 }
0690                 else
0691                 {
0692                     fprintf(outf, OUTPUT_FORMAT_WDATA);
0693                 }
0694                 
0695             }
0696             else
0697             {
0698                 if (NULL!=p_writef)
0699                 {
0700                     char *tmp;
0701                     long tmp_len;
0702                     int do_write = EXFALSE;
0703                     
0704                     NDRX_ASPRINTF(&tmp, &tmp_len, OUTPUT_FORMAT_NDATA);
0705                     
0706                     if (NULL==tmp)
0707                     {
0708                         ndrx_Bset_error_fmt(BMALLOC, "%s: NDRX_ASPRINTF failed 2", 
0709                                 __func__);
0710                         EXFAIL_OUT(ret);
0711                     }
0712                     
0713                     tmp_len++;
0714                     
0715                     if (EXSUCCEED!=(ret=p_writef(&tmp, tmp_len, dataptr1, &do_write, outf,
0716                             bfldid)))
0717                     {
0718                         ndrx_Bset_error_fmt(BEINVAL, "%s: p_writef user function "
0719                                 "failed with %d for [%s] 2", 
0720                                 __func__, ret, tmp);
0721                         NDRX_FREE(tmp);
0722                         EXFAIL_OUT(ret);
0723                     }
0724                     
0725                     if (do_write)
0726                     {
0727                         fprintf(outf, "%s", tmp);
0728                     }
0729                     
0730                     NDRX_FREE(tmp);
0731                 }
0732                 else
0733                 {
0734                     fprintf(outf, OUTPUT_FORMAT_NDATA);
0735                 }   
0736             }
0737 
0738 
0739             /* free up any buffers used: */
0740             if (NULL!=cnv_buf)
0741             {
0742                 NDRX_FREE(cnv_buf);
0743                 cnv_buf = NULL;
0744             }
0745             
0746             if (NULL!=outf && ferror(outf))
0747             {
0748                 ndrx_Bset_error_fmt(BEUNIX, "Failed to write to file with error: [%s]",
0749                             strerror(errno));
0750                 EXFAIL_OUT(ret);
0751             }
0752 
0753         }
0754         
0755     }
0756     
0757 out:
0758     /* Free up allocated resources */
0759 
0760     if (NULL!=cnv_buf)
0761     {
0762         NDRX_FREE(cnv_buf);
0763     }
0764 
0765     /* release the stuff... */
0766 
0767     if (0==level)
0768     {
0769         fflush(outf);
0770     }
0771 
0772     return ret;
0773 }
0774 
0775 /* vim: set ts=4 sw=4 et smartindent: */