diff options
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | src/cli_cstore.h | 1 | ||||
-rw-r--r-- | src/cstore/cstore.cpp | 114 | ||||
-rw-r--r-- | src/cstore/cstore.hpp | 35 |
4 files changed, 113 insertions, 38 deletions
diff --git a/Makefile.am b/Makefile.am index bc4bb78..a932d5e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -30,6 +30,7 @@ src_libvyatta_cfg_la_LIBADD += /usr/lib/libgio-2.0.la src_libvyatta_cfg_la_LIBADD += -lboost_system src_libvyatta_cfg_la_LIBADD += -lboost_filesystem src_libvyatta_cfg_la_LIBADD += -lapt-pkg +src_libvyatta_cfg_la_LIBADD += -lperl src_libvyatta_cfg_la_LDFLAGS = -version-info 1:0:0 src_libvyatta_cfg_la_SOURCES = src/cli_parse.y src/cli_def.l src/cli_val.l src_libvyatta_cfg_la_SOURCES += src/cli_new.c src/cli_path_utils.c diff --git a/src/cli_cstore.h b/src/cli_cstore.h index c03bddf..54da657 100644 --- a/src/cli_cstore.h +++ b/src/cli_cstore.h @@ -116,6 +116,7 @@ typedef struct { /* extern variables */ extern void *var_ref_handle; extern FILE *out_stream; +extern FILE *err_stream; /* note that some functions may be used outside the actual CLI operations, * so output may not have been initialized. nop in such cases. diff --git a/src/cstore/cstore.cpp b/src/cstore/cstore.cpp index 0ff8ba2..2aefed6 100644 --- a/src/cstore/cstore.cpp +++ b/src/cstore/cstore.cpp @@ -1929,11 +1929,16 @@ Cstore::output_user(const char *fmt, ...) { va_list alist; va_start(alist, fmt); - if (out_stream) { - vfprintf(out_stream, fmt, alist); - } else { - vprintf(fmt, alist); - } + voutput_user(out_stream, stdout, fmt, alist); + va_end(alist); +} + +void +Cstore::output_user_err(const char *fmt, ...) +{ + va_list alist; + va_start(alist, fmt); + voutput_user(err_stream, stderr, fmt, alist); va_end(alist); } @@ -1942,29 +1947,30 @@ Cstore::output_internal(const char *fmt, ...) { va_list alist; va_start(alist, fmt); + voutput_internal(fmt, alist); + va_end(alist); +} - int fdout = -1; - FILE *fout = NULL; - do { - if ((fdout = open(C_LOGFILE_STDOUT.c_str(), - O_WRONLY | O_CREAT, 0660)) == -1) { - break; - } - if (lseek(fdout, 0, SEEK_END) == ((off_t) -1)) { - break; - } - if ((fout = fdopen(fdout, "a")) == NULL) { - break; - } - vfprintf(fout, fmt, alist); - } while (0); +void +Cstore::exit_internal(const char *fmt, ...) +{ + va_list alist; + va_start(alist, fmt); + vexit_internal(fmt, alist); va_end(alist); - if (fout) { - fclose(fout); - // fdout is implicitly closed - } else if (fdout >= 0) { - close(fdout); +} + +void +Cstore::assert_internal(bool cond, const char *fmt, ...) +{ + if (cond) { + return; } + + va_list alist; + va_start(alist, fmt); + vexit_internal(fmt, alist); + va_end(alist); } @@ -2872,3 +2878,61 @@ Cstore::print_str_vec(const char *pre, const char *post, output_user("%s", post); } +void +Cstore::voutput_user(FILE *out, FILE *dout, const char *fmt, va_list alist) +{ + if (out) { + vfprintf(out, fmt, alist); + } else if (dout) { + vfprintf(dout, fmt, alist); + } else { + vprintf(fmt, alist); + } +} + +void +Cstore::voutput_internal(const char *fmt, va_list alist) +{ + int fdout = -1; + FILE *fout = NULL; + do { + if ((fdout = open(C_LOGFILE_STDOUT.c_str(), + O_WRONLY | O_CREAT, 0660)) == -1) { + break; + } + if (lseek(fdout, 0, SEEK_END) == ((off_t) -1)) { + break; + } + if ((fout = fdopen(fdout, "a")) == NULL) { + break; + } + vfprintf(fout, fmt, alist); + } while (0); + if (fout) { + fclose(fout); + // fdout is implicitly closed + } else if (fdout >= 0) { + close(fdout); + } +} + +void +Cstore::vexit_internal(const char *fmt, va_list alist) +{ + char buf[256]; + vsnprintf(buf, 256, fmt, alist); + output_internal("%s\n", buf); + if (Perl_get_context()) { + /* we're in a perl context. do a croak to provide more information. + * note that the message should not end in "\n", or the croak message + * will be truncated for some reason. + */ + Perl_croak_nocontext("%s", buf); + // does not return + } else { + // output error message and exit + output_user_err("%s\n", buf); + exit(1); + } +} + diff --git a/src/cstore/cstore.hpp b/src/cstore/cstore.hpp index 872fe1e..9a039af 100644 --- a/src/cstore/cstore.hpp +++ b/src/cstore/cstore.hpp @@ -16,26 +16,27 @@ #ifndef _CSTORE_H_ #define _CSTORE_H_ +#include <cstdarg> #include <vector> #include <string> #include <tr1/unordered_map> #include <cli_cstore.h> -#define exit_internal(fmt, args...) do \ - { \ - output_internal("[%s:%d] " fmt, __FILE__, __LINE__ , ##args); \ - exit(-1); \ - } while (0); +/* declare perl internal functions. just need these two so don't include + * all the perl headers. + */ +extern "C" void Perl_croak_nocontext(const char* pat, ...) + __attribute__((noreturn)) + __attribute__((format(__printf__,1,2))) + __attribute__((nonnull(1))); + +extern "C" void* Perl_get_context(void) + __attribute__((warn_unused_result)); -#define ASSERT_IN_SESSION do \ - { \ - if (!inSession()) { \ - output_user("Internal error: calling %s() without config session\n", \ - __func__); \ - exit_internal("calling %s() without config session\n", __func__); \ - } \ - } while (0); +#define ASSERT_IN_SESSION assert_internal(inSession(), \ + "calling %s() without config session", \ + __func__); /* macros for saving/restoring paths. @@ -300,7 +301,10 @@ public: protected: ////// functions for subclasses void output_user(const char *fmt, ...); + void output_user_err(const char *fmt, ...); void output_internal(const char *fmt, ...); + void exit_internal(const char *fmt, ...); + void assert_internal(bool cond, const char *fmt, ...); private: ////// member class @@ -480,6 +484,11 @@ private: void shell_escape_squotes(string& str); void print_str_vec(const char *pre, const char *post, const vector<string>& vec, const char *quote); + + // output functions + void voutput_user(FILE *out, FILE *dout, const char *fmt, va_list alist); + void voutput_internal(const char *fmt, va_list alist); + void vexit_internal(const char *fmt, va_list alist); }; #endif /* _CSTORE_H_ */ |