Posted to tcl by guest4 at Thu Nov 11 08:19:30 GMT 2021view pretty
################################################################################
# Tcl extension
// redirecttcl.c: redirect stdout to systemd journal.
#include <sys/types.h>
#include <assert.h>
#include <err.h>
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define SD_JOURNAL_SUPPRESS_LOCATION
#include <systemd/sd-journal.h>
#include <tcl.h>
//----------------------------------------------------------------------
#ifndef UNUSED
# define UNUSED(x) (void)(x)
#endif
#if !defined(INT2PTR)
# define INT2PTR(p) ((void*)(intptr_t)(p))
#endif
static int RedirectCmd(ClientData clientData, Tcl_Interp* interp, int objc, Tcl_Obj* const objv[]) {
UNUSED(clientData);
UNUSED(objc);
UNUSED(objv);
int fd = sd_journal_stream_fd("STDOUT-REDIRECTED", LOG_NOTICE, 0);
fprintf(stderr, "-- %s: fd=%d\n", __func__, fd);
fprintf(stderr, "-- %s: isatty=%d\n", __func__, isatty(fd));
if (fd < 0) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf("failed to get journal fd: %s", Tcl_PosixError(interp)));
return TCL_ERROR;
}
Tcl_Channel chan = Tcl_MakeFileChannel(INT2PTR(fd), TCL_WRITABLE);
Tcl_SetStdChannel(chan, TCL_STDOUT);
Tcl_RegisterChannel(0, chan);
if (1) {
int rc = Tcl_SetChannelOption(0, chan, "-buffering", "none");
fprintf(stderr, "-- %s: Tcl_SetChannelOption -buffering none=%d\n", __func__, rc);
Tcl_SetChannelOption(0, chan, "-translation", "auto crlf");
fprintf(stderr, "-- %s: Tcl_SetChannelOption -translation auto crlf=%d\n", __func__, rc);
}
return TCL_OK;
}
DLLEXPORT int Redirecttcl_Init(Tcl_Interp * interp) {
if (!Tcl_InitStubs(interp, "8.6", 0))
return TCL_ERROR;
Tcl_CreateObjCommand(interp, "redirect", RedirectCmd, 0, NULL);
if (Tcl_PkgProvide(interp, "redirect", "0.1") != TCL_OK)
return TCL_ERROR;
return TCL_OK;
}
################################################################################
# Tcl driver:
puts PID=[pid]
puts ""
proc demo {} {
for {set i 0} {$i < 10} {incr i} {
puts "round $i"
after 1000
}
}
try {
load redirecttcl.so
puts "CHANNELS BEFORE: [chan names]"
redirect
puts "CHANNELS AFTER: [chan names]"
demo
} on ok {} {
puts "DONE!"
} on error {err opt} {
catch {puts stderr "ERROR: $err"}
catch {puts stderr "OPTIONS: $opt"}
}
################################################################################
# output:
PID=2717
CHANNELS BEFORE: stdin stdout stderr
-- RedirectCmd: fd=3
-- RedirectCmd: isatty=0
-- RedirectCmd: Tcl_SetChannelOption -buffering none=0
-- RedirectCmd: Tcl_SetChannelOption -translation auto crlf=0
CHANNELS AFTER: stdin file1 stderr stdout
round 0
round 1
round 2
round 3
round 4
round 5
round 6
round 7
round 8
round 9
DONE!