Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief Enduro/X standard library - error handling
0003  *
0004  * @file nerror.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 /*---------------------------Includes-----------------------------------*/
0036 #include <stdio.h>
0037 #include <stdarg.h>
0038 #include <memory.h>
0039 #include <stdlib.h>
0040 #include <regex.h>
0041 #include <ubf.h>
0042 #include <ubf_int.h>
0043 #include <ndebug.h>
0044 #include <nerror.h>
0045 #include <errno.h>
0046 #include <nstd_tls.h>
0047 /*---------------------------Externs------------------------------------*/
0048 /*---------------------------Macros-------------------------------------*/
0049 
0050 /**
0051  * Function returns error description
0052  */
0053 #define NSTD_ERROR_DESCRIPTION(X) (M_nstd_error_defs[X<NMINVAL?NMINVAL:(X>NMAXVAL?NMAXVAL:X)].msg)
0054 #define NSTD_ERROR_CODESTR(X) (M_nstd_error_defs[X<NMINVAL?NMINVAL:(X>NMAXVAL?NMAXVAL:X)].codestr)
0055 
0056 #define STDE(X) X,  #X
0057 
0058 /*---------------------------Enums--------------------------------------*/
0059 /*---------------------------Typedefs-----------------------------------*/
0060 /*---------------------------Globals------------------------------------*/
0061 /*---------------------------Statics------------------------------------*/
0062 
0063 /* Do we need this to be in message catalogue?
0064  * table bellow is indexed by id (i.e. direct array erorr lookup should work)
0065  */
0066 struct err_msg
0067 {
0068     int id;
0069     char *codestr;
0070     char *msg;
0071 } M_nstd_error_defs [] =
0072 {
0073     {STDE(BMINVAL),       "No error"},        /* 0 */
0074     {STDE(NEINVALINI),    "Invalid INI file"}, /* 1 */
0075     {STDE(NEMALLOC),      "Malloc failed"},    /* 2 */
0076     {STDE(NEUNIX),        "Unix system call failed"},    /* 3 */
0077     {STDE(NEINVAL),       "Invalid parameter passed to function"}, /* 4 */
0078     {STDE(NESYSTEM),      "System failure"}, /* 5 */
0079     {STDE(NEMANDATORY),   "Mandatory key/field missing"}, /* 6 */
0080     {STDE(NEFORMAT),      "Invalid format"}, /* 7 */
0081     {STDE(NETOUT),        "Timed-out"}, /* 8 */
0082     {STDE(NENOCONN),      "No Connection"}, /* 9 */
0083     {STDE(NELIMIT),       "Limit reached"}, /* 10 */
0084     {STDE(NEPLUGIN),      "Plugin error"}, /* 11 */
0085     {STDE(NENOSPACE),     "No space to store output buffer"}, /* 12 */
0086     {STDE(NEINVALKEY),    "Probably invalid encryption key"}, /* 13 */
0087     {STDE(NENOENT),       "No such file or directory"}, /* 14 */
0088     {STDE(NEWRITE),       "Failed to opten/write to file"}, /* 15 */
0089     {STDE(NEEXEC),        "Failed to execute"}, /* 16 */
0090     {STDE(NESUPPORT),     "Command not supported"}, /* 17 */
0091     {STDE(NEEXISTS),      "Element exists"}, /* 18 */
0092     {STDE(NEVERSION),     "Invalid version"}, /* 19 */
0093     {STDE(NEBUSY),        "Resrouce is busy"} /* 20 */
0094 };
0095 /*---------------------------Prototypes---------------------------------*/
0096 /**
0097  * Standard.
0098  * Printer error to stderr
0099  * @param str
0100  */
0101 expublic void N_error (char *str)
0102 {
0103     NSTD_TLS_ENTRY;
0104     if (EXEOS!=G_nstd_tls->M_nstd_error_msg_buf[0])
0105     {
0106         fprintf(stderr, "%s:%d:%s (%s)\n", str, 
0107                 G_nstd_tls->M_nstd_error, 
0108                 NSTD_ERROR_DESCRIPTION(G_nstd_tls->M_nstd_error),
0109                 G_nstd_tls->M_nstd_error_msg_buf);
0110     }
0111     else
0112     {
0113         fprintf(stderr, "%s:%d:%s\n", str, 
0114                 G_nstd_tls->M_nstd_error, 
0115                 NSTD_ERROR_DESCRIPTION(G_nstd_tls->M_nstd_error));
0116     }
0117 }
0118 
0119 /**
0120  * Return error code in string format
0121  * note in case of invalid error code, the max or min values will be returned.
0122  * @param err error code
0123  * @return ptr to constant string (error code)
0124  */
0125 expublic char * ndrx_Necodestr(int err)
0126 {
0127     return NSTD_ERROR_CODESTR(err);
0128 }
0129 
0130 /**
0131  * Return current error buffer
0132  * @return ptr to error buffer from TLS
0133  */
0134 expublic char * ndrx_Nemsg_buf(void)
0135 {
0136     return G_nstd_tls->M_nstd_error_msg_buf;
0137 }
0138 
0139 /**
0140  * Extended version. This will print internal error message what happened.
0141  * This is not thread safe (as all other functions).
0142  * @param error_code
0143  */
0144 expublic char * Nstrerror (int err)
0145 {
0146     NSTD_TLS_ENTRY;
0147    
0148     if (EXEOS!=G_nstd_tls->M_nstd_error_msg_buf[0])
0149     {
0150         snprintf(G_nstd_tls->errbuf, sizeof(G_nstd_tls->errbuf), 
0151                                 "%d:%s (last error %d: %s)",
0152                                 err,
0153                                 NSTD_ERROR_DESCRIPTION(err),
0154                                 G_nstd_tls->M_nstd_error,
0155                                 G_nstd_tls->M_nstd_error_msg_buf);
0156     }
0157     else
0158     {
0159         snprintf(G_nstd_tls->errbuf, sizeof(G_nstd_tls->errbuf), "%d:%s",
0160                             err, NSTD_ERROR_DESCRIPTION(err));
0161     }
0162 
0163     return G_nstd_tls->errbuf;
0164 }
0165 
0166 /**
0167  * Print only error detail, if have one
0168  * @param error_code
0169  */
0170 expublic char * ndrx_Nstrerror2 (int err)
0171 {
0172     NSTD_TLS_ENTRY;
0173 
0174     if (EXEOS!=G_nstd_tls->M_nstd_error_msg_buf[0])
0175     {
0176         snprintf(G_nstd_tls->errbuf, sizeof(G_nstd_tls->errbuf), 
0177                                 "%d:%s ",
0178                                 err,
0179                                 G_nstd_tls->M_nstd_error_msg_buf);
0180     }
0181     else
0182     {
0183         snprintf(G_nstd_tls->errbuf, sizeof(G_nstd_tls->errbuf), "%d:%s",
0184                             err, NSTD_ERROR_DESCRIPTION(err));
0185     }
0186 
0187     return G_nstd_tls->errbuf;
0188 }
0189 
0190 /**
0191  * ATMI standard
0192  * @return - pointer to int holding error code?
0193  */
0194 expublic int * _Nget_Nerror_addr (void)
0195 {
0196     NSTD_TLS_ENTRY;
0197     return &(G_nstd_tls->M_nstd_error);
0198 }
0199 
0200 /**
0201  * Internetal function for setting
0202  * @param error_code
0203  * @param msg
0204  * @return
0205  */
0206 expublic void _Nset_error(int error_code)
0207 {
0208     NSTD_TLS_ENTRY;
0209     if (!G_nstd_tls->M_nstd_error)
0210     {
0211 /*
0212         NDRX_LOG(log_warn, "_Nset_error: %d (%s)", 
0213                                 error_code, NSTD_ERROR_DESCRIPTION(error_code));
0214  */
0215         G_nstd_tls->M_nstd_error_msg_buf[0] = EXEOS;
0216         G_nstd_tls->M_nstd_error = error_code;
0217     }
0218 }
0219 
0220 /**
0221  * I nternetal function for setting
0222  * @param error_code
0223  * @param msg
0224  * @return
0225  */
0226 expublic void _Nset_error_msg(int error_code, char *msg)
0227 {
0228     int msg_len;
0229     int err_len;
0230     NSTD_TLS_ENTRY;
0231     
0232     if (!G_nstd_tls->M_nstd_error)
0233     {
0234         msg_len = strlen(msg);
0235         err_len = (msg_len>MAX_ERROR_LEN)?MAX_ERROR_LEN:msg_len;
0236 
0237         G_nstd_tls->M_nstd_error_msg_buf[0] = EXEOS;
0238         strncat(G_nstd_tls->M_nstd_error_msg_buf, msg, err_len);
0239         G_nstd_tls->M_nstd_error = error_code;
0240     }
0241 }
0242 
0243 /**
0244  * Advanced error setting function, uses format list
0245  * Use this only in case where it is really needed.
0246  * @param error_code - error code
0247  * @param fmt - format stirng
0248  * @param ... - format details
0249  */
0250 expublic void _Nset_error_fmt(int error_code, const char *fmt, ...)
0251 {
0252     char msg[MAX_ERROR_LEN+1] = {EXEOS};
0253     va_list ap;
0254     NSTD_TLS_ENTRY;
0255 
0256     if (!G_nstd_tls->M_nstd_error)
0257     {
0258         va_start(ap, fmt);
0259         (void) vsnprintf(msg, sizeof(msg), fmt, ap);
0260         va_end(ap);
0261 
0262         NDRX_STRCPY_SAFE(G_nstd_tls->M_nstd_error_msg_buf, msg);
0263         G_nstd_tls->M_nstd_error = error_code;
0264         
0265     }
0266 }
0267 
0268 /**
0269  * Unset any error data currently in use
0270  */
0271 expublic void _Nunset_error(void)
0272 {
0273     NSTD_TLS_ENTRY;
0274     G_nstd_tls->M_nstd_error_msg_buf[0]=EXEOS;
0275     G_nstd_tls->M_nstd_error = BMINVAL;
0276 }
0277 /**
0278  * Return >0 if error is set
0279  * @return 
0280  */
0281 expublic int _Nis_error(void)
0282 {
0283     NSTD_TLS_ENTRY;   
0284     return G_nstd_tls->M_nstd_error;
0285 }
0286 
0287 /**
0288  * Append error message
0289  * @param msg
0290  */
0291 expublic void _Nappend_error_msg(char *msg)
0292 {
0293     int free_space;
0294     int app_error_len = strlen(msg);
0295     int n;
0296     NSTD_TLS_ENTRY;
0297     
0298     free_space = MAX_ERROR_LEN-strlen(G_nstd_tls->M_nstd_error_msg_buf);
0299     n = free_space<app_error_len?free_space:app_error_len;
0300     strncat(G_nstd_tls->M_nstd_error_msg_buf, msg, n);
0301 }
0302 
0303 /* vim: set ts=4 sw=4 et smartindent: */