added remote syslogging to sys::openlog(), sys::writelog(), sys::closelog()
This commit is contained in:
		| @ -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) | ||||||
|  | |||||||
| @ -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 | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user