Posted to tcl by guest4 at Thu Nov 11 08:19:30 GMT 2021view raw
- ################################################################################
- # 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!