Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief Tuxedo ubbconfig parsing routines
0003  *
0004  * @file ubb.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 #ifndef _GNU_SOURCE
0035 #define _GNU_SOURCE
0036 #endif
0037 
0038 #include <string.h>
0039 #include <stdio.h>
0040 #include <stdlib.h>
0041 #include <stdarg.h>
0042 #include <memory.h>
0043 #include <errno.h>
0044 #include <regex.h>
0045 #include <nstdutil.h>
0046 
0047 #include <exregex.h>
0048 #include "ubb.h"
0049 #include "ubb.tab.h"
0050 #include "ddr.tab.h"
0051 #include "ndebug.h"
0052 #include <sys_unix.h>
0053 #include <atmi_int.h>
0054 /*---------------------------Externs------------------------------------*/
0055 /*---------------------------Macros-------------------------------------*/
0056 /*---------------------------Enums--------------------------------------*/
0057 /*---------------------------Typedefs-----------------------------------*/
0058 /*---------------------------Globals------------------------------------*/
0059 expublic ndrx_ubb_parser_t ndrx_G_ubbp;      /**< Parsing time attributes*/
0060 expublic ndrx_ubb_parser_t ndrx_G_ddrp;      /**< Parsing time attributes*/
0061 /*---------------------------Statics------------------------------------*/
0062 exprivate ndrx_growlist_t  M_strbuf;
0063 exprivate char M_curfile[PATH_MAX+1]="UBBCONFIG(stdin)";/**< current UBB config file*/
0064 /*---------------------------Prototypes---------------------------------*/
0065 
0066 extern int ubbdebug;
0067 
0068 /**
0069  * DDR parsing error
0070  */
0071 void ddrerror(char *s, ...)
0072 {
0073     /* Log only first error! */
0074     if (EXFAIL!=ndrx_G_ddrp.error)
0075     {
0076         va_list ap;
0077         char context[31];
0078         char *p=NULL;
0079         int i, ctx_start;
0080         char *mem = ndrx_G_ddrp.parsebuf;
0081         int len=strlen(mem);
0082         
0083         ctx_start = ddrlloc.first_column;
0084         
0085         NDRX_LOG(log_error, "ctx_start=%d len=%d (%s)", ctx_start, len, mem);
0086         memset(context, 0, sizeof(context));
0087         
0088         /* prepare context of max 30 chars. */
0089         p = &context[16];
0090         
0091         for (i=15; i>=0 && (ctx_start-(15-i)) >= 0 && '\n'!=mem[ctx_start-(15-i)]; i--)
0092         {
0093             p--;
0094             *p=mem[ctx_start-(15-i)];
0095         }
0096 
0097         for (i=1; i<15 && ctx_start+i<len && '\n'!=mem[ctx_start+i]; i++)
0098         {
0099             context[15+i]=mem[ctx_start+i];
0100         }
0101 
0102         va_start(ap, s);
0103         snprintf(ndrx_G_ddrp.errbuf, sizeof(ndrx_G_ddrp.errbuf), 
0104                 "%s DDR parse error, line: %d near expression [%s]: ", 
0105                 M_curfile, ndrx_G_ubbline, p);
0106         
0107         len=strlen(ndrx_G_ddrp.errbuf);
0108         vsnprintf(ndrx_G_ddrp.errbuf+len, sizeof(ndrx_G_ddrp.errbuf)-len, s, ap);
0109         va_end(ap);
0110         NDRX_LOG(log_error, "Failed to parse: %s", ndrx_G_ddrp.errbuf);
0111 
0112         ndrx_G_ddrp.error = EXFAIL;
0113     }
0114 }
0115 
0116 /**
0117  * Generate parsing error
0118  * @param s
0119  * @param ...
0120  */
0121 void ubberror(char *s, ...)
0122 {
0123     /* Log only first error! */
0124     if (EXFAIL!=ndrx_G_ubbp.error)
0125     {
0126         va_list ap;
0127         char errbuf[2048];
0128         char context[31];
0129         char *p=NULL;
0130         int i, ctx_start;
0131         char *mem = M_strbuf.mem;
0132         int len=strlen(mem);
0133         
0134         ctx_start = ubblloc.first_column;
0135         
0136         NDRX_LOG(log_error, "ctx_start=%d len=%d", ctx_start, len);
0137         memset(context, 0, sizeof(context));
0138         
0139         /* prepare context of max 30 chars. */
0140         p = &context[16];
0141         
0142         for (i=15; i>=0 && (ctx_start-(15-i)) >= 0 && '\n'!=mem[ctx_start-(15-i)]; i--)
0143         {
0144             p--;
0145             *p=mem[ctx_start-(15-i)];
0146         }
0147 
0148         for (i=1; i<15 && ctx_start+i<len && '\n'!=mem[ctx_start+i]; i++)
0149         {
0150             context[15+i]=mem[ctx_start+i];
0151         }
0152 
0153         va_start(ap, s);
0154         snprintf(errbuf, sizeof(errbuf), "%s error line: %d near expression [%s]: ", 
0155                 M_curfile, ndrx_G_ubbline, p);
0156         
0157         len=strlen(errbuf);
0158         vsnprintf(errbuf+len, sizeof(errbuf)-len, s, ap);
0159         va_end(ap);
0160         NDRX_LOG(log_error, "Failed to parse: %s", errbuf);
0161         
0162         if (_Nis_error())
0163         {
0164             _Nappend_error_msg(errbuf);
0165         }
0166         else
0167         {
0168             _Nset_error_msg(NEFORMAT, errbuf);
0169         }
0170         ndrx_G_ubbp.error = EXFAIL;
0171     }
0172 }
0173 
0174 extern void ubb_scan_string (char *yy_str  );
0175 extern int ubblex_destroy  (void);
0176 extern int ndrx_G_ubbcolumn;
0177 /**
0178  * Parse range
0179  * @param p_crit current criterion in parse subject
0180  * @return EXSUCCEED/EXFAIL
0181  */
0182 exprivate int parse_ubbconfig(char *expr)
0183 {
0184     int ret = EXSUCCEED;
0185     memset(&ndrx_G_ubbp, 0, sizeof(ndrx_G_ubbp));
0186     /* init the string builder */
0187     ndrx_growlist_init(&ndrx_G_ubbp.stringbuffer, 200, sizeof(char));
0188     
0189     /* start to parse... */
0190     
0191     ndrx_G_ubbcolumn=0;
0192     /* NDRX_LOG(log_info, "Parsing config: [%s]", expr); */
0193     ubb_scan_string(expr);
0194             
0195     if (EXSUCCEED!=ubbparse() || EXSUCCEED!=ndrx_G_ubbp.error)
0196     {
0197         NDRX_LOG(log_error, "Failed to parse ubb config");
0198         
0199         /* free parsers... */
0200         ubblex_destroy();
0201         
0202         /* well if we hav */
0203         
0204         EXFAIL_OUT(ret);
0205     }
0206     ubblex_destroy();
0207     
0208 out:
0209     /* free up string buffer */
0210     ndrx_growlist_free(&ndrx_G_ubbp.stringbuffer);
0211 
0212     return ret;    
0213 }
0214 
0215 /**
0216  * print help for the command
0217  * @param name name of the program, argv[0]
0218  */
0219 exprivate void print_help(char *name)
0220 {
0221     fprintf(stderr, "Usage: %s [options] {UBBCONFIG_file | -}\n", name);
0222     fprintf(stderr, "Options:\n");
0223     fprintf(stderr, "  -n               Do syntax check only\n");
0224     fprintf(stderr, "  -y               Do not ask for confirmation\n");
0225     fprintf(stderr, "  -c               RFU, same as -n\n");
0226     fprintf(stderr, "  -b <BLOCKS>      RFU, ignored\n");
0227     fprintf(stderr, "  -L <LMID>        Convert only specified LMID\n");
0228     fprintf(stderr, "  -A               Do not try to re-use SRVIDs, assign new\n");
0229     fprintf(stderr, "  -D               Debug level 0..5\n");
0230     fprintf(stderr, "  -S               Converter script name (if not using internal)\n"); 
0231     /* All directories and files created, shall be made with prefix, mostly needed for testing: */
0232     fprintf(stderr, "  -P               Output directories and files prefix\n"); 
0233     fprintf(stderr, "  -O <OFFSET>      Listening node port offset multiplier, default 100\n"); 
0234     fprintf(stderr, "  -h               Print this help\n");
0235 }
0236 
0237 /**
0238  * Main entry point for view compiler
0239  */
0240 int main(int argc, char **argv)
0241 {
0242     int ret = EXSUCCEED;
0243     int c;
0244     char line[PATH_MAX+1];
0245     char opt_n[2] = ""; /**< no write */
0246     char opt_y[2] = ""; /**< auto confirm */
0247     char opt_A[2] = ""; /**< assing numbers */
0248     char opt_L[30+1] = "";  /**< generate particular LMID only */
0249     char opt_O[6+1] = "100";  /**< port offset multiplier by lisetning host */
0250     char opt_P[PATH_MAX+1] = "";  /**< output prefix */
0251     char script_nm[PATH_MAX+1]="";
0252     size_t len = 0;
0253     FILE *handle=NULL;
0254     NDRX_BANNER("UBB2EX Tool");
0255     
0256     /* if NDRX_DEBUG_CONF is set to empty... boot with minimum log level...*/
0257 
0258     /* put empty config -> let tool to control the debug level */
0259     if (NULL==getenv("NDRX_DEBUG_CONF"))
0260     {
0261         setenv("NDRX_DEBUG_CONF", "", 1);
0262     }
0263     tplogconfig(LOG_FACILITY_NDRX|LOG_FACILITY_UBF|LOG_FACILITY_TP, 0, "", "", "");
0264     ndrx_growlist_init(&M_strbuf, 1000, sizeof(char));
0265 
0266     /* clear any error... */
0267     _Nunset_error();
0268             
0269     while ((c = getopt (argc, argv, "nycb:hS:D:L:AP:O:")) != -1)
0270     {
0271         switch (c)
0272         {
0273             case 'O':
0274                 NDRX_STRCPY_SAFE(opt_O, optarg);
0275                 break;
0276             case 'P':
0277                 NDRX_STRCPY_SAFE(opt_P, optarg);
0278                 break;
0279             case 'A':
0280                 opt_A[0]='1';
0281                 break;
0282             case 'L':
0283                 NDRX_STRCPY_SAFE(opt_L, optarg);
0284                 break;
0285             case 'n':
0286                 /* Pass this to the script */
0287                 opt_n[0]='1';
0288                 break;
0289             case 'y':
0290                 /* Pass this to the script */
0291                 opt_y[0]='1';
0292                 break;
0293             case 'S':
0294                 NDRX_STRCPY_SAFE(script_nm, optarg);
0295                 break;
0296             case 'h':
0297                 print_help(argv[0]);
0298                 return 0; /*<<<< RETURN ! */
0299                 break;
0300             case 'D':
0301                 tplogconfig(LOG_FACILITY_NDRX|LOG_FACILITY_UBF|LOG_FACILITY_TP
0302                         , atoi(optarg), "", "", "");
0303         break;
0304             case 'c':
0305                 opt_n[0]='1';
0306                 break;
0307             case 'b':
0308                 NDRX_LOG(log_debug, "Ignored flag [%c]", c);
0309                 break;
0310             case '?':
0311             default:
0312                 print_help(argv[0]);
0313                 return EXFAIL; /*<<<< RETURN ! */
0314         }
0315     }
0316     if (optind < argc)
0317     {
0318         if (0==strcmp(argv[optind], "-"))
0319         {
0320             /* read from stdin */
0321             handle=stdin;
0322         }
0323         else
0324         {
0325             /* read from file 
0326              *  + add 
0327              */
0328             NDRX_STRCPY_SAFE(M_curfile, argv[optind]);
0329             if (NULL==(handle=NDRX_FOPEN(argv[optind], "r")))
0330             {
0331                 NDRX_LOG(log_error, "Failed to open [%s]: %s", argv[optind], strerror(errno));
0332                 
0333                 _Nset_error_fmt(NENOENT, "Failed to open [%s]: %s", 
0334                         argv[optind], strerror(errno));
0335                 EXFAIL_OUT(ret);
0336             }
0337         }
0338     
0339         len = sizeof(line);
0340         while (NULL!=fgets(line, len, handle))
0341         {
0342             if (EXSUCCEED!=ndrx_growlist_append_many(&M_strbuf, line, strlen(line)))
0343             {
0344                 _Nset_error_msg(NEMALLOC, "Failed to buffer ubb data");
0345                 EXFAIL_OUT(ret);
0346             }
0347         }
0348         
0349         /* add eos... */
0350         if (EXSUCCEED!=ndrx_growlist_append_many(&M_strbuf, "", 1))
0351         {
0352             _Nset_error_msg(NEMALLOC, "Failed to buffer ubb data (EOS)");
0353             EXFAIL_OUT(ret);
0354         }
0355         
0356         /* Init VM */
0357         if (EXSUCCEED!=init_vm(script_nm, opt_n, opt_y, opt_L, opt_A, opt_P, opt_O))
0358         {
0359             _Nset_error_msg(NESYSTEM, "Failed to load converter script");
0360             EXFAIL_OUT(ret);
0361         }
0362         
0363         if (EXSUCCEED!=parse_ubbconfig(M_strbuf.mem))
0364         {
0365             EXFAIL_OUT(ret);
0366         }
0367         
0368         if (EXSUCCEED!=call_add_func("ex_generate", ""))
0369         {
0370             /* clean up...! */
0371             call_add_func("ex_cleanup", "");
0372             EXFAIL_OUT(ret);
0373         }
0374     }
0375     else
0376     {
0377         print_help(argv[0]);
0378         return EXFAIL; /*<<<< RETURN ! */
0379     }
0380 
0381 out:
0382                 
0383     /* cleanup hash lists... */
0384     if (EXSUCCEED!=ret)
0385     {
0386         if (!_Nis_error())
0387         {
0388             _Nset_error_fmt(NESYSTEM, "Generic error - see logs.");
0389         }
0390         
0391         /* print error */
0392         fprintf(stderr, "%s: %s\n", argv[0], ndrx_Nstrerror2(Nerror));
0393     }
0394 
0395     ndrx_growlist_free(&M_strbuf);
0396     return ret;
0397 }
0398 
0399 /* vim: set ts=4 sw=4 et smartindent: */