diff --git a/.github/workflows/linux-tcl8-build.yml b/.github/workflows/linux-tcl8-build.yml new file mode 100644 index 0000000..4e4d141 --- /dev/null +++ b/.github/workflows/linux-tcl8-build.yml @@ -0,0 +1,34 @@ +# This is a basic workflow to help you get started with Actions + +name: Linux tcl8 build and install + +# Controls when the action will run. +on: + # Triggers the workflow on push or pull request events but only for the master branch + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-26.04 + + steps: + - uses: actions/checkout@v4 + - name: Install dependencies + run: | + sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test + sudo apt-get update -qq + sudo apt-get install -y gcc-11 g++-11 + sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-11 110 --slave /usr/bin/g++ g++ /usr/bin/g++-11 + sudo apt-get install -y tcl8.6-dev tclx8.4-dev + - name: configure + run: | + autoreconf -vi + ./configure --with-tcl=/usr/lib/tcl8.6 + - name: make + run: make + - name: install + run: sudo make install diff --git a/.github/workflows/linux-tcl9-build.yml b/.github/workflows/linux-tcl9-build.yml new file mode 100644 index 0000000..f4531c3 --- /dev/null +++ b/.github/workflows/linux-tcl9-build.yml @@ -0,0 +1,34 @@ +# This is a basic workflow to help you get started with Actions + +name: Linux tcl9 build and install + +# Controls when the action will run. +on: + # Triggers the workflow on push or pull request events but only for the master branch + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-26.04 + + steps: + - uses: actions/checkout@v4 + - name: Install dependencies + run: | + sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test + sudo apt-get update -qq + sudo apt-get install -y gcc-11 g++-11 + sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-11 110 --slave /usr/bin/g++ g++ /usr/bin/g++-11 + sudo apt-get install -y tcl9.0-dev tclx8.4-dev + - name: configure + run: | + autoreconf -vi + ./configure --with-tcl=/usr/lib/tcl9.0 + - name: make + run: make + - name: install + run: sudo make install diff --git a/generic/socketserver.c b/generic/socketserver.c index 9a53bb6..27bc859 100644 --- a/generic/socketserver.c +++ b/generic/socketserver.c @@ -35,6 +35,22 @@ TCL_DECLARE_MUTEX(threadMutex); +#define ERRBUFSIZE 512 +static char errbuf[ERRBUFSIZE]; + +// There are two incompatible versions of strerror_r +#ifdef __USE_XOPEN2K +#ifndef _GNU_SOURCE +#define STRERROR_R_POSIX +#endif +#endif + +#ifdef STRERROR_R_POSIX +#define strerror_r_default(e,b,l,d) (strerror_r(e,b,l) ? (d) : b) +#else +#define strerror_r_default(e,b,l) strerror_r(e,b,l) +#endif + /* * Send and fd over sock with SCM_RIGHTS. * @@ -190,7 +206,7 @@ static void * socketserver_thread(void *args) socket_desc = socket(AF_INET , SOCK_STREAM , 0); if (socket_desc == -1) { - fatal("Could not create socket"); + fatal(strerror_r_default(errno, errbuf, ERRBUFSIZE, "could not create socket")); return (void *)1; } debug("Socket created"); @@ -204,7 +220,7 @@ static void * socketserver_thread(void *args) server.sin_port = htons( targs->port ); if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0) { - fatal("bind failed"); + fatal(strerror_r_default(errno, errbuf, ERRBUFSIZE, "bind failed")); return (void *)1; } debug("bind done"); @@ -371,7 +387,7 @@ static socketserver_port * socketserver_getPort(socketserver_objectClientData *c return p; } -int socketserverObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) +int socketserverObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { socketserver_objectClientData *cdPtr = (socketserver_objectClientData *)clientData; int optIndex; @@ -383,7 +399,7 @@ int socketserverObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_ OPT_CLIENT, OPT_SERVER }; - static CONST char *options[] = { "client", "server" }; + static const char *options[] = { "client", "server" }; // basic command line processing diff --git a/generic/socketserver.h b/generic/socketserver.h index 4a7a719..eca7894 100644 --- a/generic/socketserver.h +++ b/generic/socketserver.h @@ -16,7 +16,7 @@ #include extern int -socketserverObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objvp[]); +socketserverObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objvp[]); #define SOCKETSERVER_OBJECT_MAGIC 71820352 diff --git a/tests/all.tcl b/tests/all.tcl index d8129f7..422340c 100644 --- a/tests/all.tcl +++ b/tests/all.tcl @@ -13,7 +13,29 @@ set tcltestVersion [package require tcltest] namespace import -force tcltest::* +# Hook to determine if any of the tests failed. Then we can exit with +# proper exit code: 0=all passed, 1=one or more failed +proc tcltest::cleanupTestsHook {} { + variable numTests + set ::exitCode [expr {$numTests(Failed) > 0}] +} + +proc goodtime {} { + clock format [clock seconds] -format "%Y-%m-%d %T" -gmt 0 +} + +#puts stdout "\nTests started at [goodtime]" + tcltest::testsDirectory [file dir [info script]] tcltest::runAllTests -return +## cleanup +#puts stdout "\nTests ended at [goodtime]" +#::tcltest::cleanupTests 1 + +if {$exitCode} { + puts "====== FAIL =====" + exit $exitCode +} else { + puts "====== SUCCESS =====" +} diff --git a/tests/echo_server.tcl b/tests/echo_server.tcl index 90c3afb..706f74d 100644 --- a/tests/echo_server.tcl +++ b/tests/echo_server.tcl @@ -1,7 +1,7 @@ package require Tclx -#package require socketserver - -load "./libsocketserver1.0.1.so" +if {![info exists auto_path]} { set auto_path [list] } +set auto_path [list [pwd] {*}$auto_path] +package require socketserver # Creat the socket # Start listening and accepting connections in a background thread diff --git a/tests/twoports.tcl b/tests/twoports.tcl index 2984c34..2e0652f 100644 --- a/tests/twoports.tcl +++ b/tests/twoports.tcl @@ -1,4 +1,6 @@ package require Tclx +if {![info exists auto_path]} { set auto_path [list] } +set auto_path [list [pwd] {*}$auto_path] package require socketserver # create two ports