[binutils-gdb/gdb-17-branch] gdb/ser-unix: add POSIX cfsetispeed/cfsetospeed support for custom baud rates

Sam James via Gdb-cvs <[email protected]>
Newsgroups gmane.comp.gdb.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=17d05df7da13f7b0942e4e6b5f952f66c29338a2

commit 17d05df7da13f7b0942e4e6b5f952f66c29338a2
Author: Sunil Dora <[email protected]>
Date:   Tue Mar 24 09:45:27 2026 -0700

    gdb/ser-unix: add POSIX cfsetispeed/cfsetospeed support for custom baud rates
    
    glibc 2.42 and later, and GNU Hurd, accept arbitrary baud rates
    directly via cfsetispeed and cfsetospeed.  This behaviour is expected
    to be standardized in a future POSIX revision.
    
    Introduce a configure-time test (HAVE_CFSETSPEED_ARBITRARY) that
    detects this capability and add a new platform-agnostic helper
    set_custom_baudrate_posix.  The main dispatcher now prefers the POSIX
    path when it is available, falling back to the existing Linux (BOTHER)
    or Darwin (IOSSIOSPEED) implementations otherwise.
    
    The HAVE_CUSTOM_BAUDRATE_SUPPORT guard is extended to also cover the
    new POSIX case.
    
    Suggested-by: Kevin Buettner <[email protected]>
    Suggested-by: Maciej W. Rozycki <[email protected]>
    Signed-off-by: Sunil Dora <[email protected]>
    Reviewed-By: Eli Zaretskii <[email protected]>
    Approved-by: Kevin Buettner <[email protected]>
    (cherry picked from commit 7d53467645b0430e94a3cfd13fc3c16ef19efda5)

Diff:
---
 gdb/config.in    |  3 +++
 gdb/configure    | 39 +++++++++++++++++++++++++++++++++++++++
 gdb/configure.ac | 19 +++++++++++++++++++
 gdb/ser-unix.c   | 49 ++++++++++++++++++++++++++++++++++++++++---------
 4 files changed, 101 insertions(+), 9 deletions(-)

diff --git a/gdb/config.in b/gdb/config.in
index 62ceb846824..e66127a427d 100644
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -110,6 +110,9 @@
    the CoreFoundation framework. */
 #undef HAVE_CFPREFERENCESCOPYAPPVALUE
 
+/* Define if cfsetispeed/cfsetospeed accept arbitrary baud rates. */
+#undef HAVE_CFSETSPEED_ARBITRARY
+
 /* Define if compiling support to gdb compile. */
 #undef HAVE_COMPILE
 
diff --git a/gdb/configure b/gdb/configure
index 3c321d6220b..ef645210301 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -27349,6 +27349,45 @@ _ACEOF
 fi
 
 
