[RFC PATCH 2/2] Support user specified prefix feature.

Hao Xiang hao.xiang at linux.dev
Thu Jul 18 17:49:14 UTC 2024


The original implementation of svlogd from smarden.org supports
user specified prefix but is not yet in the busybox version.
This change implements this feature.

* User defined prefix cannot be longer than 60 characters.
* Prefix applies to both file target and UDP destination.
* Prefix is added to a UDP message via IOV to minimize buffer copy.

Signed-off-by: Hao Xiang <hao.xiang at linux.dev>
---
 runit/svlogd.c | 37 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 36 insertions(+), 1 deletion(-)

diff --git a/runit/svlogd.c b/runit/svlogd.c
index c808dfc42..19a74dec0 100644
--- a/runit/svlogd.c
+++ b/runit/svlogd.c
@@ -155,7 +155,7 @@ log message, you can use a pattern like this instead
 //usage:   "\n""!PROG - process rotated log with PROG"
 //usage:   "\n""uIPADDR - send log over UDP"
 ///////:   "\n""UIPADDR - send log over UDP and DONT log" - unsupported
-///////:   "\n""pPFX - prefix each line with PFX" - unsupported
+//usage:   "\n""pPFX - prefix each line with PFX"
 //usage:   "\n""+,-PATTERN - (de)select line for logging"
 //usage:   "\n""E,ePATTERN - (de)select line for stderr"
 
@@ -190,6 +190,8 @@ struct logdir {
 	char matcherr;
 	struct sockaddr_in udpaddr;
 	int udpfd;
+	char *prefix;
+	int len;
 	struct msghdr *msg;
 };
 
@@ -308,6 +310,14 @@ static char* wstrdup(const char *str)
 	return s;
 }
 
+static char* wstrndup(const char *str, size_t n)
+{
+	char *s;
+	while (!(s = strndup(str, n)))
+		pause_nomem();
+	return s;
+}
+
 static unsigned pmatch(const char *p, const char *s, unsigned len)
 {
 	for (;;) {
@@ -776,6 +786,10 @@ static void logdir_close(struct logdir *ld)
 	if (ld->msg != NULL)
 		free(ld->msg);
 	ld->msg = NULL;
+	if (ld->prefix)
+		free(ld->prefix);
+	ld->prefix = NULL;
+	ld->len = 0;
 }
 
 static struct msghdr *create_msg(struct sockaddr_in *udpaddr)
@@ -840,6 +854,8 @@ static NOINLINE unsigned logdir_open(struct logdir *ld, const char *fn)
 	ld->udpaddr.sin_family = AF_INET;
 	ld->udpaddr.sin_port = 0;
 	ld->msg = NULL;
+	ld->prefix = NULL;
+	ld->len = 0;
 	free(ld->inst); ld->inst = NULL;
 	free(ld->processor); ld->processor = NULL;
 
@@ -949,6 +965,19 @@ static NOINLINE unsigned logdir_open(struct logdir *ld, const char *fn)
 				 * accordingly */
 				memRchr = memchr;
 				break;
+			case 'p':
+				start = &s[1];
+				if (*start == '\0') {
+					warn("No prefix specified");
+					break;
+				}
+				ld->prefix = wstrndup(start, MAX_PREFIX_LEN);
+				ld->len = strlen(ld->prefix);
+				/* Prefix requires one-line buffering,
+				 * resetting the "find newline" function
+				 * accordingly */
+				memRchr = memchr;
+				break;
 			}
 			s = np;
 		}
@@ -1365,10 +1394,16 @@ int svlogd_main(int argc, char **argv)
 			if (ld->matcherr == 'e') {
 				/* runit-1.8.0 compat: if timestamping, do it on stderr too */
 				////full_write(STDERR_FILENO, printptr, printlen);
+				fwrite(ld->prefix, 1, ld->len, stderr);
 				fwrite(printptr, 1, printlen, stderr);
 			}
 			if (ld->match != '+')
 				continue;
+			/* Add user defined prefix to UDP message */
+			if (ld->udpfd != -1 && ld->len)
+				udp_add_buf(ld->msg, ld->prefix, ld->len);
+			if (ld->len)
+				buffer_pwrite(i, ld->prefix, ld->len);
 			buffer_pwrite(i, printptr, printlen);
 		}
 
-- 
2.45.2



More information about the busybox mailing list