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!