added remote syslogging to sys::openlog(), sys::writelog(), sys::closelog()

This commit is contained in:
hyung-hwan 2019-01-22 09:41:00 +00:00
parent 39e43d4201
commit 7fb03044e8
2 changed files with 252 additions and 30 deletions

View File

@ -52,14 +52,35 @@
# define ENABLE_SYSLOG # define ENABLE_SYSLOG
# include <syslog.h> # include <syslog.h>
# include <sys/socket.h>
#endif #endif
#include <stdlib.h> /* getenv, system */ #include <stdlib.h> /* getenv, system */
#include <time.h> #include <time.h>
#include <qse/si/sio.h>
typedef enum syslog_type_t syslog_type_t;
enum syslog_type_t
{
SYSLOG_LOCAL,
SYSLOG_REMOTE
};
struct mod_ctx_t struct mod_ctx_t
{ {
char* log_ident; struct
{
syslog_type_t type;
char* ident;
qse_skad_t skad;
int syslog_opened; // has openlog() been called?
int opt;
int fac;
int sck;
qse_mbs_t* dmsgbuf;
} log;
}; };
typedef struct mod_ctx_t mod_ctx_t; typedef struct mod_ctx_t mod_ctx_t;
@ -884,12 +905,14 @@ static int fnc_openlog (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
int rx = -1; int rx = -1;
qse_awk_int_t opt, fac; qse_awk_int_t opt, fac;
qse_awk_val_t* retv; qse_awk_val_t* retv;
qse_char_t* ident = QSE_NULL; qse_char_t* ident = QSE_NULL, * actual_ident;
qse_size_t ident_len; qse_size_t ident_len;
qse_mchar_t* mbs_ident; qse_mchar_t* mbs_ident;
mod_ctx_t* mctx = fi->mod->ctx; mod_ctx_t* mctx = fi->mod->ctx;
qse_nwad_t nwad;
syslog_type_t log_type = SYSLOG_LOCAL;
#if defined(ENABLE_SYSLOG)
ident = qse_awk_rtx_getvalstr(rtx, qse_awk_rtx_getarg(rtx, 0), &ident_len); ident = qse_awk_rtx_getvalstr(rtx, qse_awk_rtx_getarg(rtx, 0), &ident_len);
if (!ident) goto done; if (!ident) goto done;
@ -900,19 +923,69 @@ static int fnc_openlog (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
if (qse_awk_rtx_valtoint(rtx, qse_awk_rtx_getarg(rtx, 1), &opt) <= -1) goto done; if (qse_awk_rtx_valtoint(rtx, qse_awk_rtx_getarg(rtx, 1), &opt) <= -1) goto done;
if (qse_awk_rtx_valtoint(rtx, qse_awk_rtx_getarg(rtx, 2), &fac) <= -1) goto done; if (qse_awk_rtx_valtoint(rtx, qse_awk_rtx_getarg(rtx, 2), &fac) <= -1) goto done;
if (qse_strbeg(ident, QSE_T("remote://")))
{
qse_char_t* slash;
/* "udp://remote-addr:remote-port/syslog-identifier" */
log_type = SYSLOG_REMOTE;
actual_ident = ident + 9;
slash = qse_strchr(actual_ident, QSE_T('/'));
if (!slash) goto done;
if (qse_strntonwad(actual_ident, slash - actual_ident, &nwad) <= -1) goto done;
actual_ident = slash + 1;
}
else if (qse_strbeg(ident, QSE_T("local://")))
{
/* "local://syslog-identifier" */
actual_ident = ident + 8;
}
else
{
actual_ident = ident;
}
#if defined(QSE_CHAR_IS_MCHAR) #if defined(QSE_CHAR_IS_MCHAR)
mbs_ident = qse_mbsdup(ident, qse_awk_rtx_getmmgr(rtx)); mbs_ident = qse_mbsdup(actual_ident, qse_awk_rtx_getmmgr(rtx));
#else #else
mbs_ident = qse_wcstombsdup(ident, QSE_NULL, qse_awk_rtx_getmmgr(rtx)); mbs_ident = qse_wcstombsdup(actual_ident, QSE_NULL, qse_awk_rtx_getmmgr(rtx));
#endif #endif
if (!mbs_ident) goto done; if (!mbs_ident) goto done;
if (mctx->log_ident) qse_awk_rtx_freemem (rtx, mctx->log_ident); if (mctx->log.ident) qse_awk_rtx_freemem (rtx, mctx->log.ident);
mctx->log_ident = mbs_ident; mctx->log.ident = mbs_ident;
openlog(mbs_ident, opt, fac); #if defined(ENABLE_SYSLOG)
rx = 0; if (mctx->log.syslog_opened)
{
closelog ();
mctx->log.syslog_opened = 0;
}
#endif #endif
if (mctx->log.sck >= 0)
{
close (mctx->log.sck);
mctx->log.sck = -1;
}
mctx->log.type = log_type;
mctx->log.opt = opt;
mctx->log.fac = fac;
if (mctx->log.type == SYSLOG_LOCAL)
{
#if defined(ENABLE_SYSLOG)
openlog(mbs_ident, opt, fac);
mctx->log.syslog_opened = 1;
#endif
}
else if (mctx->log.type == SYSLOG_REMOTE)
{
qse_nwadtoskad (&nwad, &mctx->log.skad);
/* TODO: open socket? */
}
rx = 0;
done: done:
if (ident) qse_awk_rtx_freevalstr(rtx, qse_awk_rtx_getarg(rtx, 0), ident); if (ident) qse_awk_rtx_freevalstr(rtx, qse_awk_rtx_getarg(rtx, 0), ident);
@ -930,15 +1003,39 @@ static int fnc_closelog (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
qse_awk_val_t* retv; qse_awk_val_t* retv;
mod_ctx_t* mctx = fi->mod->ctx; mod_ctx_t* mctx = fi->mod->ctx;
#if defined(ENABLE_SYSLOG) if (mctx->log.type == SYSLOG_LOCAL)
if (mctx->log_ident)
{ {
qse_awk_rtx_freemem (rtx, mctx->log_ident); #if defined(ENABLE_SYSLOG)
mctx->log_ident = QSE_NULL;
}
closelog (); closelog ();
// closelog() might be called without openlog(). so there is no
// check if syslog_opened is true.
// it is just used as an indicator to decide wheter closelog()
// upon module finalization(fini).
mctx->log.syslog_opened = 0;
#endif
}
else if (mctx->log.type == SYSLOG_REMOTE)
{
if (mctx->log.sck >= 0)
{
close (mctx->log.sck);
mctx->log.sck = -1;
}
if (mctx->log.dmsgbuf)
{
qse_mbs_close (mctx->log.dmsgbuf);
mctx->log.dmsgbuf = QSE_NULL;
}
}
if (mctx->log.ident)
{
qse_awk_rtx_freemem (rtx, mctx->log.ident);
mctx->log.ident = QSE_NULL;
}
rx = 0; rx = 0;
#endif
retv = qse_awk_rtx_makeintval(rtx, rx); retv = qse_awk_rtx_makeintval(rtx, rx);
if (retv == QSE_NULL) return -1; if (retv == QSE_NULL) return -1;
@ -954,14 +1051,18 @@ static int fnc_writelog (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
qse_awk_int_t pri; qse_awk_int_t pri;
qse_char_t* msg = QSE_NULL; qse_char_t* msg = QSE_NULL;
qse_size_t msglen; qse_size_t msglen;
mod_ctx_t* mctx = fi->mod->ctx;
#if defined(ENABLE_SYSLOG)
if (qse_awk_rtx_valtoint(rtx, qse_awk_rtx_getarg(rtx, 0), &pri) <= -1) goto done; if (qse_awk_rtx_valtoint(rtx, qse_awk_rtx_getarg(rtx, 0), &pri) <= -1) goto done;
msg = qse_awk_rtx_getvalstr(rtx, qse_awk_rtx_getarg(rtx, 1), &msglen); msg = qse_awk_rtx_getvalstr(rtx, qse_awk_rtx_getarg(rtx, 1), &msglen);
if (!msg) goto done; if (!msg) goto done;
if (qse_strxchr(msg, msglen, QSE_T('\0'))) goto done; if (qse_strxchr(msg, msglen, QSE_T('\0'))) goto done;
if (mctx->log.type == SYSLOG_LOCAL)
{
#if defined(ENABLE_SYSLOG)
#if defined(QSE_CHAR_IS_MCHAR) #if defined(QSE_CHAR_IS_MCHAR)
syslog(pri, "%s", msg); syslog(pri, "%s", msg);
#else #else
@ -973,8 +1074,91 @@ static int fnc_writelog (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
qse_awk_rtx_freemem (rtx, mbs); qse_awk_rtx_freemem (rtx, mbs);
} }
#endif #endif
#endif
}
else if (mctx->log.type == SYSLOG_REMOTE)
{
#if defined(_WIN32)
/* TODO: implement this */
#else
qse_ntime_t now;
qse_btime_t cnow;
static const qse_mchar_t* __syslog_month_names[] =
{
QSE_MT("Jan"),
QSE_MT("Feb"),
QSE_MT("Mar"),
QSE_MT("Apr"),
QSE_MT("May"),
QSE_MT("Jun"),
QSE_MT("Jul"),
QSE_MT("Aug"),
QSE_MT("Sep"),
QSE_MT("Oct"),
QSE_MT("Nov"),
QSE_MT("Dec"),
};
if (mctx->log.sck <= -1)
{
#if defined(SOCK_CLOEXECX)
mctx->log.sck = socket (qse_skadfamily(&mctx->log.skad), SOCK_DGRAM | SOCK_CLOEXEC, 0);
#else
mctx->log.sck = socket (qse_skadfamily(&mctx->log.skad), SOCK_DGRAM, 0);
#if defined(FD_CLOEXEC)
if (mctx->log.sck >= 0)
{
int flag = fcntl (mctx->log.sck, F_GETFD);
if (flag >= 0) fcntl (mctx->log.sck, F_SETFD, flag | FD_CLOEXEC);
}
#endif
#endif
}
if (mctx->log.sck >= 0)
{
///////////////////////////
if (!mctx->log.dmsgbuf) mctx->log.dmsgbuf = qse_mbs_open(qse_awk_rtx_getmmgr(rtx), 0, 0);
if (!mctx->log.dmsgbuf) goto done;
if (qse_gettime(&now) || qse_localtime(&now, &cnow) <= -1) goto done;
if (qse_mbs_fmt (
mctx->log.dmsgbuf, QSE_MT("<%d>%s %02d %02d:%02d:%02d "),
(int)(mctx->log.fac | pri),
__syslog_month_names[cnow.mon], cnow.mday,
cnow.hour, cnow.min, cnow.sec) == (qse_size_t)-1) goto done;
if (mctx->log.ident || (mctx->log.opt & LOG_PID))
{
/* if the identifier is set or LOG_PID is set, the produced tag won't be empty.
* so appending ':' is kind of ok */
if (qse_mbs_fcat(mctx->log.dmsgbuf, QSE_MT("%hs"), (mctx->log.ident? mctx->log.ident: QSE_MT(""))) == (qse_size_t)-1) goto done;
if (mctx->log.opt & LOG_PID)
{
if (qse_mbs_fcat(mctx->log.dmsgbuf, QSE_MT("[%d]"), (int)QSE_GETPID()) == (qse_size_t)-1) goto done;
}
if (qse_mbs_fcat(mctx->log.dmsgbuf, QSE_MT(": ")) == (qse_size_t)-1) goto done;
}
#if defined(QSE_CHAR_IS_MCHAR)
if (qse_mbs_fcat(mctx->log.dmsgbuf, QSE_MT("%hs"), msg) == (qse_size_t)-1) goto done;
#else
if (qse_mbs_fcat(mctx->log.dmsgbuf, QSE_MT("%ls"), msg) == (qse_size_t)-1) goto done;
#endif
/* don't care about output failure */
sendto (mctx->log.sck, QSE_MBS_PTR(mctx->log.dmsgbuf), QSE_MBS_LEN(mctx->log.dmsgbuf),
0, (struct sockaddr*)&mctx->log.skad, qse_skadsize(&mctx->log.skad));
}
#endif
}
rx = 0; rx = 0;
#endif
done: done:
if (msg) qse_awk_rtx_freevalstr(rtx, qse_awk_rtx_getarg(rtx, 1), msg); if (msg) qse_awk_rtx_freevalstr(rtx, qse_awk_rtx_getarg(rtx, 1), msg);
@ -1160,6 +1344,10 @@ static int query (qse_awk_mod_t* mod, qse_awk_t* awk, const qse_char_t* name, qs
static int init (qse_awk_mod_t* mod, qse_awk_rtx_t* rtx) static int init (qse_awk_mod_t* mod, qse_awk_rtx_t* rtx)
{ {
mod_ctx_t* mctx = (mod_ctx_t*)mod->ctx;
mctx->log.type = SYSLOG_LOCAL;
mctx->log.syslog_opened = 0;
mctx->log.sck = -1;
return 0; return 0;
} }
@ -1169,11 +1357,45 @@ static void fini (qse_awk_mod_t* mod, qse_awk_rtx_t* rtx)
for (each pid for rtx) kill (pid, SIGKILL); for (each pid for rtx) kill (pid, SIGKILL);
for (each pid for rtx) waitpid (pid, QSE_NULL, 0); for (each pid for rtx) waitpid (pid, QSE_NULL, 0);
*/ */
mod_ctx_t* mctx = (mod_ctx_t*)mod->ctx;
#if defined(ENABLE_SYSLOG)
if (mctx->log.syslog_opened)
{
/* closelog() only if openlog() has been called explicitly */
closelog ();
mctx->log.syslog_opened = 0;
}
#endif
if (mctx->log.sck >= 0)
{
#if defined(_WIN32)
/* TODO: implement this */
#else
close (mctx->log.sck);
#endif
mctx->log.sck = -1;
}
if (mctx->log.dmsgbuf)
{
qse_mbs_close (mctx->log.dmsgbuf);
mctx->log.dmsgbuf = QSE_NULL;
}
if (mctx->log.ident)
{
qse_awk_rtx_freemem (rtx, mctx->log.ident);
mctx->log.ident = QSE_NULL;
}
} }
static void unload (qse_awk_mod_t* mod, qse_awk_t* awk) static void unload (qse_awk_mod_t* mod, qse_awk_t* awk)
{ {
qse_awk_freemem (awk, mod->ctx); mod_ctx_t* mctx = (mod_ctx_t*)mod->ctx;
qse_awk_freemem (awk, mctx);
} }
int qse_awk_mod_sys (qse_awk_mod_t* mod, qse_awk_t* awk) int qse_awk_mod_sys (qse_awk_mod_t* mod, qse_awk_t* awk)

View File

@ -624,7 +624,7 @@ void qse_log_reportv (qse_log_t* log, const qse_char_t* ident, int pri, const qs
if (id_out) if (id_out)
{ {
fpdilen = qse_mbs_fcat (log->dmsgbuf, QSE_MT(": "), log->ident); fpdilen = qse_mbs_fcat (log->dmsgbuf, QSE_MT(": "));
if (fpdilen == (qse_size_t)-1) goto done; if (fpdilen == (qse_size_t)-1) goto done;
} }
else else