added remote syslogging to sys::openlog(), sys::writelog(), sys::closelog()
This commit is contained in:
		| @ -52,14 +52,35 @@ | ||||
|  | ||||
| #	define ENABLE_SYSLOG | ||||
| #	include <syslog.h> | ||||
|  | ||||
| #	include <sys/socket.h> | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #include <stdlib.h> /* getenv, system */ | ||||
| #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 | ||||
| { | ||||
| 	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; | ||||
|  | ||||
| @ -884,12 +905,14 @@ static int fnc_openlog (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi) | ||||
| 	int rx = -1; | ||||
| 	qse_awk_int_t opt, fac; | ||||
| 	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_mchar_t* mbs_ident; | ||||
| 	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); | ||||
| 	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, 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) | ||||
| 	mbs_ident = qse_mbsdup(ident, qse_awk_rtx_getmmgr(rtx)); | ||||
| 	mbs_ident = qse_mbsdup(actual_ident, qse_awk_rtx_getmmgr(rtx)); | ||||
| #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 | ||||
| 	if (!mbs_ident) goto done; | ||||
|  | ||||
| 	if (mctx->log_ident) qse_awk_rtx_freemem (rtx, mctx->log_ident); | ||||
| 	mctx->log_ident = mbs_ident; | ||||
| 	if (mctx->log.ident) qse_awk_rtx_freemem (rtx, mctx->log.ident); | ||||
| 	mctx->log.ident = mbs_ident; | ||||
|  | ||||
| 	openlog(mbs_ident, opt, fac); | ||||
| 	rx = 0; | ||||
| #if defined(ENABLE_SYSLOG) | ||||
| 	if (mctx->log.syslog_opened) | ||||
| 	{ | ||||
| 		closelog (); | ||||
| 		mctx->log.syslog_opened = 0; | ||||
| 	} | ||||
| #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: | ||||
| 	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; | ||||
| 	mod_ctx_t* mctx = fi->mod->ctx; | ||||
|  | ||||
| #if defined(ENABLE_SYSLOG) | ||||
| 	if (mctx->log_ident) | ||||
| 	if (mctx->log.type == SYSLOG_LOCAL) | ||||
| 	{ | ||||
| 		qse_awk_rtx_freemem (rtx, mctx->log_ident); | ||||
| 		mctx->log_ident = QSE_NULL; | ||||
| 	} | ||||
| 	#if defined(ENABLE_SYSLOG) | ||||
| 		closelog (); | ||||
| 	rx = 0; | ||||
| 		// 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; | ||||
|  | ||||
| 	retv = qse_awk_rtx_makeintval(rtx, rx); | ||||
| 	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_char_t* msg = QSE_NULL; | ||||
| 	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; | ||||
|  | ||||
| 	msg = qse_awk_rtx_getvalstr(rtx, qse_awk_rtx_getarg(rtx, 1), &msglen); | ||||
| 	if (!msg) 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) | ||||
| 		syslog(pri, "%s", msg); | ||||
| 		#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); | ||||
| 		} | ||||
| 		#endif | ||||
| 	rx = 0; | ||||
| 	#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; | ||||
|  | ||||
| done: | ||||
| 	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) | ||||
| { | ||||
| 	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; | ||||
| } | ||||
|  | ||||
| @ -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) 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) | ||||
| { | ||||
| 	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) | ||||
|  | ||||
| @ -624,7 +624,7 @@ void qse_log_reportv (qse_log_t* log, const qse_char_t* ident, int pri, const qs | ||||
|  | ||||
| 		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; | ||||
| 		} | ||||
| 		else | ||||
|  | ||||
		Reference in New Issue
	
	Block a user