-
Notifications
You must be signed in to change notification settings - Fork 285
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fe_test: add test for syslog feature
The syslog feature allows to run a program and redirect its output/error stream to system log. It's triggered passing "syslog_stdout" argument to "Forkhelpers" functions like "execute_command_get_output". To test this feature use a small preload library to redirect syslog writing. This allows to test program without changing it. The log is redirected to /tmp/xyz instead of /dev/log. The name was chosen to allow for future static build redirection. The C program is used only for the test, so the code style take into account this (specifically it does not try to handle all redirect situation and all error paths). Signed-off-by: Frediano Ziglio <[email protected]>
- Loading branch information
Showing
4 changed files
with
207 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,18 @@ | ||
(executable | ||
(modes exe) | ||
(name fe_test) | ||
(libraries forkexec uuid xapi-stdext-unix fd-send-recv)) | ||
(libraries forkexec uuid xapi-stdext-unix fd-send-recv xapi-log)) | ||
|
||
; preload library to redirect "/dev/log" | ||
(rule | ||
(targets syslog.so) | ||
(deps syslog.c) | ||
(action | ||
(run %{cc} -O2 -Wall -DPIC -fPIC -s --shared -o %{targets} %{deps} -ldl))) | ||
|
||
(rule | ||
(alias runtest) | ||
(package xapi-forkexecd) | ||
(deps fe_test.sh fe_test.exe ../src/fe_main.exe) | ||
(deps fe_test.sh fe_test.exe ../src/fe_main.exe syslog.so) | ||
(action | ||
(run ./fe_test.sh))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
#define _GNU_SOURCE | ||
#define _DEFAULT_SOURCE | ||
#include <stdarg.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <stdbool.h> | ||
#include <time.h> | ||
#include <alloca.h> | ||
#include <unistd.h> | ||
#include <dlfcn.h> | ||
#include <syslog.h> | ||
#include <sys/types.h> | ||
#include <sys/socket.h> | ||
#include <sys/un.h> | ||
|
||
#define START(name) \ | ||
static typeof(name) *old_func = NULL; \ | ||
if (!old_func) \ | ||
old_func = (typeof(name) *) dlsym(RTLD_NEXT, #name); | ||
|
||
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) | ||
{ | ||
static const char dev_log[] = "/dev/log"; | ||
START(connect); | ||
|
||
struct sockaddr_un *un = (struct sockaddr_un *) addr; | ||
if (!addr || addr->sa_family != AF_UNIX | ||
|| memcmp(un->sun_path, dev_log, sizeof(dev_log)) != 0) | ||
return old_func(sockfd, addr, addrlen); | ||
|
||
struct sockaddr_un new_addr; | ||
new_addr.sun_family = AF_UNIX; | ||
strcpy(new_addr.sun_path, "/tmp/xyz"); | ||
return old_func(sockfd, (struct sockaddr *) &new_addr, sizeof(new_addr)); | ||
} | ||
|
||
static const char *month_name(int month) | ||
{ | ||
static const char names[12][4] = { | ||
"Jan", | ||
"Feb", | ||
"Mar", | ||
"Apr", | ||
"May", | ||
"Jun", | ||
"Jul", | ||
"Aug", | ||
"Sep", | ||
"Oct", | ||
"Nov", | ||
"Dec", | ||
}; | ||
if (month >= 0 && month < 12) | ||
return names[month]; | ||
|
||
return "Xxx"; | ||
} | ||
|
||
static void vsyslog_internal(int priority, const char *format, va_list ap) | ||
{ | ||
// format is "<13>Jul 9 07:19:01 hostname: message" | ||
time_t now = time(NULL); | ||
struct tm tm, *p; | ||
p = gmtime_r(&now, &tm); | ||
|
||
if (LOG_FAC(priority) == 0) | ||
priority |= LOG_USER; | ||
|
||
char buffer[1024]; | ||
char *buf = buffer; | ||
const int prefix_len = sprintf(buffer, "<%d> %s % 2d %02d:%02d:%02d %s: ", priority, month_name(p->tm_mon), | ||
p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec, "dummy"); | ||
|
||
int left = (int) sizeof(buffer) - prefix_len; | ||
int l = vsnprintf(buffer + prefix_len, left, format, ap); | ||
if (l >= left) { | ||
buf = malloc(prefix_len + l + 1); | ||
if (!buf) | ||
return; | ||
memcpy(buf, buffer, prefix_len); | ||
l = vsnprintf(buf + prefix_len, l + 1, format, ap); | ||
} | ||
|
||
int sock = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0); | ||
if (sock >= 0) { | ||
struct sockaddr_un addr; | ||
addr.sun_family = AF_UNIX; | ||
strcpy(addr.sun_path, "/tmp/xyz"); | ||
sendto(sock, buf, prefix_len + l, MSG_NOSIGNAL, &addr, sizeof(addr)); | ||
|
||
close(sock); | ||
} | ||
if (buf != buffer) | ||
free(buf); | ||
} | ||
|
||
void syslog(int priority, const char *format, ...) | ||
{ | ||
va_list ap; | ||
va_start(ap, format); | ||
vsyslog_internal(priority, format, ap); | ||
va_end(ap); | ||
} | ||
|
||
void vsyslog(int priority, const char *format, va_list ap) | ||
{ | ||
vsyslog_internal(priority, format, ap); | ||
} | ||
|
||
void __syslog_chk(int priority, int flags, const char *format, ...) | ||
{ | ||
va_list ap; | ||
va_start(ap, format); | ||
vsyslog_internal(priority, format, ap); | ||
va_end(ap); | ||
} | ||
|
||
void __vsyslog_chk(int priority, int flags, const char *format, va_list ap) | ||
{ | ||
vsyslog_internal(priority, format, ap); | ||
} |