+# Check whether cfsetispeed/cfsetospeed accept arbitrary baud rates.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cfsetispeed/cfsetospeed accept arbitrary baud rates" >&5
+$as_echo_n "checking whether cfsetispeed/cfsetospeed accept arbitrary baud rates... " >&6; }
+if ${gdb_cv_cfsetspeed_arbitrary+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <termios.h>
+int
+main ()
+{
+
+       #if B9600 != 9600
+       #error B-constants are not numeric symbols
+       #endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  gdb_cv_cfsetspeed_arbitrary=yes
+else
+  gdb_cv_cfsetspeed_arbitrary=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gdb_cv_cfsetspeed_arbitrary" >&5
+$as_echo "$gdb_cv_cfsetspeed_arbitrary" >&6; }
+
+if test "$gdb_cv_cfsetspeed_arbitrary" = yes; then
+
+$as_echo "#define HAVE_CFSETSPEED_ARBITRARY 1" >>confdefs.h
+
+fi
+
 
 
 # Check whether --with-jit-reader-dir was given.
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 9d3377f3c40..dfa40d34c10 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -736,6 +736,25 @@ AC_SEARCH_LIBS(dlopen, dl)
 # Check for members required by the legacy Linux custom baud rate path.
 AC_CHECK_MEMBERS([struct termios.c_ospeed], [], [], [[#include <termios.h>]])
 
+# Check whether cfsetispeed/cfsetospeed accept arbitrary baud rates.
+AC_CACHE_CHECK([whether cfsetispeed/cfsetospeed accept arbitrary baud rates],
+  [gdb_cv_cfsetspeed_arbitrary], [
+  AC_COMPILE_IFELSE(
+    [AC_LANG_PROGRAM([[#include <termios.h>]],
+      [[
+       #if B9600 != 9600
+       #error B-constants are not numeric symbols
+       #endif
+      ]])],
+    [gdb_cv_cfsetspeed_arbitrary=yes],
+    [gdb_cv_cfsetspeed_arbitrary=no])
+])
+
+if test "$gdb_cv_cfsetspeed_arbitrary" = yes; then
+  AC_DEFINE([HAVE_CFSETSPEED_ARBITRARY], [1],
+	    [Define if cfsetispeed/cfsetospeed accept arbitrary baud rates.])
+fi
+
 GDB_AC_WITH_DIR([JIT_READER_DIR], [jit-reader-dir],
                 [directory to load the JIT readers from],
                 [${libdir}/gdb])
diff --git a/gdb/ser-unix.c b/gdb/ser-unix.c
index ffd721ad599..5ec664df1f3 100644
--- a/gdb/ser-unix.c
+++ b/gdb/ser-unix.c
@@ -53,9 +53,10 @@
 
 #include "gdbsupport/scoped_ignore_sigttou.h"
 
-#if (defined(HAVE_SYS_IOCTL_H) \
-     && ((defined(BOTHER) && defined(HAVE_STRUCT_TERMIOS_C_OSPEED)) \
-	  || defined(IOSSIOSPEED)))
+#if (defined(HAVE_CFSETSPEED_ARBITRARY) \
+     || (defined(HAVE_SYS_IOCTL_H) \
+	 && ((defined(BOTHER) && defined(HAVE_STRUCT_TERMIOS_C_OSPEED)) \
+	     || defined(IOSSIOSPEED))))
 #  define HAVE_CUSTOM_BAUDRATE_SUPPORT 1
 #endif
 
@@ -508,7 +509,32 @@ set_baudcode_baudrate (struct serial *scb, int baud_code)
     perror_with_name (_("could not set tty state"));
 }
 
-#if HAVE_CUSTOM_BAUDRATE_SUPPORT && defined(BOTHER)
+#if HAVE_CUSTOM_BAUDRATE_SUPPORT && defined(HAVE_CFSETSPEED_ARBITRARY)
+
+/* Set a custom baud rate using the POSIX cfsetispeed/cfsetospeed
+   interface.  Supported in glibc 2.42 and later and expected to be
+   standardized in a future POSIX revision.  It is platform-agnostic
+   and also covers systems like GNU Hurd that do not provide BOTHER.  */
+
+static void
+set_custom_baudrate_posix (int fd, int rate)
+{
+  struct termios tio;
+
+  if (tcgetattr (fd, &tio) < 0)
+    perror_with_name (_("Cannot get current baud rate"));
+
+  if (cfsetispeed (&tio, rate) < 0)
+    perror_with_name (_("Cannot set custom input baud rate"));
+
+  if (cfsetospeed (&tio, rate) < 0)
+    perror_with_name (_("Cannot set custom output baud rate"));
+
+  if (tcsetattr (fd, TCSANOW, &tio) < 0)
+    perror_with_name (_("Cannot set custom baud rate"));
+}
+
+#elif HAVE_CUSTOM_BAUDRATE_SUPPORT && defined(BOTHER)
 
 /* Set a custom baud rate using the termios BOTHER.  */
 
@@ -555,19 +581,24 @@ set_custom_baudrate_darwin (int fd, int rate)
 }
 
 #endif /* HAVE_CUSTOM_BAUDRATE_SUPPORT
-	  && (defined(BOTHER) || defined(IOSSIOSPEED)) */
+	  && (defined(HAVE_CFSETSPEED_ARBITRARY)
+	     || defined(BOTHER)
+	     || defined(IOSSIOSPEED)) */
 
 #if HAVE_CUSTOM_BAUDRATE_SUPPORT
 
 /* Set a baud rate that differs from the OS B_codes.
-   This is possible if one of the following macros is available:
-   - BOTHER (Linux).
-   - IOSSIOSPEED (Darwin).  */
+   Prefer the POSIX cfsetispeed/cfsetospeed interface when the host
+   libc accepts arbitrary baud rates.  Otherwise fall back to
+   Linux-specific (BOTHER) or Darwin-specific (IOSSIOSPEED)
+   interfaces.  */
 
 static void
 set_custom_baudrate (int fd, int rate)
 {
-#if defined(BOTHER)
+#if defined(HAVE_CFSETSPEED_ARBITRARY)
+  set_custom_baudrate_posix (fd, rate);
+#elif defined(BOTHER)
   set_custom_baudrate_linux (fd, rate);
 #elif defined(IOSSIOSPEED)
   set_custom_baudrate_darwin (fd, rate);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.