Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief Run the script
0003  *
0004  * @file script.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 
0055 #include <pscript.h>
0056 #include <psstdblob.h>
0057 #include <psstdio.h>
0058 #include <psstdsystem.h>
0059 #include <psstdmath.h>
0060 #include <psstdstring.h>
0061 #include <psstdexutil.h>
0062 #include <psstdaux.h>
0063 #include "buildtools.h"
0064 /*---------------------------Externs------------------------------------*/
0065 extern void ddr_scan_string (char *yy_str  );
0066 extern int ddrlex_destroy  (void);
0067 extern int ndrx_G_ddrcolumn;
0068 
0069 extern const char ndrx_G_resource_ubb2ex_bytecode[];
0070 extern const size_t ndrx_G_resource_ubb2ex_bytecode_len;
0071 
0072 /*---------------------------Macros-------------------------------------*/
0073 /*---------------------------Enums--------------------------------------*/
0074 /*---------------------------Typedefs-----------------------------------*/
0075 /*---------------------------Globals------------------------------------*/
0076 /*---------------------------Statics------------------------------------*/
0077 exprivate HPSCRIPTVM v;
0078 /*---------------------------Prototypes---------------------------------*/
0079 
0080 expublic int call_add_func(const char *func, char *arg)
0081 {
0082     int ret = EXSUCCEED;
0083     PSInteger i=0;
0084     const PSChar *err;
0085     
0086     ps_pushroottable(v);
0087     ps_pushstring(v,func,-1);
0088     ps_get(v,-2);
0089     ps_pushroottable(v);
0090     ps_pushstring(v,arg,-1);
0091     
0092     if (PS_FAILED(ps_call(v,2,PSTrue,PSTrue)))
0093     {
0094         ps_getlasterror(v);
0095         if(PS_SUCCEEDED(ps_getstring(v,-1,&err)))
0096         {
0097             _Nset_error_fmt(NESYSTEM, "Failed to call script func %s: %s", func,
0098                     err);
0099         }
0100         EXFAIL_OUT(ret);
0101     }
0102     
0103     ps_pop(v,3); /* pops the roottable and the function*/
0104     
0105 out:
0106     
0107     return ret;
0108      
0109 }
0110 
0111 expublic int ubb_add_val(char *arg)
0112 {
0113     int ret=EXSUCCEED;
0114     NDRX_LOG(log_debug, "Add value [%s]", arg);
0115     
0116     ret=call_add_func(__func__, arg);
0117     
0118     NDRX_FREE(arg);
0119     return ret;
0120 }
0121 
0122 expublic int ubb_add_res_parm(char *arg)
0123 {
0124     int ret=EXSUCCEED;
0125     NDRX_LOG(log_debug, "Add resource param [%s]", arg);
0126     
0127     ret=call_add_func(__func__, arg);
0128     NDRX_FREE(arg);
0129     return ret;
0130 }
0131 
0132 expublic int ubb_add_sect_parm(char *arg)
0133 {
0134     int ret=EXSUCCEED;
0135     NDRX_LOG(log_debug, "Add section param [%s]", arg);
0136     ret=call_add_func(__func__, arg);
0137     NDRX_FREE(arg);
0138     return ret;
0139 }
0140 
0141 expublic int ubb_add_sect_keyw(char *arg)
0142 {
0143     int ret=EXSUCCEED;
0144     NDRX_LOG(log_debug, "Add section keyword [%s]", arg);
0145     ret=call_add_func(__func__, arg);
0146     NDRX_FREE(arg);
0147     return ret;
0148 }
0149 
0150 expublic int ubb_add_sect(char *arg)
0151 {
0152     int ret=EXSUCCEED;
0153     NDRX_LOG(log_debug, "Add section [%s]", arg);
0154     ret=call_add_func(__func__, arg);
0155     NDRX_FREE(arg);
0156     return ret;
0157 }
0158 
0159 /**
0160  * This is callback from script
0161  * When DDR is requested to be parsed.
0162  * @param v
0163  * @return 1 - ok, 0 - fail
0164  */
0165 static PSInteger ubb_ddr_parse(HPSCRIPTVM v)
0166 {
0167     int ret = EXSUCCEED;
0168     const PSChar *s=NULL;
0169     char err[256];
0170     
0171     memset(&ndrx_G_ddrp, 0, sizeof(ndrx_G_ddrp));
0172     /* init the string builder */
0173     ndrx_growlist_init(&ndrx_G_ddrp.stringbuffer, 200, sizeof(char));
0174     
0175     if(PS_SUCCEEDED(ps_getstring(v,2,&s)))
0176     {
0177         NDRX_LOG(log_debug, "PARSE RANGE [%s]", s);
0178         /* start to parse... */
0179         ndrx_G_ddrcolumn=0;
0180                 
0181         ndrx_G_ddrp.parsebuf=(char *)s;
0182         
0183         ddr_scan_string((char *)s);
0184 
0185         if (EXSUCCEED!=ddrparse() || EXSUCCEED!=ndrx_G_ddrp.error)
0186         {
0187             NDRX_LOG(log_error, "Failed to parse tux config");
0188 
0189             /* free parsers... */
0190             ddrlex_destroy();
0191 
0192             /* well if we hav */
0193             EXFAIL_OUT(ret);
0194         }
0195         ddrlex_destroy();
0196     }    
0197     else
0198     {
0199         EXFAIL_OUT(ret);
0200     }
0201     
0202 out:
0203     
0204     /* free up string buffer */
0205     ndrx_growlist_free(&ndrx_G_ddrp.stringbuffer);
0206     
0207     if (EXSUCCEED!=ret)
0208     {
0209         if (EXEOS!=ndrx_G_ddrp.errbuf[0])
0210         {
0211             return ps_throwerror(v, ndrx_G_ddrp.errbuf);
0212         }
0213         else
0214         {
0215             snprintf(err, sizeof(err), "Failed to parse DDR expression [%.20s] near line %d",
0216                     (char *)s, ndrx_G_ubbline);
0217             return ps_throwerror(v, err);
0218         }
0219     }
0220 
0221     return ret;
0222 }
0223 
0224 /**
0225  * Mark group as routed
0226  * @param seq
0227  * @param grp
0228  * @param is_mallocd
0229  * @return 
0230  */
0231 expublic int ndrx_ddr_add_group(ndrx_routcritseq_dl_t * seq, char *grp, int is_mallocd)
0232 {
0233     int ret;
0234     
0235     ret = call_add_func("ubb_mark_group_routed", grp);
0236     
0237     NDRX_FREE(grp);
0238     NDRX_FREE(seq);
0239     
0240     return ret;
0241 }
0242 
0243 /**
0244  * Dummy not used
0245  * @param range
0246  * @param is_negative
0247  * @param dealloc
0248  * @return 
0249  */
0250 expublic char *ndrx_ddr_new_rangeval(char *range, int is_negative, int dealloc)
0251 {   
0252     char *ret=NULL;
0253     int len;
0254     
0255     if (!is_negative)
0256     {
0257         ret=NDRX_STRDUP(range);
0258     }
0259     else
0260     {
0261         NDRX_ASPRINTF(&ret, &len, "-%s", range);
0262     }
0263     
0264     if (dealloc)
0265     {
0266         NDRX_FREE(range);
0267     }
0268     
0269     return ret;
0270 
0271 }
0272 
0273 /**
0274  * Dummy not used.
0275  * @param range_min
0276  * @param range_max
0277  * @return 
0278  */
0279 expublic ndrx_routcritseq_dl_t * ndrx_ddr_new_rangeexpr(char *range_min, char *range_max)
0280 {   
0281     if (NULL!=range_min)
0282     {
0283         NDRX_FREE(range_min);
0284     }
0285     
0286     if (range_max!=range_min && NULL!=range_max)
0287     {
0288         NDRX_FREE(range_max);
0289     }
0290     
0291     return (ndrx_routcritseq_dl_t *)(NDRX_MALLOC(1));
0292 }
0293 
0294 /**
0295  * Print function for pscript
0296  * @param v
0297  * @param s
0298  * @param ...
0299  */
0300 expublic void printfunc(HPSCRIPTVM v,const PSChar *s,...)
0301 {
0302     char buf[5000];
0303     char *p;
0304     
0305     buf[0]=EXEOS;
0306     
0307     va_list vl;
0308     va_start(vl, s);
0309     vsnprintf(buf, sizeof(buf), s, vl);
0310     va_end(vl);
0311     
0312     p=ndrx_str_lstrip_ptr(buf, "\n");
0313     ndrx_str_rstrip(p, "\n");
0314     NDRX_LOG(log_debug, "%s", p);
0315 }
0316 
0317 /**
0318  * Get RM switch
0319  * @param [script] RM name
0320  * @return XASwitch struct name, or "" empty string
0321  */
0322 static PSInteger ubb_get_rmswitch(HPSCRIPTVM v)
0323 {
0324     const PSChar *str;
0325     
0326     ndrx_rm_def_t sw;
0327     ps_getstring(v,2,&str);
0328     
0329     if (EXTRUE==ndrx_get_rm_name((char *)str, &sw))
0330     {
0331         ps_pushstring(v, sw.structname, -1);
0332     }
0333     else
0334     {
0335         ps_pushstring(v, "", -1);
0336     }
0337     
0338     return 1;
0339 
0340 }
0341 
0342 /**
0343  * Error function
0344  * @param v
0345  * @param s
0346  * @param ...
0347  */
0348 expublic void errorfunc(HPSCRIPTVM v,const PSChar *s,...)
0349 {
0350     char buf[5000];
0351     char *p;
0352     buf[0]=EXEOS;
0353     
0354     va_list vl;
0355     va_start(vl, s);
0356     vsnprintf(buf, sizeof(buf), s, vl);
0357     va_end(vl);
0358     
0359     p=ndrx_str_lstrip_ptr(buf, "\n");
0360     ndrx_str_rstrip(p, "\n");
0361     NDRX_LOG(log_error, "%s", p);
0362 }
0363 
0364 
0365 /**
0366  * Start the VM, firstly to fill up the structures
0367  * @param script_nm script name to load
0368  * @param opt_n check only
0369  * @param opt_y auto confirm overwrite
0370  * @param opt_L LMDID only which shall be generated.
0371  * @param opt_A assign new SRVIDs
0372  * @param opt_P prefix
0373  * @param opt_O Lisetning port offset multiplier
0374  * @return EXSUCCEED/EXFAIL
0375  */
0376 expublic int init_vm(char *script_nm,
0377         char *opt_n, char *opt_y, char *opt_L, char *opt_A,
0378         char *opt_P, char *opt_O)
0379 {
0380     int ret=EXSUCCEED;
0381     const PSChar *s;
0382     const PSChar *err;
0383     char *script = NULL;
0384     size_t len=0;
0385     v = ps_open(2048); /* creates a VM with initial stack size 1024 */
0386     
0387     ps_setprintfunc(v,printfunc,errorfunc);
0388     
0389     ps_pushroottable(v);
0390     
0391     /* Load settings into root table */
0392     
0393     ps_pushstring(v,"M_opt_n",-1);
0394     ps_pushstring(v,opt_n,-1);
0395     ps_newslot(v,-3,PSFalse);
0396     
0397     ps_pushstring(v,"M_opt_y",-1);
0398     ps_pushstring(v,opt_y,-1);
0399     ps_newslot(v,-3,PSFalse);
0400     
0401     ps_pushstring(v,"M_opt_L",-1);
0402     ps_pushstring(v,opt_L,-1);
0403     ps_newslot(v,-3,PSFalse);
0404     
0405     ps_pushstring(v,"M_opt_A",-1);
0406     ps_pushstring(v,opt_A,-1);
0407     ps_newslot(v,-3,PSFalse);
0408     
0409     ps_pushstring(v,"M_opt_P",-1);
0410     ps_pushstring(v,opt_P,-1);
0411     ps_newslot(v,-3,PSFalse);
0412 
0413     ps_pushstring(v,"M_opt_O",-1);
0414     ps_pushstring(v,opt_O,-1);
0415     ps_newslot(v,-3,PSFalse);
0416     
0417     /* register functions */
0418     psstd_register_bloblib(v);
0419     psstd_register_iolib(v);
0420     psstd_register_systemlib(v);
0421     psstd_register_mathlib(v);
0422     psstd_register_stringlib(v);
0423     psstd_register_exutillib(v);
0424 
0425     /* register new func for DDR parsing. */
0426     ps_pushstring(v,"ubb_ddr_parse",-1);
0427     ps_newclosure(v,ubb_ddr_parse,0);
0428     ps_setparamscheck(v,2,".s");
0429     ps_setnativeclosurename(v,-1,"ubb_ddr_parse");
0430     ps_newslot(v,-3,PSFalse);
0431     
0432     /* Switch resolver */
0433     ps_pushstring(v,"ubb_get_rmswitch",-1);
0434     ps_newclosure(v,ubb_get_rmswitch,0);
0435     ps_setparamscheck(v,2,".s");
0436     ps_setnativeclosurename(v,-1,"ubb_ddr_parse");
0437     ps_newslot(v,-3,PSFalse);
0438     
0439     /* aux library
0440      * sets error handlers */
0441     psstd_seterrorhandlers(v);
0442     
0443     if (EXEOS!=script_nm[0])
0444     {
0445         script=ndrx_file_read(script_nm, &len);
0446 
0447         if (NULL==script)
0448         {
0449             EXFAIL_OUT(ret);
0450         }
0451 
0452         /* Compile & load the script */
0453         if (PS_FAILED(ps_compilebuffer(v, script, len, script_nm, PSTrue)))
0454         {
0455             if(PS_SUCCEEDED(ps_getstring(v, -1, &err)))
0456             {
0457                 _Nset_error_fmt(NESYSTEM, "Failed to compile script: %s", err);
0458                 EXFAIL_OUT(ret);
0459             }
0460             EXFAIL_OUT(ret);
0461         }
0462     }
0463     else
0464     {
0465         PSMemReader reader;
0466         
0467         memset(&reader, 0, sizeof(reader));
0468         
0469         reader.memptr = (char *)ndrx_G_resource_ubb2ex_bytecode;
0470         reader.size = ndrx_G_resource_ubb2ex_bytecode_len;
0471         
0472         if (PS_FAILED(psstd_loadmem(v, &reader)))
0473         {
0474             if(PS_SUCCEEDED(ps_getstring(v, -1, &err)))
0475             {
0476                 _Nset_error_fmt(NESYSTEM, "Failed to load bytecode: %s", err);
0477                 EXFAIL_OUT(ret);
0478             }
0479             else
0480             {
0481                 _Nset_error_msg(NESYSTEM, "Failed to load bytecode: no error specfied");
0482                 EXFAIL_OUT(ret);
0483             }
0484         }
0485     }
0486     
0487     ps_pushroottable(v);
0488     
0489     
0490     /* Load the function */
0491     if (PS_FAILED(ps_call(v,1,PSTrue, PSTrue)))
0492     {
0493         ps_getlasterror(v);
0494         if(PS_SUCCEEDED(ps_getstring(v,-1,&err)))
0495         {
0496             _Nset_error_fmt(NESYSTEM, "Failed load closure", err);
0497             EXFAIL_OUT(ret);
0498         }
0499     }
0500     
0501     
0502     NDRX_LOG(log_debug, "VM Script Loaded");
0503      
0504 out:
0505 
0506     if (NULL!=script)
0507     {
0508         NDRX_FREE(script);
0509     }
0510 
0511     return ret;
0512 
0513 }
0514 
0515 /* vim: set ts=4 sw=4 et smartindent: */