125125# define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)
126126# define HAVE_MKFIFOAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
127127# define HAVE_MKNODAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
128+ # define HAVE_PTSNAME_R_RUNTIME __builtin_available(macOS 10.13.4, iOS 11.3, tvOS 11.3, watchOS 4.3, *)
128129
129130# define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *)
130131
206207# define HAVE_MKNODAT_RUNTIME (mknodat != NULL)
207208# endif
208209
210+ # ifdef HAVE_PTSNAME_R
211+ # define HAVE_PTSNAME_R_RUNTIME (ptsname_r != NULL)
212+ # endif
213+
209214#endif
210215
211216#ifdef HAVE_FUTIMESAT
231236# define HAVE_PWRITEV_RUNTIME 1
232237# define HAVE_MKFIFOAT_RUNTIME 1
233238# define HAVE_MKNODAT_RUNTIME 1
239+ # define HAVE_PTSNAME_R_RUNTIME 1
234240#endif
235241
236242
@@ -8635,6 +8641,19 @@ os_unlockpt_impl(PyObject *module, int fd)
86358641#endif /* HAVE_UNLOCKPT */
86368642
86378643#if defined(HAVE_PTSNAME ) || defined(HAVE_PTSNAME_R )
8644+ static PyObject *
8645+ py_ptsname (int fd )
8646+ {
8647+ // POSIX manpage: Upon failure, ptsname() shall return a null pointer
8648+ // and may set errno. Always initialize errno to avoid undefined behavior.
8649+ errno = 0 ;
8650+ char * name = ptsname (fd );
8651+ if (name == NULL ) {
8652+ return posix_error ();
8653+ }
8654+ return PyUnicode_DecodeFSDefault (name );
8655+ }
8656+
86388657/*[clinic input]
86398658os.ptsname
86408659
@@ -8656,22 +8675,22 @@ os_ptsname_impl(PyObject *module, int fd)
86568675 int ret ;
86578676 char name [MAXPATHLEN + 1 ];
86588677
8659- ret = ptsname_r (fd , name , sizeof (name ));
8678+ if (HAVE_PTSNAME_R_RUNTIME ) {
8679+ ret = ptsname_r (fd , name , sizeof (name ));
8680+ }
8681+ else {
8682+ // fallback to ptsname() if ptsname_r() is not available in runtime.
8683+ return py_ptsname (fd );
8684+ }
86608685 if (ret != 0 ) {
86618686 errno = ret ;
86628687 return posix_error ();
86638688 }
8664- #else
8665- char * name ;
8666-
8667- name = ptsname (fd );
8668- /* POSIX manpage: Upon failure, ptsname() shall return a null pointer and may set errno.
8669- *MAY* set errno? Hmm... */
8670- if (name == NULL )
8671- return posix_error ();
8672- #endif /* HAVE_PTSNAME_R */
86738689
86748690 return PyUnicode_DecodeFSDefault (name );
8691+ #else
8692+ return py_ptsname (fd );
8693+ #endif /* HAVE_PTSNAME_R */
86758694}
86768695#endif /* defined(HAVE_PTSNAME) || defined(HAVE_PTSNAME_R) */
86778696
@@ -17736,6 +17755,9 @@ PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
1773617755PROBE (probe_utimensat , HAVE_UTIMENSAT_RUNTIME )
1773717756#endif
1773817757
17758+ #ifdef HAVE_PTSNAME_R
17759+ PROBE (probe_ptsname_r , HAVE_PTSNAME_R_RUNTIME )
17760+ #endif
1773917761
1774017762
1774117763
@@ -17876,6 +17898,10 @@ static const struct have_function {
1787617898 { "HAVE_UTIMENSAT" , probe_utimensat },
1787717899#endif
1787817900
17901+ #ifdef HAVE_PTSNAME_R
17902+ { "HAVE_PTSNAME_R" , probe_ptsname_r },
17903+ #endif
17904+
1787917905#ifdef MS_WINDOWS
1788017906 { "MS_WINDOWS" , NULL },
1788117907#endif
0 commit comments