Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Length: 431755 Content-Disposition: inline; filename="posixmodule.c" Last-Modified: Sun, 31 Aug 2025 18:51:31 GMT Expires: Wed, 29 Aug 2035 18:51:31 GMT ETag: "b84fb0d280f4e3195600fc30aeaa0aebff54f235" /* POSIX module implementation */ /* This file is also used for Windows NT/MS-Win. In that case the module actually calls itself 'nt', not 'posix', and a few functions are either unimplemented or implemented differently. The source assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent of the compiler used. Different compilers define their own feature test macro, e.g. '_MSC_VER'. */ #define PY_SSIZE_T_CLEAN #include "Python.h" // Include before pycore internal headers. FSCTL_GET_REPARSE_POINT // is not exported by if the WIN32_LEAN_AND_MEAN macro is defined, // whereas pycore_condvar.h defines the WIN32_LEAN_AND_MEAN macro. #ifdef MS_WINDOWS # include # include # include // UNLEN # include "osdefs.h" // SEP # define HAVE_SYMLINK #endif #ifdef __VXWORKS__ # include "pycore_bitutils.h" // _Py_popcount32() #endif #include "pycore_call.h" // _PyObject_CallNoArgs() #include "pycore_ceval.h" // _PyEval_ReInitThreads() #include "pycore_fileutils.h" // _Py_closerange() #include "pycore_import.h" // _PyImport_ReInitLock() #include "pycore_initconfig.h" // _PyStatus_EXCEPTION() #include "pycore_moduleobject.h" // _PyModule_GetState() #include "pycore_object.h" // _PyObject_LookupSpecial() #include "pycore_pystate.h" // _PyInterpreterState_GET() #include "pycore_signal.h" // Py_NSIG #include "structmember.h" // PyMemberDef #ifndef MS_WINDOWS # include "posixmodule.h" #else # include "winreparse.h" #endif #if !defined(EX_OK) && defined(EXIT_SUCCESS) # define EX_OK EXIT_SUCCESS #endif /* On android API level 21, 'AT_EACCESS' is not declared although * HAVE_FACCESSAT is defined. */ #ifdef __ANDROID__ # undef HAVE_FACCESSAT #endif #include // ctermid() #include // system() /* * A number of APIs are available on macOS from a certain macOS version. * To support building with a new SDK while deploying to older versions * the availability test is split into two: * - HAVE_: The configure check for compile time availability * - HAVE__RUNTIME: Runtime check for availability * * The latter is always true when not on macOS, or when using a compiler * that does not support __has_builtin (older versions of Xcode). * * Due to compiler restrictions there is one valid use of HAVE__RUNTIME: * if (HAVE__RUNTIME) { ... } * * In mixing the test with other tests or using negations will result in compile * errors. */ #if defined(__APPLE__) #include #if defined(__has_builtin) #if __has_builtin(__builtin_available) #define HAVE_BUILTIN_AVAILABLE 1 #endif #endif #ifdef HAVE_BUILTIN_AVAILABLE # define HAVE_FSTATAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) # define HAVE_FACCESSAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) # define HAVE_FCHMODAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) # define HAVE_FCHOWNAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) # define HAVE_LINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) # define HAVE_FDOPENDIR_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) # define HAVE_MKDIRAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) # define HAVE_RENAMEAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) # define HAVE_UNLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) # define HAVE_OPENAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) # define HAVE_READLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) # define HAVE_SYMLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *) # define HAVE_FUTIMENS_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *) # define HAVE_UTIMENSAT_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *) # define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *) # define HAVE_MKFIFOAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *) # define HAVE_MKNODAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *) # define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *) #else /* Xcode 8 or earlier */ /* __builtin_available is not present in these compilers, but * some of the symbols might be weak linked (10.10 SDK or later * deploying on 10.9. * * Fall back to the older style of availability checking for * symbols introduced in macOS 10.10. */ # ifdef HAVE_FSTATAT # define HAVE_FSTATAT_RUNTIME (fstatat != NULL) # endif # ifdef HAVE_FACCESSAT # define HAVE_FACCESSAT_RUNTIME (faccessat != NULL) # endif # ifdef HAVE_FCHMODAT # define HAVE_FCHMODAT_RUNTIME (fchmodat != NULL) # endif # ifdef HAVE_FCHOWNAT # define HAVE_FCHOWNAT_RUNTIME (fchownat != NULL) # endif # ifdef HAVE_LINKAT # define HAVE_LINKAT_RUNTIME (linkat != NULL) # endif # ifdef HAVE_FDOPENDIR # define HAVE_FDOPENDIR_RUNTIME (fdopendir != NULL) # endif # ifdef HAVE_MKDIRAT # define HAVE_MKDIRAT_RUNTIME (mkdirat != NULL) # endif # ifdef HAVE_RENAMEAT # define HAVE_RENAMEAT_RUNTIME (renameat != NULL) # endif # ifdef HAVE_UNLINKAT # define HAVE_UNLINKAT_RUNTIME (unlinkat != NULL) # endif # ifdef HAVE_OPENAT # define HAVE_OPENAT_RUNTIME (openat != NULL) # endif # ifdef HAVE_READLINKAT # define HAVE_READLINKAT_RUNTIME (readlinkat != NULL) # endif # ifdef HAVE_SYMLINKAT # define HAVE_SYMLINKAT_RUNTIME (symlinkat != NULL) # endif # ifdef HAVE_UTIMENSAT # define HAVE_UTIMENSAT_RUNTIME (utimensat != NULL) # endif # ifdef HAVE_FUTIMENS # define HAVE_FUTIMENS_RUNTIME (futimens != NULL) # endif # ifdef HAVE_PWRITEV # define HAVE_PWRITEV_RUNTIME (pwritev != NULL) # endif #endif #ifdef HAVE_FUTIMESAT /* Some of the logic for weak linking depends on this assertion */ # error "HAVE_FUTIMESAT unexpectedly defined" #endif #else # define HAVE_FSTATAT_RUNTIME 1 # define HAVE_FACCESSAT_RUNTIME 1 # define HAVE_FCHMODAT_RUNTIME 1 # define HAVE_FCHOWNAT_RUNTIME 1 # define HAVE_LINKAT_RUNTIME 1 # define HAVE_FDOPENDIR_RUNTIME 1 # define HAVE_MKDIRAT_RUNTIME 1 # define HAVE_RENAMEAT_RUNTIME 1 # define HAVE_UNLINKAT_RUNTIME 1 # define HAVE_OPENAT_RUNTIME 1 # define HAVE_READLINKAT_RUNTIME 1 # define HAVE_SYMLINKAT_RUNTIME 1 # define HAVE_FUTIMENS_RUNTIME 1 # define HAVE_UTIMENSAT_RUNTIME 1 # define HAVE_PWRITEV_RUNTIME 1 # define HAVE_MKFIFOAT_RUNTIME 1 # define HAVE_MKNODAT_RUNTIME 1 #endif #ifdef __cplusplus extern "C" { #endif PyDoc_STRVAR(posix__doc__, "This module provides access to operating system functionality that is\n\ standardized by the C Standard and the POSIX standard (a thinly\n\ disguised Unix interface). Refer to the library manual and\n\ corresponding Unix manual entries for more information on calls."); #ifdef HAVE_SYS_UIO_H # include #endif #ifdef HAVE_SYS_SYSMACROS_H /* GNU C Library: major(), minor(), makedev() */ # include #endif #ifdef HAVE_SYS_TYPES_H # include #endif /* HAVE_SYS_TYPES_H */ #ifdef HAVE_SYS_STAT_H # include #endif /* HAVE_SYS_STAT_H */ #ifdef HAVE_SYS_WAIT_H # include // WNOHANG #endif #ifdef HAVE_LINUX_WAIT_H # include // P_PIDFD #endif #ifdef HAVE_SIGNAL_H # include #endif #ifdef HAVE_FCNTL_H # include #endif #ifdef HAVE_GRP_H # include #endif #ifdef HAVE_SYSEXITS_H # include #endif #ifdef HAVE_SYS_LOADAVG_H # include #endif #ifdef HAVE_SYS_SENDFILE_H # include #endif #if defined(__APPLE__) # include #endif #ifdef HAVE_SCHED_H # include #endif #ifdef HAVE_COPY_FILE_RANGE # include #endif #if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY) # undef HAVE_SCHED_SETAFFINITY #endif #if defined(HAVE_SYS_XATTR_H) && defined(__GLIBC__) && !defined(__FreeBSD_kernel__) && !defined(__GNU__) # define USE_XATTRS #endif #ifdef USE_XATTRS # include #endif #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__) # ifdef HAVE_SYS_SOCKET_H # include # endif #endif #ifdef HAVE_DLFCN_H # include #endif #ifdef __hpux # include #endif #if defined(__DragonFly__) || \ defined(__OpenBSD__) || \ defined(__FreeBSD__) || \ defined(__NetBSD__) || \ defined(__APPLE__) # include #endif #ifdef HAVE_LINUX_RANDOM_H # include #endif #ifdef HAVE_GETRANDOM_SYSCALL # include #endif #if defined(MS_WINDOWS) # define TERMSIZE_USE_CONIO #elif defined(HAVE_SYS_IOCTL_H) # include # if defined(HAVE_TERMIOS_H) # include # endif # if defined(TIOCGWINSZ) # define TERMSIZE_USE_IOCTL # endif #endif /* MS_WINDOWS */ /* Various compilers have only certain posix functions */ /* XXX Gosh I wish these were all moved into pyconfig.h */ #if defined(__WATCOMC__) && !defined(__QNX__) /* Watcom compiler */ # define HAVE_OPENDIR 1 # define HAVE_SYSTEM 1 # include #else # ifdef _MSC_VER /* Microsoft compiler */ # define HAVE_GETPPID 1 # define HAVE_GETLOGIN 1 # define HAVE_SPAWNV 1 # define HAVE_EXECV 1 # define HAVE_WSPAWNV 1 # define HAVE_WEXECV 1 # define HAVE_PIPE 1 # define HAVE_SYSTEM 1 # define HAVE_CWAIT 1 # define HAVE_FSYNC 1 # define fsync _commit # endif /* _MSC_VER */ #endif /* ! __WATCOMC__ || __QNX__ */ /*[clinic input] # one of the few times we lie about this name! module os [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/ #ifndef _MSC_VER #if defined(__sgi)&&_COMPILER_VERSION>=700 /* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode (default) */ extern char *ctermid_r(char *); #endif #endif /* !_MSC_VER */ #if defined(__VXWORKS__) # include # include # include # include # ifndef _P_WAIT # define _P_WAIT 0 # define _P_NOWAIT 1 # define _P_NOWAITO 1 # endif #endif /* __VXWORKS__ */ #ifdef HAVE_POSIX_SPAWN # include #endif #ifdef HAVE_UTIME_H # include #endif /* HAVE_UTIME_H */ #ifdef HAVE_SYS_UTIME_H # include # define HAVE_UTIME_H /* pretend we do for the rest of this file */ #endif /* HAVE_SYS_UTIME_H */ #ifdef HAVE_SYS_TIMES_H # include #endif /* HAVE_SYS_TIMES_H */ #ifdef HAVE_SYS_PARAM_H # include #endif /* HAVE_SYS_PARAM_H */ #ifdef HAVE_SYS_UTSNAME_H # include #endif /* HAVE_SYS_UTSNAME_H */ #ifdef HAVE_DIRENT_H # include # define NAMLEN(dirent) strlen((dirent)->d_name) #else # if defined(__WATCOMC__) && !defined(__QNX__) # include # define NAMLEN(dirent) strlen((dirent)->d_name) # else # define dirent direct # define NAMLEN(dirent) (dirent)->d_namlen # endif # ifdef HAVE_SYS_NDIR_H # include # endif # ifdef HAVE_SYS_DIR_H # include # endif # ifdef HAVE_NDIR_H # include # endif #endif #ifdef _MSC_VER # ifdef HAVE_DIRECT_H # include # endif # ifdef HAVE_IO_H # include # endif # ifdef HAVE_PROCESS_H # include # endif # include #endif /* _MSC_VER */ #ifndef MAXPATHLEN # if defined(PATH_MAX) && PATH_MAX > 1024 # define MAXPATHLEN PATH_MAX # else # define MAXPATHLEN 1024 # endif #endif /* MAXPATHLEN */ #ifdef UNION_WAIT /* Emulate some macros on systems that have a union instead of macros */ # ifndef WIFEXITED # define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump) # endif # ifndef WEXITSTATUS # define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1) # endif # ifndef WTERMSIG # define WTERMSIG(u_wait) ((u_wait).w_termsig) # endif # define WAIT_TYPE union wait # define WAIT_STATUS_INT(s) (s.w_status) #else /* !UNION_WAIT */ # define WAIT_TYPE int # define WAIT_STATUS_INT(s) (s) #endif /* UNION_WAIT */ /* Don't use the "_r" form if we don't need it (also, won't have a prototype for it, at least on Solaris -- maybe others as well?). */ #if defined(HAVE_CTERMID_R) # define USE_CTERMID_R #endif /* choose the appropriate stat and fstat functions and return structs */ #undef STAT #undef FSTAT #undef STRUCT_STAT #ifdef MS_WINDOWS # define STAT win32_stat # define LSTAT win32_lstat # define FSTAT _Py_fstat_noraise # define STRUCT_STAT struct _Py_stat_struct #else # define STAT stat # define LSTAT lstat # define FSTAT fstat # define STRUCT_STAT struct stat #endif #if defined(MAJOR_IN_MKDEV) # include #else # if defined(MAJOR_IN_SYSMACROS) # include # endif # if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H) # include # endif #endif #ifdef MS_WINDOWS # define INITFUNC PyInit_nt # define MODNAME "nt" # define MODNAME_OBJ &_Py_ID(nt) #else # define INITFUNC PyInit_posix # define MODNAME "posix" # define MODNAME_OBJ &_Py_ID(posix) #endif #if defined(__sun) /* Something to implement in autoconf, not present in autoconf 2.69 */ # define HAVE_STRUCT_STAT_ST_FSTYPE 1 #endif /* memfd_create is either defined in sys/mman.h or sys/memfd.h * linux/memfd.h defines additional flags */ #ifdef HAVE_SYS_MMAN_H # include #endif #ifdef HAVE_SYS_MEMFD_H # include #endif #ifdef HAVE_LINUX_MEMFD_H # include #endif /* eventfd() */ #ifdef HAVE_SYS_EVENTFD_H # include #endif #ifdef _Py_MEMORY_SANITIZER # include #endif #ifdef HAVE_FORK static void run_at_forkers(PyObject *lst, int reverse) { Py_ssize_t i; PyObject *cpy; if (lst != NULL) { assert(PyList_CheckExact(lst)); /* Use a list copy in case register_at_fork() is called from * one of the callbacks. */ cpy = PyList_GetSlice(lst, 0, PyList_GET_SIZE(lst)); if (cpy == NULL) PyErr_WriteUnraisable(lst); else { if (reverse) PyList_Reverse(cpy); for (i = 0; i < PyList_GET_SIZE(cpy); i++) { PyObject *func, *res; func = PyList_GET_ITEM(cpy, i); res = _PyObject_CallNoArgs(func); if (res == NULL) PyErr_WriteUnraisable(func); else Py_DECREF(res); } Py_DECREF(cpy); } } } void PyOS_BeforeFork(void) { run_at_forkers(_PyInterpreterState_GET()->before_forkers, 1); _PyImport_AcquireLock(); } void PyOS_AfterFork_Parent(void) { if (_PyImport_ReleaseLock() <= 0) Py_FatalError("failed releasing import lock after fork"); run_at_forkers(_PyInterpreterState_GET()->after_forkers_parent, 0); } void PyOS_AfterFork_Child(void) { PyStatus status; _PyRuntimeState *runtime = &_PyRuntime; status = _PyRuntimeState_ReInitThreads(runtime); if (_PyStatus_EXCEPTION(status)) { goto fatal_error; } PyThreadState *tstate = _PyThreadState_GET(); _Py_EnsureTstateNotNULL(tstate); #ifdef PY_HAVE_THREAD_NATIVE_ID tstate->native_thread_id = PyThread_get_thread_native_id(); #endif status = _PyEval_ReInitThreads(tstate); if (_PyStatus_EXCEPTION(status)) { goto fatal_error; } status = _PyImport_ReInitLock(); if (_PyStatus_EXCEPTION(status)) { goto fatal_error; } _PySignal_AfterFork(); status = _PyInterpreterState_DeleteExceptMain(runtime); if (_PyStatus_EXCEPTION(status)) { goto fatal_error; } assert(_PyThreadState_GET() == tstate); status = _PyPerfTrampoline_AfterFork_Child(); if (_PyStatus_EXCEPTION(status)) { goto fatal_error; } run_at_forkers(tstate->interp->after_forkers_child, 0); return; fatal_error: Py_ExitStatusException(status); } static int register_at_forker(PyObject **lst, PyObject *func) { if (func == NULL) /* nothing to register? do nothing. */ return 0; if (*lst == NULL) { *lst = PyList_New(0); if (*lst == NULL) return -1; } return PyList_Append(*lst, func); } #endif /* HAVE_FORK */ /* Legacy wrapper */ void PyOS_AfterFork(void) { #ifdef HAVE_FORK PyOS_AfterFork_Child(); #endif } #ifdef MS_WINDOWS /* defined in fileutils.c */ void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *); void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *, ULONG, struct _Py_stat_struct *); #endif #ifndef MS_WINDOWS PyObject * _PyLong_FromUid(uid_t uid) { if (uid == (uid_t)-1) return PyLong_FromLong(-1); return PyLong_FromUnsignedLong(uid); } PyObject * _PyLong_FromGid(gid_t gid) { if (gid == (gid_t)-1) return PyLong_FromLong(-1); return PyLong_FromUnsignedLong(gid); } int _Py_Uid_Converter(PyObject *obj, uid_t *p) { uid_t uid; PyObject *index; int overflow; long result; unsigned long uresult; index = _PyNumber_Index(obj); if (index == NULL) { PyErr_Format(PyExc_TypeError, "uid should be integer, not %.200s", _PyType_Name(Py_TYPE(obj))); return 0; } /* * Handling uid_t is complicated for two reasons: * * Although uid_t is (always?) unsigned, it still * accepts -1. * * We don't know its size in advance--it may be * bigger than an int, or it may be smaller than * a long. * * So a bit of defensive programming is in order. * Start with interpreting the value passed * in as a signed long and see if it works. */ result = PyLong_AsLongAndOverflow(index, &overflow); if (!overflow) { uid = (uid_t)result; if (result == -1) { if (PyErr_Occurred()) goto fail; /* It's a legitimate -1, we're done. */ goto success; } /* Any other negative number is disallowed. */ if (result < 0) goto underflow; /* Ensure the value wasn't truncated. */ if (sizeof(uid_t) < sizeof(long) && (long)uid != result) goto underflow; goto success; } if (overflow < 0) goto underflow; /* * Okay, the value overflowed a signed long. If it * fits in an *unsigned* long, it may still be okay, * as uid_t may be unsigned long on this platform. */ uresult = PyLong_AsUnsignedLong(index); if (PyErr_Occurred()) { if (PyErr_ExceptionMatches(PyExc_OverflowError)) goto overflow; goto fail; } uid = (uid_t)uresult; /* * If uid == (uid_t)-1, the user actually passed in ULONG_MAX, * but this value would get interpreted as (uid_t)-1 by chown * and its siblings. That's not what the user meant! So we * throw an overflow exception instead. (We already * handled a real -1 with PyLong_AsLongAndOverflow() above.) */ if (uid == (uid_t)-1) goto overflow; /* Ensure the value wasn't truncated. */ if (sizeof(uid_t) < sizeof(long) && (unsigned long)uid != uresult) goto overflow; /* fallthrough */ success: Py_DECREF(index); *p = uid; return 1; underflow: PyErr_SetString(PyExc_OverflowError, "uid is less than minimum"); goto fail; overflow: PyErr_SetString(PyExc_OverflowError, "uid is greater than maximum"); /* fallthrough */ fail: Py_DECREF(index); return 0; } int _Py_Gid_Converter(PyObject *obj, gid_t *p) { gid_t gid; PyObject *index; int overflow; long result; unsigned long uresult; index = _PyNumber_Index(obj); if (index == NULL) { PyErr_Format(PyExc_TypeError, "gid should be integer, not %.200s", _PyType_Name(Py_TYPE(obj))); return 0; } /* * Handling gid_t is complicated for two reasons: * * Although gid_t is (always?) unsigned, it still * accepts -1. * * We don't know its size in advance--it may be * bigger than an int, or it may be smaller than * a long. * * So a bit of defensive programming is in order. * Start with interpreting the value passed * in as a signed long and see if it works. */ result = PyLong_AsLongAndOverflow(index, &overflow); if (!overflow) { gid = (gid_t)result; if (result == -1) { if (PyErr_Occurred()) goto fail; /* It's a legitimate -1, we're done. */ goto success; } /* Any other negative number is disallowed. */ if (result < 0) { goto underflow; } /* Ensure the value wasn't truncated. */ if (sizeof(gid_t) < sizeof(long) && (long)gid != result) goto underflow; goto success; } if (overflow < 0) goto underflow; /* * Okay, the value overflowed a signed long. If it * fits in an *unsigned* long, it may still be okay, * as gid_t may be unsigned long on this platform. */ uresult = PyLong_AsUnsignedLong(index); if (PyErr_Occurred()) { if (PyErr_ExceptionMatches(PyExc_OverflowError)) goto overflow; goto fail; } gid = (gid_t)uresult; /* * If gid == (gid_t)-1, the user actually passed in ULONG_MAX, * but this value would get interpreted as (gid_t)-1 by chown * and its siblings. That's not what the user meant! So we * throw an overflow exception instead. (We already * handled a real -1 with PyLong_AsLongAndOverflow() above.) */ if (gid == (gid_t)-1) goto overflow; /* Ensure the value wasn't truncated. */ if (sizeof(gid_t) < sizeof(long) && (unsigned long)gid != uresult) goto overflow; /* fallthrough */ success: Py_DECREF(index); *p = gid; return 1; underflow: PyErr_SetString(PyExc_OverflowError, "gid is less than minimum"); goto fail; overflow: PyErr_SetString(PyExc_OverflowError, "gid is greater than maximum"); /* fallthrough */ fail: Py_DECREF(index); return 0; } #endif /* MS_WINDOWS */ #define _PyLong_FromDev PyLong_FromLongLong #if (defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)) || defined(HAVE_DEVICE_MACROS) static int _Py_Dev_Converter(PyObject *obj, void *p) { *((dev_t *)p) = PyLong_AsUnsignedLongLong(obj); if (PyErr_Occurred()) return 0; return 1; } #endif /* (HAVE_MKNOD && HAVE_MAKEDEV) || HAVE_DEVICE_MACROS */ #ifdef AT_FDCWD /* * Why the (int) cast? Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965); * without the int cast, the value gets interpreted as uint (4291925331), * which doesn't play nicely with all the initializer lines in this file that * look like this: * int dir_fd = DEFAULT_DIR_FD; */ #define DEFAULT_DIR_FD (int)AT_FDCWD #else #define DEFAULT_DIR_FD (-100) #endif static int _fd_converter(PyObject *o, int *p) { int overflow; long long_value; PyObject *index = _PyNumber_Index(o); if (index == NULL) { return 0; } assert(PyLong_Check(index)); long_value = PyLong_AsLongAndOverflow(index, &overflow); Py_DECREF(index); assert(!PyErr_Occurred()); if (overflow > 0 || long_value > INT_MAX) { PyErr_SetString(PyExc_OverflowError, "fd is greater than maximum"); return 0; } if (overflow < 0 || long_value < INT_MIN) { PyErr_SetString(PyExc_OverflowError, "fd is less than minimum"); return 0; } *p = (int)long_value; return 1; } static int dir_fd_converter(PyObject *o, void *p) { if (o == Py_None) { *(int *)p = DEFAULT_DIR_FD; return 1; } else if (PyIndex_Check(o)) { return _fd_converter(o, (int *)p); } else { PyErr_Format(PyExc_TypeError, "argument should be integer or None, not %.200s", _PyType_Name(Py_TYPE(o))); return 0; } } typedef struct { PyObject *billion; PyObject *DirEntryType; PyObject *ScandirIteratorType; #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) PyObject *SchedParamType; #endif newfunc statresult_new_orig; PyObject *StatResultType; PyObject *StatVFSResultType; PyObject *TerminalSizeType; PyObject *TimesResultType; PyObject *UnameResultType; #if defined(HAVE_WAITID) && !defined(__APPLE__) PyObject *WaitidResultType; #endif #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) PyObject *struct_rusage; #endif PyObject *st_mode; } _posixstate; static inline _posixstate* get_posix_state(PyObject *module) { void *state = _PyModule_GetState(module); assert(state != NULL); return (_posixstate *)state; } /* * A PyArg_ParseTuple "converter" function * that handles filesystem paths in the manner * preferred by the os module. * * path_converter accepts (Unicode) strings and their * subclasses, and bytes and their subclasses. What * it does with the argument depends on the platform: * * * On Windows, if we get a (Unicode) string we * extract the wchar_t * and return it; if we get * bytes we decode to wchar_t * and return that. * * * On all other platforms, strings are encoded * to bytes using PyUnicode_FSConverter, then we * extract the char * from the bytes object and * return that. * * path_converter also optionally accepts signed * integers (representing open file descriptors) instead * of path strings. * * Input fields: * path.nullable * If nonzero, the path is permitted to be None. * path.allow_fd * If nonzero, the path is permitted to be a file handle * (a signed int) instead of a string. * path.function_name * If non-NULL, path_converter will use that as the name * of the function in error messages. * (If path.function_name is NULL it omits the function name.) * path.argument_name * If non-NULL, path_converter will use that as the name * of the parameter in error messages. * (If path.argument_name is NULL it uses "path".) * * Output fields: * path.wide * Points to the path if it was expressed as Unicode * and was not encoded. (Only used on Windows.) * path.narrow * Points to the path if it was expressed as bytes, * or it was Unicode and was encoded to bytes. (On Windows, * is a non-zero integer if the path was expressed as bytes. * The type is deliberately incompatible to prevent misuse.) * path.fd * Contains a file descriptor if path.accept_fd was true * and the caller provided a signed integer instead of any * sort of string. * * WARNING: if your "path" parameter is optional, and is * unspecified, path_converter will never get called. * So if you set allow_fd, you *MUST* initialize path.fd = -1 * yourself! * path.length * The length of the path in characters, if specified as * a string. * path.object * The original object passed in (if get a PathLike object, * the result of PyOS_FSPath() is treated as the original object). * Own a reference to the object. * path.cleanup * For internal use only. May point to a temporary object. * (Pay no attention to the man behind the curtain.) * * At most one of path.wide or path.narrow will be non-NULL. * If path was None and path.nullable was set, * or if path was an integer and path.allow_fd was set, * both path.wide and path.narrow will be NULL * and path.length will be 0. * * path_converter takes care to not write to the path_t * unless it's successful. However it must reset the * "cleanup" field each time it's called. * * Use as follows: * path_t path; * memset(&path, 0, sizeof(path)); * PyArg_ParseTuple(args, "O&", path_converter, &path); * // ... use values from path ... * path_cleanup(&path); * * (Note that if PyArg_Parse fails you don't need to call * path_cleanup(). However it is safe to do so.) */ typedef struct { const char *function_name; const char *argument_name; int nullable; int allow_fd; const wchar_t *wide; #ifdef MS_WINDOWS BOOL narrow; #else const char *narrow; #endif int fd; Py_ssize_t length; PyObject *object; PyObject *cleanup; } path_t; #ifdef MS_WINDOWS #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \ {function_name, argument_name, nullable, allow_fd, NULL, FALSE, -1, 0, NULL, NULL} #else #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \ {function_name, argument_name, nullable, allow_fd, NULL, NULL, -1, 0, NULL, NULL} #endif static void path_cleanup(path_t *path) { wchar_t *wide = (wchar_t *)path->wide; path->wide = NULL; PyMem_Free(wide); Py_CLEAR(path->object); Py_CLEAR(path->cleanup); } static int path_converter(PyObject *o, void *p) { path_t *path = (path_t *)p; PyObject *bytes = NULL; Py_ssize_t length = 0; int is_index, is_bytes, is_unicode; const char *narrow; #ifdef MS_WINDOWS PyObject *wo = NULL; wchar_t *wide = NULL; #endif #define FORMAT_EXCEPTION(exc, fmt) \ PyErr_Format(exc, "%s%s" fmt, \ path->function_name ? path->function_name : "", \ path->function_name ? ": " : "", \ path->argument_name ? path->argument_name : "path") /* Py_CLEANUP_SUPPORTED support */ if (o == NULL) { path_cleanup(path); return 1; } /* Ensure it's always safe to call path_cleanup(). */ path->object = path->cleanup = NULL; /* path->object owns a reference to the original object */ Py_INCREF(o); if ((o == Py_None) && path->nullable) { path->wide = NULL; #ifdef MS_WINDOWS path->narrow = FALSE; #else path->narrow = NULL; #endif path->fd = -1; goto success_exit; } /* Only call this here so that we don't treat the return value of os.fspath() as an fd or buffer. */ is_index = path->allow_fd && PyIndex_Check(o); is_bytes = PyBytes_Check(o); is_unicode = PyUnicode_Check(o); if (!is_index && !is_unicode && !is_bytes) { /* Inline PyOS_FSPath() for better error messages. */ PyObject *func, *res; func = _PyObject_LookupSpecial(o, &_Py_ID(__fspath__)); if (NULL == func) { goto error_format; } res = _PyObject_CallNoArgs(func); Py_DECREF(func); if (NULL == res) { goto error_exit; } else if (PyUnicode_Check(res)) { is_unicode = 1; } else if (PyBytes_Check(res)) { is_bytes = 1; } else { PyErr_Format(PyExc_TypeError, "expected %.200s.__fspath__() to return str or bytes, " "not %.200s", _PyType_Name(Py_TYPE(o)), _PyType_Name(Py_TYPE(res))); Py_DECREF(res); goto error_exit; } /* still owns a reference to the original object */ Py_SETREF(o, res); } if (is_unicode) { #ifdef MS_WINDOWS wide = PyUnicode_AsWideCharString(o, &length); if (!wide) { goto error_exit; } if (length > 32767) { FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows"); goto error_exit; } if (wcslen(wide) != length) { FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); goto error_exit; } path->wide = wide; path->narrow = FALSE; path->fd = -1; wide = NULL; goto success_exit; #else if (!PyUnicode_FSConverter(o, &bytes)) { goto error_exit; } #endif } else if (is_bytes) { bytes = Py_NewRef(o); } else if (is_index) { if (!_fd_converter(o, &path->fd)) { goto error_exit; } path->wide = NULL; #ifdef MS_WINDOWS path->narrow = FALSE; #else path->narrow = NULL; #endif goto success_exit; } else { error_format: PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s", path->function_name ? path->function_name : "", path->function_name ? ": " : "", path->argument_name ? path->argument_name : "path", path->allow_fd && path->nullable ? "string, bytes, os.PathLike, " "integer or None" : path->allow_fd ? "string, bytes, os.PathLike or integer" : path->nullable ? "string, bytes, os.PathLike or None" : "string, bytes or os.PathLike", _PyType_Name(Py_TYPE(o))); goto error_exit; } length = PyBytes_GET_SIZE(bytes); narrow = PyBytes_AS_STRING(bytes); if ((size_t)length != strlen(narrow)) { FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); goto error_exit; } #ifdef MS_WINDOWS wo = PyUnicode_DecodeFSDefaultAndSize( narrow, length ); if (!wo) { goto error_exit; } wide = PyUnicode_AsWideCharString(wo, &length); Py_DECREF(wo); if (!wide) { goto error_exit; } if (length > 32767) { FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows"); goto error_exit; } if (wcslen(wide) != length) { FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); goto error_exit; } path->wide = wide; path->narrow = TRUE; Py_DECREF(bytes); wide = NULL; #else path->wide = NULL; path->narrow = narrow; if (bytes == o) { /* Still a reference owned by path->object, don't have to worry about path->narrow is used after free. */ Py_DECREF(bytes); } else { path->cleanup = bytes; } #endif path->fd = -1; success_exit: path->length = length; path->object = o; return Py_CLEANUP_SUPPORTED; error_exit: Py_XDECREF(o); Py_XDECREF(bytes); #ifdef MS_WINDOWS PyMem_Free(wide); #endif return 0; } static void argument_unavailable_error(const char *function_name, const char *argument_name) { PyErr_Format(PyExc_NotImplementedError, "%s%s%s unavailable on this platform", (function_name != NULL) ? function_name : "", (function_name != NULL) ? ": ": "", argument_name); } static int dir_fd_unavailable(PyObject *o, void *p) { int dir_fd; if (!dir_fd_converter(o, &dir_fd)) return 0; if (dir_fd != DEFAULT_DIR_FD) { argument_unavailable_error(NULL, "dir_fd"); return 0; } *(int *)p = dir_fd; return 1; } static int fd_specified(const char *function_name, int fd) { if (fd == -1) return 0; argument_unavailable_error(function_name, "fd"); return 1; } static int follow_symlinks_specified(const char *function_name, int follow_symlinks) { if (follow_symlinks) return 0; argument_unavailable_error(function_name, "follow_symlinks"); return 1; } static int path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd) { if (!path->wide && (dir_fd != DEFAULT_DIR_FD) #ifndef MS_WINDOWS && !path->narrow #endif ) { PyErr_Format(PyExc_ValueError, "%s: can't specify dir_fd without matching path", function_name); return 1; } return 0; } static int dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd) { if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) { PyErr_Format(PyExc_ValueError, "%s: can't specify both dir_fd and fd", function_name); return 1; } return 0; } static int fd_and_follow_symlinks_invalid(const char *function_name, int fd, int follow_symlinks) { if ((fd > 0) && (!follow_symlinks)) { PyErr_Format(PyExc_ValueError, "%s: cannot use fd and follow_symlinks together", function_name); return 1; } return 0; } static int dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd, int follow_symlinks) { if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) { PyErr_Format(PyExc_ValueError, "%s: cannot use dir_fd and follow_symlinks together", function_name); return 1; } return 0; } #ifdef MS_WINDOWS typedef long long Py_off_t; #else typedef off_t Py_off_t; #endif static int Py_off_t_converter(PyObject *arg, void *addr) { #ifdef HAVE_LARGEFILE_SUPPORT *((Py_off_t *)addr) = PyLong_AsLongLong(arg); #else *((Py_off_t *)addr) = PyLong_AsLong(arg); #endif if (PyErr_Occurred()) return 0; return 1; } static PyObject * PyLong_FromPy_off_t(Py_off_t offset) { #ifdef HAVE_LARGEFILE_SUPPORT return PyLong_FromLongLong(offset); #else return PyLong_FromLong(offset); #endif } #ifdef HAVE_SIGSET_T /* Convert an iterable of integers to a sigset. Return 1 on success, return 0 and raise an exception on error. */ int _Py_Sigset_Converter(PyObject *obj, void *addr) { sigset_t *mask = (sigset_t *)addr; PyObject *iterator, *item; long signum; int overflow; // The extra parens suppress the unreachable-code warning with clang on MacOS if (sigemptyset(mask) < (0)) { /* Probably only if mask == NULL. */ PyErr_SetFromErrno(PyExc_OSError); return 0; } iterator = PyObject_GetIter(obj); if (iterator == NULL) { return 0; } while ((item = PyIter_Next(iterator)) != NULL) { signum = PyLong_AsLongAndOverflow(item, &overflow); Py_DECREF(item); if (signum <= 0 || signum >= Py_NSIG) { if (overflow || signum != -1 || !PyErr_Occurred()) { PyErr_Format(PyExc_ValueError, "signal number %ld out of range [1; %i]", signum, Py_NSIG - 1); } goto error; } if (sigaddset(mask, (int)signum)) { if (errno != EINVAL) { /* Probably impossible */ PyErr_SetFromErrno(PyExc_OSError); goto error; } /* For backwards compatibility, allow idioms such as * `range(1, NSIG)` but warn about invalid signal numbers */ const char msg[] = "invalid signal number %ld, please use valid_signals()"; if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) { goto error; } } } if (!PyErr_Occurred()) { Py_DECREF(iterator); return 1; } error: Py_DECREF(iterator); return 0; } #endif /* HAVE_SIGSET_T */ #ifdef MS_WINDOWS static int win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag) { char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer; DWORD n_bytes_returned; if (0 == DeviceIoControl( reparse_point_handle, FSCTL_GET_REPARSE_POINT, NULL, 0, /* in buffer */ target_buffer, sizeof(target_buffer), &n_bytes_returned, NULL)) /* we're not using OVERLAPPED_IO */ return FALSE; if (reparse_tag) *reparse_tag = rdb->ReparseTag; return TRUE; } #endif /* MS_WINDOWS */ /* Return a dictionary corresponding to the POSIX environment table */ #if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED)) /* On Darwin/MacOSX a shared library or framework has no access to ** environ directly, we must obtain it with _NSGetEnviron(). See also ** man environ(7). */ #include #elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__)) extern char **environ; #endif /* !_MSC_VER */ static PyObject * convertenviron(void) { PyObject *d; #ifdef MS_WINDOWS wchar_t **e; #else char **e; #endif d = PyDict_New(); if (d == NULL) return NULL; #ifdef MS_WINDOWS /* _wenviron must be initialized in this way if the program is started through main() instead of wmain(). */ _wgetenv(L""); e = _wenviron; #elif defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED)) /* environ is not accessible as an extern in a shared object on OSX; use _NSGetEnviron to resolve it. The value changes if you add environment variables between calls to Py_Initialize, so don't cache the value. */ e = *_NSGetEnviron(); #else e = environ; #endif if (e == NULL) return d; for (; *e != NULL; e++) { PyObject *k; PyObject *v; #ifdef MS_WINDOWS const wchar_t *p = wcschr(*e, L'='); #else const char *p = strchr(*e, '='); #endif if (p == NULL) continue; #ifdef MS_WINDOWS k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e)); #else k = PyBytes_FromStringAndSize(*e, (int)(p-*e)); #endif if (k == NULL) { Py_DECREF(d); return NULL; } #ifdef MS_WINDOWS v = PyUnicode_FromWideChar(p+1, wcslen(p+1)); #else v = PyBytes_FromStringAndSize(p+1, strlen(p+1)); #endif if (v == NULL) { Py_DECREF(k); Py_DECREF(d); return NULL; } if (PyDict_SetDefault(d, k, v) == NULL) { Py_DECREF(v); Py_DECREF(k); Py_DECREF(d); return NULL; } Py_DECREF(k); Py_DECREF(v); } return d; } /* Set a POSIX-specific error from errno, and return NULL */ static PyObject * posix_error(void) { return PyErr_SetFromErrno(PyExc_OSError); } #ifdef MS_WINDOWS static PyObject * win32_error(const char* function, const char* filename) { /* XXX We should pass the function name along in the future. (winreg.c also wants to pass the function name.) This would however require an additional param to the Windows error object, which is non-trivial. */ errno = GetLastError(); if (filename) return PyErr_SetFromWindowsErrWithFilename(errno, filename); else return PyErr_SetFromWindowsErr(errno); } static PyObject * win32_error_object_err(const char* function, PyObject* filename, DWORD err) { /* XXX - see win32_error for comments on 'function' */ if (filename) return PyErr_SetExcFromWindowsErrWithFilenameObject( PyExc_OSError, err, filename); else return PyErr_SetFromWindowsErr(err); } static PyObject * win32_error_object(const char* function, PyObject* filename) { errno = GetLastError(); return win32_error_object_err(function, filename, errno); } #endif /* MS_WINDOWS */ static PyObject * posix_path_object_error(PyObject *path) { return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path); } static PyObject * path_object_error(PyObject *path) { #ifdef MS_WINDOWS return PyErr_SetExcFromWindowsErrWithFilenameObject( PyExc_OSError, 0, path); #else return posix_path_object_error(path); #endif } static PyObject * path_object_error2(PyObject *path, PyObject *path2) { #ifdef MS_WINDOWS return PyErr_SetExcFromWindowsErrWithFilenameObjects( PyExc_OSError, 0, path, path2); #else return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2); #endif } static PyObject * path_error(path_t *path) { return path_object_error(path->object); } static PyObject * posix_path_error(path_t *path) { return posix_path_object_error(path->object); } static PyObject * path_error2(path_t *path, path_t *path2) { return path_object_error2(path->object, path2->object); } /* POSIX generic methods */ static PyObject * posix_fildes_fd(int fd, int (*func)(int)) { int res; int async_err = 0; do { Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH res = (*func)(fd); _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); if (res != 0) return (!async_err) ? posix_error() : NULL; Py_RETURN_NONE; } #ifdef MS_WINDOWS /* This is a reimplementation of the C library's chdir function, but one that produces Win32 errors instead of DOS error codes. chdir is essentially a wrapper around SetCurrentDirectory; however, it also needs to set "magic" environment variables indicating the per-drive current directory, which are of the form =: */ static BOOL __stdcall win32_wchdir(LPCWSTR path) { wchar_t path_buf[MAX_PATH], *new_path = path_buf; int result; wchar_t env[4] = L"=x:"; if(!SetCurrentDirectoryW(path)) return FALSE; result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path); if (!result) return FALSE; if (result > Py_ARRAY_LENGTH(path_buf)) { new_path = PyMem_RawMalloc(result * sizeof(wchar_t)); if (!new_path) { SetLastError(ERROR_OUTOFMEMORY); return FALSE; } result = GetCurrentDirectoryW(result, new_path); if (!result) { PyMem_RawFree(new_path); return FALSE; } } int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 || wcsncmp(new_path, L"//", 2) == 0); if (!is_unc_like_path) { env[1] = new_path[0]; result = SetEnvironmentVariableW(env, new_path); } if (new_path != path_buf) PyMem_RawFree(new_path); return result ? TRUE : FALSE; } #endif #ifdef MS_WINDOWS /* The CRT of Windows has a number of flaws wrt. its stat() implementation: - time stamps are restricted to second resolution - file modification times suffer from forth-and-back conversions between UTC and local time Therefore, we implement our own stat, based on the Win32 API directly. */ #define HAVE_STAT_NSEC 1 #define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1 #define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1 static void find_data_to_file_info(WIN32_FIND_DATAW *pFileData, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag) { memset(info, 0, sizeof(*info)); info->dwFileAttributes = pFileData->dwFileAttributes; info->ftCreationTime = pFileData->ftCreationTime; info->ftLastAccessTime = pFileData->ftLastAccessTime; info->ftLastWriteTime = pFileData->ftLastWriteTime; info->nFileSizeHigh = pFileData->nFileSizeHigh; info->nFileSizeLow = pFileData->nFileSizeLow; /* info->nNumberOfLinks = 1; */ if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) *reparse_tag = pFileData->dwReserved0; else *reparse_tag = 0; } static BOOL attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag) { HANDLE hFindFile; WIN32_FIND_DATAW FileData; LPCWSTR filename = pszFile; size_t n = wcslen(pszFile); if (n && (pszFile[n - 1] == L'\\' || pszFile[n - 1] == L'/')) { // cannot use PyMem_Malloc here because we do not hold the GIL filename = (LPCWSTR)malloc((n + 1) * sizeof(filename[0])); wcsncpy_s((LPWSTR)filename, n + 1, pszFile, n); while (--n > 0 && (filename[n] == L'\\' || filename[n] == L'/')) { ((LPWSTR)filename)[n] = L'\0'; } if (!n || (n == 1 && filename[1] == L':')) { // Nothing left to query free((void *)filename); return FALSE; } } hFindFile = FindFirstFileW(filename, &FileData); if (pszFile != filename) { free((void *)filename); } if (hFindFile == INVALID_HANDLE_VALUE) { return FALSE; } FindClose(hFindFile); find_data_to_file_info(&FileData, info, reparse_tag); return TRUE; } static int win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse) { HANDLE hFile; BY_HANDLE_FILE_INFORMATION fileInfo; FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 }; DWORD fileType, error; BOOL isUnhandledTag = FALSE; int retval = 0; DWORD access = FILE_READ_ATTRIBUTES; DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */ if (!traverse) { flags |= FILE_FLAG_OPEN_REPARSE_POINT; } hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL); if (hFile == INVALID_HANDLE_VALUE) { /* Either the path doesn't exist, or the caller lacks access. */ error = GetLastError(); switch (error) { case ERROR_ACCESS_DENIED: /* Cannot sync or read attributes. */ case ERROR_SHARING_VIOLATION: /* It's a paging file. */ /* Try reading the parent directory. */ if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) { /* Cannot read the parent directory. */ switch (GetLastError()) { case ERROR_FILE_NOT_FOUND: /* File cannot be found */ case ERROR_PATH_NOT_FOUND: /* File parent directory cannot be found */ case ERROR_NOT_READY: /* Drive exists but unavailable */ case ERROR_BAD_NET_NAME: /* Remote drive unavailable */ break; /* Restore the error from CreateFileW(). */ default: SetLastError(error); } return -1; } if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { if (traverse || !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) { /* The stat call has to traverse but cannot, so fail. */ SetLastError(error); return -1; } } break; case ERROR_INVALID_PARAMETER: /* \\.\con requires read or write access. */ hFile = CreateFileW(path, access | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, flags, NULL); if (hFile == INVALID_HANDLE_VALUE) { SetLastError(error); return -1; } break; case ERROR_CANT_ACCESS_FILE: /* bpo37834: open unhandled reparse points if traverse fails. */ if (traverse) { traverse = FALSE; isUnhandledTag = TRUE; hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL); } if (hFile == INVALID_HANDLE_VALUE) { SetLastError(error); return -1; } break; default: return -1; } } if (hFile != INVALID_HANDLE_VALUE) { /* Handle types other than files on disk. */ fileType = GetFileType(hFile); if (fileType != FILE_TYPE_DISK) { if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) { retval = -1; goto cleanup; } DWORD fileAttributes = GetFileAttributesW(path); memset(result, 0, sizeof(*result)); if (fileAttributes != INVALID_FILE_ATTRIBUTES && fileAttributes & FILE_ATTRIBUTE_DIRECTORY) { /* \\.\pipe\ or \\.\mailslot\ */ result->st_mode = _S_IFDIR; } else if (fileType == FILE_TYPE_CHAR) { /* \\.\nul */ result->st_mode = _S_IFCHR; } else if (fileType == FILE_TYPE_PIPE) { /* \\.\pipe\spam */ result->st_mode = _S_IFIFO; } /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */ goto cleanup; } /* Query the reparse tag, and traverse a non-link. */ if (!traverse) { if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo, &tagInfo, sizeof(tagInfo))) { /* Allow devices that do not support FileAttributeTagInfo. */ switch (GetLastError()) { case ERROR_INVALID_PARAMETER: case ERROR_INVALID_FUNCTION: case ERROR_NOT_SUPPORTED: tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL; tagInfo.ReparseTag = 0; break; default: retval = -1; goto cleanup; } } else if (tagInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) { if (isUnhandledTag) { /* Traversing previously failed for either this link or its target. */ SetLastError(ERROR_CANT_ACCESS_FILE); retval = -1; goto cleanup; } /* Traverse a non-link, but not if traversing already failed for an unhandled tag. */ } else if (!isUnhandledTag) { CloseHandle(hFile); return win32_xstat_impl(path, result, TRUE); } } } if (!GetFileInformationByHandle(hFile, &fileInfo)) { switch (GetLastError()) { case ERROR_INVALID_PARAMETER: case ERROR_INVALID_FUNCTION: case ERROR_NOT_SUPPORTED: /* Volumes and physical disks are block devices, e.g. \\.\C: and \\.\PhysicalDrive0. */ memset(result, 0, sizeof(*result)); result->st_mode = 0x6000; /* S_IFBLK */ goto cleanup; } retval = -1; goto cleanup; } } _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, result); if (!(fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { /* Fix the file execute permissions. This hack sets S_IEXEC if the filename has an extension that is commonly used by files that CreateProcessW can execute. A real implementation calls GetSecurityInfo, OpenThreadToken/OpenProcessToken, and AccessCheck to check for generic read, write, and execute access. */ const wchar_t *fileExtension = wcsrchr(path, '.'); if (fileExtension) { if (_wcsicmp(fileExtension, L".exe") == 0 || _wcsicmp(fileExtension, L".bat") == 0 || _wcsicmp(fileExtension, L".cmd") == 0 || _wcsicmp(fileExtension, L".com") == 0) { result->st_mode |= 0111; } } } cleanup: if (hFile != INVALID_HANDLE_VALUE) { /* Preserve last error if we are failing */ error = retval ? GetLastError() : 0; if (!CloseHandle(hFile)) { retval = -1; } else if (retval) { /* Restore last error */ SetLastError(error); } } return retval; } static int win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse) { /* Protocol violation: we explicitly clear errno, instead of setting it to a POSIX error. Callers should use GetLastError. */ int code = win32_xstat_impl(path, result, traverse); errno = 0; return code; } /* About the following functions: win32_lstat_w, win32_stat, win32_stat_w In Posix, stat automatically traverses symlinks and returns the stat structure for the target. In Windows, the equivalent GetFileAttributes by default does not traverse symlinks and instead returns attributes for the symlink. Instead, we will open the file (which *does* traverse symlinks by default) and GetFileInformationByHandle(). */ static int win32_lstat(const wchar_t* path, struct _Py_stat_struct *result) { return win32_xstat(path, result, FALSE); } static int win32_stat(const wchar_t* path, struct _Py_stat_struct *result) { return win32_xstat(path, result, TRUE); } #endif /* MS_WINDOWS */ PyDoc_STRVAR(stat_result__doc__, "stat_result: Result from stat, fstat, or lstat.\n\n\ This object may be accessed either as a tuple of\n\ (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\ or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\ \n\ Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\ or st_flags, they are available as attributes only.\n\ \n\ See os.stat for more information."); static PyStructSequence_Field stat_result_fields[] = { {"st_mode", "protection bits"}, {"st_ino", "inode"}, {"st_dev", "device"}, {"st_nlink", "number of hard links"}, {"st_uid", "user ID of owner"}, {"st_gid", "group ID of owner"}, {"st_size", "total size, in bytes"}, /* The NULL is replaced with PyStructSequence_UnnamedField later. */ {NULL, "integer time of last access"}, {NULL, "integer time of last modification"}, {NULL, "integer time of last change"}, {"st_atime", "time of last access"}, {"st_mtime", "time of last modification"}, {"st_ctime", "time of last change"}, {"st_atime_ns", "time of last access in nanoseconds"}, {"st_mtime_ns", "time of last modification in nanoseconds"}, {"st_ctime_ns", "time of last change in nanoseconds"}, #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE {"st_blksize", "blocksize for filesystem I/O"}, #endif #ifdef HAVE_STRUCT_STAT_ST_BLOCKS {"st_blocks", "number of blocks allocated"}, #endif #ifdef HAVE_STRUCT_STAT_ST_RDEV {"st_rdev", "device type (if inode device)"}, #endif #ifdef HAVE_STRUCT_STAT_ST_FLAGS {"st_flags", "user defined flags for file"}, #endif #ifdef HAVE_STRUCT_STAT_ST_GEN {"st_gen", "generation number"}, #endif #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME {"st_birthtime", "time of creation"}, #endif #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES {"st_file_attributes", "Windows file attribute bits"}, #endif #ifdef HAVE_STRUCT_STAT_ST_FSTYPE {"st_fstype", "Type of filesystem"}, #endif #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG {"st_reparse_tag", "Windows reparse tag"}, #endif {0} }; #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE #define ST_BLKSIZE_IDX 16 #else #define ST_BLKSIZE_IDX 15 #endif #ifdef HAVE_STRUCT_STAT_ST_BLOCKS #define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1) #else #define ST_BLOCKS_IDX ST_BLKSIZE_IDX #endif #ifdef HAVE_STRUCT_STAT_ST_RDEV #define ST_RDEV_IDX (ST_BLOCKS_IDX+1) #else #define ST_RDEV_IDX ST_BLOCKS_IDX #endif #ifdef HAVE_STRUCT_STAT_ST_FLAGS #define ST_FLAGS_IDX (ST_RDEV_IDX+1) #else #define ST_FLAGS_IDX ST_RDEV_IDX #endif #ifdef HAVE_STRUCT_STAT_ST_GEN #define ST_GEN_IDX (ST_FLAGS_IDX+1) #else #define ST_GEN_IDX ST_FLAGS_IDX #endif #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME #define ST_BIRTHTIME_IDX (ST_GEN_IDX+1) #else #define ST_BIRTHTIME_IDX ST_GEN_IDX #endif #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES #define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_IDX+1) #else #define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_IDX #endif #ifdef HAVE_STRUCT_STAT_ST_FSTYPE #define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1) #else #define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX #endif #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG #define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1) #else #define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX #endif static PyStructSequence_Desc stat_result_desc = { "stat_result", /* name */ stat_result__doc__, /* doc */ stat_result_fields, 10 }; PyDoc_STRVAR(statvfs_result__doc__, "statvfs_result: Result from statvfs or fstatvfs.\n\n\ This object may be accessed either as a tuple of\n\ (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\ or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\ \n\ See os.statvfs for more information."); static PyStructSequence_Field statvfs_result_fields[] = { {"f_bsize", }, {"f_frsize", }, {"f_blocks", }, {"f_bfree", }, {"f_bavail", }, {"f_files", }, {"f_ffree", }, {"f_favail", }, {"f_flag", }, {"f_namemax",}, {"f_fsid", }, {0} }; static PyStructSequence_Desc statvfs_result_desc = { "statvfs_result", /* name */ statvfs_result__doc__, /* doc */ statvfs_result_fields, 10 }; #if defined(HAVE_WAITID) && !defined(__APPLE__) PyDoc_STRVAR(waitid_result__doc__, "waitid_result: Result from waitid.\n\n\ This object may be accessed either as a tuple of\n\ (si_pid, si_uid, si_signo, si_status, si_code),\n\ or via the attributes si_pid, si_uid, and so on.\n\ \n\ See os.waitid for more information."); static PyStructSequence_Field waitid_result_fields[] = { {"si_pid", }, {"si_uid", }, {"si_signo", }, {"si_status", }, {"si_code", }, {0} }; static PyStructSequence_Desc waitid_result_desc = { "waitid_result", /* name */ waitid_result__doc__, /* doc */ waitid_result_fields, 5 }; #endif static PyObject * statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyStructSequence *result; int i; // ht_module doesn't get set in PyStructSequence_NewType(), // so we can't use PyType_GetModule(). PyObject *mod = PyImport_GetModule(MODNAME_OBJ); if (mod == NULL) { return NULL; } _posixstate *state = get_posix_state(mod); Py_DECREF(mod); if (state == NULL) { return NULL; } #define structseq_new state->statresult_new_orig result = (PyStructSequence*)structseq_new(type, args, kwds); if (!result) return NULL; /* If we have been initialized from a tuple, st_?time might be set to None. Initialize it from the int slots. */ for (i = 7; i <= 9; i++) { if (result->ob_item[i+3] == Py_None) { Py_DECREF(Py_None); result->ob_item[i+3] = Py_NewRef(result->ob_item[i]); } } return (PyObject*)result; } static int _posix_clear(PyObject *module) { _posixstate *state = get_posix_state(module); Py_CLEAR(state->billion); Py_CLEAR(state->DirEntryType); Py_CLEAR(state->ScandirIteratorType); #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) Py_CLEAR(state->SchedParamType); #endif Py_CLEAR(state->StatResultType); Py_CLEAR(state->StatVFSResultType); Py_CLEAR(state->TerminalSizeType); Py_CLEAR(state->TimesResultType); Py_CLEAR(state->UnameResultType); #if defined(HAVE_WAITID) && !defined(__APPLE__) Py_CLEAR(state->WaitidResultType); #endif #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) Py_CLEAR(state->struct_rusage); #endif Py_CLEAR(state->st_mode); return 0; } static int _posix_traverse(PyObject *module, visitproc visit, void *arg) { _posixstate *state = get_posix_state(module); Py_VISIT(state->billion); Py_VISIT(state->DirEntryType); Py_VISIT(state->ScandirIteratorType); #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) Py_VISIT(state->SchedParamType); #endif Py_VISIT(state->StatResultType); Py_VISIT(state->StatVFSResultType); Py_VISIT(state->TerminalSizeType); Py_VISIT(state->TimesResultType); Py_VISIT(state->UnameResultType); #if defined(HAVE_WAITID) && !defined(__APPLE__) Py_VISIT(state->WaitidResultType); #endif #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) Py_VISIT(state->struct_rusage); #endif Py_VISIT(state->st_mode); return 0; } static void _posix_free(void *module) { _posix_clear((PyObject *)module); } static void fill_time(PyObject *module, PyObject *v, int index, time_t sec, unsigned long nsec) { PyObject *s = _PyLong_FromTime_t(sec); PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec); PyObject *s_in_ns = NULL; PyObject *ns_total = NULL; PyObject *float_s = NULL; if (!(s && ns_fractional)) goto exit; s_in_ns = PyNumber_Multiply(s, get_posix_state(module)->billion); if (!s_in_ns) goto exit; ns_total = PyNumber_Add(s_in_ns, ns_fractional); if (!ns_total) goto exit; float_s = PyFloat_FromDouble(sec + 1e-9*nsec); if (!float_s) { goto exit; } PyStructSequence_SET_ITEM(v, index, s); PyStructSequence_SET_ITEM(v, index+3, float_s); PyStructSequence_SET_ITEM(v, index+6, ns_total); s = NULL; float_s = NULL; ns_total = NULL; exit: Py_XDECREF(s); Py_XDECREF(ns_fractional); Py_XDECREF(s_in_ns); Py_XDECREF(ns_total); Py_XDECREF(float_s); } /* pack a system stat C structure into the Python stat tuple (used by posix_stat() and posix_fstat()) */ static PyObject* _pystat_fromstructstat(PyObject *module, STRUCT_STAT *st) { unsigned long ansec, mnsec, cnsec; PyObject *StatResultType = get_posix_state(module)->StatResultType; PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType); if (v == NULL) return NULL; PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode)); static_assert(sizeof(unsigned long long) >= sizeof(st->st_ino), "stat.st_ino is larger than unsigned long long"); PyStructSequence_SET_ITEM(v, 1, PyLong_FromUnsignedLongLong(st->st_ino)); #ifdef MS_WINDOWS PyStructSequence_SET_ITEM(v, 2, PyLong_FromUnsignedLong(st->st_dev)); #else PyStructSequence_SET_ITEM(v, 2, _PyLong_FromDev(st->st_dev)); #endif PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink)); #if defined(MS_WINDOWS) PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong(0)); PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong(0)); #else PyStructSequence_SET_ITEM(v, 4, _PyLong_FromUid(st->st_uid)); PyStructSequence_SET_ITEM(v, 5, _PyLong_FromGid(st->st_gid)); #endif static_assert(sizeof(long long) >= sizeof(st->st_size), "stat.st_size is larger than long long"); PyStructSequence_SET_ITEM(v, 6, PyLong_FromLongLong(st->st_size)); #if defined(HAVE_STAT_TV_NSEC) ansec = st->st_atim.tv_nsec; mnsec = st->st_mtim.tv_nsec; cnsec = st->st_ctim.tv_nsec; #elif defined(HAVE_STAT_TV_NSEC2) ansec = st->st_atimespec.tv_nsec; mnsec = st->st_mtimespec.tv_nsec; cnsec = st->st_ctimespec.tv_nsec; #elif defined(HAVE_STAT_NSEC) ansec = st->st_atime_nsec; mnsec = st->st_mtime_nsec; cnsec = st->st_ctime_nsec; #else ansec = mnsec = cnsec = 0; #endif fill_time(module, v, 7, st->st_atime, ansec); fill_time(module, v, 8, st->st_mtime, mnsec); fill_time(module, v, 9, st->st_ctime, cnsec); #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX, PyLong_FromLong((long)st->st_blksize)); #endif #ifdef HAVE_STRUCT_STAT_ST_BLOCKS PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX, PyLong_FromLong((long)st->st_blocks)); #endif #ifdef HAVE_STRUCT_STAT_ST_RDEV PyStructSequence_SET_ITEM(v, ST_RDEV_IDX, PyLong_FromLong((long)st->st_rdev)); #endif #ifdef HAVE_STRUCT_STAT_ST_GEN PyStructSequence_SET_ITEM(v, ST_GEN_IDX, PyLong_FromLong((long)st->st_gen)); #endif #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME { PyObject *val; unsigned long bsec,bnsec; bsec = (long)st->st_birthtime; #ifdef HAVE_STAT_TV_NSEC2 bnsec = st->st_birthtimespec.tv_nsec; #else bnsec = 0; #endif val = PyFloat_FromDouble(bsec + 1e-9*bnsec); PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX, val); } #endif #ifdef HAVE_STRUCT_STAT_ST_FLAGS PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX, PyLong_FromLong((long)st->st_flags)); #endif #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES PyStructSequence_SET_ITEM(v, ST_FILE_ATTRIBUTES_IDX, PyLong_FromUnsignedLong(st->st_file_attributes)); #endif #ifdef HAVE_STRUCT_STAT_ST_FSTYPE PyStructSequence_SET_ITEM(v, ST_FSTYPE_IDX, PyUnicode_FromString(st->st_fstype)); #endif #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG PyStructSequence_SET_ITEM(v, ST_REPARSE_TAG_IDX, PyLong_FromUnsignedLong(st->st_reparse_tag)); #endif if (PyErr_Occurred()) { Py_DECREF(v); return NULL; } return v; } /* POSIX methods */ static PyObject * posix_do_stat(PyObject *module, const char *function_name, path_t *path, int dir_fd, int follow_symlinks) { STRUCT_STAT st; int result; #ifdef HAVE_FSTATAT int fstatat_unavailable = 0; #endif #if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT) if (follow_symlinks_specified(function_name, follow_symlinks)) return NULL; #endif if (path_and_dir_fd_invalid("stat", path, dir_fd) || dir_fd_and_fd_invalid("stat", dir_fd, path->fd) || fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks)) return NULL; Py_BEGIN_ALLOW_THREADS if (path->fd != -1) result = FSTAT(path->fd, &st); #ifdef MS_WINDOWS else if (follow_symlinks) result = win32_stat(path->wide, &st); else result = win32_lstat(path->wide, &st); #else else #if defined(HAVE_LSTAT) if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) result = LSTAT(path->narrow, &st); else #endif /* HAVE_LSTAT */ #ifdef HAVE_FSTATAT if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) { if (HAVE_FSTATAT_RUNTIME) { result = fstatat(dir_fd, path->narrow, &st, follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW); } else { fstatat_unavailable = 1; } } else #endif /* HAVE_FSTATAT */ result = STAT(path->narrow, &st); #endif /* MS_WINDOWS */ Py_END_ALLOW_THREADS #ifdef HAVE_FSTATAT if (fstatat_unavailable) { argument_unavailable_error("stat", "dir_fd"); return NULL; } #endif if (result != 0) { return path_error(path); } return _pystat_fromstructstat(module, &st); } /*[python input] for s in """ FACCESSAT FCHMODAT FCHOWNAT FSTATAT LINKAT MKDIRAT MKFIFOAT MKNODAT OPENAT READLINKAT SYMLINKAT UNLINKAT """.strip().split(): s = s.strip() print(""" #ifdef HAVE_{s} #define {s}_DIR_FD_CONVERTER dir_fd_converter #else #define {s}_DIR_FD_CONVERTER dir_fd_unavailable #endif """.rstrip().format(s=s)) for s in """ FCHDIR FCHMOD FCHOWN FDOPENDIR FEXECVE FPATHCONF FSTATVFS FTRUNCATE """.strip().split(): s = s.strip() print(""" #ifdef HAVE_{s} #define PATH_HAVE_{s} 1 #else #define PATH_HAVE_{s} 0 #endif """.rstrip().format(s=s)) [python start generated code]*/ #ifdef HAVE_FACCESSAT #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter #else #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable #endif #ifdef HAVE_FCHMODAT #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter #else #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable #endif #ifdef HAVE_FCHOWNAT #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter #else #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable #endif #ifdef HAVE_FSTATAT #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter #else #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable #endif #ifdef HAVE_LINKAT #define LINKAT_DIR_FD_CONVERTER dir_fd_converter #else #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable #endif #ifdef HAVE_MKDIRAT #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter #else #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable #endif #ifdef HAVE_MKFIFOAT #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter #else #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable #endif #ifdef HAVE_MKNODAT #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter #else #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable #endif #ifdef HAVE_OPENAT #define OPENAT_DIR_FD_CONVERTER dir_fd_converter #else #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable #endif #ifdef HAVE_READLINKAT #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter #else #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable #endif #ifdef HAVE_SYMLINKAT #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter #else #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable #endif #ifdef HAVE_UNLINKAT #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter #else #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable #endif #ifdef HAVE_FCHDIR #define PATH_HAVE_FCHDIR 1 #else #define PATH_HAVE_FCHDIR 0 #endif #ifdef HAVE_FCHMOD #define PATH_HAVE_FCHMOD 1 #else #define PATH_HAVE_FCHMOD 0 #endif #ifdef HAVE_FCHOWN #define PATH_HAVE_FCHOWN 1 #else #define PATH_HAVE_FCHOWN 0 #endif #ifdef HAVE_FDOPENDIR #define PATH_HAVE_FDOPENDIR 1 #else #define PATH_HAVE_FDOPENDIR 0 #endif #ifdef HAVE_FEXECVE #define PATH_HAVE_FEXECVE 1 #else #define PATH_HAVE_FEXECVE 0 #endif #ifdef HAVE_FPATHCONF #define PATH_HAVE_FPATHCONF 1 #else #define PATH_HAVE_FPATHCONF 0 #endif #ifdef HAVE_FSTATVFS #define PATH_HAVE_FSTATVFS 1 #else #define PATH_HAVE_FSTATVFS 0 #endif #ifdef HAVE_FTRUNCATE #define PATH_HAVE_FTRUNCATE 1 #else #define PATH_HAVE_FTRUNCATE 0 #endif /*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/ #ifdef MS_WINDOWS #undef PATH_HAVE_FTRUNCATE #define PATH_HAVE_FTRUNCATE 1 #endif /*[python input] class path_t_converter(CConverter): type = "path_t" impl_by_reference = True parse_by_reference = True converter = 'path_converter' def converter_init(self, *, allow_fd=False, nullable=False): # right now path_t doesn't support default values. # to support a default value, you'll need to override initialize(). if self.default not in (unspecified, None): fail("Can't specify a default to the path_t converter!") if self.c_default not in (None, 'Py_None'): raise RuntimeError("Can't specify a c_default to the path_t converter!") self.nullable = nullable self.allow_fd = allow_fd def pre_render(self): def strify(value): if isinstance(value, str): return value return str(int(bool(value))) # add self.py_name here when merging with posixmodule conversion self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {})'.format( self.function.name, self.name, strify(self.nullable), strify(self.allow_fd), ) def cleanup(self): return "path_cleanup(&" + self.name + ");\n" class dir_fd_converter(CConverter): type = 'int' def converter_init(self, requires=None): if self.default in (unspecified, None): self.c_default = 'DEFAULT_DIR_FD' if isinstance(requires, str): self.converter = requires.upper() + '_DIR_FD_CONVERTER' else: self.converter = 'dir_fd_converter' class uid_t_converter(CConverter): type = "uid_t" converter = '_Py_Uid_Converter' class gid_t_converter(CConverter): type = "gid_t" converter = '_Py_Gid_Converter' class dev_t_converter(CConverter): type = 'dev_t' converter = '_Py_Dev_Converter' class dev_t_return_converter(unsigned_long_return_converter): type = 'dev_t' conversion_fn = '_PyLong_FromDev' unsigned_cast = '(dev_t)' class FSConverter_converter(CConverter): type = 'PyObject *' converter = 'PyUnicode_FSConverter' def converter_init(self): if self.default is not unspecified: fail("FSConverter_converter does not support default values") self.c_default = 'NULL' def cleanup(self): return "Py_XDECREF(" + self.name + ");\n" class pid_t_converter(CConverter): type = 'pid_t' format_unit = '" _Py_PARSE_PID "' class idtype_t_converter(int_converter): type = 'idtype_t' class id_t_converter(CConverter): type = 'id_t' format_unit = '" _Py_PARSE_PID "' class intptr_t_converter(CConverter): type = 'intptr_t' format_unit = '" _Py_PARSE_INTPTR "' class Py_off_t_converter(CConverter): type = 'Py_off_t' converter = 'Py_off_t_converter' class Py_off_t_return_converter(long_return_converter): type = 'Py_off_t' conversion_fn = 'PyLong_FromPy_off_t' class path_confname_converter(CConverter): type="int" converter="conv_path_confname" class confstr_confname_converter(path_confname_converter): converter='conv_confstr_confname' class sysconf_confname_converter(path_confname_converter): converter="conv_sysconf_confname" [python start generated code]*/ /*[python end generated code: output=da39a3ee5e6b4b0d input=3338733161aa7879]*/ /*[clinic input] os.stat path : path_t(allow_fd=True) Path to be examined; can be string, bytes, a path-like object or open-file-descriptor int. * dir_fd : dir_fd(requires='fstatat') = None If not None, it should be a file descriptor open to a directory, and path should be a relative string; path will then be relative to that directory. follow_symlinks: bool = True If False, and the last element of the path is a symbolic link, stat will examine the symbolic link itself instead of the file the link points to. Perform a stat system call on the given path. dir_fd and follow_symlinks may not be implemented on your platform. If they are unavailable, using them will raise a NotImplementedError. It's an error to use dir_fd or follow_symlinks when specifying path as an open file descriptor. [clinic start generated code]*/ static PyObject * os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks) /*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/ { return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks); } /*[clinic input] os.lstat path : path_t * dir_fd : dir_fd(requires='fstatat') = None Perform a stat system call on the given path, without following symbolic links. Like stat(), but do not follow symbolic links. Equivalent to stat(path, follow_symlinks=False). [clinic start generated code]*/ static PyObject * os_lstat_impl(PyObject *module, path_t *path, int dir_fd) /*[clinic end generated code: output=ef82a5d35ce8ab37 input=0b7474765927b925]*/ { int follow_symlinks = 0; return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks); } /*[clinic input] os.access -> bool path: path_t Path to be tested; can be string, bytes, or a path-like object. mode: int Operating-system mode bitfield. Can be F_OK to test existence, or the inclusive-OR of R_OK, W_OK, and X_OK. * dir_fd : dir_fd(requires='faccessat') = None If not None, it should be a file descriptor open to a directory, and path should be relative; path will then be relative to that directory. effective_ids: bool = False If True, access will use the effective uid/gid instead of the real uid/gid. follow_symlinks: bool = True If False, and the last element of the path is a symbolic link, access will examine the symbolic link itself instead of the file the link points to. Use the real uid/gid to test for access to a path. {parameters} dir_fd, effective_ids, and follow_symlinks may not be implemented on your platform. If they are unavailable, using them will raise a NotImplementedError. Note that most operations will use the effective uid/gid, therefore this routine can be used in a suid/sgid environment to test if the invoking user has the specified access to the path. [clinic start generated code]*/ static int os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd, int effective_ids, int follow_symlinks) /*[clinic end generated code: output=cf84158bc90b1a77 input=3ffe4e650ee3bf20]*/ { int return_value; #ifdef MS_WINDOWS DWORD attr; #else int result; #endif #ifdef HAVE_FACCESSAT int faccessat_unavailable = 0; #endif #ifndef HAVE_FACCESSAT if (follow_symlinks_specified("access", follow_symlinks)) return -1; if (effective_ids) { argument_unavailable_error("access", "effective_ids"); return -1; } #endif #ifdef MS_WINDOWS Py_BEGIN_ALLOW_THREADS attr = GetFileAttributesW(path->wide); Py_END_ALLOW_THREADS /* * Access is possible if * * we didn't get a -1, and * * write access wasn't requested, * * or the file isn't read-only, * * or it's a directory. * (Directories cannot be read-only on Windows.) */ return_value = (attr != INVALID_FILE_ATTRIBUTES) && (!(mode & 2) || !(attr & FILE_ATTRIBUTE_READONLY) || (attr & FILE_ATTRIBUTE_DIRECTORY)); #else Py_BEGIN_ALLOW_THREADS #ifdef HAVE_FACCESSAT if ((dir_fd != DEFAULT_DIR_FD) || effective_ids || !follow_symlinks) { if (HAVE_FACCESSAT_RUNTIME) { int flags = 0; if (!follow_symlinks) flags |= AT_SYMLINK_NOFOLLOW; if (effective_ids) flags |= AT_EACCESS; result = faccessat(dir_fd, path->narrow, mode, flags); } else { faccessat_unavailable = 1; } } else #endif result = access(path->narrow, mode); Py_END_ALLOW_THREADS #ifdef HAVE_FACCESSAT if (faccessat_unavailable) { if (dir_fd != DEFAULT_DIR_FD) { argument_unavailable_error("access", "dir_fd"); return -1; } if (follow_symlinks_specified("access", follow_symlinks)) return -1; if (effective_ids) { argument_unavailable_error("access", "effective_ids"); return -1; } /* should be unreachable */ return -1; } #endif return_value = !result; #endif return return_value; } #ifndef F_OK #define F_OK 0 #endif #ifndef R_OK #define R_OK 4 #endif #ifndef W_OK #define W_OK 2 #endif #ifndef X_OK #define X_OK 1 #endif #ifdef HAVE_TTYNAME /*[clinic input] os.ttyname fd: int Integer file descriptor handle. / Return the name of the terminal device connected to 'fd'. [clinic start generated code]*/ static PyObject * os_ttyname_impl(PyObject *module, int fd) /*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/ { long size = sysconf(_SC_TTY_NAME_MAX); if (size == -1) { return posix_error(); } char *buffer = (char *)PyMem_RawMalloc(size); if (buffer == NULL) { return PyErr_NoMemory(); } int ret = ttyname_r(fd, buffer, size); if (ret != 0) { PyMem_RawFree(buffer); errno = ret; return posix_error(); } PyObject *res = PyUnicode_DecodeFSDefault(buffer); PyMem_RawFree(buffer); return res; } #endif #ifdef HAVE_CTERMID /*[clinic input] os.ctermid Return the name of the controlling terminal for this process. [clinic start generated code]*/ static PyObject * os_ctermid_impl(PyObject *module) /*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/ { char *ret; char buffer[L_ctermid]; #ifdef USE_CTERMID_R ret = ctermid_r(buffer); #else ret = ctermid(buffer); #endif if (ret == NULL) return posix_error(); return PyUnicode_DecodeFSDefault(buffer); } #endif /* HAVE_CTERMID */ /*[clinic input] os.chdir path: path_t(allow_fd='PATH_HAVE_FCHDIR') Change the current working directory to the specified path. path may always be specified as a string. On some platforms, path may also be specified as an open file descriptor. If this functionality is unavailable, using it raises an exception. [clinic start generated code]*/ static PyObject * os_chdir_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=3be6400eee26eaae input=1a4a15b4d12cb15d]*/ { int result; if (PySys_Audit("os.chdir", "(O)", path->object) < 0) { return NULL; } Py_BEGIN_ALLOW_THREADS #ifdef MS_WINDOWS /* on unix, success = 0, on windows, success = !0 */ result = !win32_wchdir(path->wide); #else #ifdef HAVE_FCHDIR if (path->fd != -1) result = fchdir(path->fd); else #endif result = chdir(path->narrow); #endif Py_END_ALLOW_THREADS if (result) { return path_error(path); } Py_RETURN_NONE; } #ifdef HAVE_FCHDIR /*[clinic input] os.fchdir fd: fildes Change to the directory of the given file descriptor. fd must be opened on a directory, not a file. Equivalent to os.chdir(fd). [clinic start generated code]*/ static PyObject * os_fchdir_impl(PyObject *module, int fd) /*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/ { if (PySys_Audit("os.chdir", "(i)", fd) < 0) { return NULL; } return posix_fildes_fd(fd, fchdir); } #endif /* HAVE_FCHDIR */ /*[clinic input] os.chmod path: path_t(allow_fd='PATH_HAVE_FCHMOD') Path to be modified. May always be specified as a str, bytes, or a path-like object. On some platforms, path may also be specified as an open file descriptor. If this functionality is unavailable, using it raises an exception. mode: int Operating-system mode bitfield. Be careful when using number literals for *mode*. The conventional UNIX notation for numeric modes uses an octal base, which needs to be indicated with a ``0o`` prefix in Python. * dir_fd : dir_fd(requires='fchmodat') = None If not None, it should be a file descriptor open to a directory, and path should be relative; path will then be relative to that directory. follow_symlinks: bool = True If False, and the last element of the path is a symbolic link, chmod will modify the symbolic link itself instead of the file the link points to. Change the access permissions of a file. It is an error to use dir_fd or follow_symlinks when specifying path as an open file descriptor. dir_fd and follow_symlinks may not be implemented on your platform. If they are unavailable, using them will raise a NotImplementedError. [clinic start generated code]*/ static PyObject * os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd, int follow_symlinks) /*[clinic end generated code: output=5cf6a94915cc7bff input=674a14bc998de09d]*/ { int result; #ifdef MS_WINDOWS DWORD attr; #endif #ifdef HAVE_FCHMODAT int fchmodat_nofollow_unsupported = 0; int fchmodat_unsupported = 0; #endif #if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD)) if (follow_symlinks_specified("chmod", follow_symlinks)) return NULL; #endif if (PySys_Audit("os.chmod", "Oii", path->object, mode, dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { return NULL; } #ifdef MS_WINDOWS Py_BEGIN_ALLOW_THREADS attr = GetFileAttributesW(path->wide); if (attr == INVALID_FILE_ATTRIBUTES) result = 0; else { if (mode & _S_IWRITE) attr &= ~FILE_ATTRIBUTE_READONLY; else attr |= FILE_ATTRIBUTE_READONLY; result = SetFileAttributesW(path->wide, attr); } Py_END_ALLOW_THREADS if (!result) { return path_error(path); } #else /* MS_WINDOWS */ Py_BEGIN_ALLOW_THREADS #ifdef HAVE_FCHMOD if (path->fd != -1) result = fchmod(path->fd, mode); else #endif /* HAVE_CHMOD */ #ifdef HAVE_LCHMOD if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) result = lchmod(path->narrow, mode); else #endif /* HAVE_LCHMOD */ #ifdef HAVE_FCHMODAT if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) { if (HAVE_FCHMODAT_RUNTIME) { /* * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW! * The documentation specifically shows how to use it, * and then says it isn't implemented yet. * (true on linux with glibc 2.15, and openindiana 3.x) * * Once it is supported, os.chmod will automatically * support dir_fd and follow_symlinks=False. (Hopefully.) * Until then, we need to be careful what exception we raise. */ result = fchmodat(dir_fd, path->narrow, mode, follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW); /* * But wait! We can't throw the exception without allowing threads, * and we can't do that in this nested scope. (Macro trickery, sigh.) */ fchmodat_nofollow_unsupported = result && ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) && !follow_symlinks; } else { fchmodat_unsupported = 1; fchmodat_nofollow_unsupported = 1; result = -1; } } else #endif /* HAVE_FHCMODAT */ { #ifdef HAVE_CHMOD result = chmod(path->narrow, mode); #elif defined(__wasi__) // WASI SDK 15.0 does not support chmod. // Ignore missing syscall for now. result = 0; #else result = -1; errno = ENOSYS; #endif } Py_END_ALLOW_THREADS if (result) { #ifdef HAVE_FCHMODAT if (fchmodat_unsupported) { if (dir_fd != DEFAULT_DIR_FD) { argument_unavailable_error("chmod", "dir_fd"); return NULL; } } if (fchmodat_nofollow_unsupported) { if (dir_fd != DEFAULT_DIR_FD) dir_fd_and_follow_symlinks_invalid("chmod", dir_fd, follow_symlinks); else follow_symlinks_specified("chmod", follow_symlinks); return NULL; } else #endif /* HAVE_FCHMODAT */ return path_error(path); } #endif /* MS_WINDOWS */ Py_RETURN_NONE; } #ifdef HAVE_FCHMOD /*[clinic input] os.fchmod fd: int The file descriptor of the file to be modified. mode: int Operating-system mode bitfield. Be careful when using number literals for *mode*. The conventional UNIX notation for numeric modes uses an octal base, which needs to be indicated with a ``0o`` prefix in Python. Change the access permissions of the file given by file descriptor fd. Equivalent to os.chmod(fd, mode). [clinic start generated code]*/ static PyObject * os_fchmod_impl(PyObject *module, int fd, int mode) /*[clinic end generated code: output=afd9bc05b4e426b3 input=b5594618bbbc22df]*/ { int res; int async_err = 0; if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) { return NULL; } do { Py_BEGIN_ALLOW_THREADS res = fchmod(fd, mode); Py_END_ALLOW_THREADS } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); if (res != 0) return (!async_err) ? posix_error() : NULL; Py_RETURN_NONE; } #endif /* HAVE_FCHMOD */ #ifdef HAVE_LCHMOD /*[clinic input] os.lchmod path: path_t mode: int Change the access permissions of a file, without following symbolic links. If path is a symlink, this affects the link itself rather than the target. Equivalent to chmod(path, mode, follow_symlinks=False)." [clinic start generated code]*/ static PyObject * os_lchmod_impl(PyObject *module, path_t *path, int mode) /*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/ { int res; if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) { return NULL; } Py_BEGIN_ALLOW_THREADS res = lchmod(path->narrow, mode); Py_END_ALLOW_THREADS if (res < 0) { path_error(path); return NULL; } Py_RETURN_NONE; } #endif /* HAVE_LCHMOD */ #ifdef HAVE_CHFLAGS /*[clinic input] os.chflags path: path_t flags: unsigned_long(bitwise=True) follow_symlinks: bool=True Set file flags. If follow_symlinks is False, and the last element of the path is a symbolic link, chflags will change flags on the symbolic link itself instead of the file the link points to. follow_symlinks may not be implemented on your platform. If it is unavailable, using it will raise a NotImplementedError. [clinic start generated code]*/ static PyObject * os_chflags_impl(PyObject *module, path_t *path, unsigned long flags, int follow_symlinks) /*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/ { int result; #ifndef HAVE_LCHFLAGS if (follow_symlinks_specified("chflags", follow_symlinks)) return NULL; #endif if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) { return NULL; } Py_BEGIN_ALLOW_THREADS #ifdef HAVE_LCHFLAGS if (!follow_symlinks) result = lchflags(path->narrow, flags); else #endif result = chflags(path->narrow, flags); Py_END_ALLOW_THREADS if (result) return path_error(path); Py_RETURN_NONE; } #endif /* HAVE_CHFLAGS */ #ifdef HAVE_LCHFLAGS /*[clinic input] os.lchflags path: path_t flags: unsigned_long(bitwise=True) Set file flags. This function will not follow symbolic links. Equivalent to chflags(path, flags, follow_symlinks=False). [clinic start generated code]*/ static PyObject * os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags) /*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/ { int res; if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) { return NULL; } Py_BEGIN_ALLOW_THREADS res = lchflags(path->narrow, flags); Py_END_ALLOW_THREADS if (res < 0) { return path_error(path); } Py_RETURN_NONE; } #endif /* HAVE_LCHFLAGS */ #ifdef HAVE_CHROOT /*[clinic input] os.chroot path: path_t Change root directory to path. [clinic start generated code]*/ static PyObject * os_chroot_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/ { int res; Py_BEGIN_ALLOW_THREADS res = chroot(path->narrow); Py_END_ALLOW_THREADS if (res < 0) return path_error(path); Py_RETURN_NONE; } #endif /* HAVE_CHROOT */ #ifdef HAVE_FSYNC /*[clinic input] os.fsync fd: fildes Force write of fd to disk. [clinic start generated code]*/ static PyObject * os_fsync_impl(PyObject *module, int fd) /*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/ { return posix_fildes_fd(fd, fsync); } #endif /* HAVE_FSYNC */ #ifdef HAVE_SYNC /*[clinic input] os.sync Force write of everything to disk. [clinic start generated code]*/ static PyObject * os_sync_impl(PyObject *module) /*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/ { Py_BEGIN_ALLOW_THREADS sync(); Py_END_ALLOW_THREADS Py_RETURN_NONE; } #endif /* HAVE_SYNC */ #ifdef HAVE_FDATASYNC #ifdef __hpux extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */ #endif /*[clinic input] os.fdatasync fd: fildes Force write of fd to disk without forcing update of metadata. [clinic start generated code]*/ static PyObject * os_fdatasync_impl(PyObject *module, int fd) /*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/ { return posix_fildes_fd(fd, fdatasync); } #endif /* HAVE_FDATASYNC */ #ifdef HAVE_CHOWN /*[clinic input] os.chown path : path_t(allow_fd='PATH_HAVE_FCHOWN') Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int. uid: uid_t gid: gid_t * dir_fd : dir_fd(requires='fchownat') = None If not None, it should be a file descriptor open to a directory, and path should be relative; path will then be relative to that directory. follow_symlinks: bool = True If False, and the last element of the path is a symbolic link, stat will examine the symbolic link itself instead of the file the link points to. Change the owner and group id of path to the numeric uid and gid.\ path may always be specified as a string. On some platforms, path may also be specified as an open file descriptor. If this functionality is unavailable, using it raises an exception. If dir_fd is not None, it should be a file descriptor open to a directory, and path should be relative; path will then be relative to that directory. If follow_symlinks is False, and the last element of the path is a symbolic link, chown will modify the symbolic link itself instead of the file the link points to. It is an error to use dir_fd or follow_symlinks when specifying path as an open file descriptor. dir_fd and follow_symlinks may not be implemented on your platform. If they are unavailable, using them will raise a NotImplementedError. [clinic start generated code]*/ static PyObject * os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid, int dir_fd, int follow_symlinks) /*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/ { int result; #if defined(HAVE_FCHOWNAT) int fchownat_unsupported = 0; #endif #if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT)) if (follow_symlinks_specified("chown", follow_symlinks)) return NULL; #endif if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) || fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks)) return NULL; if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { return NULL; } Py_BEGIN_ALLOW_THREADS #ifdef HAVE_FCHOWN if (path->fd != -1) result = fchown(path->fd, uid, gid); else #endif #ifdef HAVE_LCHOWN if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) result = lchown(path->narrow, uid, gid); else #endif #ifdef HAVE_FCHOWNAT if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) { if (HAVE_FCHOWNAT_RUNTIME) { result = fchownat(dir_fd, path->narrow, uid, gid, follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW); } else { fchownat_unsupported = 1; } } else #endif result = chown(path->narrow, uid, gid); Py_END_ALLOW_THREADS #ifdef HAVE_FCHOWNAT if (fchownat_unsupported) { /* This would be incorrect if the current platform * doesn't support lchown. */ argument_unavailable_error(NULL, "dir_fd"); return NULL; } #endif if (result) return path_error(path); Py_RETURN_NONE; } #endif /* HAVE_CHOWN */ #ifdef HAVE_FCHOWN /*[clinic input] os.fchown fd: int uid: uid_t gid: gid_t Change the owner and group id of the file specified by file descriptor. Equivalent to os.chown(fd, uid, gid). [clinic start generated code]*/ static PyObject * os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid) /*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/ { int res; int async_err = 0; if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) { return NULL; } do { Py_BEGIN_ALLOW_THREADS res = fchown(fd, uid, gid); Py_END_ALLOW_THREADS } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); if (res != 0) return (!async_err) ? posix_error() : NULL; Py_RETURN_NONE; } #endif /* HAVE_FCHOWN */ #ifdef HAVE_LCHOWN /*[clinic input] os.lchown path : path_t uid: uid_t gid: gid_t Change the owner and group id of path to the numeric uid and gid. This function will not follow symbolic links. Equivalent to os.chown(path, uid, gid, follow_symlinks=False). [clinic start generated code]*/ static PyObject * os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid) /*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/ { int res; if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) { return NULL; } Py_BEGIN_ALLOW_THREADS res = lchown(path->narrow, uid, gid); Py_END_ALLOW_THREADS if (res < 0) { return path_error(path); } Py_RETURN_NONE; } #endif /* HAVE_LCHOWN */ static PyObject * posix_getcwd(int use_bytes) { #ifdef MS_WINDOWS wchar_t wbuf[MAXPATHLEN]; wchar_t *wbuf2 = wbuf; DWORD len; Py_BEGIN_ALLOW_THREADS len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf); /* If the buffer is large enough, len does not include the terminating \0. If the buffer is too small, len includes the space needed for the terminator. */ if (len >= Py_ARRAY_LENGTH(wbuf)) { if (len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) { wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t)); } else { wbuf2 = NULL; } if (wbuf2) { len = GetCurrentDirectoryW(len, wbuf2); } } Py_END_ALLOW_THREADS if (!wbuf2) { PyErr_NoMemory(); return NULL; } if (!len) { if (wbuf2 != wbuf) PyMem_RawFree(wbuf2); return PyErr_SetFromWindowsErr(0); } PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len); if (wbuf2 != wbuf) { PyMem_RawFree(wbuf2); } if (use_bytes) { if (resobj == NULL) { return NULL; } Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj)); } return resobj; #else const size_t chunk = 1024; char *buf = NULL; char *cwd = NULL; size_t buflen = 0; Py_BEGIN_ALLOW_THREADS do { char *newbuf; if (buflen <= PY_SSIZE_T_MAX - chunk) { buflen += chunk; newbuf = PyMem_RawRealloc(buf, buflen); } else { newbuf = NULL; } if (newbuf == NULL) { PyMem_RawFree(buf); buf = NULL; break; } buf = newbuf; cwd = getcwd(buf, buflen); } while (cwd == NULL && errno == ERANGE); Py_END_ALLOW_THREADS if (buf == NULL) { return PyErr_NoMemory(); } if (cwd == NULL) { PyMem_RawFree(buf); return posix_error(); } PyObject *obj; if (use_bytes) { obj = PyBytes_FromStringAndSize(buf, strlen(buf)); } else { obj = PyUnicode_DecodeFSDefault(buf); } PyMem_RawFree(buf); return obj; #endif /* !MS_WINDOWS */ } /*[clinic input] os.getcwd Return a unicode string representing the current working directory. [clinic start generated code]*/ static PyObject * os_getcwd_impl(PyObject *module) /*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/ { return posix_getcwd(0); } /*[clinic input] os.getcwdb Return a bytes string representing the current working directory. [clinic start generated code]*/ static PyObject * os_getcwdb_impl(PyObject *module) /*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/ { return posix_getcwd(1); } #if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS)) #define HAVE_LINK 1 #endif #ifdef HAVE_LINK /*[clinic input] os.link src : path_t dst : path_t * src_dir_fd : dir_fd = None dst_dir_fd : dir_fd = None follow_symlinks: bool = True Create a hard link to a file. If either src_dir_fd or dst_dir_fd is not None, it should be a file descriptor open to a directory, and the respective path string (src or dst) should be relative; the path will then be relative to that directory. If follow_symlinks is False, and the last element of src is a symbolic link, link will create a link to the symbolic link itself instead of the file the link points to. src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your platform. If they are unavailable, using them will raise a NotImplementedError. [clinic start generated code]*/ static PyObject * os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int follow_symlinks) /*[clinic end generated code: output=7f00f6007fd5269a input=b0095ebbcbaa7e04]*/ { #ifdef MS_WINDOWS BOOL result = FALSE; #else int result; #endif #if defined(HAVE_LINKAT) int linkat_unavailable = 0; #endif #ifndef HAVE_LINKAT if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) { argument_unavailable_error("link", "src_dir_fd and dst_dir_fd"); return NULL; } #endif #ifndef MS_WINDOWS if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) { PyErr_SetString(PyExc_NotImplementedError, "link: src and dst must be the same type"); return NULL; } #endif if (PySys_Audit("os.link", "OOii", src->object, dst->object, src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd, dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) { return NULL; } #ifdef MS_WINDOWS Py_BEGIN_ALLOW_THREADS result = CreateHardLinkW(dst->wide, src->wide, NULL); Py_END_ALLOW_THREADS if (!result) return path_error2(src, dst); #else Py_BEGIN_ALLOW_THREADS #ifdef HAVE_LINKAT if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) { if (HAVE_LINKAT_RUNTIME) { result = linkat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow, follow_symlinks ? AT_SYMLINK_FOLLOW : 0); } #ifdef __APPLE__ else { if (src_dir_fd == DEFAULT_DIR_FD && dst_dir_fd == DEFAULT_DIR_FD) { /* See issue 41355: This matches the behaviour of !HAVE_LINKAT */ result = link(src->narrow, dst->narrow); } else { linkat_unavailable = 1; } } #endif } else #endif /* HAVE_LINKAT */ result = link(src->narrow, dst->narrow); Py_END_ALLOW_THREADS #ifdef HAVE_LINKAT if (linkat_unavailable) { /* Either or both dir_fd arguments were specified */ if (src_dir_fd != DEFAULT_DIR_FD) { argument_unavailable_error("link", "src_dir_fd"); } else { argument_unavailable_error("link", "dst_dir_fd"); } return NULL; } #endif if (result) return path_error2(src, dst); #endif /* MS_WINDOWS */ Py_RETURN_NONE; } #endif #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR) static PyObject * _listdir_windows_no_opendir(path_t *path, PyObject *list) { PyObject *v; HANDLE hFindFile = INVALID_HANDLE_VALUE; BOOL result; wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */ /* only claim to have space for MAX_PATH */ Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4; wchar_t *wnamebuf = NULL; WIN32_FIND_DATAW wFileData; const wchar_t *po_wchars; if (!path->wide) { /* Default arg: "." */ po_wchars = L"."; len = 1; } else { po_wchars = path->wide; len = wcslen(path->wide); } /* The +5 is so we can append "\\*.*\0" */ wnamebuf = PyMem_New(wchar_t, len + 5); if (!wnamebuf) { PyErr_NoMemory(); goto exit; } wcscpy(wnamebuf, po_wchars); if (len > 0) { wchar_t wch = wnamebuf[len-1]; if (wch != SEP && wch != ALTSEP && wch != L':') wnamebuf[len++] = SEP; wcscpy(wnamebuf + len, L"*.*"); } if ((list = PyList_New(0)) == NULL) { goto exit; } Py_BEGIN_ALLOW_THREADS hFindFile = FindFirstFileW(wnamebuf, &wFileData); Py_END_ALLOW_THREADS if (hFindFile == INVALID_HANDLE_VALUE) { int error = GetLastError(); if (error == ERROR_FILE_NOT_FOUND) goto exit; Py_DECREF(list); list = path_error(path); goto exit; } do { /* Skip over . and .. */ if (wcscmp(wFileData.cFileName, L".") != 0 && wcscmp(wFileData.cFileName, L"..") != 0) { v = PyUnicode_FromWideChar(wFileData.cFileName, wcslen(wFileData.cFileName)); if (path->narrow && v) { Py_SETREF(v, PyUnicode_EncodeFSDefault(v)); } if (v == NULL) { Py_SETREF(list, NULL); break; } if (PyList_Append(list, v) != 0) { Py_DECREF(v); Py_SETREF(list, NULL); break; } Py_DECREF(v); } Py_BEGIN_ALLOW_THREADS result = FindNextFileW(hFindFile, &wFileData); Py_END_ALLOW_THREADS /* FindNextFile sets error to ERROR_NO_MORE_FILES if it got to the end of the directory. */ if (!result && GetLastError() != ERROR_NO_MORE_FILES) { Py_DECREF(list); list = path_error(path); goto exit; } } while (result == TRUE); exit: if (hFindFile != INVALID_HANDLE_VALUE) { if (FindClose(hFindFile) == FALSE) { if (list != NULL) { Py_DECREF(list); list = path_error(path); } } } PyMem_Free(wnamebuf); return list; } /* end of _listdir_windows_no_opendir */ #else /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */ static PyObject * _posix_listdir(path_t *path, PyObject *list) { PyObject *v; DIR *dirp = NULL; struct dirent *ep; int return_str; /* if false, return bytes */ #ifdef HAVE_FDOPENDIR int fd = -1; #endif errno = 0; #ifdef HAVE_FDOPENDIR if (path->fd != -1) { if (HAVE_FDOPENDIR_RUNTIME) { /* closedir() closes the FD, so we duplicate it */ fd = _Py_dup(path->fd); if (fd == -1) return NULL; return_str = 1; Py_BEGIN_ALLOW_THREADS dirp = fdopendir(fd); Py_END_ALLOW_THREADS } else { PyErr_SetString(PyExc_TypeError, "listdir: path should be string, bytes, os.PathLike or None, not int"); return NULL; } } else #endif { const char *name; if (path->narrow) { name = path->narrow; /* only return bytes if they specified a bytes object */ return_str = !PyBytes_Check(path->object); } else { name = "."; return_str = 1; } Py_BEGIN_ALLOW_THREADS dirp = opendir(name); Py_END_ALLOW_THREADS } if (dirp == NULL) { list = path_error(path); #ifdef HAVE_FDOPENDIR if (fd != -1) { Py_BEGIN_ALLOW_THREADS close(fd); Py_END_ALLOW_THREADS } #endif goto exit; } if ((list = PyList_New(0)) == NULL) { goto exit; } for (;;) { errno = 0; Py_BEGIN_ALLOW_THREADS ep = readdir(dirp); Py_END_ALLOW_THREADS if (ep == NULL) { if (errno == 0) { break; } else { Py_DECREF(list); list = path_error(path); goto exit; } } if (ep->d_name[0] == '.' && (NAMLEN(ep) == 1 || (ep->d_name[1] == '.' && NAMLEN(ep) == 2))) continue; if (return_str) v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep)); else v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep)); if (v == NULL) { Py_CLEAR(list); break; } if (PyList_Append(list, v) != 0) { Py_DECREF(v); Py_CLEAR(list); break; } Py_DECREF(v); } exit: if (dirp != NULL) { Py_BEGIN_ALLOW_THREADS #ifdef HAVE_FDOPENDIR if (fd > -1) rewinddir(dirp); #endif closedir(dirp); Py_END_ALLOW_THREADS } return list; } /* end of _posix_listdir */ #endif /* which OS */ /*[clinic input] os.listdir path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None Return a list containing the names of the files in the directory. path can be specified as either str, bytes, or a path-like object. If path is bytes, the filenames returned will also be bytes; in all other circumstances the filenames returned will be str. If path is None, uses the path='.'. On some platforms, path may also be specified as an open file descriptor;\ the file descriptor must refer to a directory. If this functionality is unavailable, using it raises NotImplementedError. The list is in arbitrary order. It does not include the special entries '.' and '..' even if they are present in the directory. [clinic start generated code]*/ static PyObject * os_listdir_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=293045673fcd1a75 input=e3f58030f538295d]*/ { if (PySys_Audit("os.listdir", "O", path->object ? path->object : Py_None) < 0) { return NULL; } #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR) return _listdir_windows_no_opendir(path, NULL); #else return _posix_listdir(path, NULL); #endif } #ifdef MS_WINDOWS int _PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p) { wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf; DWORD result; result = GetFullPathNameW(path, Py_ARRAY_LENGTH(woutbuf), woutbuf, NULL); if (!result) { return -1; } if (result >= Py_ARRAY_LENGTH(woutbuf)) { if ((size_t)result <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) { woutbufp = PyMem_RawMalloc((size_t)result * sizeof(wchar_t)); } else { woutbufp = NULL; } if (!woutbufp) { *abspath_p = NULL; return 0; } result = GetFullPathNameW(path, result, woutbufp, NULL); if (!result) { PyMem_RawFree(woutbufp); return -1; } } if (woutbufp != woutbuf) { *abspath_p = woutbufp; return 0; } *abspath_p = _PyMem_RawWcsdup(woutbufp); return 0; } /* A helper function for abspath on win32 */ /*[clinic input] os._getfullpathname path: path_t / [clinic start generated code]*/ static PyObject * os__getfullpathname_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/ { wchar_t *abspath; if (_PyOS_getfullpathname(path->wide, &abspath) < 0) { return win32_error_object("GetFullPathNameW", path->object); } if (abspath == NULL) { return PyErr_NoMemory(); } PyObject *str = PyUnicode_FromWideChar(abspath, wcslen(abspath)); PyMem_RawFree(abspath); if (str == NULL) { return NULL; } if (path->narrow) { Py_SETREF(str, PyUnicode_EncodeFSDefault(str)); } return str; } /*[clinic input] os._getfinalpathname path: path_t / A helper function for samepath on windows. [clinic start generated code]*/ static PyObject * os__getfinalpathname_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/ { HANDLE hFile; wchar_t buf[MAXPATHLEN], *target_path = buf; int buf_size = Py_ARRAY_LENGTH(buf); int result_length; PyObject *result; Py_BEGIN_ALLOW_THREADS hFile = CreateFileW( path->wide, 0, /* desired access */ 0, /* share mode */ NULL, /* security attributes */ OPEN_EXISTING, /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */ FILE_FLAG_BACKUP_SEMANTICS, NULL); Py_END_ALLOW_THREADS if (hFile == INVALID_HANDLE_VALUE) { return win32_error_object("CreateFileW", path->object); } /* We have a good handle to the target, use it to determine the target path name. */ while (1) { Py_BEGIN_ALLOW_THREADS result_length = GetFinalPathNameByHandleW(hFile, target_path, buf_size, VOLUME_NAME_DOS); Py_END_ALLOW_THREADS if (!result_length) { result = win32_error_object("GetFinalPathNameByHandleW", path->object); goto cleanup; } if (result_length < buf_size) { break; } wchar_t *tmp; tmp = PyMem_Realloc(target_path != buf ? target_path : NULL, result_length * sizeof(*tmp)); if (!tmp) { result = PyErr_NoMemory(); goto cleanup; } buf_size = result_length; target_path = tmp; } result = PyUnicode_FromWideChar(target_path, result_length); if (result && path->narrow) { Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); } cleanup: if (target_path != buf) { PyMem_Free(target_path); } CloseHandle(hFile); return result; } /*[clinic input] os._getvolumepathname path: path_t A helper function for ismount on Win32. [clinic start generated code]*/ static PyObject * os__getvolumepathname_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/ { PyObject *result; wchar_t *mountpath=NULL; size_t buflen; BOOL ret; /* Volume path should be shorter than entire path */ buflen = Py_MAX(path->length, MAX_PATH); if (buflen > PY_DWORD_MAX) { PyErr_SetString(PyExc_OverflowError, "path too long"); return NULL; } mountpath = PyMem_New(wchar_t, buflen); if (mountpath == NULL) return PyErr_NoMemory(); Py_BEGIN_ALLOW_THREADS ret = GetVolumePathNameW(path->wide, mountpath, Py_SAFE_DOWNCAST(buflen, size_t, DWORD)); Py_END_ALLOW_THREADS if (!ret) { result = win32_error_object("_getvolumepathname", path->object); goto exit; } result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath)); if (path->narrow) Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); exit: PyMem_Free(mountpath); return result; } /*[clinic input] os._path_splitroot path: path_t Removes everything after the root on Win32. [clinic start generated code]*/ static PyObject * os__path_splitroot_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=ab7f1a88b654581c input=dc93b1d3984cffb6]*/ { wchar_t *buffer; wchar_t *end; PyObject *result = NULL; HRESULT ret; buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1)); if (!buffer) { return NULL; } wcscpy(buffer, path->wide); for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) { *p = L'\\'; } Py_BEGIN_ALLOW_THREADS ret = PathCchSkipRoot(buffer, &end); Py_END_ALLOW_THREADS if (FAILED(ret)) { result = Py_BuildValue("sO", "", path->object); } else if (end != buffer) { size_t rootLen = (size_t)(end - buffer); result = Py_BuildValue("NN", PyUnicode_FromWideChar(path->wide, rootLen), PyUnicode_FromWideChar(path->wide + rootLen, -1) ); } else { result = Py_BuildValue("Os", path->object, ""); } PyMem_Free(buffer); return result; } #endif /* MS_WINDOWS */ /*[clinic input] os._path_normpath path: object Basic path normalization. [clinic start generated code]*/ static PyObject * os__path_normpath_impl(PyObject *module, PyObject *path) /*[clinic end generated code: output=b94d696d828019da input=5e90c39e12549dc0]*/ { if (!PyUnicode_Check(path)) { PyErr_Format(PyExc_TypeError, "expected 'str', not '%.200s'", Py_TYPE(path)->tp_name); return NULL; } Py_ssize_t len; wchar_t *buffer = PyUnicode_AsWideCharString(path, &len); if (!buffer) { return NULL; } PyObject *result = PyUnicode_FromWideChar(_Py_normpath(buffer, len), -1); PyMem_Free(buffer); return result; } /*[clinic input] os.mkdir path : path_t mode: int = 0o777 * dir_fd : dir_fd(requires='mkdirat') = None # "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\ Create a directory. If dir_fd is not None, it should be a file descriptor open to a directory, and path should be relative; path will then be relative to that directory. dir_fd may not be implemented on your platform. If it is unavailable, using it will raise a NotImplementedError. The mode argument is ignored on Windows. Where it is used, the current umask value is first masked out. [clinic start generated code]*/ static PyObject * os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd) /*[clinic end generated code: output=a70446903abe821f input=a61722e1576fab03]*/ { int result; #ifdef HAVE_MKDIRAT int mkdirat_unavailable = 0; #endif if (PySys_Audit("os.mkdir", "Oii", path->object, mode, dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { return NULL; } #ifdef MS_WINDOWS Py_BEGIN_ALLOW_THREADS result = CreateDirectoryW(path->wide, NULL); Py_END_ALLOW_THREADS if (!result) return path_error(path); #else Py_BEGIN_ALLOW_THREADS #if HAVE_MKDIRAT if (dir_fd != DEFAULT_DIR_FD) { if (HAVE_MKDIRAT_RUNTIME) { result = mkdirat(dir_fd, path->narrow, mode); } else { mkdirat_unavailable = 1; } } else #endif #if defined(__WATCOMC__) && !defined(__QNX__) result = mkdir(path->narrow); #else result = mkdir(path->narrow, mode); #endif Py_END_ALLOW_THREADS #if HAVE_MKDIRAT if (mkdirat_unavailable) { argument_unavailable_error(NULL, "dir_fd"); return NULL; } #endif if (result < 0) return path_error(path); #endif /* MS_WINDOWS */ Py_RETURN_NONE; } /* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */ #if defined(HAVE_SYS_RESOURCE_H) #include #endif #ifdef HAVE_NICE /*[clinic input] os.nice increment: int / Add increment to the priority of process and return the new priority. [clinic start generated code]*/ static PyObject * os_nice_impl(PyObject *module, int increment) /*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/ { int value; /* There are two flavours of 'nice': one that returns the new priority (as required by almost all standards out there) and the Linux/FreeBSD one, which returns '0' on success and advices the use of getpriority() to get the new priority. If we are of the nice family that returns the new priority, we need to clear errno before the call, and check if errno is filled before calling posix_error() on a returnvalue of -1, because the -1 may be the actual new priority! */ errno = 0; value = nice(increment); #if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY) if (value == 0) value = getpriority(PRIO_PROCESS, 0); #endif if (value == -1 && errno != 0) /* either nice() or getpriority() returned an error */ return posix_error(); return PyLong_FromLong((long) value); } #endif /* HAVE_NICE */ #ifdef HAVE_GETPRIORITY /*[clinic input] os.getpriority which: int who: int Return program scheduling priority. [clinic start generated code]*/ static PyObject * os_getpriority_impl(PyObject *module, int which, int who) /*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/ { int retval; errno = 0; retval = getpriority(which, who); if (errno != 0) return posix_error(); return PyLong_FromLong((long)retval); } #endif /* HAVE_GETPRIORITY */ #ifdef HAVE_SETPRIORITY /*[clinic input] os.setpriority which: int who: int priority: int Set program scheduling priority. [clinic start generated code]*/ static PyObject * os_setpriority_impl(PyObject *module, int which, int who, int priority) /*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/ { int retval; retval = setpriority(which, who, priority); if (retval == -1) return posix_error(); Py_RETURN_NONE; } #endif /* HAVE_SETPRIORITY */ static PyObject * internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace) { const char *function_name = is_replace ? "replace" : "rename"; int dir_fd_specified; #ifdef HAVE_RENAMEAT int renameat_unavailable = 0; #endif #ifdef MS_WINDOWS BOOL result; int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0; #else int result; #endif dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD); #ifndef HAVE_RENAMEAT if (dir_fd_specified) { argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd"); return NULL; } #endif if (PySys_Audit("os.rename", "OOii", src->object, dst->object, src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd, dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) { return NULL; } #ifdef MS_WINDOWS Py_BEGIN_ALLOW_THREADS result = MoveFileExW(src->wide, dst->wide, flags); Py_END_ALLOW_THREADS if (!result) return path_error2(src, dst); #else if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) { PyErr_Format(PyExc_ValueError, "%s: src and dst must be the same type", function_name); return NULL; } Py_BEGIN_ALLOW_THREADS #ifdef HAVE_RENAMEAT if (dir_fd_specified) { if (HAVE_RENAMEAT_RUNTIME) { result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow); } else { renameat_unavailable = 1; } } else #endif result = rename(src->narrow, dst->narrow); Py_END_ALLOW_THREADS #ifdef HAVE_RENAMEAT if (renameat_unavailable) { argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd"); return NULL; } #endif if (result) return path_error2(src, dst); #endif Py_RETURN_NONE; } /*[clinic input] os.rename src : path_t dst : path_t * src_dir_fd : dir_fd = None dst_dir_fd : dir_fd = None Rename a file or directory. If either src_dir_fd or dst_dir_fd is not None, it should be a file descriptor open to a directory, and the respective path string (src or dst) should be relative; the path will then be relative to that directory. src_dir_fd and dst_dir_fd, may not be implemented on your platform. If they are unavailable, using them will raise a NotImplementedError. [clinic start generated code]*/ static PyObject * os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd) /*[clinic end generated code: output=59e803072cf41230 input=faa61c847912c850]*/ { return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0); } /*[clinic input] os.replace = os.rename Rename a file or directory, overwriting the destination. If either src_dir_fd or dst_dir_fd is not None, it should be a file descriptor open to a directory, and the respective path string (src or dst) should be relative; the path will then be relative to that directory. src_dir_fd and dst_dir_fd, may not be implemented on your platform. If they are unavailable, using them will raise a NotImplementedError. [clinic start generated code]*/ static PyObject * os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd) /*[clinic end generated code: output=1968c02e7857422b input=c003f0def43378ef]*/ { return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1); } /*[clinic input] os.rmdir path: path_t * dir_fd: dir_fd(requires='unlinkat') = None Remove a directory. If dir_fd is not None, it should be a file descriptor open to a directory, and path should be relative; path will then be relative to that directory. dir_fd may not be implemented on your platform. If it is unavailable, using it will raise a NotImplementedError. [clinic start generated code]*/ static PyObject * os_rmdir_impl(PyObject *module, path_t *path, int dir_fd) /*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/ { int result; #ifdef HAVE_UNLINKAT int unlinkat_unavailable = 0; #endif if (PySys_Audit("os.rmdir", "Oi", path->object, dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { return NULL; } Py_BEGIN_ALLOW_THREADS #ifdef MS_WINDOWS /* Windows, success=1, UNIX, success=0 */ result = !RemoveDirectoryW(path->wide); #else #ifdef HAVE_UNLINKAT if (dir_fd != DEFAULT_DIR_FD) { if (HAVE_UNLINKAT_RUNTIME) { result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR); } else { unlinkat_unavailable = 1; result = -1; } } else #endif result = rmdir(path->narrow); #endif Py_END_ALLOW_THREADS #ifdef HAVE_UNLINKAT if (unlinkat_unavailable) { argument_unavailable_error("rmdir", "dir_fd"); return NULL; } #endif if (result) return path_error(path); Py_RETURN_NONE; } #ifdef HAVE_SYSTEM #ifdef MS_WINDOWS /*[clinic input] os.system -> long command: Py_UNICODE Execute the command in a subshell. [clinic start generated code]*/ static long os_system_impl(PyObject *module, const Py_UNICODE *command) /*[clinic end generated code: output=5b7c3599c068ca42 input=303f5ce97df606b0]*/ { long result; if (PySys_Audit("os.system", "(u)", command) < 0) { return -1; } Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH result = _wsystem(command); _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS return result; } #else /* MS_WINDOWS */ /*[clinic input] os.system -> long command: FSConverter Execute the command in a subshell. [clinic start generated code]*/ static long os_system_impl(PyObject *module, PyObject *command) /*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/ { long result; const char *bytes = PyBytes_AsString(command); if (PySys_Audit("os.system", "(O)", command) < 0) { return -1; } Py_BEGIN_ALLOW_THREADS result = system(bytes); Py_END_ALLOW_THREADS return result; } #endif #endif /* HAVE_SYSTEM */ #ifdef HAVE_UMASK /*[clinic input] os.umask mask: int / Set the current numeric umask and return the previous umask. [clinic start generated code]*/ static PyObject * os_umask_impl(PyObject *module, int mask) /*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/ { int i = (int)umask(mask); if (i < 0) return posix_error(); return PyLong_FromLong((long)i); } #endif #ifdef MS_WINDOWS /* override the default DeleteFileW behavior so that directory symlinks can be removed with this function, the same as with Unix symlinks */ BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName) { WIN32_FILE_ATTRIBUTE_DATA info; WIN32_FIND_DATAW find_data; HANDLE find_data_handle; int is_directory = 0; int is_link = 0; if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) { is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; /* Get WIN32_FIND_DATA structure for the path to determine if it is a symlink */ if(is_directory && info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { find_data_handle = FindFirstFileW(lpFileName, &find_data); if(find_data_handle != INVALID_HANDLE_VALUE) { /* IO_REPARSE_TAG_SYMLINK if it is a symlink and IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */ is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK || find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT; FindClose(find_data_handle); } } } if (is_directory && is_link) return RemoveDirectoryW(lpFileName); return DeleteFileW(lpFileName); } #endif /* MS_WINDOWS */ /*[clinic input] os.unlink path: path_t * dir_fd: dir_fd(requires='unlinkat')=None Remove a file (same as remove()). If dir_fd is not None, it should be a file descriptor open to a directory, and path should be relative; path will then be relative to that directory. dir_fd may not be implemented on your platform. If it is unavailable, using it will raise a NotImplementedError. [clinic start generated code]*/ static PyObject * os_unlink_impl(PyObject *module, path_t *path, int dir_fd) /*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/ { int result; #ifdef HAVE_UNLINKAT int unlinkat_unavailable = 0; #endif if (PySys_Audit("os.remove", "Oi", path->object, dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { return NULL; } Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH #ifdef MS_WINDOWS /* Windows, success=1, UNIX, success=0 */ result = !Py_DeleteFileW(path->wide); #else #ifdef HAVE_UNLINKAT if (dir_fd != DEFAULT_DIR_FD) { if (HAVE_UNLINKAT_RUNTIME) { result = unlinkat(dir_fd, path->narrow, 0); } else { unlinkat_unavailable = 1; } } else #endif /* HAVE_UNLINKAT */ result = unlink(path->narrow); #endif _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS #ifdef HAVE_UNLINKAT if (unlinkat_unavailable) { argument_unavailable_error(NULL, "dir_fd"); return NULL; } #endif if (result) return path_error(path); Py_RETURN_NONE; } /*[clinic input] os.remove = os.unlink Remove a file (same as unlink()). If dir_fd is not None, it should be a file descriptor open to a directory, and path should be relative; path will then be relative to that directory. dir_fd may not be implemented on your platform. If it is unavailable, using it will raise a NotImplementedError. [clinic start generated code]*/ static PyObject * os_remove_impl(PyObject *module, path_t *path, int dir_fd) /*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/ { return os_unlink_impl(module, path, dir_fd); } static PyStructSequence_Field uname_result_fields[] = { {"sysname", "operating system name"}, {"nodename", "name of machine on network (implementation-defined)"}, {"release", "operating system release"}, {"version", "operating system version"}, {"machine", "hardware identifier"}, {NULL} }; PyDoc_STRVAR(uname_result__doc__, "uname_result: Result from os.uname().\n\n\ This object may be accessed either as a tuple of\n\ (sysname, nodename, release, version, machine),\n\ or via the attributes sysname, nodename, release, version, and machine.\n\ \n\ See os.uname for more information."); static PyStructSequence_Desc uname_result_desc = { MODNAME ".uname_result", /* name */ uname_result__doc__, /* doc */ uname_result_fields, 5 }; #ifdef HAVE_UNAME /*[clinic input] os.uname Return an object identifying the current operating system. The object behaves like a named tuple with the following fields: (sysname, nodename, release, version, machine) [clinic start generated code]*/ static PyObject * os_uname_impl(PyObject *module) /*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/ { struct utsname u; int res; PyObject *value; Py_BEGIN_ALLOW_THREADS res = uname(&u); Py_END_ALLOW_THREADS if (res < 0) return posix_error(); PyObject *UnameResultType = get_posix_state(module)->UnameResultType; value = PyStructSequence_New((PyTypeObject *)UnameResultType); if (value == NULL) return NULL; #define SET(i, field) \ { \ PyObject *o = PyUnicode_DecodeFSDefault(field); \ if (!o) { \ Py_DECREF(value); \ return NULL; \ } \ PyStructSequence_SET_ITEM(value, i, o); \ } \ SET(0, u.sysname); SET(1, u.nodename); SET(2, u.release); SET(3, u.version); SET(4, u.machine); #undef SET return value; } #endif /* HAVE_UNAME */ typedef struct { int now; time_t atime_s; long atime_ns; time_t mtime_s; long mtime_ns; } utime_t; /* * these macros assume that "ut" is a pointer to a utime_t * they also intentionally leak the declaration of a pointer named "time" */ #define UTIME_TO_TIMESPEC \ struct timespec ts[2]; \ struct timespec *time; \ if (ut->now) \ time = NULL; \ else { \ ts[0].tv_sec = ut->atime_s; \ ts[0].tv_nsec = ut->atime_ns; \ ts[1].tv_sec = ut->mtime_s; \ ts[1].tv_nsec = ut->mtime_ns; \ time = ts; \ } \ #define UTIME_TO_TIMEVAL \ struct timeval tv[2]; \ struct timeval *time; \ if (ut->now) \ time = NULL; \ else { \ tv[0].tv_sec = ut->atime_s; \ tv[0].tv_usec = ut->atime_ns / 1000; \ tv[1].tv_sec = ut->mtime_s; \ tv[1].tv_usec = ut->mtime_ns / 1000; \ time = tv; \ } \ #define UTIME_TO_UTIMBUF \ struct utimbuf u; \ struct utimbuf *time; \ if (ut->now) \ time = NULL; \ else { \ u.actime = ut->atime_s; \ u.modtime = ut->mtime_s; \ time = &u; \ } #define UTIME_TO_TIME_T \ time_t timet[2]; \ time_t *time; \ if (ut->now) \ time = NULL; \ else { \ timet[0] = ut->atime_s; \ timet[1] = ut->mtime_s; \ time = timet; \ } \ #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT) static int utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks) { #if defined(__APPLE__) && defined(HAVE_UTIMENSAT) if (HAVE_UTIMENSAT_RUNTIME) { int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW; UTIME_TO_TIMESPEC; return utimensat(dir_fd, path, time, flags); } else { errno = ENOSYS; return -1; } #elif defined(HAVE_UTIMENSAT) int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW; UTIME_TO_TIMESPEC; return utimensat(dir_fd, path, time, flags); #elif defined(HAVE_FUTIMESAT) UTIME_TO_TIMEVAL; /* * follow_symlinks will never be false here; * we only allow !follow_symlinks and dir_fd together * if we have utimensat() */ assert(follow_symlinks); return futimesat(dir_fd, path, time); #endif } #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter #else #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable #endif #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS) static int utime_fd(utime_t *ut, int fd) { #ifdef HAVE_FUTIMENS if (HAVE_FUTIMENS_RUNTIME) { UTIME_TO_TIMESPEC; return futimens(fd, time); } else #ifndef HAVE_FUTIMES { /* Not sure if this can happen */ PyErr_SetString( PyExc_RuntimeError, "neither futimens nor futimes are supported" " on this system"); return -1; } #endif #endif #ifdef HAVE_FUTIMES { UTIME_TO_TIMEVAL; return futimes(fd, time); } #endif } #define PATH_UTIME_HAVE_FD 1 #else #define PATH_UTIME_HAVE_FD 0 #endif #if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES) # define UTIME_HAVE_NOFOLLOW_SYMLINKS #endif #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS static int utime_nofollow_symlinks(utime_t *ut, const char *path) { #ifdef HAVE_UTIMENSAT if (HAVE_UTIMENSAT_RUNTIME) { UTIME_TO_TIMESPEC; return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW); } else #ifndef HAVE_LUTIMES { /* Not sure if this can happen */ PyErr_SetString( PyExc_RuntimeError, "neither utimensat nor lutimes are supported" " on this system"); return -1; } #endif #endif #ifdef HAVE_LUTIMES { UTIME_TO_TIMEVAL; return lutimes(path, time); } #endif } #endif #ifndef MS_WINDOWS static int utime_default(utime_t *ut, const char *path) { #if defined(__APPLE__) && defined(HAVE_UTIMENSAT) if (HAVE_UTIMENSAT_RUNTIME) { UTIME_TO_TIMESPEC; return utimensat(DEFAULT_DIR_FD, path, time, 0); } else { UTIME_TO_TIMEVAL; return utimes(path, time); } #elif defined(HAVE_UTIMENSAT) UTIME_TO_TIMESPEC; return utimensat(DEFAULT_DIR_FD, path, time, 0); #elif defined(HAVE_UTIMES) UTIME_TO_TIMEVAL; return utimes(path, time); #elif defined(HAVE_UTIME_H) UTIME_TO_UTIMBUF; return utime(path, time); #else UTIME_TO_TIME_T; return utime(path, time); #endif } #endif static int split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns) { int result = 0; PyObject *divmod; divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion); if (!divmod) goto exit; if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) { PyErr_Format(PyExc_TypeError, "%.200s.__divmod__() must return a 2-tuple, not %.200s", _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod))); goto exit; } *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0)); if ((*s == -1) && PyErr_Occurred()) goto exit; *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1)); if ((*ns == -1) && PyErr_Occurred()) goto exit; result = 1; exit: Py_XDECREF(divmod); return result; } /*[clinic input] os.utime path: path_t(allow_fd='PATH_UTIME_HAVE_FD') times: object = None * ns: object = NULL dir_fd: dir_fd(requires='futimensat') = None follow_symlinks: bool=True # "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\ Set the access and modified time of path. path may always be specified as a string. On some platforms, path may also be specified as an open file descriptor. If this functionality is unavailable, using it raises an exception. If times is not None, it must be a tuple (atime, mtime); atime and mtime should be expressed as float seconds since the epoch. If ns is specified, it must be a tuple (atime_ns, mtime_ns); atime_ns and mtime_ns should be expressed as integer nanoseconds since the epoch. If times is None and ns is unspecified, utime uses the current time. Specifying tuples for both times and ns is an error. If dir_fd is not None, it should be a file descriptor open to a directory, and path should be relative; path will then be relative to that directory. If follow_symlinks is False, and the last element of the path is a symbolic link, utime will modify the symbolic link itself instead of the file the link points to. It is an error to use dir_fd or follow_symlinks when specifying path as an open file descriptor. dir_fd and follow_symlinks may not be available on your platform. If they are unavailable, using them will raise a NotImplementedError. [clinic start generated code]*/ static PyObject * os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, int dir_fd, int follow_symlinks) /*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/ { #ifdef MS_WINDOWS HANDLE hFile; FILETIME atime, mtime; #else int result; #endif utime_t utime; memset(&utime, 0, sizeof(utime_t)); if (times != Py_None && ns) { PyErr_SetString(PyExc_ValueError, "utime: you may specify either 'times'" " or 'ns' but not both"); return NULL; } if (times != Py_None) { time_t a_sec, m_sec; long a_nsec, m_nsec; if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) { PyErr_SetString(PyExc_TypeError, "utime: 'times' must be either" " a tuple of two ints or None"); return NULL; } utime.now = 0; if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0), &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 || _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1), &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) { return NULL; } utime.atime_s = a_sec; utime.atime_ns = a_nsec; utime.mtime_s = m_sec; utime.mtime_ns = m_nsec; } else if (ns) { if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) { PyErr_SetString(PyExc_TypeError, "utime: 'ns' must be a tuple of two ints"); return NULL; } utime.now = 0; if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0), &utime.atime_s, &utime.atime_ns) || !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1), &utime.mtime_s, &utime.mtime_ns)) { return NULL; } } else { /* times and ns are both None/unspecified. use "now". */ utime.now = 1; } #if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS) if (follow_symlinks_specified("utime", follow_symlinks)) return NULL; #endif if (path_and_dir_fd_invalid("utime", path, dir_fd) || dir_fd_and_fd_invalid("utime", dir_fd, path->fd) || fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks)) return NULL; #if !defined(HAVE_UTIMENSAT) if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) { PyErr_SetString(PyExc_ValueError, "utime: cannot use dir_fd and follow_symlinks " "together on this platform"); return NULL; } #endif if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None, dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { return NULL; } #ifdef MS_WINDOWS Py_BEGIN_ALLOW_THREADS hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); Py_END_ALLOW_THREADS if (hFile == INVALID_HANDLE_VALUE) { path_error(path); return NULL; } if (utime.now) { GetSystemTimeAsFileTime(&mtime); atime = mtime; } else { _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime); _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime); } if (!SetFileTime(hFile, NULL, &atime, &mtime)) { /* Avoid putting the file name into the error here, as that may confuse the user into believing that something is wrong with the file, when it also could be the time stamp that gives a problem. */ PyErr_SetFromWindowsErr(0); CloseHandle(hFile); return NULL; } CloseHandle(hFile); #else /* MS_WINDOWS */ Py_BEGIN_ALLOW_THREADS #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) result = utime_nofollow_symlinks(&utime, path->narrow); else #endif #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT) if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) { result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks); } else #endif #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS) if (path->fd != -1) result = utime_fd(&utime, path->fd); else #endif result = utime_default(&utime, path->narrow); Py_END_ALLOW_THREADS #if defined(__APPLE__) && defined(HAVE_UTIMENSAT) /* See utime_dir_fd implementation */ if (result == -1 && errno == ENOSYS) { argument_unavailable_error(NULL, "dir_fd"); return NULL; } #endif if (result < 0) { /* see previous comment about not putting filename in error here */ posix_error(); return NULL; } #endif /* MS_WINDOWS */ Py_RETURN_NONE; } /* Process operations */ /*[clinic input] os._exit status: int Exit to the system with specified status, without normal exit processing. [clinic start generated code]*/ static PyObject * os__exit_impl(PyObject *module, int status) /*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/ { _exit(status); return NULL; /* Make gcc -Wall happy */ } #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV) #define EXECV_CHAR wchar_t #else #define EXECV_CHAR char #endif #if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN) static void free_string_array(EXECV_CHAR **array, Py_ssize_t count) { Py_ssize_t i; for (i = 0; i < count; i++) PyMem_Free(array[i]); PyMem_Free(array); } static int fsconvert_strdup(PyObject *o, EXECV_CHAR **out) { Py_ssize_t size; PyObject *ub; int result = 0; #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV) if (!PyUnicode_FSDecoder(o, &ub)) return 0; *out = PyUnicode_AsWideCharString(ub, &size); if (*out) result = 1; #else if (!PyUnicode_FSConverter(o, &ub)) return 0; size = PyBytes_GET_SIZE(ub); *out = PyMem_Malloc(size + 1); if (*out) { memcpy(*out, PyBytes_AS_STRING(ub), size + 1); result = 1; } else PyErr_NoMemory(); #endif Py_DECREF(ub); return result; } #endif #if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN) static EXECV_CHAR** parse_envlist(PyObject* env, Py_ssize_t *envc_ptr) { Py_ssize_t i, pos, envc; PyObject *keys=NULL, *vals=NULL; PyObject *key, *val, *key2, *val2, *keyval; EXECV_CHAR **envlist; i = PyMapping_Size(env); if (i < 0) return NULL; envlist = PyMem_NEW(EXECV_CHAR *, i + 1); if (envlist == NULL) { PyErr_NoMemory(); return NULL; } envc = 0; keys = PyMapping_Keys(env); if (!keys) goto error; vals = PyMapping_Values(env); if (!vals) goto error; if (!PyList_Check(keys) || !PyList_Check(vals)) { PyErr_Format(PyExc_TypeError, "env.keys() or env.values() is not a list"); goto error; } for (pos = 0; pos < i; pos++) { key = PyList_GetItem(keys, pos); val = PyList_GetItem(vals, pos); if (!key || !val) goto error; #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV) if (!PyUnicode_FSDecoder(key, &key2)) goto error; if (!PyUnicode_FSDecoder(val, &val2)) { Py_DECREF(key2); goto error; } /* Search from index 1 because on Windows starting '=' is allowed for defining hidden environment variables. */ if (PyUnicode_GET_LENGTH(key2) == 0 || PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1) { PyErr_SetString(PyExc_ValueError, "illegal environment variable name"); Py_DECREF(key2); Py_DECREF(val2); goto error; } keyval = PyUnicode_FromFormat("%U=%U", key2, val2); #else if (!PyUnicode_FSConverter(key, &key2)) goto error; if (!PyUnicode_FSConverter(val, &val2)) { Py_DECREF(key2); goto error; } if (PyBytes_GET_SIZE(key2) == 0 || strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL) { PyErr_SetString(PyExc_ValueError, "illegal environment variable name"); Py_DECREF(key2); Py_DECREF(val2); goto error; } keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2), PyBytes_AS_STRING(val2)); #endif Py_DECREF(key2); Py_DECREF(val2); if (!keyval) goto error; if (!fsconvert_strdup(keyval, &envlist[envc++])) { Py_DECREF(keyval); goto error; } Py_DECREF(keyval); } Py_DECREF(vals); Py_DECREF(keys); envlist[envc] = 0; *envc_ptr = envc; return envlist; error: Py_XDECREF(keys); Py_XDECREF(vals); free_string_array(envlist, envc); return NULL; } static EXECV_CHAR** parse_arglist(PyObject* argv, Py_ssize_t *argc) { int i; EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1); if (argvlist == NULL) { PyErr_NoMemory(); return NULL; } for (i = 0; i < *argc; i++) { PyObject* item = PySequence_ITEM(argv, i); if (item == NULL) goto fail; if (!fsconvert_strdup(item, &argvlist[i])) { Py_DECREF(item); goto fail; } Py_DECREF(item); } argvlist[*argc] = NULL; return argvlist; fail: *argc = i; free_string_array(argvlist, *argc); return NULL; } #endif #ifdef HAVE_EXECV /*[clinic input] os.execv path: path_t Path of executable file. argv: object Tuple or list of strings. / Execute an executable path with arguments, replacing current process. [clinic start generated code]*/ static PyObject * os_execv_impl(PyObject *module, path_t *path, PyObject *argv) /*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/ { EXECV_CHAR **argvlist; Py_ssize_t argc; PyInterpreterState *interp = _PyInterpreterState_GET(); if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) { PyErr_SetString(PyExc_RuntimeError, "exec not supported for isolated subinterpreters"); return NULL; } /* execv has two arguments: (path, argv), where argv is a list or tuple of strings. */ if (!PyList_Check(argv) && !PyTuple_Check(argv)) { PyErr_SetString(PyExc_TypeError, "execv() arg 2 must be a tuple or list"); return NULL; } argc = PySequence_Size(argv); if (argc < 1) { PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty"); return NULL; } argvlist = parse_arglist(argv, &argc); if (argvlist == NULL) { return NULL; } if (!argvlist[0][0]) { PyErr_SetString(PyExc_ValueError, "execv() arg 2 first element cannot be empty"); free_string_array(argvlist, argc); return NULL; } if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) { free_string_array(argvlist, argc); return NULL; } _Py_BEGIN_SUPPRESS_IPH #ifdef HAVE_WEXECV _wexecv(path->wide, argvlist); #else execv(path->narrow, argvlist); #endif _Py_END_SUPPRESS_IPH /* If we get here it's definitely an error */ free_string_array(argvlist, argc); return posix_error(); } /*[clinic input] os.execve path: path_t(allow_fd='PATH_HAVE_FEXECVE') Path of executable file. argv: object Tuple or list of strings. env: object Dictionary of strings mapping to strings. Execute an executable path with arguments, replacing current process. [clinic start generated code]*/ static PyObject * os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env) /*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/ { EXECV_CHAR **argvlist = NULL; EXECV_CHAR **envlist; Py_ssize_t argc, envc; PyInterpreterState *interp = _PyInterpreterState_GET(); if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_EXEC)) { PyErr_SetString(PyExc_RuntimeError, "exec not supported for isolated subinterpreters"); return NULL; } /* execve has three arguments: (path, argv, env), where argv is a list or tuple of strings and env is a dictionary like posix.environ. */ if (!PyList_Check(argv) && !PyTuple_Check(argv)) { PyErr_SetString(PyExc_TypeError, "execve: argv must be a tuple or list"); goto fail_0; } argc = PySequence_Size(argv); if (argc < 1) { PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty"); return NULL; } if (!PyMapping_Check(env)) { PyErr_SetString(PyExc_TypeError, "execve: environment must be a mapping object"); goto fail_0; } argvlist = parse_arglist(argv, &argc); if (argvlist == NULL) { goto fail_0; } if (!argvlist[0][0]) { PyErr_SetString(PyExc_ValueError, "execve: argv first element cannot be empty"); goto fail_0; } envlist = parse_envlist(env, &envc); if (envlist == NULL) goto fail_0; if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) { goto fail_1; } _Py_BEGIN_SUPPRESS_IPH #ifdef HAVE_FEXECVE if (path->fd > -1) fexecve(path->fd, argvlist, envlist); else #endif #ifdef HAVE_WEXECV _wexecve(path->wide, argvlist, envlist); #else execve(path->narrow, argvlist, envlist); #endif _Py_END_SUPPRESS_IPH /* If we get here it's definitely an error */ posix_path_error(path); fail_1: free_string_array(envlist, envc); fail_0: if (argvlist) free_string_array(argvlist, argc); return NULL; } #endif /* HAVE_EXECV */ #ifdef HAVE_POSIX_SPAWN enum posix_spawn_file_actions_identifier { POSIX_SPAWN_OPEN, POSIX_SPAWN_CLOSE, POSIX_SPAWN_DUP2 }; #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) static int convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res); #endif static int parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask, PyObject *setsigdef, PyObject *scheduler, posix_spawnattr_t *attrp) { long all_flags = 0; errno = posix_spawnattr_init(attrp); if (errno) { posix_error(); return -1; } if (setpgroup) { pid_t pgid = PyLong_AsPid(setpgroup); if (pgid == (pid_t)-1 && PyErr_Occurred()) { goto fail; } errno = posix_spawnattr_setpgroup(attrp, pgid); if (errno) { posix_error(); goto fail; } all_flags |= POSIX_SPAWN_SETPGROUP; } if (resetids) { all_flags |= POSIX_SPAWN_RESETIDS; } if (setsid) { #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) { #endif #ifdef POSIX_SPAWN_SETSID all_flags |= POSIX_SPAWN_SETSID; #elif defined(POSIX_SPAWN_SETSID_NP) all_flags |= POSIX_SPAWN_SETSID_NP; #else argument_unavailable_error(func_name, "setsid"); return -1; #endif #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME } else { argument_unavailable_error(func_name, "setsid"); return -1; } #endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */ } #ifdef HAVE_SIGSET_T if (setsigmask) { sigset_t set; if (!_Py_Sigset_Converter(setsigmask, &set)) { goto fail; } errno = posix_spawnattr_setsigmask(attrp, &set); if (errno) { posix_error(); goto fail; } all_flags |= POSIX_SPAWN_SETSIGMASK; } if (setsigdef) { sigset_t set; if (!_Py_Sigset_Converter(setsigdef, &set)) { goto fail; } errno = posix_spawnattr_setsigdefault(attrp, &set); if (errno) { posix_error(); goto fail; } all_flags |= POSIX_SPAWN_SETSIGDEF; } #else if (setsigmask || setsigdef) { PyErr_SetString(PyExc_NotImplementedError, "sigset is not supported on this platform"); goto fail; } #endif if (scheduler) { #ifdef POSIX_SPAWN_SETSCHEDULER PyObject *py_schedpolicy; PyObject *schedparam_obj; struct sched_param schedparam; if (!PyArg_ParseTuple(scheduler, "OO" ";A scheduler tuple must have two elements", &py_schedpolicy, &schedparam_obj)) { goto fail; } if (!convert_sched_param(module, schedparam_obj, &schedparam)) { goto fail; } if (py_schedpolicy != Py_None) { int schedpolicy = _PyLong_AsInt(py_schedpolicy); if (schedpolicy == -1 && PyErr_Occurred()) { goto fail; } errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy); if (errno) { posix_error(); goto fail; } all_flags |= POSIX_SPAWN_SETSCHEDULER; } errno = posix_spawnattr_setschedparam(attrp, &schedparam); if (errno) { posix_error(); goto fail; } all_flags |= POSIX_SPAWN_SETSCHEDPARAM; #else PyErr_SetString(PyExc_NotImplementedError, "The scheduler option is not supported in this system."); goto fail; #endif } errno = posix_spawnattr_setflags(attrp, all_flags); if (errno) { posix_error(); goto fail; } return 0; fail: (void)posix_spawnattr_destroy(attrp); return -1; } static int parse_file_actions(PyObject *file_actions, posix_spawn_file_actions_t *file_actionsp, PyObject *temp_buffer) { PyObject *seq; PyObject *file_action = NULL; PyObject *tag_obj; seq = PySequence_Fast(file_actions, "file_actions must be a sequence or None"); if (seq == NULL) { return -1; } errno = posix_spawn_file_actions_init(file_actionsp); if (errno) { posix_error(); Py_DECREF(seq); return -1; } for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) { file_action = PySequence_Fast_GET_ITEM(seq, i); Py_INCREF(file_action); if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) { PyErr_SetString(PyExc_TypeError, "Each file_actions element must be a non-empty tuple"); goto fail; } long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0)); if (tag == -1 && PyErr_Occurred()) { goto fail; } /* Populate the file_actions object */ switch (tag) { case POSIX_SPAWN_OPEN: { int fd, oflag; PyObject *path; unsigned long mode; if (!PyArg_ParseTuple(file_action, "OiO&ik" ";A open file_action tuple must have 5 elements", &tag_obj, &fd, PyUnicode_FSConverter, &path, &oflag, &mode)) { goto fail; } if (PyList_Append(temp_buffer, path)) { Py_DECREF(path); goto fail; } errno = posix_spawn_file_actions_addopen(file_actionsp, fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode); Py_DECREF(path); if (errno) { posix_error(); goto fail; } break; } case POSIX_SPAWN_CLOSE: { int fd; if (!PyArg_ParseTuple(file_action, "Oi" ";A close file_action tuple must have 2 elements", &tag_obj, &fd)) { goto fail; } errno = posix_spawn_file_actions_addclose(file_actionsp, fd); if (errno) { posix_error(); goto fail; } break; } case POSIX_SPAWN_DUP2: { int fd1, fd2; if (!PyArg_ParseTuple(file_action, "Oii" ";A dup2 file_action tuple must have 3 elements", &tag_obj, &fd1, &fd2)) { goto fail; } errno = posix_spawn_file_actions_adddup2(file_actionsp, fd1, fd2); if (errno) { posix_error(); goto fail; } break; } default: { PyErr_SetString(PyExc_TypeError, "Unknown file_actions identifier"); goto fail; } } Py_DECREF(file_action); } Py_DECREF(seq); return 0; fail: Py_DECREF(seq); Py_DECREF(file_action); (void)posix_spawn_file_actions_destroy(file_actionsp); return -1; } static PyObject * py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv, PyObject *env, PyObject *file_actions, PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask, PyObject *setsigdef, PyObject *scheduler) { const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn"; EXECV_CHAR **argvlist = NULL; EXECV_CHAR **envlist = NULL; posix_spawn_file_actions_t file_actions_buf; posix_spawn_file_actions_t *file_actionsp = NULL; posix_spawnattr_t attr; posix_spawnattr_t *attrp = NULL; Py_ssize_t argc, envc; PyObject *result = NULL; PyObject *temp_buffer = NULL; pid_t pid; int err_code; /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where argv is a list or tuple of strings and env is a dictionary like posix.environ. */ if (!PyList_Check(argv) && !PyTuple_Check(argv)) { PyErr_Format(PyExc_TypeError, "%s: argv must be a tuple or list", func_name); goto exit; } argc = PySequence_Size(argv); if (argc < 1) { PyErr_Format(PyExc_ValueError, "%s: argv must not be empty", func_name); return NULL; } if (!PyMapping_Check(env)) { PyErr_Format(PyExc_TypeError, "%s: environment must be a mapping object", func_name); goto exit; } argvlist = parse_arglist(argv, &argc); if (argvlist == NULL) { goto exit; } if (!argvlist[0][0]) { PyErr_Format(PyExc_ValueError, "%s: argv first element cannot be empty", func_name); goto exit; } envlist = parse_envlist(env, &envc); if (envlist == NULL) { goto exit; } if (file_actions != NULL && file_actions != Py_None) { /* There is a bug in old versions of glibc that makes some of the * helper functions for manipulating file actions not copy the provided * buffers. The problem is that posix_spawn_file_actions_addopen does not * copy the value of path for some old versions of glibc (<2.20). * The use of temp_buffer here is a workaround that keeps the * python objects that own the buffers alive until posix_spawn gets called. * Check https://bugs.python.org/issue33630 and * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/ temp_buffer = PyList_New(0); if (!temp_buffer) { goto exit; } if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) { goto exit; } file_actionsp = &file_actions_buf; } if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid, setsigmask, setsigdef, scheduler, &attr)) { goto exit; } attrp = &attr; if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) { goto exit; } _Py_BEGIN_SUPPRESS_IPH #ifdef HAVE_POSIX_SPAWNP if (use_posix_spawnp) { err_code = posix_spawnp(&pid, path->narrow, file_actionsp, attrp, argvlist, envlist); } else #endif /* HAVE_POSIX_SPAWNP */ { err_code = posix_spawn(&pid, path->narrow, file_actionsp, attrp, argvlist, envlist); } _Py_END_SUPPRESS_IPH if (err_code) { errno = err_code; PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object); goto exit; } #ifdef _Py_MEMORY_SANITIZER __msan_unpoison(&pid, sizeof(pid)); #endif result = PyLong_FromPid(pid); exit: if (file_actionsp) { (void)posix_spawn_file_actions_destroy(file_actionsp); } if (attrp) { (void)posix_spawnattr_destroy(attrp); } if (envlist) { free_string_array(envlist, envc); } if (argvlist) { free_string_array(argvlist, argc); } Py_XDECREF(temp_buffer); return result; } /*[clinic input] os.posix_spawn path: path_t Path of executable file. argv: object Tuple or list of strings. env: object Dictionary of strings mapping to strings. / * file_actions: object(c_default='NULL') = () A sequence of file action tuples. setpgroup: object = NULL The pgroup to use with the POSIX_SPAWN_SETPGROUP flag. resetids: bool = False If the value is `true` the POSIX_SPAWN_RESETIDS will be activated. setsid: bool = False If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated. setsigmask: object(c_default='NULL') = () The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag. setsigdef: object(c_default='NULL') = () The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag. scheduler: object = NULL A tuple with the scheduler policy (optional) and parameters. Execute the program specified by path in a new process. [clinic start generated code]*/ static PyObject * os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env, PyObject *file_actions, PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask, PyObject *setsigdef, PyObject *scheduler) /*[clinic end generated code: output=14a1098c566bc675 input=808aed1090d84e33]*/ { return py_posix_spawn(0, module, path, argv, env, file_actions, setpgroup, resetids, setsid, setsigmask, setsigdef, scheduler); } #endif /* HAVE_POSIX_SPAWN */ #ifdef HAVE_POSIX_SPAWNP /*[clinic input] os.posix_spawnp path: path_t Path of executable file. argv: object Tuple or list of strings. env: object Dictionary of strings mapping to strings. / * file_actions: object(c_default='NULL') = () A sequence of file action tuples. setpgroup: object = NULL The pgroup to use with the POSIX_SPAWN_SETPGROUP flag. resetids: bool = False If the value is `True` the POSIX_SPAWN_RESETIDS will be activated. setsid: bool = False If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated. setsigmask: object(c_default='NULL') = () The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag. setsigdef: object(c_default='NULL') = () The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag. scheduler: object = NULL A tuple with the scheduler policy (optional) and parameters. Execute the program specified by path in a new process. [clinic start generated code]*/ static PyObject * os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env, PyObject *file_actions, PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask, PyObject *setsigdef, PyObject *scheduler) /*[clinic end generated code: output=7b9aaefe3031238d input=9e89e616116752a1]*/ { return py_posix_spawn(1, module, path, argv, env, file_actions, setpgroup, resetids, setsid, setsigmask, setsigdef, scheduler); } #endif /* HAVE_POSIX_SPAWNP */ #ifdef HAVE_RTPSPAWN static intptr_t _rtp_spawn(int mode, const char *rtpFileName, const char *argv[], const char *envp[]) { RTP_ID rtpid; int status; pid_t res; int async_err = 0; /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes. uStackSize=0 cannot be used, the default stack size is too small for Python. */ if (envp) { rtpid = rtpSpawn(rtpFileName, argv, envp, 100, 0x1000000, 0, VX_FP_TASK); } else { rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ, 100, 0x1000000, 0, VX_FP_TASK); } if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) { do { res = waitpid((pid_t)rtpid, &status, 0); } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); if (res < 0) return RTP_ID_ERROR; return ((intptr_t)status); } return ((intptr_t)rtpid); } #endif #if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN) /*[clinic input] os.spawnv mode: int Mode of process creation. path: path_t Path of executable file. argv: object Tuple or list of strings. / Execute the program specified by path in a new process. [clinic start generated code]*/ static PyObject * os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv) /*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/ { EXECV_CHAR **argvlist; int i; Py_ssize_t argc; intptr_t spawnval; PyObject *(*getitem)(PyObject *, Py_ssize_t); /* spawnv has three arguments: (mode, path, argv), where argv is a list or tuple of strings. */ if (PyList_Check(argv)) { argc = PyList_Size(argv); getitem = PyList_GetItem; } else if (PyTuple_Check(argv)) { argc = PyTuple_Size(argv); getitem = PyTuple_GetItem; } else { PyErr_SetString(PyExc_TypeError, "spawnv() arg 2 must be a tuple or list"); return NULL; } if (argc == 0) { PyErr_SetString(PyExc_ValueError, "spawnv() arg 2 cannot be empty"); return NULL; } argvlist = PyMem_NEW(EXECV_CHAR *, argc+1); if (argvlist == NULL) { return PyErr_NoMemory(); } for (i = 0; i < argc; i++) { if (!fsconvert_strdup((*getitem)(argv, i), &argvlist[i])) { free_string_array(argvlist, i); PyErr_SetString( PyExc_TypeError, "spawnv() arg 2 must contain only strings"); return NULL; } if (i == 0 && !argvlist[0][0]) { free_string_array(argvlist, i + 1); PyErr_SetString( PyExc_ValueError, "spawnv() arg 2 first element cannot be empty"); return NULL; } } argvlist[argc] = NULL; #if !defined(HAVE_RTPSPAWN) if (mode == _OLD_P_OVERLAY) mode = _P_OVERLAY; #endif if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, Py_None) < 0) { free_string_array(argvlist, argc); return NULL; } Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH #ifdef HAVE_WSPAWNV spawnval = _wspawnv(mode, path->wide, argvlist); #elif defined(HAVE_RTPSPAWN) spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL); #else spawnval = _spawnv(mode, path->narrow, argvlist); #endif _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS free_string_array(argvlist, argc); if (spawnval == -1) return posix_error(); else return Py_BuildValue(_Py_PARSE_INTPTR, spawnval); } /*[clinic input] os.spawnve mode: int Mode of process creation. path: path_t Path of executable file. argv: object Tuple or list of strings. env: object Dictionary of strings mapping to strings. / Execute the program specified by path in a new process. [clinic start generated code]*/ static PyObject * os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv, PyObject *env) /*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/ { EXECV_CHAR **argvlist; EXECV_CHAR **envlist; PyObject *res = NULL; Py_ssize_t argc, i, envc; intptr_t spawnval; PyObject *(*getitem)(PyObject *, Py_ssize_t); Py_ssize_t lastarg = 0; /* spawnve has four arguments: (mode, path, argv, env), where argv is a list or tuple of strings and env is a dictionary like posix.environ. */ if (PyList_Check(argv)) { argc = PyList_Size(argv); getitem = PyList_GetItem; } else if (PyTuple_Check(argv)) { argc = PyTuple_Size(argv); getitem = PyTuple_GetItem; } else { PyErr_SetString(PyExc_TypeError, "spawnve() arg 2 must be a tuple or list"); goto fail_0; } if (argc == 0) { PyErr_SetString(PyExc_ValueError, "spawnve() arg 2 cannot be empty"); goto fail_0; } if (!PyMapping_Check(env)) { PyErr_SetString(PyExc_TypeError, "spawnve() arg 3 must be a mapping object"); goto fail_0; } argvlist = PyMem_NEW(EXECV_CHAR *, argc+1); if (argvlist == NULL) { PyErr_NoMemory(); goto fail_0; } for (i = 0; i < argc; i++) { if (!fsconvert_strdup((*getitem)(argv, i), &argvlist[i])) { lastarg = i; goto fail_1; } if (i == 0 && !argvlist[0][0]) { lastarg = i + 1; PyErr_SetString( PyExc_ValueError, "spawnv() arg 2 first element cannot be empty"); goto fail_1; } } lastarg = argc; argvlist[argc] = NULL; envlist = parse_envlist(env, &envc); if (envlist == NULL) goto fail_1; #if !defined(HAVE_RTPSPAWN) if (mode == _OLD_P_OVERLAY) mode = _P_OVERLAY; #endif if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) { goto fail_2; } Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH #ifdef HAVE_WSPAWNV spawnval = _wspawnve(mode, path->wide, argvlist, envlist); #elif defined(HAVE_RTPSPAWN) spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, (const char **)envlist); #else spawnval = _spawnve(mode, path->narrow, argvlist, envlist); #endif _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS if (spawnval == -1) (void) posix_error(); else res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval); fail_2: while (--envc >= 0) { PyMem_Free(envlist[envc]); } PyMem_Free(envlist); fail_1: free_string_array(argvlist, lastarg); fail_0: return res; } #endif /* HAVE_SPAWNV */ #ifdef HAVE_FORK /* Helper function to validate arguments. Returns 0 on success. non-zero on failure with a TypeError raised. If obj is non-NULL it must be callable. */ static int check_null_or_callable(PyObject *obj, const char* obj_name) { if (obj && !PyCallable_Check(obj)) { PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s", obj_name, _PyType_Name(Py_TYPE(obj))); return -1; } return 0; } /*[clinic input] os.register_at_fork * before: object=NULL A callable to be called in the parent before the fork() syscall. after_in_child: object=NULL A callable to be called in the child after fork(). after_in_parent: object=NULL A callable to be called in the parent after fork(). Register callables to be called when forking a new process. 'before' callbacks are called in reverse order. 'after_in_child' and 'after_in_parent' callbacks are called in order. [clinic start generated code]*/ static PyObject * os_register_at_fork_impl(PyObject *module, PyObject *before, PyObject *after_in_child, PyObject *after_in_parent) /*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/ { PyInterpreterState *interp; if (!before && !after_in_child && !after_in_parent) { PyErr_SetString(PyExc_TypeError, "At least one argument is required."); return NULL; } if (check_null_or_callable(before, "before") || check_null_or_callable(after_in_child, "after_in_child") || check_null_or_callable(after_in_parent, "after_in_parent")) { return NULL; } interp = _PyInterpreterState_GET(); if (register_at_forker(&interp->before_forkers, before)) { return NULL; } if (register_at_forker(&interp->after_forkers_child, after_in_child)) { return NULL; } if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) { return NULL; } Py_RETURN_NONE; } #endif /* HAVE_FORK */ // Common code to raise a warning if we detect there is more than one thread // running in the process. Best effort, silent if unable to count threads. // Constraint: Quick. Never overcounts. Never leaves an error set. // // This code might do an import, thus acquiring the import lock, which // PyOS_BeforeFork() also does. As this should only be called from // the parent process, it is in the same thread so that works. static void warn_about_fork_with_threads(const char* name) { // TODO: Consider making an `os` module API to return the current number // of threads in the process. That'd presumably use this platform code but // raise an error rather than using the inaccurate fallback. Py_ssize_t num_python_threads = 0; #if defined(__APPLE__) && defined(HAVE_GETPID) mach_port_t macos_self = mach_task_self(); mach_port_t macos_task; if (task_for_pid(macos_self, getpid(), &macos_task) == KERN_SUCCESS) { thread_array_t macos_threads; mach_msg_type_number_t macos_n_threads; if (task_threads(macos_task, &macos_threads, &macos_n_threads) == KERN_SUCCESS) { num_python_threads = macos_n_threads; } } #elif defined(__linux__) // Linux /proc/self/stat 20th field is the number of threads. FILE* proc_stat = fopen("/proc/self/stat", "r"); if (proc_stat) { size_t n; // Size chosen arbitrarily. ~60% more bytes than a 20th column index // observed on the author's workstation. char stat_line[160]; n = fread(&stat_line, 1, 159, proc_stat); stat_line[n] = '\0'; fclose(proc_stat); char *saveptr = NULL; char *field = strtok_r(stat_line, " ", &saveptr); unsigned int idx; for (idx = 19; idx && field; --idx) { field = strtok_r(NULL, " ", &saveptr); } if (idx == 0 && field) { // found the 20th field num_python_threads = atoi(field); // 0 on error } } #endif if (num_python_threads <= 0) { // Fall back to just the number our threading module knows about. // An incomplete view of the world, but better than nothing. PyObject *threading = PyImport_GetModule(&_Py_ID(threading)); if (!threading) { PyErr_Clear(); return; } PyObject *threading_active = PyObject_GetAttr(threading, &_Py_ID(_active)); if (!threading_active) { PyErr_Clear(); Py_DECREF(threading); return; } PyObject *threading_limbo = PyObject_GetAttr(threading, &_Py_ID(_limbo)); if (!threading_limbo) { PyErr_Clear(); Py_DECREF(threading); Py_DECREF(threading_active); return; } Py_DECREF(threading); // Duplicating what threading.active_count() does but without holding // threading._active_limbo_lock so our count could be inaccurate if // these dicts are mid-update from another thread. Not a big deal. // Worst case if someone replaced threading._active or threading._limbo // with non-dicts, we get -1 from *Length() below and undercount. // Nobody should, but we're best effort so we clear errors and move on. num_python_threads = (PyMapping_Length(threading_active) + PyMapping_Length(threading_limbo)); PyErr_Clear(); Py_DECREF(threading_active); Py_DECREF(threading_limbo); } if (num_python_threads > 1) { PyErr_WarnFormat( PyExc_DeprecationWarning, 1, #ifdef HAVE_GETPID "This process (pid=%d) is multi-threaded, " #else "This process is multi-threaded, " #endif "use of %s() may lead to deadlocks in the child.", #ifdef HAVE_GETPID getpid(), #endif name); PyErr_Clear(); } } #ifdef HAVE_FORK1 /*[clinic input] os.fork1 Fork a child process with a single multiplexed (i.e., not bound) thread. Return 0 to child process and PID of child to parent process. [clinic start generated code]*/ static PyObject * os_fork1_impl(PyObject *module) /*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/ { pid_t pid; if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) { PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters"); return NULL; } PyOS_BeforeFork(); pid = fork1(); if (pid == 0) { /* child: this clobbers and resets the import lock. */ PyOS_AfterFork_Child(); } else { warn_about_fork_with_threads("fork1"); /* parent: release the import lock. */ PyOS_AfterFork_Parent(); } if (pid == -1) return posix_error(); return PyLong_FromPid(pid); } #endif /* HAVE_FORK1 */ #ifdef HAVE_FORK /*[clinic input] os.fork Fork a child process. Return 0 to child process and PID of child to parent process. [clinic start generated code]*/ static PyObject * os_fork_impl(PyObject *module) /*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/ { pid_t pid; PyInterpreterState *interp = _PyInterpreterState_GET(); if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_FORK)) { PyErr_SetString(PyExc_RuntimeError, "fork not supported for isolated subinterpreters"); return NULL; } if (PySys_Audit("os.fork", NULL) < 0) { return NULL; } PyOS_BeforeFork(); pid = fork(); if (pid == 0) { /* child: this clobbers and resets the import lock. */ PyOS_AfterFork_Child(); } else { warn_about_fork_with_threads("fork"); /* parent: release the import lock. */ PyOS_AfterFork_Parent(); } if (pid == -1) return posix_error(); return PyLong_FromPid(pid); } #endif /* HAVE_FORK */ #ifdef HAVE_SCHED_H #ifdef HAVE_SCHED_GET_PRIORITY_MAX /*[clinic input] os.sched_get_priority_max policy: int Get the maximum scheduling priority for policy. [clinic start generated code]*/ static PyObject * os_sched_get_priority_max_impl(PyObject *module, int policy) /*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/ { int max; max = sched_get_priority_max(policy); if (max < 0) return posix_error(); return PyLong_FromLong(max); } /*[clinic input] os.sched_get_priority_min policy: int Get the minimum scheduling priority for policy. [clinic start generated code]*/ static PyObject * os_sched_get_priority_min_impl(PyObject *module, int policy) /*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/ { int min = sched_get_priority_min(policy); if (min < 0) return posix_error(); return PyLong_FromLong(min); } #endif /* HAVE_SCHED_GET_PRIORITY_MAX */ #ifdef HAVE_SCHED_SETSCHEDULER /*[clinic input] os.sched_getscheduler pid: pid_t / Get the scheduling policy for the process identified by pid. Passing 0 for pid returns the scheduling policy for the calling process. [clinic start generated code]*/ static PyObject * os_sched_getscheduler_impl(PyObject *module, pid_t pid) /*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/ { int policy; policy = sched_getscheduler(pid); if (policy < 0) return posix_error(); return PyLong_FromLong(policy); } #endif /* HAVE_SCHED_SETSCHEDULER */ #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) /*[clinic input] class os.sched_param "PyObject *" "SchedParamType" @classmethod os.sched_param.__new__ sched_priority: object A scheduling parameter. Currently has only one field: sched_priority [clinic start generated code]*/ static PyObject * os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority) /*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/ { PyObject *res; res = PyStructSequence_New(type); if (!res) return NULL; PyStructSequence_SET_ITEM(res, 0, Py_NewRef(sched_priority)); return res; } PyDoc_VAR(os_sched_param__doc__); static PyStructSequence_Field sched_param_fields[] = { {"sched_priority", "the scheduling priority"}, {0} }; static PyStructSequence_Desc sched_param_desc = { "sched_param", /* name */ os_sched_param__doc__, /* doc */ sched_param_fields, 1 }; static int convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res) { long priority; if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) { PyErr_SetString(PyExc_TypeError, "must have a sched_param object"); return 0; } priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0)); if (priority == -1 && PyErr_Occurred()) return 0; if (priority > INT_MAX || priority < INT_MIN) { PyErr_SetString(PyExc_OverflowError, "sched_priority out of range"); return 0; } res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int); return 1; } #endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */ #ifdef HAVE_SCHED_SETSCHEDULER /*[clinic input] os.sched_setscheduler pid: pid_t policy: int param as param_obj: object / Set the scheduling policy for the process identified by pid. If pid is 0, the calling process is changed. param is an instance of sched_param. [clinic start generated code]*/ static PyObject * os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy, PyObject *param_obj) /*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/ { struct sched_param param; if (!convert_sched_param(module, param_obj, ¶m)) { return NULL; } /* ** sched_setscheduler() returns 0 in Linux, but the previous ** scheduling policy under Solaris/Illumos, and others. ** On error, -1 is returned in all Operating Systems. */ if (sched_setscheduler(pid, policy, ¶m) == -1) return posix_error(); Py_RETURN_NONE; } #endif /* HAVE_SCHED_SETSCHEDULER*/ #ifdef HAVE_SCHED_SETPARAM /*[clinic input] os.sched_getparam pid: pid_t / Returns scheduling parameters for the process identified by pid. If pid is 0, returns parameters for the calling process. Return value is an instance of sched_param. [clinic start generated code]*/ static PyObject * os_sched_getparam_impl(PyObject *module, pid_t pid) /*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/ { struct sched_param param; PyObject *result; PyObject *priority; if (sched_getparam(pid, ¶m)) return posix_error(); PyObject *SchedParamType = get_posix_state(module)->SchedParamType; result = PyStructSequence_New((PyTypeObject *)SchedParamType); if (!result) return NULL; priority = PyLong_FromLong(param.sched_priority); if (!priority) { Py_DECREF(result); return NULL; } PyStructSequence_SET_ITEM(result, 0, priority); return result; } /*[clinic input] os.sched_setparam pid: pid_t param as param_obj: object / Set scheduling parameters for the process identified by pid. If pid is 0, sets parameters for the calling process. param should be an instance of sched_param. [clinic start generated code]*/ static PyObject * os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj) /*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/ { struct sched_param param; if (!convert_sched_param(module, param_obj, ¶m)) { return NULL; } if (sched_setparam(pid, ¶m)) return posix_error(); Py_RETURN_NONE; } #endif /* HAVE_SCHED_SETPARAM */ #ifdef HAVE_SCHED_RR_GET_INTERVAL /*[clinic input] os.sched_rr_get_interval -> double pid: pid_t / Return the round-robin quantum for the process identified by pid, in seconds. Value returned is a float. [clinic start generated code]*/ static double os_sched_rr_get_interval_impl(PyObject *module, pid_t pid) /*[clinic end generated code: output=7e2d935833ab47dc input=2a973da15cca6fae]*/ { struct timespec interval; if (sched_rr_get_interval(pid, &interval)) { posix_error(); return -1.0; } #ifdef _Py_MEMORY_SANITIZER __msan_unpoison(&interval, sizeof(interval)); #endif return (double)interval.tv_sec + 1e-9*interval.tv_nsec; } #endif /* HAVE_SCHED_RR_GET_INTERVAL */ /*[clinic input] os.sched_yield Voluntarily relinquish the CPU. [clinic start generated code]*/ static PyObject * os_sched_yield_impl(PyObject *module) /*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/ { int result; Py_BEGIN_ALLOW_THREADS result = sched_yield(); Py_END_ALLOW_THREADS if (result < 0) { return posix_error(); } Py_RETURN_NONE; } #ifdef HAVE_SCHED_SETAFFINITY /* The minimum number of CPUs allocated in a cpu_set_t */ static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT; /*[clinic input] os.sched_setaffinity pid: pid_t mask : object / Set the CPU affinity of the process identified by pid to mask. mask should be an iterable of integers identifying CPUs. [clinic start generated code]*/ static PyObject * os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask) /*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/ { int ncpus; size_t setsize; cpu_set_t *cpu_set = NULL; PyObject *iterator = NULL, *item; iterator = PyObject_GetIter(mask); if (iterator == NULL) return NULL; ncpus = NCPUS_START; setsize = CPU_ALLOC_SIZE(ncpus); cpu_set = CPU_ALLOC(ncpus); if (cpu_set == NULL) { PyErr_NoMemory(); goto error; } CPU_ZERO_S(setsize, cpu_set); while ((item = PyIter_Next(iterator))) { long cpu; if (!PyLong_Check(item)) { PyErr_Format(PyExc_TypeError, "expected an iterator of ints, " "but iterator yielded %R", Py_TYPE(item)); Py_DECREF(item); goto error; } cpu = PyLong_AsLong(item); Py_DECREF(item); if (cpu < 0) { if (!PyErr_Occurred()) PyErr_SetString(PyExc_ValueError, "negative CPU number"); goto error; } if (cpu > INT_MAX - 1) { PyErr_SetString(PyExc_OverflowError, "CPU number too large"); goto error; } if (cpu >= ncpus) { /* Grow CPU mask to fit the CPU number */ int newncpus = ncpus; cpu_set_t *newmask; size_t newsetsize; while (newncpus <= cpu) { if (newncpus > INT_MAX / 2) newncpus = cpu + 1; else newncpus = newncpus * 2; } newmask = CPU_ALLOC(newncpus); if (newmask == NULL) { PyErr_NoMemory(); goto error; } newsetsize = CPU_ALLOC_SIZE(newncpus); CPU_ZERO_S(newsetsize, newmask); memcpy(newmask, cpu_set, setsize); CPU_FREE(cpu_set); setsize = newsetsize; cpu_set = newmask; ncpus = newncpus; } CPU_SET_S(cpu, setsize, cpu_set); } if (PyErr_Occurred()) { goto error; } Py_CLEAR(iterator); if (sched_setaffinity(pid, setsize, cpu_set)) { posix_error(); goto error; } CPU_FREE(cpu_set); Py_RETURN_NONE; error: if (cpu_set) CPU_FREE(cpu_set); Py_XDECREF(iterator); return NULL; } /*[clinic input] os.sched_getaffinity pid: pid_t / Return the affinity of the process identified by pid (or the current process if zero). The affinity is returned as a set of CPU identifiers. [clinic start generated code]*/ static PyObject * os_sched_getaffinity_impl(PyObject *module, pid_t pid) /*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/ { int cpu, ncpus, count; size_t setsize; cpu_set_t *mask = NULL; PyObject *res = NULL; ncpus = NCPUS_START; while (1) { setsize = CPU_ALLOC_SIZE(ncpus); mask = CPU_ALLOC(ncpus); if (mask == NULL) return PyErr_NoMemory(); if (sched_getaffinity(pid, setsize, mask) == 0) break; CPU_FREE(mask); if (errno != EINVAL) return posix_error(); if (ncpus > INT_MAX / 2) { PyErr_SetString(PyExc_OverflowError, "could not allocate " "a large enough CPU set"); return NULL; } ncpus = ncpus * 2; } res = PySet_New(NULL); if (res == NULL) goto error; for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) { if (CPU_ISSET_S(cpu, setsize, mask)) { PyObject *cpu_num = PyLong_FromLong(cpu); --count; if (cpu_num == NULL) goto error; if (PySet_Add(res, cpu_num)) { Py_DECREF(cpu_num); goto error; } Py_DECREF(cpu_num); } } CPU_FREE(mask); return res; error: if (mask) CPU_FREE(mask); Py_XDECREF(res); return NULL; } #endif /* HAVE_SCHED_SETAFFINITY */ #endif /* HAVE_SCHED_H */ /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */ #if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX) # define DEV_PTY_FILE "/dev/ptc" # define HAVE_DEV_PTMX #else # define DEV_PTY_FILE "/dev/ptmx" #endif #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) #ifdef HAVE_PTY_H #include #ifdef HAVE_UTMP_H #include #endif /* HAVE_UTMP_H */ #elif defined(HAVE_LIBUTIL_H) #include #elif defined(HAVE_UTIL_H) #include #endif /* HAVE_PTY_H */ #ifdef HAVE_STROPTS_H #include #endif #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */ #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) /*[clinic input] os.openpty Open a pseudo-terminal. Return a tuple of (master_fd, slave_fd) containing open file descriptors for both the master and slave ends. [clinic start generated code]*/ static PyObject * os_openpty_impl(PyObject *module) /*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/ { int master_fd = -1, slave_fd = -1; #ifndef HAVE_OPENPTY char * slave_name; #endif #if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY) PyOS_sighandler_t sig_saved; #if defined(__sun) && defined(__SVR4) extern char *ptsname(int fildes); #endif #endif #ifdef HAVE_OPENPTY if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0) goto posix_error; if (_Py_set_inheritable(master_fd, 0, NULL) < 0) goto error; if (_Py_set_inheritable(slave_fd, 0, NULL) < 0) goto error; #elif defined(HAVE__GETPTY) slave_name = _getpty(&master_fd, O_RDWR, 0666, 0); if (slave_name == NULL) goto posix_error; if (_Py_set_inheritable(master_fd, 0, NULL) < 0) goto error; slave_fd = _Py_open(slave_name, O_RDWR); if (slave_fd < 0) goto error; #else master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */ if (master_fd < 0) goto posix_error; sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL); /* change permission of slave */ if (grantpt(master_fd) < 0) { PyOS_setsig(SIGCHLD, sig_saved); goto posix_error; } /* unlock slave */ if (unlockpt(master_fd) < 0) { PyOS_setsig(SIGCHLD, sig_saved); goto posix_error; } PyOS_setsig(SIGCHLD, sig_saved); slave_name = ptsname(master_fd); /* get name of slave */ if (slave_name == NULL) goto posix_error; slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */ if (slave_fd == -1) goto error; if (_Py_set_inheritable(master_fd, 0, NULL) < 0) goto posix_error; #if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC) ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */ ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */ #ifndef __hpux ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */ #endif /* __hpux */ #endif /* HAVE_CYGWIN */ #endif /* HAVE_OPENPTY */ return Py_BuildValue("(ii)", master_fd, slave_fd); posix_error: posix_error(); error: if (master_fd != -1) close(master_fd); if (slave_fd != -1) close(slave_fd); return NULL; } #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */ #if defined(HAVE_SETSID) && defined(TIOCSCTTY) #define HAVE_FALLBACK_LOGIN_TTY 1 #endif /* defined(HAVE_SETSID) && defined(TIOCSCTTY) */ #if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) /*[clinic input] os.login_tty fd: fildes / Prepare the tty of which fd is a file descriptor for a new login session. Make the calling process a session leader; make the tty the controlling tty, the stdin, the stdout, and the stderr of the calling process; close fd. [clinic start generated code]*/ static PyObject * os_login_tty_impl(PyObject *module, int fd) /*[clinic end generated code: output=495a79911b4cc1bc input=5f298565099903a2]*/ { #ifdef HAVE_LOGIN_TTY if (login_tty(fd) == -1) { return posix_error(); } #else /* defined(HAVE_FALLBACK_LOGIN_TTY) */ /* Establish a new session. */ if (setsid() == -1) { return posix_error(); } /* The tty becomes the controlling terminal. */ if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) { return posix_error(); } /* The tty becomes stdin/stdout/stderr */ if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) { return posix_error(); } if (fd > 2) { close(fd); } #endif /* HAVE_LOGIN_TTY */ Py_RETURN_NONE; } #endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */ #ifdef HAVE_FORKPTY /*[clinic input] os.forkpty Fork a new process with a new pseudo-terminal as controlling tty. Returns a tuple of (pid, master_fd). Like fork(), return pid of 0 to the child process, and pid of child to the parent process. To both, return fd of newly opened pseudo-terminal. [clinic start generated code]*/ static PyObject * os_forkpty_impl(PyObject *module) /*[clinic end generated code: output=60d0a5c7512e4087 input=f1f7f4bae3966010]*/ { int master_fd = -1; pid_t pid; if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) { PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters"); return NULL; } if (PySys_Audit("os.forkpty", NULL) < 0) { return NULL; } PyOS_BeforeFork(); pid = forkpty(&master_fd, NULL, NULL, NULL); if (pid == 0) { /* child: this clobbers and resets the import lock. */ PyOS_AfterFork_Child(); } else { warn_about_fork_with_threads("forkpty"); /* parent: release the import lock. */ PyOS_AfterFork_Parent(); } if (pid == -1) { return posix_error(); } return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd); } #endif /* HAVE_FORKPTY */ #ifdef HAVE_GETEGID /*[clinic input] os.getegid Return the current process's effective group id. [clinic start generated code]*/ static PyObject * os_getegid_impl(PyObject *module) /*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/ { return _PyLong_FromGid(getegid()); } #endif /* HAVE_GETEGID */ #ifdef HAVE_GETEUID /*[clinic input] os.geteuid Return the current process's effective user id. [clinic start generated code]*/ static PyObject * os_geteuid_impl(PyObject *module) /*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/ { return _PyLong_FromUid(geteuid()); } #endif /* HAVE_GETEUID */ #ifdef HAVE_GETGID /*[clinic input] os.getgid Return the current process's group id. [clinic start generated code]*/ static PyObject * os_getgid_impl(PyObject *module) /*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/ { return _PyLong_FromGid(getgid()); } #endif /* HAVE_GETGID */ #ifdef HAVE_GETPID /*[clinic input] os.getpid Return the current process id. [clinic start generated code]*/ static PyObject * os_getpid_impl(PyObject *module) /*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/ { return PyLong_FromPid(getpid()); } #endif /* HAVE_GETPID */ #ifdef NGROUPS_MAX #define MAX_GROUPS NGROUPS_MAX #else /* defined to be 16 on Solaris7, so this should be a small number */ #define MAX_GROUPS 64 #endif #ifdef HAVE_GETGROUPLIST #ifdef __APPLE__ /*[clinic input] os.getgrouplist user: str username to lookup group as basegid: int base group id of the user / Returns a list of groups to which a user belongs. [clinic start generated code]*/ static PyObject * os_getgrouplist_impl(PyObject *module, const char *user, int basegid) /*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/ #else /*[clinic input] os.getgrouplist user: str username to lookup group as basegid: gid_t base group id of the user / Returns a list of groups to which a user belongs. [clinic start generated code]*/ static PyObject * os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid) /*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/ #endif { int i, ngroups; PyObject *list; #ifdef __APPLE__ int *groups; #else gid_t *groups; #endif /* * NGROUPS_MAX is defined by POSIX.1 as the maximum * number of supplimental groups a users can belong to. * We have to increment it by one because * getgrouplist() returns both the supplemental groups * and the primary group, i.e. all of the groups the * user belongs to. */ ngroups = 1 + MAX_GROUPS; while (1) { #ifdef __APPLE__ groups = PyMem_New(int, ngroups); #else groups = PyMem_New(gid_t, ngroups); #endif if (groups == NULL) { return PyErr_NoMemory(); } int old_ngroups = ngroups; if (getgrouplist(user, basegid, groups, &ngroups) != -1) { /* Success */ break; } /* getgrouplist() fails if the group list is too small */ PyMem_Free(groups); if (ngroups > old_ngroups) { /* If the group list is too small, the glibc implementation of getgrouplist() sets ngroups to the total number of groups and returns -1. */ } else { /* Double the group list size */ if (ngroups > INT_MAX / 2) { return PyErr_NoMemory(); } ngroups *= 2; } /* Retry getgrouplist() with a larger group list */ } #ifdef _Py_MEMORY_SANITIZER /* Clang memory sanitizer libc intercepts don't know getgrouplist. */ __msan_unpoison(&ngroups, sizeof(ngroups)); __msan_unpoison(groups, ngroups*sizeof(*groups)); #endif list = PyList_New(ngroups); if (list == NULL) { PyMem_Free(groups); return NULL; } for (i = 0; i < ngroups; i++) { #ifdef __APPLE__ PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]); #else PyObject *o = _PyLong_FromGid(groups[i]); #endif if (o == NULL) { Py_DECREF(list); PyMem_Free(groups); return NULL; } PyList_SET_ITEM(list, i, o); } PyMem_Free(groups); return list; } #endif /* HAVE_GETGROUPLIST */ #ifdef HAVE_GETGROUPS /*[clinic input] os.getgroups Return list of supplemental group IDs for the process. [clinic start generated code]*/ static PyObject * os_getgroups_impl(PyObject *module) /*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/ { // Call getgroups with length 0 to get the actual number of groups int n = getgroups(0, NULL); if (n < 0) { return posix_error(); } if (n == 0) { return PyList_New(0); } gid_t *grouplist = PyMem_New(gid_t, n); if (grouplist == NULL) { return PyErr_NoMemory(); } n = getgroups(n, grouplist); if (n == -1) { PyMem_Free(grouplist); return posix_error(); } PyObject *result = PyList_New(n); if (result == NULL) { goto error; } for (int i = 0; i < n; ++i) { PyObject *group = _PyLong_FromGid(grouplist[i]); if (group == NULL) { goto error; } PyList_SET_ITEM(result, i, group); } PyMem_Free(grouplist); return result; error: PyMem_Free(grouplist); Py_XDECREF(result); return NULL; } #endif /* HAVE_GETGROUPS */ #ifdef HAVE_INITGROUPS #ifdef __APPLE__ /*[clinic input] os.initgroups username as oname: FSConverter gid: int / Initialize the group access list. Call the system initgroups() to initialize the group access list with all of the groups of which the specified username is a member, plus the specified group id. [clinic start generated code]*/ static PyObject * os_initgroups_impl(PyObject *module, PyObject *oname, int gid) /*[clinic end generated code: output=7f074d30a425fd3a input=df3d54331b0af204]*/ #else /*[clinic input] os.initgroups username as oname: FSConverter gid: gid_t / Initialize the group access list. Call the system initgroups() to initialize the group access list with all of the groups of which the specified username is a member, plus the specified group id. [clinic start generated code]*/ static PyObject * os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid) /*[clinic end generated code: output=59341244521a9e3f input=0cb91bdc59a4c564]*/ #endif { const char *username = PyBytes_AS_STRING(oname); if (initgroups(username, gid) == -1) return PyErr_SetFromErrno(PyExc_OSError); Py_RETURN_NONE; } #endif /* HAVE_INITGROUPS */ #ifdef HAVE_GETPGID /*[clinic input] os.getpgid pid: pid_t Call the system call getpgid(), and return the result. [clinic start generated code]*/ static PyObject * os_getpgid_impl(PyObject *module, pid_t pid) /*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/ { pid_t pgid = getpgid(pid); if (pgid < 0) return posix_error(); return PyLong_FromPid(pgid); } #endif /* HAVE_GETPGID */ #ifdef HAVE_GETPGRP /*[clinic input] os.getpgrp Return the current process group id. [clinic start generated code]*/ static PyObject * os_getpgrp_impl(PyObject *module) /*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/ { #ifdef GETPGRP_HAVE_ARG return PyLong_FromPid(getpgrp(0)); #else /* GETPGRP_HAVE_ARG */ return PyLong_FromPid(getpgrp()); #endif /* GETPGRP_HAVE_ARG */ } #endif /* HAVE_GETPGRP */ #ifdef HAVE_SETPGRP /*[clinic input] os.setpgrp Make the current process the leader of its process group. [clinic start generated code]*/ static PyObject * os_setpgrp_impl(PyObject *module) /*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/ { #ifdef SETPGRP_HAVE_ARG if (setpgrp(0, 0) < 0) #else /* SETPGRP_HAVE_ARG */ if (setpgrp() < 0) #endif /* SETPGRP_HAVE_ARG */ return posix_error(); Py_RETURN_NONE; } #endif /* HAVE_SETPGRP */ #ifdef HAVE_GETPPID #ifdef MS_WINDOWS #include static PyObject* win32_getppid() { HANDLE snapshot; pid_t mypid; PyObject* result = NULL; BOOL have_record; PROCESSENTRY32 pe; mypid = getpid(); /* This function never fails */ snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (snapshot == INVALID_HANDLE_VALUE) return PyErr_SetFromWindowsErr(GetLastError()); pe.dwSize = sizeof(pe); have_record = Process32First(snapshot, &pe); while (have_record) { if (mypid == (pid_t)pe.th32ProcessID) { /* We could cache the ulong value in a static variable. */ result = PyLong_FromPid((pid_t)pe.th32ParentProcessID); break; } have_record = Process32Next(snapshot, &pe); } /* If our loop exits and our pid was not found (result will be NULL) * then GetLastError will return ERROR_NO_MORE_FILES. This is an * error anyway, so let's raise it. */ if (!result) result = PyErr_SetFromWindowsErr(GetLastError()); CloseHandle(snapshot); return result; } #endif /*MS_WINDOWS*/ /*[clinic input] os.getppid Return the parent's process id. If the parent process has already exited, Windows machines will still return its id; others systems will return the id of the 'init' process (1). [clinic start generated code]*/ static PyObject * os_getppid_impl(PyObject *module) /*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/ { #ifdef MS_WINDOWS return win32_getppid(); #else return PyLong_FromPid(getppid()); #endif } #endif /* HAVE_GETPPID */ #ifdef HAVE_GETLOGIN /*[clinic input] os.getlogin Return the actual login name. [clinic start generated code]*/ static PyObject * os_getlogin_impl(PyObject *module) /*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/ { PyObject *result = NULL; #ifdef MS_WINDOWS wchar_t user_name[UNLEN + 1]; DWORD num_chars = Py_ARRAY_LENGTH(user_name); if (GetUserNameW(user_name, &num_chars)) { /* num_chars is the number of unicode chars plus null terminator */ result = PyUnicode_FromWideChar(user_name, num_chars - 1); } else result = PyErr_SetFromWindowsErr(GetLastError()); #else char *name; int old_errno = errno; errno = 0; name = getlogin(); if (name == NULL) { if (errno) posix_error(); else PyErr_SetString(PyExc_OSError, "unable to determine login name"); } else result = PyUnicode_DecodeFSDefault(name); errno = old_errno; #endif return result; } #endif /* HAVE_GETLOGIN */ #ifdef HAVE_GETUID /*[clinic input] os.getuid Return the current process's user id. [clinic start generated code]*/ static PyObject * os_getuid_impl(PyObject *module) /*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/ { return _PyLong_FromUid(getuid()); } #endif /* HAVE_GETUID */ #ifdef MS_WINDOWS #define HAVE_KILL #endif /* MS_WINDOWS */ #ifdef HAVE_KILL /*[clinic input] os.kill pid: pid_t signal: Py_ssize_t / Kill a process with a signal. [clinic start generated code]*/ static PyObject * os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal) /*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/ { if (PySys_Audit("os.kill", "in", pid, signal) < 0) { return NULL; } #ifndef MS_WINDOWS if (kill(pid, (int)signal) == -1) { return posix_error(); } // Check immediately if the signal was sent to the current process. // Don't micro-optimize pid == getpid(), since PyErr_SetString() check // is cheap. if (PyErr_CheckSignals()) { return NULL; } Py_RETURN_NONE; #else /* !MS_WINDOWS */ PyObject *result; DWORD sig = (DWORD)signal; DWORD err; HANDLE handle; /* Console processes which share a common console can be sent CTRL+C or CTRL+BREAK events, provided they handle said events. */ if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) { if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) { err = GetLastError(); PyErr_SetFromWindowsErr(err); } else Py_RETURN_NONE; } /* If the signal is outside of what GenerateConsoleCtrlEvent can use, attempt to open and terminate the process. */ handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid); if (handle == NULL) { err = GetLastError(); return PyErr_SetFromWindowsErr(err); } if (TerminateProcess(handle, sig) == 0) { err = GetLastError(); result = PyErr_SetFromWindowsErr(err); } else { result = Py_NewRef(Py_None); } CloseHandle(handle); return result; #endif /* !MS_WINDOWS */ } #endif /* HAVE_KILL */ #ifdef HAVE_KILLPG /*[clinic input] os.killpg pgid: pid_t signal: int / Kill a process group with a signal. [clinic start generated code]*/ static PyObject * os_killpg_impl(PyObject *module, pid_t pgid, int signal) /*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/ { if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) { return NULL; } /* XXX some man pages make the `pgid` parameter an int, others a pid_t. Since getpgrp() returns a pid_t, we assume killpg should take the same type. Moreover, pid_t is always at least as wide as int (else compilation of this module fails), which is safe. */ if (killpg(pgid, signal) == -1) return posix_error(); Py_RETURN_NONE; } #endif /* HAVE_KILLPG */ #ifdef HAVE_PLOCK #ifdef HAVE_SYS_LOCK_H #include #endif /*[clinic input] os.plock op: int / Lock program segments into memory."); [clinic start generated code]*/ static PyObject * os_plock_impl(PyObject *module, int op) /*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/ { if (plock(op) == -1) return posix_error(); Py_RETURN_NONE; } #endif /* HAVE_PLOCK */ #ifdef HAVE_SETUID /*[clinic input] os.setuid uid: uid_t / Set the current process's user id. [clinic start generated code]*/ static PyObject * os_setuid_impl(PyObject *module, uid_t uid) /*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/ { if (setuid(uid) < 0) return posix_error(); Py_RETURN_NONE; } #endif /* HAVE_SETUID */ #ifdef HAVE_SETEUID /*[clinic input] os.seteuid euid: uid_t / Set the current process's effective user id. [clinic start generated code]*/ static PyObject * os_seteuid_impl(PyObject *module, uid_t euid) /*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/ { if (seteuid(euid) < 0) return posix_error(); Py_RETURN_NONE; } #endif /* HAVE_SETEUID */ #ifdef HAVE_SETEGID /*[clinic input] os.setegid egid: gid_t / Set the current process's effective group id. [clinic start generated code]*/ static PyObject * os_setegid_impl(PyObject *module, gid_t egid) /*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/ { if (setegid(egid) < 0) return posix_error(); Py_RETURN_NONE; } #endif /* HAVE_SETEGID */ #ifdef HAVE_SETREUID /*[clinic input] os.setreuid ruid: uid_t euid: uid_t / Set the current process's real and effective user ids. [clinic start generated code]*/ static PyObject * os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid) /*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/ { if (setreuid(ruid, euid) < 0) { return posix_error(); } else { Py_RETURN_NONE; } } #endif /* HAVE_SETREUID */ #ifdef HAVE_SETREGID /*[clinic input] os.setregid rgid: gid_t egid: gid_t / Set the current process's real and effective group ids. [clinic start generated code]*/ static PyObject * os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid) /*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/ { if (setregid(rgid, egid) < 0) return posix_error(); Py_RETURN_NONE; } #endif /* HAVE_SETREGID */ #ifdef HAVE_SETGID /*[clinic input] os.setgid gid: gid_t / Set the current process's group id. [clinic start generated code]*/ static PyObject * os_setgid_impl(PyObject *module, gid_t gid) /*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/ { if (setgid(gid) < 0) return posix_error(); Py_RETURN_NONE; } #endif /* HAVE_SETGID */ #ifdef HAVE_SETGROUPS /*[clinic input] os.setgroups groups: object / Set the groups of the current process to list. [clinic start generated code]*/ static PyObject * os_setgroups(PyObject *module, PyObject *groups) /*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/ { if (!PySequence_Check(groups)) { PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence"); return NULL; } Py_ssize_t len = PySequence_Size(groups); if (len < 0) { return NULL; } if (len > MAX_GROUPS) { PyErr_SetString(PyExc_ValueError, "too many groups"); return NULL; } gid_t *grouplist = PyMem_New(gid_t, len); for (Py_ssize_t i = 0; i < len; i++) { PyObject *elem; elem = PySequence_GetItem(groups, i); if (!elem) { PyMem_Free(grouplist); return NULL; } if (!PyLong_Check(elem)) { PyErr_SetString(PyExc_TypeError, "groups must be integers"); Py_DECREF(elem); PyMem_Free(grouplist); return NULL; } else { if (!_Py_Gid_Converter(elem, &grouplist[i])) { Py_DECREF(elem); PyMem_Free(grouplist); return NULL; } } Py_DECREF(elem); } if (setgroups(len, grouplist) < 0) { PyMem_Free(grouplist); return posix_error(); } PyMem_Free(grouplist); Py_RETURN_NONE; } #endif /* HAVE_SETGROUPS */ #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) static PyObject * wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru) { PyObject *result; PyObject *struct_rusage; if (pid == -1) return posix_error(); // If wait succeeded but no child was ready to report status, ru will not // have been populated. if (pid == 0) { memset(ru, 0, sizeof(*ru)); } struct_rusage = _PyImport_GetModuleAttrString("resource", "struct_rusage"); if (struct_rusage == NULL) return NULL; /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */ result = PyStructSequence_New((PyTypeObject*) struct_rusage); Py_DECREF(struct_rusage); if (!result) return NULL; #ifndef doubletime #define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001) #endif PyStructSequence_SET_ITEM(result, 0, PyFloat_FromDouble(doubletime(ru->ru_utime))); PyStructSequence_SET_ITEM(result, 1, PyFloat_FromDouble(doubletime(ru->ru_stime))); #define SET_INT(result, index, value)\ PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value)) SET_INT(result, 2, ru->ru_maxrss); SET_INT(result, 3, ru->ru_ixrss); SET_INT(result, 4, ru->ru_idrss); SET_INT(result, 5, ru->ru_isrss); SET_INT(result, 6, ru->ru_minflt); SET_INT(result, 7, ru->ru_majflt); SET_INT(result, 8, ru->ru_nswap); SET_INT(result, 9, ru->ru_inblock); SET_INT(result, 10, ru->ru_oublock); SET_INT(result, 11, ru->ru_msgsnd); SET_INT(result, 12, ru->ru_msgrcv); SET_INT(result, 13, ru->ru_nsignals); SET_INT(result, 14, ru->ru_nvcsw); SET_INT(result, 15, ru->ru_nivcsw); #undef SET_INT if (PyErr_Occurred()) { Py_DECREF(result); return NULL; } return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result); } #endif /* HAVE_WAIT3 || HAVE_WAIT4 */ #ifdef HAVE_WAIT3 /*[clinic input] os.wait3 options: int Wait for completion of a child process. Returns a tuple of information about the child process: (pid, status, rusage) [clinic start generated code]*/ static PyObject * os_wait3_impl(PyObject *module, int options) /*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/ { pid_t pid; struct rusage ru; int async_err = 0; WAIT_TYPE status; WAIT_STATUS_INT(status) = 0; do { Py_BEGIN_ALLOW_THREADS pid = wait3(&status, options, &ru); Py_END_ALLOW_THREADS } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); if (pid < 0) return (!async_err) ? posix_error() : NULL; return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru); } #endif /* HAVE_WAIT3 */ #ifdef HAVE_WAIT4 /*[clinic input] os.wait4 pid: pid_t options: int Wait for completion of a specific child process. Returns a tuple of information about the child process: (pid, status, rusage) [clinic start generated code]*/ static PyObject * os_wait4_impl(PyObject *module, pid_t pid, int options) /*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/ { pid_t res; struct rusage ru; int async_err = 0; WAIT_TYPE status; WAIT_STATUS_INT(status) = 0; do { Py_BEGIN_ALLOW_THREADS res = wait4(pid, &status, options, &ru); Py_END_ALLOW_THREADS } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); if (res < 0) return (!async_err) ? posix_error() : NULL; return wait_helper(module, res, WAIT_STATUS_INT(status), &ru); } #endif /* HAVE_WAIT4 */ #if defined(HAVE_WAITID) && !defined(__APPLE__) /*[clinic input] os.waitid idtype: idtype_t Must be one of be P_PID, P_PGID or P_ALL. id: id_t The id to wait on. options: int Constructed from the ORing of one or more of WEXITED, WSTOPPED or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT. / Returns the result of waiting for a process or processes. Returns either waitid_result or None if WNOHANG is specified and there are no children in a waitable state. [clinic start generated code]*/ static PyObject * os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options) /*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/ { PyObject *result; int res; int async_err = 0; siginfo_t si; si.si_pid = 0; do { Py_BEGIN_ALLOW_THREADS res = waitid(idtype, id, &si, options); Py_END_ALLOW_THREADS } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); if (res < 0) return (!async_err) ? posix_error() : NULL; if (si.si_pid == 0) Py_RETURN_NONE; PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType; result = PyStructSequence_New((PyTypeObject *)WaitidResultType); if (!result) return NULL; PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid)); PyStructSequence_SET_ITEM(result, 1, _PyLong_FromUid(si.si_uid)); PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo))); PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status))); PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code))); if (PyErr_Occurred()) { Py_DECREF(result); return NULL; } return result; } #endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */ #if defined(HAVE_WAITPID) /*[clinic input] os.waitpid pid: pid_t options: int / Wait for completion of a given child process. Returns a tuple of information regarding the child process: (pid, status) The options argument is ignored on Windows. [clinic start generated code]*/ static PyObject * os_waitpid_impl(PyObject *module, pid_t pid, int options) /*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/ { pid_t res; int async_err = 0; WAIT_TYPE status; WAIT_STATUS_INT(status) = 0; do { Py_BEGIN_ALLOW_THREADS res = waitpid(pid, &status, options); Py_END_ALLOW_THREADS } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); if (res < 0) return (!async_err) ? posix_error() : NULL; return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status)); } #elif defined(HAVE_CWAIT) /* MS C has a variant of waitpid() that's usable for most purposes. */ /*[clinic input] os.waitpid pid: intptr_t options: int / Wait for completion of a given process. Returns a tuple of information regarding the process: (pid, status << 8) The options argument is ignored on Windows. [clinic start generated code]*/ static PyObject * os_waitpid_impl(PyObject *module, intptr_t pid, int options) /*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/ { int status; intptr_t res; int async_err = 0; do { Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH res = _cwait(&status, pid, options); _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); if (res < 0) return (!async_err) ? posix_error() : NULL; unsigned long long ustatus = (unsigned int)status; /* shift the status left a byte so this is more like the POSIX waitpid */ return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8); } #endif #ifdef HAVE_WAIT /*[clinic input] os.wait Wait for completion of a child process. Returns a tuple of information about the child process: (pid, status) [clinic start generated code]*/ static PyObject * os_wait_impl(PyObject *module) /*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/ { pid_t pid; int async_err = 0; WAIT_TYPE status; WAIT_STATUS_INT(status) = 0; do { Py_BEGIN_ALLOW_THREADS pid = wait(&status); Py_END_ALLOW_THREADS } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); if (pid < 0) return (!async_err) ? posix_error() : NULL; return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status)); } #endif /* HAVE_WAIT */ #if defined(__linux__) && defined(__NR_pidfd_open) /*[clinic input] os.pidfd_open pid: pid_t flags: unsigned_int = 0 Return a file descriptor referring to the process *pid*. The descriptor can be used to perform process management without races and signals. [clinic start generated code]*/ static PyObject * os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags) /*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/ { int fd = syscall(__NR_pidfd_open, pid, flags); if (fd < 0) { return posix_error(); } return PyLong_FromLong(fd); } #endif #ifdef HAVE_SETNS /*[clinic input] os.setns fd: fildes A file descriptor to a namespace. nstype: int = 0 Type of namespace. Move the calling thread into different namespaces. [clinic start generated code]*/ static PyObject * os_setns_impl(PyObject *module, int fd, int nstype) /*[clinic end generated code: output=5dbd055bfb66ecd0 input=42787871226bf3ee]*/ { int res; Py_BEGIN_ALLOW_THREADS res = setns(fd, nstype); Py_END_ALLOW_THREADS if (res != 0) { return posix_error(); } Py_RETURN_NONE; } #endif #ifdef HAVE_UNSHARE /*[clinic input] os.unshare flags: int Namespaces to be unshared. Disassociate parts of a process (or thread) execution context. [clinic start generated code]*/ static PyObject * os_unshare_impl(PyObject *module, int flags) /*[clinic end generated code: output=1b3177906dd237ee input=9e065db3232b8b1b]*/ { int res; Py_BEGIN_ALLOW_THREADS res = unshare(flags); Py_END_ALLOW_THREADS if (res != 0) { return posix_error(); } Py_RETURN_NONE; } #endif #if defined(HAVE_READLINK) || defined(MS_WINDOWS) /*[clinic input] os.readlink path: path_t * dir_fd: dir_fd(requires='readlinkat') = None Return a string representing the path to which the symbolic link points. If dir_fd is not None, it should be a file descriptor open to a directory, and path should be relative; path will then be relative to that directory. dir_fd may not be implemented on your platform. If it is unavailable, using it will raise a NotImplementedError. [clinic start generated code]*/ static PyObject * os_readlink_impl(PyObject *module, path_t *path, int dir_fd) /*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/ { #if defined(HAVE_READLINK) char buffer[MAXPATHLEN+1]; ssize_t length; #ifdef HAVE_READLINKAT int readlinkat_unavailable = 0; #endif Py_BEGIN_ALLOW_THREADS #ifdef HAVE_READLINKAT if (dir_fd != DEFAULT_DIR_FD) { if (HAVE_READLINKAT_RUNTIME) { length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN); } else { readlinkat_unavailable = 1; } } else #endif length = readlink(path->narrow, buffer, MAXPATHLEN); Py_END_ALLOW_THREADS #ifdef HAVE_READLINKAT if (readlinkat_unavailable) { argument_unavailable_error(NULL, "dir_fd"); return NULL; } #endif if (length < 0) { return path_error(path); } buffer[length] = '\0'; if (PyUnicode_Check(path->object)) return PyUnicode_DecodeFSDefaultAndSize(buffer, length); else return PyBytes_FromStringAndSize(buffer, length); #elif defined(MS_WINDOWS) DWORD n_bytes_returned; DWORD io_result = 0; HANDLE reparse_point_handle; char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer; PyObject *result = NULL; /* First get a handle to the reparse point */ Py_BEGIN_ALLOW_THREADS reparse_point_handle = CreateFileW( path->wide, 0, 0, 0, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, 0); if (reparse_point_handle != INVALID_HANDLE_VALUE) { /* New call DeviceIoControl to read the reparse point */ io_result = DeviceIoControl( reparse_point_handle, FSCTL_GET_REPARSE_POINT, 0, 0, /* in buffer */ target_buffer, sizeof(target_buffer), &n_bytes_returned, 0 /* we're not using OVERLAPPED_IO */ ); CloseHandle(reparse_point_handle); } Py_END_ALLOW_THREADS if (io_result == 0) { return path_error(path); } wchar_t *name = NULL; Py_ssize_t nameLen = 0; if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK) { name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer + rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset); nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t); } else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) { name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer + rdb->MountPointReparseBuffer.SubstituteNameOffset); nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t); } else { PyErr_SetString(PyExc_ValueError, "not a symbolic link"); } if (name) { if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) { /* Our buffer is mutable, so this is okay */ name[1] = L'\\'; } result = PyUnicode_FromWideChar(name, nameLen); if (result && path->narrow) { Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); } } return result; #endif } #endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */ #if defined(MS_WINDOWS) /* Remove the last portion of the path - return 0 on success */ static int _dirnameW(WCHAR *path) { WCHAR *ptr; size_t length = wcsnlen_s(path, MAX_PATH); if (length == MAX_PATH) { return -1; } /* walk the path from the end until a backslash is encountered */ for(ptr = path + length; ptr != path; ptr--) { if (*ptr == L'\\' || *ptr == L'/') { break; } } *ptr = 0; return 0; } #endif #ifdef HAVE_SYMLINK #if defined(MS_WINDOWS) /* Is this path absolute? */ static int _is_absW(const WCHAR *path) { return path[0] == L'\\' || path[0] == L'/' || (path[0] && path[1] == L':'); } /* join root and rest with a backslash - return 0 on success */ static int _joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest) { if (_is_absW(rest)) { return wcscpy_s(dest_path, MAX_PATH, rest); } if (wcscpy_s(dest_path, MAX_PATH, root)) { return -1; } if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) { return -1; } return wcscat_s(dest_path, MAX_PATH, rest); } /* Return True if the path at src relative to dest is a directory */ static int _check_dirW(LPCWSTR src, LPCWSTR dest) { WIN32_FILE_ATTRIBUTE_DATA src_info; WCHAR dest_parent[MAX_PATH]; WCHAR src_resolved[MAX_PATH] = L""; /* dest_parent = os.path.dirname(dest) */ if (wcscpy_s(dest_parent, MAX_PATH, dest) || _dirnameW(dest_parent)) { return 0; } /* src_resolved = os.path.join(dest_parent, src) */ if (_joinW(src_resolved, dest_parent, src)) { return 0; } return ( GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info) && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ); } #endif /*[clinic input] os.symlink src: path_t dst: path_t target_is_directory: bool = False * dir_fd: dir_fd(requires='symlinkat')=None # "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\ Create a symbolic link pointing to src named dst. target_is_directory is required on Windows if the target is to be interpreted as a directory. (On Windows, symlink requires Windows 6.0 or greater, and raises a NotImplementedError otherwise.) target_is_directory is ignored on non-Windows platforms. If dir_fd is not None, it should be a file descriptor open to a directory, and path should be relative; path will then be relative to that directory. dir_fd may not be implemented on your platform. If it is unavailable, using it will raise a NotImplementedError. [clinic start generated code]*/ static PyObject * os_symlink_impl(PyObject *module, path_t *src, path_t *dst, int target_is_directory, int dir_fd) /*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/ { #ifdef MS_WINDOWS DWORD result; DWORD flags = 0; /* Assumed true, set to false if detected to not be available. */ static int windows_has_symlink_unprivileged_flag = TRUE; #else int result; #ifdef HAVE_SYMLINKAT int symlinkat_unavailable = 0; #endif #endif if (PySys_Audit("os.symlink", "OOi", src->object, dst->object, dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) { return NULL; } #ifdef MS_WINDOWS if (windows_has_symlink_unprivileged_flag) { /* Allow non-admin symlinks if system allows it. */ flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE; } Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH /* if src is a directory, ensure flags==1 (target_is_directory bit) */ if (target_is_directory || _check_dirW(src->wide, dst->wide)) { flags |= SYMBOLIC_LINK_FLAG_DIRECTORY; } result = CreateSymbolicLinkW(dst->wide, src->wide, flags); _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS if (windows_has_symlink_unprivileged_flag && !result && ERROR_INVALID_PARAMETER == GetLastError()) { Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH /* This error might be caused by SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported. Try again, and update windows_has_symlink_unprivileged_flag if we are successful this time. NOTE: There is a risk of a race condition here if there are other conditions than the flag causing ERROR_INVALID_PARAMETER, and another process (or thread) changes that condition in between our calls to CreateSymbolicLink. */ flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE); result = CreateSymbolicLinkW(dst->wide, src->wide, flags); _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS if (result || ERROR_INVALID_PARAMETER != GetLastError()) { windows_has_symlink_unprivileged_flag = FALSE; } } if (!result) return path_error2(src, dst); #else if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) { PyErr_SetString(PyExc_ValueError, "symlink: src and dst must be the same type"); return NULL; } Py_BEGIN_ALLOW_THREADS #ifdef HAVE_SYMLINKAT if (dir_fd != DEFAULT_DIR_FD) { if (HAVE_SYMLINKAT_RUNTIME) { result = symlinkat(src->narrow, dir_fd, dst->narrow); } else { symlinkat_unavailable = 1; } } else #endif result = symlink(src->narrow, dst->narrow); Py_END_ALLOW_THREADS #ifdef HAVE_SYMLINKAT if (symlinkat_unavailable) { argument_unavailable_error(NULL, "dir_fd"); return NULL; } #endif if (result) return path_error2(src, dst); #endif Py_RETURN_NONE; } #endif /* HAVE_SYMLINK */ static PyStructSequence_Field times_result_fields[] = { {"user", "user time"}, {"system", "system time"}, {"children_user", "user time of children"}, {"children_system", "system time of children"}, {"elapsed", "elapsed time since an arbitrary point in the past"}, {NULL} }; PyDoc_STRVAR(times_result__doc__, "times_result: Result from os.times().\n\n\ This object may be accessed either as a tuple of\n\ (user, system, children_user, children_system, elapsed),\n\ or via the attributes user, system, children_user, children_system,\n\ and elapsed.\n\ \n\ See os.times for more information."); static PyStructSequence_Desc times_result_desc = { "times_result", /* name */ times_result__doc__, /* doc */ times_result_fields, 5 }; #ifdef MS_WINDOWS #define HAVE_TIMES /* mandatory, for the method table */ #endif #ifdef HAVE_TIMES static PyObject * build_times_result(PyObject *module, double user, double system, double children_user, double children_system, double elapsed) { PyObject *TimesResultType = get_posix_state(module)->TimesResultType; PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType); if (value == NULL) return NULL; #define SET(i, field) \ { \ PyObject *o = PyFloat_FromDouble(field); \ if (!o) { \ Py_DECREF(value); \ return NULL; \ } \ PyStructSequence_SET_ITEM(value, i, o); \ } \ SET(0, user); SET(1, system); SET(2, children_user); SET(3, children_system); SET(4, elapsed); #undef SET return value; } /*[clinic input] os.times Return a collection containing process timing information. The object returned behaves like a named tuple with these fields: (utime, stime, cutime, cstime, elapsed_time) All fields are floating point numbers. [clinic start generated code]*/ static PyObject * os_times_impl(PyObject *module) /*[clinic end generated code: output=35f640503557d32a input=2bf9df3d6ab2e48b]*/ #ifdef MS_WINDOWS { FILETIME create, exit, kernel, user; HANDLE hProc; hProc = GetCurrentProcess(); GetProcessTimes(hProc, &create, &exit, &kernel, &user); /* The fields of a FILETIME structure are the hi and lo part of a 64-bit value expressed in 100 nanosecond units. 1e7 is one second in such units; 1e-7 the inverse. 429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7. */ return build_times_result(module, (double)(user.dwHighDateTime*429.4967296 + user.dwLowDateTime*1e-7), (double)(kernel.dwHighDateTime*429.4967296 + kernel.dwLowDateTime*1e-7), (double)0, (double)0, (double)0); } #else /* MS_WINDOWS */ { struct tms t; clock_t c; errno = 0; c = times(&t); if (c == (clock_t) -1) { return posix_error(); } assert(_PyRuntime.time.ticks_per_second_initialized); #define ticks_per_second _PyRuntime.time.ticks_per_second return build_times_result(module, (double)t.tms_utime / ticks_per_second, (double)t.tms_stime / ticks_per_second, (double)t.tms_cutime / ticks_per_second, (double)t.tms_cstime / ticks_per_second, (double)c / ticks_per_second); #undef ticks_per_second } #endif /* MS_WINDOWS */ #endif /* HAVE_TIMES */ #ifdef HAVE_GETSID /*[clinic input] os.getsid pid: pid_t / Call the system call getsid(pid) and return the result. [clinic start generated code]*/ static PyObject * os_getsid_impl(PyObject *module, pid_t pid) /*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/ { int sid; sid = getsid(pid); if (sid < 0) return posix_error(); return PyLong_FromLong((long)sid); } #endif /* HAVE_GETSID */ #ifdef HAVE_SETSID /*[clinic input] os.setsid Call the system call setsid(). [clinic start generated code]*/ static PyObject * os_setsid_impl(PyObject *module) /*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/ { if (setsid() < 0) return posix_error(); Py_RETURN_NONE; } #endif /* HAVE_SETSID */ #ifdef HAVE_SETPGID /*[clinic input] os.setpgid pid: pid_t pgrp: pid_t / Call the system call setpgid(pid, pgrp). [clinic start generated code]*/ static PyObject * os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp) /*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/ { if (setpgid(pid, pgrp) < 0) return posix_error(); Py_RETURN_NONE; } #endif /* HAVE_SETPGID */ #ifdef HAVE_TCGETPGRP /*[clinic input] os.tcgetpgrp fd: int / Return the process group associated with the terminal specified by fd. [clinic start generated code]*/ static PyObject * os_tcgetpgrp_impl(PyObject *module, int fd) /*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/ { pid_t pgid = tcgetpgrp(fd); if (pgid < 0) return posix_error(); return PyLong_FromPid(pgid); } #endif /* HAVE_TCGETPGRP */ #ifdef HAVE_TCSETPGRP /*[clinic input] os.tcsetpgrp fd: int pgid: pid_t / Set the process group associated with the terminal specified by fd. [clinic start generated code]*/ static PyObject * os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid) /*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/ { if (tcsetpgrp(fd, pgid) < 0) return posix_error(); Py_RETURN_NONE; } #endif /* HAVE_TCSETPGRP */ /* Functions acting on file descriptors */ #ifdef O_CLOEXEC extern int _Py_open_cloexec_works; #endif /*[clinic input] os.open -> int path: path_t flags: int mode: int = 0o777 * dir_fd: dir_fd(requires='openat') = None # "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\ Open a file for low level IO. Returns a file descriptor (integer). If dir_fd is not None, it should be a file descriptor open to a directory, and path should be relative; path will then be relative to that directory. dir_fd may not be implemented on your platform. If it is unavailable, using it will raise a NotImplementedError. [clinic start generated code]*/ static int os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd) /*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/ { int fd; int async_err = 0; #ifdef HAVE_OPENAT int openat_unavailable = 0; #endif #ifdef O_CLOEXEC int *atomic_flag_works = &_Py_open_cloexec_works; #elif !defined(MS_WINDOWS) int *atomic_flag_works = NULL; #endif #ifdef MS_WINDOWS flags |= O_NOINHERIT; #elif defined(O_CLOEXEC) flags |= O_CLOEXEC; #endif if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) { return -1; } _Py_BEGIN_SUPPRESS_IPH do { Py_BEGIN_ALLOW_THREADS #ifdef MS_WINDOWS fd = _wopen(path->wide, flags, mode); #else #ifdef HAVE_OPENAT if (dir_fd != DEFAULT_DIR_FD) { if (HAVE_OPENAT_RUNTIME) { fd = openat(dir_fd, path->narrow, flags, mode); } else { openat_unavailable = 1; fd = -1; } } else #endif /* HAVE_OPENAT */ fd = open(path->narrow, flags, mode); #endif /* !MS_WINDOWS */ Py_END_ALLOW_THREADS } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); _Py_END_SUPPRESS_IPH #ifdef HAVE_OPENAT if (openat_unavailable) { argument_unavailable_error(NULL, "dir_fd"); return -1; } #endif if (fd < 0) { if (!async_err) PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object); return -1; } #ifndef MS_WINDOWS if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) { close(fd); return -1; } #endif return fd; } /*[clinic input] os.close fd: int Close a file descriptor. [clinic start generated code]*/ static PyObject * os_close_impl(PyObject *module, int fd) /*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/ { int res; /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/ * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html * for more details. */ Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH res = close(fd); _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS if (res < 0) return posix_error(); Py_RETURN_NONE; } /*[clinic input] os.closerange fd_low: int fd_high: int / Closes all file descriptors in [fd_low, fd_high), ignoring errors. [clinic start generated code]*/ static PyObject * os_closerange_impl(PyObject *module, int fd_low, int fd_high) /*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/ { Py_BEGIN_ALLOW_THREADS _Py_closerange(fd_low, fd_high - 1); Py_END_ALLOW_THREADS Py_RETURN_NONE; } /*[clinic input] os.dup -> int fd: int / Return a duplicate of a file descriptor. [clinic start generated code]*/ static int os_dup_impl(PyObject *module, int fd) /*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/ { return _Py_dup(fd); } // dup2() is either provided by libc or dup2.c with AC_REPLACE_FUNCS(). // dup2.c provides working dup2() if and only if F_DUPFD is available. #if (defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS)) /*[clinic input] os.dup2 -> int fd: int fd2: int inheritable: bool=True Duplicate file descriptor. [clinic start generated code]*/ static int os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable) /*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/ { int res = 0; #if defined(HAVE_DUP3) && \ !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)) /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */ static int dup3_works = -1; #endif if (fd < 0 || fd2 < 0) { posix_error(); return -1; } /* dup2() can fail with EINTR if the target FD is already open, because it * then has to be closed. See os_close_impl() for why we don't handle EINTR * upon close(), and therefore below. */ #ifdef MS_WINDOWS Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH res = dup2(fd, fd2); _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS if (res < 0) { posix_error(); return -1; } res = fd2; // msvcrt dup2 returns 0 on success. /* Character files like console cannot be make non-inheritable */ if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) { close(fd2); return -1; } #elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC) Py_BEGIN_ALLOW_THREADS if (!inheritable) res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2); else res = dup2(fd, fd2); Py_END_ALLOW_THREADS if (res < 0) { posix_error(); return -1; } #else #ifdef HAVE_DUP3 if (!inheritable && dup3_works != 0) { Py_BEGIN_ALLOW_THREADS res = dup3(fd, fd2, O_CLOEXEC); Py_END_ALLOW_THREADS if (res < 0) { if (dup3_works == -1) dup3_works = (errno != ENOSYS); if (dup3_works) { posix_error(); return -1; } } } if (inheritable || dup3_works == 0) { #endif Py_BEGIN_ALLOW_THREADS res = dup2(fd, fd2); Py_END_ALLOW_THREADS if (res < 0) { posix_error(); return -1; } if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) { close(fd2); return -1; } #ifdef HAVE_DUP3 } #endif #endif return res; } #endif #ifdef HAVE_LOCKF /*[clinic input] os.lockf fd: int An open file descriptor. command: int One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST. length: Py_off_t The number of bytes to lock, starting at the current position. / Apply, test or remove a POSIX lock on an open file descriptor. [clinic start generated code]*/ static PyObject * os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length) /*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/ { int res; if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) { return NULL; } Py_BEGIN_ALLOW_THREADS res = lockf(fd, command, length); Py_END_ALLOW_THREADS if (res < 0) return posix_error(); Py_RETURN_NONE; } #endif /* HAVE_LOCKF */ /*[clinic input] os.lseek -> Py_off_t fd: int position: Py_off_t how: int / Set the position of a file descriptor. Return the new position. Return the new cursor position in number of bytes relative to the beginning of the file. [clinic start generated code]*/ static Py_off_t os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how) /*[clinic end generated code: output=971e1efb6b30bd2f input=902654ad3f96a6d3]*/ { Py_off_t result; #ifdef SEEK_SET /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */ switch (how) { case 0: how = SEEK_SET; break; case 1: how = SEEK_CUR; break; case 2: how = SEEK_END; break; } #endif /* SEEK_END */ Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH #ifdef MS_WINDOWS result = _lseeki64(fd, position, how); #else result = lseek(fd, position, how); #endif _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS if (result < 0) posix_error(); return result; } /*[clinic input] os.read fd: int length: Py_ssize_t / Read from a file descriptor. Returns a bytes object. [clinic start generated code]*/ static PyObject * os_read_impl(PyObject *module, int fd, Py_ssize_t length) /*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/ { Py_ssize_t n; PyObject *buffer; if (length < 0) { errno = EINVAL; return posix_error(); } length = Py_MIN(length, _PY_READ_MAX); buffer = PyBytes_FromStringAndSize((char *)NULL, length); if (buffer == NULL) return NULL; n = _Py_read(fd, PyBytes_AS_STRING(buffer), length); if (n == -1) { Py_DECREF(buffer); return NULL; } if (n != length) _PyBytes_Resize(&buffer, n); return buffer; } #if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \ || defined(__APPLE__))) \ || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \ || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2) static int iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type) { Py_ssize_t i, j; *iov = PyMem_New(struct iovec, cnt); if (*iov == NULL) { PyErr_NoMemory(); return -1; } *buf = PyMem_New(Py_buffer, cnt); if (*buf == NULL) { PyMem_Free(*iov); PyErr_NoMemory(); return -1; } for (i = 0; i < cnt; i++) { PyObject *item = PySequence_GetItem(seq, i); if (item == NULL) goto fail; if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) { Py_DECREF(item); goto fail; } Py_DECREF(item); (*iov)[i].iov_base = (*buf)[i].buf; (*iov)[i].iov_len = (*buf)[i].len; } return 0; fail: PyMem_Free(*iov); for (j = 0; j < i; j++) { PyBuffer_Release(&(*buf)[j]); } PyMem_Free(*buf); return -1; } static void iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt) { int i; PyMem_Free(iov); for (i = 0; i < cnt; i++) { PyBuffer_Release(&buf[i]); } PyMem_Free(buf); } #endif #ifdef HAVE_READV /*[clinic input] os.readv -> Py_ssize_t fd: int buffers: object / Read from a file descriptor fd into an iterable of buffers. The buffers should be mutable buffers accepting bytes. readv will transfer data into each buffer until it is full and then move on to the next buffer in the sequence to hold the rest of the data. readv returns the total number of bytes read, which may be less than the total capacity of all the buffers. [clinic start generated code]*/ static Py_ssize_t os_readv_impl(PyObject *module, int fd, PyObject *buffers) /*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/ { Py_ssize_t cnt, n; int async_err = 0; struct iovec *iov; Py_buffer *buf; if (!PySequence_Check(buffers)) { PyErr_SetString(PyExc_TypeError, "readv() arg 2 must be a sequence"); return -1; } cnt = PySequence_Size(buffers); if (cnt < 0) return -1; if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) return -1; do { Py_BEGIN_ALLOW_THREADS n = readv(fd, iov, cnt); Py_END_ALLOW_THREADS } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); iov_cleanup(iov, buf, cnt); if (n < 0) { if (!async_err) posix_error(); return -1; } return n; } #endif /* HAVE_READV */ #ifdef HAVE_PREAD /*[clinic input] os.pread fd: int length: Py_ssize_t offset: Py_off_t / Read a number of bytes from a file descriptor starting at a particular offset. Read length bytes from file descriptor fd, starting at offset bytes from the beginning of the file. The file offset remains unchanged. [clinic start generated code]*/ static PyObject * os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset) /*[clinic end generated code: output=3f875c1eef82e32f input=85cb4a5589627144]*/ { Py_ssize_t n; int async_err = 0; PyObject *buffer; if (length < 0) { errno = EINVAL; return posix_error(); } buffer = PyBytes_FromStringAndSize((char *)NULL, length); if (buffer == NULL) return NULL; do { Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH n = pread(fd, PyBytes_AS_STRING(buffer), length, offset); _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); if (n < 0) { Py_DECREF(buffer); return (!async_err) ? posix_error() : NULL; } if (n != length) _PyBytes_Resize(&buffer, n); return buffer; } #endif /* HAVE_PREAD */ #if defined(HAVE_PREADV) || defined (HAVE_PREADV2) /*[clinic input] os.preadv -> Py_ssize_t fd: int buffers: object offset: Py_off_t flags: int = 0 / Reads from a file descriptor into a number of mutable bytes-like objects. Combines the functionality of readv() and pread(). As readv(), it will transfer data into each buffer until it is full and then move on to the next buffer in the sequence to hold the rest of the data. Its fourth argument, specifies the file offset at which the input operation is to be performed. It will return the total number of bytes read (which can be less than the total capacity of all the objects). The flags argument contains a bitwise OR of zero or more of the following flags: - RWF_HIPRI - RWF_NOWAIT Using non-zero flags requires Linux 4.6 or newer. [clinic start generated code]*/ static Py_ssize_t os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, int flags) /*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/ { Py_ssize_t cnt, n; int async_err = 0; struct iovec *iov; Py_buffer *buf; if (!PySequence_Check(buffers)) { PyErr_SetString(PyExc_TypeError, "preadv2() arg 2 must be a sequence"); return -1; } cnt = PySequence_Size(buffers); if (cnt < 0) { return -1; } #ifndef HAVE_PREADV2 if(flags != 0) { argument_unavailable_error("preadv2", "flags"); return -1; } #endif if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) { return -1; } #ifdef HAVE_PREADV2 do { Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH n = preadv2(fd, iov, cnt, offset, flags); _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); #else do { #if defined(__APPLE__) && defined(__clang__) /* This entire function will be removed from the module dict when the API * is not available. */ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunguarded-availability" #pragma clang diagnostic ignored "-Wunguarded-availability-new" #endif Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH n = preadv(fd, iov, cnt, offset); _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); #if defined(__APPLE__) && defined(__clang__) #pragma clang diagnostic pop #endif #endif iov_cleanup(iov, buf, cnt); if (n < 0) { if (!async_err) { posix_error(); } return -1; } return n; } #endif /* HAVE_PREADV */ /*[clinic input] os.write -> Py_ssize_t fd: int data: Py_buffer / Write a bytes object to a file descriptor. [clinic start generated code]*/ static Py_ssize_t os_write_impl(PyObject *module, int fd, Py_buffer *data) /*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/ { return _Py_write(fd, data->buf, data->len); } #ifdef HAVE_SENDFILE #ifdef __APPLE__ /*[clinic input] os.sendfile out_fd: int in_fd: int offset: Py_off_t count as sbytes: Py_off_t headers: object(c_default="NULL") = () trailers: object(c_default="NULL") = () flags: int = 0 Copy count bytes from file descriptor in_fd to file descriptor out_fd. [clinic start generated code]*/ static PyObject * os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset, Py_off_t sbytes, PyObject *headers, PyObject *trailers, int flags) /*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/ #elif defined(__FreeBSD__) || defined(__DragonFly__) /*[clinic input] os.sendfile out_fd: int in_fd: int offset: Py_off_t count: Py_ssize_t headers: object(c_default="NULL") = () trailers: object(c_default="NULL") = () flags: int = 0 Copy count bytes from file descriptor in_fd to file descriptor out_fd. [clinic start generated code]*/ static PyObject * os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset, Py_ssize_t count, PyObject *headers, PyObject *trailers, int flags) /*[clinic end generated code: output=329ea009bdd55afc input=338adb8ff84ae8cd]*/ #else /*[clinic input] os.sendfile out_fd: int in_fd: int offset as offobj: object count: Py_ssize_t Copy count bytes from file descriptor in_fd to file descriptor out_fd. [clinic start generated code]*/ static PyObject * os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj, Py_ssize_t count) /*[clinic end generated code: output=ae81216e40f167d8 input=76d64058c74477ba]*/ #endif { Py_ssize_t ret; int async_err = 0; #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__) #ifndef __APPLE__ off_t sbytes; #endif Py_buffer *hbuf, *tbuf; struct sf_hdtr sf; sf.headers = NULL; sf.trailers = NULL; if (headers != NULL) { if (!PySequence_Check(headers)) { PyErr_SetString(PyExc_TypeError, "sendfile() headers must be a sequence"); return NULL; } else { Py_ssize_t i = PySequence_Size(headers); if (i < 0) return NULL; if (i > INT_MAX) { PyErr_SetString(PyExc_OverflowError, "sendfile() header is too large"); return NULL; } if (i > 0) { sf.hdr_cnt = (int)i; if (iov_setup(&(sf.headers), &hbuf, headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0) return NULL; #ifdef __APPLE__ for (i = 0; i < sf.hdr_cnt; i++) { Py_ssize_t blen = sf.headers[i].iov_len; # define OFF_T_MAX 0x7fffffffffffffff if (sbytes >= OFF_T_MAX - blen) { PyErr_SetString(PyExc_OverflowError, "sendfile() header is too large"); return NULL; } sbytes += blen; } #endif } } } if (trailers != NULL) { if (!PySequence_Check(trailers)) { PyErr_SetString(PyExc_TypeError, "sendfile() trailers must be a sequence"); return NULL; } else { Py_ssize_t i = PySequence_Size(trailers); if (i < 0) return NULL; if (i > INT_MAX) { PyErr_SetString(PyExc_OverflowError, "sendfile() trailer is too large"); return NULL; } if (i > 0) { sf.trl_cnt = (int)i; if (iov_setup(&(sf.trailers), &tbuf, trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0) return NULL; } } } _Py_BEGIN_SUPPRESS_IPH do { Py_BEGIN_ALLOW_THREADS #ifdef __APPLE__ ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags); #else ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags); #endif Py_END_ALLOW_THREADS } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); _Py_END_SUPPRESS_IPH if (sf.headers != NULL) iov_cleanup(sf.headers, hbuf, sf.hdr_cnt); if (sf.trailers != NULL) iov_cleanup(sf.trailers, tbuf, sf.trl_cnt); if (ret < 0) { if ((errno == EAGAIN) || (errno == EBUSY)) { if (sbytes != 0) { // some data has been sent goto done; } else { // no data has been sent; upper application is supposed // to retry on EAGAIN or EBUSY return posix_error(); } } return (!async_err) ? posix_error() : NULL; } goto done; done: #if !defined(HAVE_LARGEFILE_SUPPORT) return Py_BuildValue("l", sbytes); #else return Py_BuildValue("L", sbytes); #endif #else #ifdef __linux__ if (offobj == Py_None) { do { Py_BEGIN_ALLOW_THREADS ret = sendfile(out_fd, in_fd, NULL, count); Py_END_ALLOW_THREADS } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); if (ret < 0) return (!async_err) ? posix_error() : NULL; return Py_BuildValue("n", ret); } #endif off_t offset; if (!Py_off_t_converter(offobj, &offset)) return NULL; #if defined(__sun) && defined(__SVR4) // On Solaris, sendfile raises EINVAL rather than returning 0 // when the offset is equal or bigger than the in_fd size. struct stat st; do { Py_BEGIN_ALLOW_THREADS ret = fstat(in_fd, &st); Py_END_ALLOW_THREADS } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); if (ret < 0) return (!async_err) ? posix_error() : NULL; if (offset >= st.st_size) { return Py_BuildValue("i", 0); } // On illumos specifically sendfile() may perform a partial write but // return -1/an error (in one confirmed case the destination socket // had a 5 second timeout set and errno was EAGAIN) and it's on the client // code to check if the offset parameter was modified by sendfile(). // // We need this variable to track said change. off_t original_offset = offset; #endif do { Py_BEGIN_ALLOW_THREADS ret = sendfile(out_fd, in_fd, &offset, count); #if defined(__sun) && defined(__SVR4) // This handles illumos-specific sendfile() partial write behavior, // see a comment above for more details. if (ret < 0 && offset != original_offset) { ret = offset - original_offset; } #endif Py_END_ALLOW_THREADS } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); if (ret < 0) return (!async_err) ? posix_error() : NULL; return Py_BuildValue("n", ret); #endif } #endif /* HAVE_SENDFILE */ #if defined(__APPLE__) /*[clinic input] os._fcopyfile in_fd: int out_fd: int flags: int / Efficiently copy content or metadata of 2 regular file descriptors (macOS). [clinic start generated code]*/ static PyObject * os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags) /*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/ { int ret; Py_BEGIN_ALLOW_THREADS ret = fcopyfile(in_fd, out_fd, NULL, flags); Py_END_ALLOW_THREADS if (ret < 0) return posix_error(); Py_RETURN_NONE; } #endif /*[clinic input] os.fstat fd : int Perform a stat system call on the given file descriptor. Like stat(), but for an open file descriptor. Equivalent to os.stat(fd). [clinic start generated code]*/ static PyObject * os_fstat_impl(PyObject *module, int fd) /*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/ { STRUCT_STAT st; int res; int async_err = 0; do { Py_BEGIN_ALLOW_THREADS res = FSTAT(fd, &st); Py_END_ALLOW_THREADS } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); if (res != 0) { #ifdef MS_WINDOWS return PyErr_SetFromWindowsErr(0); #else return (!async_err) ? posix_error() : NULL; #endif } return _pystat_fromstructstat(module, &st); } /*[clinic input] os.isatty -> bool fd: int / Return True if the fd is connected to a terminal. Return True if the file descriptor is an open file descriptor connected to the slave end of a terminal. [clinic start generated code]*/ static int os_isatty_impl(PyObject *module, int fd) /*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/ { int return_value; Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH return_value = isatty(fd); _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS return return_value; } #ifdef HAVE_PIPE /*[clinic input] os.pipe Create a pipe. Returns a tuple of two file descriptors: (read_fd, write_fd) [clinic start generated code]*/ static PyObject * os_pipe_impl(PyObject *module) /*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/ { int fds[2]; #ifdef MS_WINDOWS HANDLE read, write; SECURITY_ATTRIBUTES attr; BOOL ok; #else int res; #endif #ifdef MS_WINDOWS attr.nLength = sizeof(attr); attr.lpSecurityDescriptor = NULL; attr.bInheritHandle = FALSE; Py_BEGIN_ALLOW_THREADS ok = CreatePipe(&read, &write, &attr, 0); if (ok) { fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY); fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY); if (fds[0] == -1 || fds[1] == -1) { CloseHandle(read); CloseHandle(write); ok = 0; } } Py_END_ALLOW_THREADS if (!ok) return PyErr_SetFromWindowsErr(0); #else #ifdef HAVE_PIPE2 Py_BEGIN_ALLOW_THREADS res = pipe2(fds, O_CLOEXEC); Py_END_ALLOW_THREADS if (res != 0 && errno == ENOSYS) { #endif Py_BEGIN_ALLOW_THREADS res = pipe(fds); Py_END_ALLOW_THREADS if (res == 0) { if (_Py_set_inheritable(fds[0], 0, NULL) < 0) { close(fds[0]); close(fds[1]); return NULL; } if (_Py_set_inheritable(fds[1], 0, NULL) < 0) { close(fds[0]); close(fds[1]); return NULL; } } #ifdef HAVE_PIPE2 } #endif if (res != 0) return PyErr_SetFromErrno(PyExc_OSError); #endif /* !MS_WINDOWS */ return Py_BuildValue("(ii)", fds[0], fds[1]); } #endif /* HAVE_PIPE */ #ifdef HAVE_PIPE2 /*[clinic input] os.pipe2 flags: int / Create a pipe with flags set atomically. Returns a tuple of two file descriptors: (read_fd, write_fd) flags can be constructed by ORing together one or more of these values: O_NONBLOCK, O_CLOEXEC. [clinic start generated code]*/ static PyObject * os_pipe2_impl(PyObject *module, int flags) /*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/ { int fds[2]; int res; res = pipe2(fds, flags); if (res != 0) return posix_error(); return Py_BuildValue("(ii)", fds[0], fds[1]); } #endif /* HAVE_PIPE2 */ #ifdef HAVE_WRITEV /*[clinic input] os.writev -> Py_ssize_t fd: int buffers: object / Iterate over buffers, and write the contents of each to a file descriptor. Returns the total number of bytes written. buffers must be a sequence of bytes-like objects. [clinic start generated code]*/ static Py_ssize_t os_writev_impl(PyObject *module, int fd, PyObject *buffers) /*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/ { Py_ssize_t cnt; Py_ssize_t result; int async_err = 0; struct iovec *iov; Py_buffer *buf; if (!PySequence_Check(buffers)) { PyErr_SetString(PyExc_TypeError, "writev() arg 2 must be a sequence"); return -1; } cnt = PySequence_Size(buffers); if (cnt < 0) return -1; if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) { return -1; } do { Py_BEGIN_ALLOW_THREADS result = writev(fd, iov, cnt); Py_END_ALLOW_THREADS } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); iov_cleanup(iov, buf, cnt); if (result < 0 && !async_err) posix_error(); return result; } #endif /* HAVE_WRITEV */ #ifdef HAVE_PWRITE /*[clinic input] os.pwrite -> Py_ssize_t fd: int buffer: Py_buffer offset: Py_off_t / Write bytes to a file descriptor starting at a particular offset. Write buffer to fd, starting at offset bytes from the beginning of the file. Returns the number of bytes writte. Does not change the current file offset. [clinic start generated code]*/ static Py_ssize_t os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset) /*[clinic end generated code: output=c74da630758ee925 input=19903f1b3dd26377]*/ { Py_ssize_t size; int async_err = 0; do { Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset); _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); if (size < 0 && !async_err) posix_error(); return size; } #endif /* HAVE_PWRITE */ #if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2) /*[clinic input] os.pwritev -> Py_ssize_t fd: int buffers: object offset: Py_off_t flags: int = 0 / Writes the contents of bytes-like objects to a file descriptor at a given offset. Combines the functionality of writev() and pwrite(). All buffers must be a sequence of bytes-like objects. Buffers are processed in array order. Entire contents of first buffer is written before proceeding to second, and so on. The operating system may set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used. This function writes the contents of each object to the file descriptor and returns the total number of bytes written. The flags argument contains a bitwise OR of zero or more of the following flags: - RWF_DSYNC - RWF_SYNC - RWF_APPEND Using non-zero flags requires Linux 4.7 or newer. [clinic start generated code]*/ static Py_ssize_t os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, int flags) /*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=35358c327e1a2a8e]*/ { Py_ssize_t cnt; Py_ssize_t result; int async_err = 0; struct iovec *iov; Py_buffer *buf; if (!PySequence_Check(buffers)) { PyErr_SetString(PyExc_TypeError, "pwritev() arg 2 must be a sequence"); return -1; } cnt = PySequence_Size(buffers); if (cnt < 0) { return -1; } #ifndef HAVE_PWRITEV2 if(flags != 0) { argument_unavailable_error("pwritev2", "flags"); return -1; } #endif if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) { return -1; } #ifdef HAVE_PWRITEV2 do { Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH result = pwritev2(fd, iov, cnt, offset, flags); _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); #else #if defined(__APPLE__) && defined(__clang__) /* This entire function will be removed from the module dict when the API * is not available. */ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunguarded-availability" #pragma clang diagnostic ignored "-Wunguarded-availability-new" #endif do { Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH result = pwritev(fd, iov, cnt, offset); _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); #if defined(__APPLE__) && defined(__clang__) #pragma clang diagnostic pop #endif #endif iov_cleanup(iov, buf, cnt); if (result < 0) { if (!async_err) { posix_error(); } return -1; } return result; } #endif /* HAVE_PWRITEV */ #ifdef HAVE_COPY_FILE_RANGE /*[clinic input] os.copy_file_range src: int Source file descriptor. dst: int Destination file descriptor. count: Py_ssize_t Number of bytes to copy. offset_src: object = None Starting offset in src. offset_dst: object = None Starting offset in dst. Copy count bytes from one file descriptor to another. If offset_src is None, then src is read from the current position; respectively for offset_dst. [clinic start generated code]*/ static PyObject * os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count, PyObject *offset_src, PyObject *offset_dst) /*[clinic end generated code: output=1a91713a1d99fc7a input=42fdce72681b25a9]*/ { off_t offset_src_val, offset_dst_val; off_t *p_offset_src = NULL; off_t *p_offset_dst = NULL; Py_ssize_t ret; int async_err = 0; /* The flags argument is provided to allow * for future extensions and currently must be to 0. */ int flags = 0; if (count < 0) { PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed"); return NULL; } if (offset_src != Py_None) { if (!Py_off_t_converter(offset_src, &offset_src_val)) { return NULL; } p_offset_src = &offset_src_val; } if (offset_dst != Py_None) { if (!Py_off_t_converter(offset_dst, &offset_dst_val)) { return NULL; } p_offset_dst = &offset_dst_val; } do { Py_BEGIN_ALLOW_THREADS ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags); Py_END_ALLOW_THREADS } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); if (ret < 0) { return (!async_err) ? posix_error() : NULL; } return PyLong_FromSsize_t(ret); } #endif /* HAVE_COPY_FILE_RANGE*/ #if (defined(HAVE_SPLICE) && !defined(_AIX)) /*[clinic input] os.splice src: int Source file descriptor. dst: int Destination file descriptor. count: Py_ssize_t Number of bytes to copy. offset_src: object = None Starting offset in src. offset_dst: object = None Starting offset in dst. flags: unsigned_int = 0 Flags to modify the semantics of the call. Transfer count bytes from one pipe to a descriptor or vice versa. If offset_src is None, then src is read from the current position; respectively for offset_dst. The offset associated to the file descriptor that refers to a pipe must be None. [clinic start generated code]*/ static PyObject * os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count, PyObject *offset_src, PyObject *offset_dst, unsigned int flags) /*[clinic end generated code: output=d0386f25a8519dc5 input=047527c66c6d2e0a]*/ { off_t offset_src_val, offset_dst_val; off_t *p_offset_src = NULL; off_t *p_offset_dst = NULL; Py_ssize_t ret; int async_err = 0; if (count < 0) { PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed"); return NULL; } if (offset_src != Py_None) { if (!Py_off_t_converter(offset_src, &offset_src_val)) { return NULL; } p_offset_src = &offset_src_val; } if (offset_dst != Py_None) { if (!Py_off_t_converter(offset_dst, &offset_dst_val)) { return NULL; } p_offset_dst = &offset_dst_val; } do { Py_BEGIN_ALLOW_THREADS ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags); Py_END_ALLOW_THREADS } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); if (ret < 0) { return (!async_err) ? posix_error() : NULL; } return PyLong_FromSsize_t(ret); } #endif /* HAVE_SPLICE*/ #ifdef HAVE_MKFIFO /*[clinic input] os.mkfifo path: path_t mode: int=0o666 * dir_fd: dir_fd(requires='mkfifoat')=None Create a "fifo" (a POSIX named pipe). If dir_fd is not None, it should be a file descriptor open to a directory, and path should be relative; path will then be relative to that directory. dir_fd may not be implemented on your platform. If it is unavailable, using it will raise a NotImplementedError. [clinic start generated code]*/ static PyObject * os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd) /*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/ { int result; int async_err = 0; #ifdef HAVE_MKFIFOAT int mkfifoat_unavailable = 0; #endif do { Py_BEGIN_ALLOW_THREADS #ifdef HAVE_MKFIFOAT if (dir_fd != DEFAULT_DIR_FD) { if (HAVE_MKFIFOAT_RUNTIME) { result = mkfifoat(dir_fd, path->narrow, mode); } else { mkfifoat_unavailable = 1; result = 0; } } else #endif result = mkfifo(path->narrow, mode); Py_END_ALLOW_THREADS } while (result != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); #ifdef HAVE_MKFIFOAT if (mkfifoat_unavailable) { argument_unavailable_error(NULL, "dir_fd"); return NULL; } #endif if (result != 0) return (!async_err) ? posix_error() : NULL; Py_RETURN_NONE; } #endif /* HAVE_MKFIFO */ #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) /*[clinic input] os.mknod path: path_t mode: int=0o600 device: dev_t=0 * dir_fd: dir_fd(requires='mknodat')=None Create a node in the file system. Create a node in the file system (file, device special file or named pipe) at path. mode specifies both the permissions to use and the type of node to be created, being combined (bitwise OR) with one of S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. If S_IFCHR or S_IFBLK is set on mode, device defines the newly created device special file (probably using os.makedev()). Otherwise device is ignored. If dir_fd is not None, it should be a file descriptor open to a directory, and path should be relative; path will then be relative to that directory. dir_fd may not be implemented on your platform. If it is unavailable, using it will raise a NotImplementedError. [clinic start generated code]*/ static PyObject * os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device, int dir_fd) /*[clinic end generated code: output=92e55d3ca8917461 input=ee44531551a4d83b]*/ { int result; int async_err = 0; #ifdef HAVE_MKNODAT int mknodat_unavailable = 0; #endif do { Py_BEGIN_ALLOW_THREADS #ifdef HAVE_MKNODAT if (dir_fd != DEFAULT_DIR_FD) { if (HAVE_MKNODAT_RUNTIME) { result = mknodat(dir_fd, path->narrow, mode, device); } else { mknodat_unavailable = 1; result = 0; } } else #endif result = mknod(path->narrow, mode, device); Py_END_ALLOW_THREADS } while (result != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); #ifdef HAVE_MKNODAT if (mknodat_unavailable) { argument_unavailable_error(NULL, "dir_fd"); return NULL; } #endif if (result != 0) return (!async_err) ? posix_error() : NULL; Py_RETURN_NONE; } #endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */ #ifdef HAVE_DEVICE_MACROS /*[clinic input] os.major -> unsigned_int device: dev_t / Extracts a device major number from a raw device number. [clinic start generated code]*/ static unsigned int os_major_impl(PyObject *module, dev_t device) /*[clinic end generated code: output=5b3b2589bafb498e input=1e16a4d30c4d4462]*/ { return major(device); } /*[clinic input] os.minor -> unsigned_int device: dev_t / Extracts a device minor number from a raw device number. [clinic start generated code]*/ static unsigned int os_minor_impl(PyObject *module, dev_t device) /*[clinic end generated code: output=5e1a25e630b0157d input=0842c6d23f24c65e]*/ { return minor(device); } /*[clinic input] os.makedev -> dev_t major: int minor: int / Composes a raw device number from the major and minor device numbers. [clinic start generated code]*/ static dev_t os_makedev_impl(PyObject *module, int major, int minor) /*[clinic end generated code: output=881aaa4aba6f6a52 input=4b9fd8fc73cbe48f]*/ { return makedev(major, minor); } #endif /* HAVE_DEVICE_MACROS */ #if defined HAVE_FTRUNCATE || defined MS_WINDOWS /*[clinic input] os.ftruncate fd: int length: Py_off_t / Truncate a file, specified by file descriptor, to a specific length. [clinic start generated code]*/ static PyObject * os_ftruncate_impl(PyObject *module, int fd, Py_off_t length) /*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/ { int result; int async_err = 0; if (PySys_Audit("os.truncate", "in", fd, length) < 0) { return NULL; } do { Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH #ifdef MS_WINDOWS result = _chsize_s(fd, length); #else result = ftruncate(fd, length); #endif _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS } while (result != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); if (result != 0) return (!async_err) ? posix_error() : NULL; Py_RETURN_NONE; } #endif /* HAVE_FTRUNCATE || MS_WINDOWS */ #if defined HAVE_TRUNCATE || defined MS_WINDOWS /*[clinic input] os.truncate path: path_t(allow_fd='PATH_HAVE_FTRUNCATE') length: Py_off_t Truncate a file, specified by path, to a specific length. On some platforms, path may also be specified as an open file descriptor. If this functionality is unavailable, using it raises an exception. [clinic start generated code]*/ static PyObject * os_truncate_impl(PyObject *module, path_t *path, Py_off_t length) /*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/ { int result; #ifdef MS_WINDOWS int fd; #endif if (path->fd != -1) return os_ftruncate_impl(module, path->fd, length); if (PySys_Audit("os.truncate", "On", path->object, length) < 0) { return NULL; } Py_BEGIN_ALLOW_THREADS _Py_BEGIN_SUPPRESS_IPH #ifdef MS_WINDOWS fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT); if (fd < 0) result = -1; else { result = _chsize_s(fd, length); close(fd); if (result < 0) errno = result; } #else result = truncate(path->narrow, length); #endif _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS if (result < 0) return posix_path_error(path); Py_RETURN_NONE; } #endif /* HAVE_TRUNCATE || MS_WINDOWS */ /* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise() and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is defined, which is the case in Python on AIX. AIX bug report: http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */ #if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__) # define POSIX_FADVISE_AIX_BUG #endif #if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG) /*[clinic input] os.posix_fallocate fd: int offset: Py_off_t length: Py_off_t / Ensure a file has allocated at least a particular number of bytes on disk. Ensure that the file specified by fd encompasses a range of bytes starting at offset bytes from the beginning and continuing for length bytes. [clinic start generated code]*/ static PyObject * os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset, Py_off_t length) /*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/ { int result; int async_err = 0; do { Py_BEGIN_ALLOW_THREADS result = posix_fallocate(fd, offset, length); Py_END_ALLOW_THREADS } while (result == EINTR && !(async_err = PyErr_CheckSignals())); if (result == 0) Py_RETURN_NONE; if (async_err) return NULL; errno = result; return posix_error(); } #endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */ #if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG) /*[clinic input] os.posix_fadvise fd: int offset: Py_off_t length: Py_off_t advice: int / Announce an intention to access data in a specific pattern. Announce an intention to access data in a specific pattern, thus allowing the kernel to make optimizations. The advice applies to the region of the file specified by fd starting at offset and continuing for length bytes. advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL, POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or POSIX_FADV_DONTNEED. [clinic start generated code]*/ static PyObject * os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset, Py_off_t length, int advice) /*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/ { int result; int async_err = 0; do { Py_BEGIN_ALLOW_THREADS result = posix_fadvise(fd, offset, length, advice); Py_END_ALLOW_THREADS } while (result == EINTR && !(async_err = PyErr_CheckSignals())); if (result == 0) Py_RETURN_NONE; if (async_err) return NULL; errno = result; return posix_error(); } #endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */ #ifdef MS_WINDOWS static PyObject* win32_putenv(PyObject *name, PyObject *value) { /* Search from index 1 because on Windows starting '=' is allowed for defining hidden environment variables. */ if (PyUnicode_GET_LENGTH(name) == 0 || PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1) { PyErr_SetString(PyExc_ValueError, "illegal environment variable name"); return NULL; } PyObject *unicode; if (value != NULL) { unicode = PyUnicode_FromFormat("%U=%U", name, value); } else { unicode = PyUnicode_FromFormat("%U=", name); } if (unicode == NULL) { return NULL; } Py_ssize_t size; /* PyUnicode_AsWideCharString() rejects embedded null characters */ wchar_t *env = PyUnicode_AsWideCharString(unicode, &size); Py_DECREF(unicode); if (env == NULL) { return NULL; } if (size > _MAX_ENV) { PyErr_Format(PyExc_ValueError, "the environment variable is longer than %u characters", _MAX_ENV); PyMem_Free(env); return NULL; } /* _wputenv() and SetEnvironmentVariableW() update the environment in the Process Environment Block (PEB). _wputenv() also updates CRT 'environ' and '_wenviron' variables, whereas SetEnvironmentVariableW() does not. Prefer _wputenv() to be compatible with C libraries using CRT variables and CRT functions using these variables (ex: getenv()). */ int err = _wputenv(env); PyMem_Free(env); if (err) { posix_error(); return NULL; } Py_RETURN_NONE; } #endif #ifdef MS_WINDOWS /*[clinic input] os.putenv name: unicode value: unicode / Change or add an environment variable. [clinic start generated code]*/ static PyObject * os_putenv_impl(PyObject *module, PyObject *name, PyObject *value) /*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/ { if (PySys_Audit("os.putenv", "OO", name, value) < 0) { return NULL; } return win32_putenv(name, value); } #else /*[clinic input] os.putenv name: FSConverter value: FSConverter / Change or add an environment variable. [clinic start generated code]*/ static PyObject * os_putenv_impl(PyObject *module, PyObject *name, PyObject *value) /*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/ { const char *name_string = PyBytes_AS_STRING(name); const char *value_string = PyBytes_AS_STRING(value); if (strchr(name_string, '=') != NULL) { PyErr_SetString(PyExc_ValueError, "illegal environment variable name"); return NULL; } if (PySys_Audit("os.putenv", "OO", name, value) < 0) { return NULL; } if (setenv(name_string, value_string, 1)) { return posix_error(); } Py_RETURN_NONE; } #endif /* !defined(MS_WINDOWS) */ #ifdef MS_WINDOWS /*[clinic input] os.unsetenv name: unicode / Delete an environment variable. [clinic start generated code]*/ static PyObject * os_unsetenv_impl(PyObject *module, PyObject *name) /*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/ { if (PySys_Audit("os.unsetenv", "(O)", name) < 0) { return NULL; } return win32_putenv(name, NULL); } #else /*[clinic input] os.unsetenv name: FSConverter / Delete an environment variable. [clinic start generated code]*/ static PyObject * os_unsetenv_impl(PyObject *module, PyObject *name) /*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/ { if (PySys_Audit("os.unsetenv", "(O)", name) < 0) { return NULL; } #ifdef HAVE_BROKEN_UNSETENV unsetenv(PyBytes_AS_STRING(name)); #else int err = unsetenv(PyBytes_AS_STRING(name)); if (err) { return posix_error(); } #endif Py_RETURN_NONE; } #endif /* !MS_WINDOWS */ /*[clinic input] os.strerror code: int / Translate an error code to a message string. [clinic start generated code]*/ static PyObject * os_strerror_impl(PyObject *module, int code) /*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/ { char *message = strerror(code); if (message == NULL) { PyErr_SetString(PyExc_ValueError, "strerror() argument out of range"); return NULL; } return PyUnicode_DecodeLocale(message, "surrogateescape"); } #ifdef HAVE_SYS_WAIT_H #ifdef WCOREDUMP /*[clinic input] os.WCOREDUMP -> bool status: int / Return True if the process returning status was dumped to a core file. [clinic start generated code]*/ static int os_WCOREDUMP_impl(PyObject *module, int status) /*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/ { WAIT_TYPE wait_status; WAIT_STATUS_INT(wait_status) = status; return WCOREDUMP(wait_status); } #endif /* WCOREDUMP */ #ifdef WIFCONTINUED /*[clinic input] os.WIFCONTINUED -> bool status: int Return True if a particular process was continued from a job control stop. Return True if the process returning status was continued from a job control stop. [clinic start generated code]*/ static int os_WIFCONTINUED_impl(PyObject *module, int status) /*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/ { WAIT_TYPE wait_status; WAIT_STATUS_INT(wait_status) = status; return WIFCONTINUED(wait_status); } #endif /* WIFCONTINUED */ #ifdef WIFSTOPPED /*[clinic input] os.WIFSTOPPED -> bool status: int Return True if the process returning status was stopped. [clinic start generated code]*/ static int os_WIFSTOPPED_impl(PyObject *module, int status) /*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/ { WAIT_TYPE wait_status; WAIT_STATUS_INT(wait_status) = status; return WIFSTOPPED(wait_status); } #endif /* WIFSTOPPED */ #ifdef WIFSIGNALED /*[clinic input] os.WIFSIGNALED -> bool status: int Return True if the process returning status was terminated by a signal. [clinic start generated code]*/ static int os_WIFSIGNALED_impl(PyObject *module, int status) /*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/ { WAIT_TYPE wait_status; WAIT_STATUS_INT(wait_status) = status; return WIFSIGNALED(wait_status); } #endif /* WIFSIGNALED */ #ifdef WIFEXITED /*[clinic input] os.WIFEXITED -> bool status: int Return True if the process returning status exited via the exit() system call. [clinic start generated code]*/ static int os_WIFEXITED_impl(PyObject *module, int status) /*[clinic end generated code: output=01c09d6ebfeea397 input=d63775a6791586c0]*/ { WAIT_TYPE wait_status; WAIT_STATUS_INT(wait_status) = status; return WIFEXITED(wait_status); } #endif /* WIFEXITED */ #ifdef WEXITSTATUS /*[clinic input] os.WEXITSTATUS -> int status: int Return the process return code from status. [clinic start generated code]*/ static int os_WEXITSTATUS_impl(PyObject *module, int status) /*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/ { WAIT_TYPE wait_status; WAIT_STATUS_INT(wait_status) = status; return WEXITSTATUS(wait_status); } #endif /* WEXITSTATUS */ #ifdef WTERMSIG /*[clinic input] os.WTERMSIG -> int status: int Return the signal that terminated the process that provided the status value. [clinic start generated code]*/ static int os_WTERMSIG_impl(PyObject *module, int status) /*[clinic end generated code: output=172f7dfc8dcfc3ad input=727fd7f84ec3f243]*/ { WAIT_TYPE wait_status; WAIT_STATUS_INT(wait_status) = status; return WTERMSIG(wait_status); } #endif /* WTERMSIG */ #ifdef WSTOPSIG /*[clinic input] os.WSTOPSIG -> int status: int Return the signal that stopped the process that provided the status value. [clinic start generated code]*/ static int os_WSTOPSIG_impl(PyObject *module, int status) /*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/ { WAIT_TYPE wait_status; WAIT_STATUS_INT(wait_status) = status; return WSTOPSIG(wait_status); } #endif /* WSTOPSIG */ #endif /* HAVE_SYS_WAIT_H */ #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) #ifdef _SCO_DS /* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the needed definitions in sys/statvfs.h */ #define _SVID3 #endif #include static PyObject* _pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) { PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType; PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType); if (v == NULL) return NULL; #if !defined(HAVE_LARGEFILE_SUPPORT) PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize)); PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize)); PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks)); PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree)); PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail)); PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files)); PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree)); PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail)); PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag)); PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax)); #else PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize)); PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize)); PyStructSequence_SET_ITEM(v, 2, PyLong_FromLongLong((long long) st.f_blocks)); PyStructSequence_SET_ITEM(v, 3, PyLong_FromLongLong((long long) st.f_bfree)); PyStructSequence_SET_ITEM(v, 4, PyLong_FromLongLong((long long) st.f_bavail)); PyStructSequence_SET_ITEM(v, 5, PyLong_FromLongLong((long long) st.f_files)); PyStructSequence_SET_ITEM(v, 6, PyLong_FromLongLong((long long) st.f_ffree)); PyStructSequence_SET_ITEM(v, 7, PyLong_FromLongLong((long long) st.f_favail)); PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag)); PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax)); #endif /* The _ALL_SOURCE feature test macro defines f_fsid as a structure * (issue #32390). */ #if defined(_AIX) && defined(_ALL_SOURCE) PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0])); #else PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid)); #endif if (PyErr_Occurred()) { Py_DECREF(v); return NULL; } return v; } /*[clinic input] os.fstatvfs fd: int / Perform an fstatvfs system call on the given fd. Equivalent to statvfs(fd). [clinic start generated code]*/ static PyObject * os_fstatvfs_impl(PyObject *module, int fd) /*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/ { int result; int async_err = 0; struct statvfs st; do { Py_BEGIN_ALLOW_THREADS result = fstatvfs(fd, &st); Py_END_ALLOW_THREADS } while (result != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); if (result != 0) return (!async_err) ? posix_error() : NULL; return _pystatvfs_fromstructstatvfs(module, st); } #endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */ #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) #include /*[clinic input] os.statvfs path: path_t(allow_fd='PATH_HAVE_FSTATVFS') Perform a statvfs system call on the given path. path may always be specified as a string. On some platforms, path may also be specified as an open file descriptor. If this functionality is unavailable, using it raises an exception. [clinic start generated code]*/ static PyObject * os_statvfs_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/ { int result; struct statvfs st; Py_BEGIN_ALLOW_THREADS #ifdef HAVE_FSTATVFS if (path->fd != -1) { result = fstatvfs(path->fd, &st); } else #endif result = statvfs(path->narrow, &st); Py_END_ALLOW_THREADS if (result) { return path_error(path); } return _pystatvfs_fromstructstatvfs(module, st); } #endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */ #ifdef MS_WINDOWS /*[clinic input] os._getdiskusage path: path_t Return disk usage statistics about the given path as a (total, free) tuple. [clinic start generated code]*/ static PyObject * os__getdiskusage_impl(PyObject *module, path_t *path) /*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/ { BOOL retval; ULARGE_INTEGER _, total, free; DWORD err = 0; Py_BEGIN_ALLOW_THREADS retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free); Py_END_ALLOW_THREADS if (retval == 0) { if (GetLastError() == ERROR_DIRECTORY) { wchar_t *dir_path = NULL; dir_path = PyMem_New(wchar_t, path->length + 1); if (dir_path == NULL) { return PyErr_NoMemory(); } wcscpy_s(dir_path, path->length + 1, path->wide); if (_dirnameW(dir_path) != -1) { Py_BEGIN_ALLOW_THREADS retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free); Py_END_ALLOW_THREADS } /* Record the last error in case it's modified by PyMem_Free. */ err = GetLastError(); PyMem_Free(dir_path); if (retval) { goto success; } } return PyErr_SetFromWindowsErr(err); } success: return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart); } #endif /* MS_WINDOWS */ /* This is used for fpathconf(), pathconf(), confstr() and sysconf(). * It maps strings representing configuration variable names to * integer values, allowing those functions to be called with the * magic names instead of polluting the module's namespace with tons of * rarely-used constants. There are three separate tables that use * these definitions. * * This code is always included, even if none of the interfaces that * need it are included. The #if hackery needed to avoid it would be * sufficiently pervasive that it's not worth the loss of readability. */ struct constdef { const char *name; int value; }; static int conv_confname(PyObject *arg, int *valuep, struct constdef *table, size_t tablesize) { if (PyLong_Check(arg)) { int value = _PyLong_AsInt(arg); if (value == -1 && PyErr_Occurred()) return 0; *valuep = value; return 1; } else { /* look up the value in the table using a binary search */ size_t lo = 0; size_t mid; size_t hi = tablesize; int cmp; const char *confname; if (!PyUnicode_Check(arg)) { PyErr_SetString(PyExc_TypeError, "configuration names must be strings or integers"); return 0; } confname = PyUnicode_AsUTF8(arg); if (confname == NULL) return 0; while (lo < hi) { mid = (lo + hi) / 2; cmp = strcmp(confname, table[mid].name); if (cmp < 0) hi = mid; else if (cmp > 0) lo = mid + 1; else { *valuep = table[mid].value; return 1; } } PyErr_SetString(PyExc_ValueError, "unrecognized configuration name"); return 0; } } #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF) static struct constdef posix_constants_pathconf[] = { #ifdef _PC_ABI_AIO_XFER_MAX {"PC_ABI_AIO_XFER_MAX", _PC_ABI_AIO_XFER_MAX}, #endif #ifdef _PC_ABI_ASYNC_IO {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO}, #endif #ifdef _PC_ASYNC_IO {"PC_ASYNC_IO", _PC_ASYNC_IO}, #endif #ifdef _PC_CHOWN_RESTRICTED {"PC_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED}, #endif #ifdef _PC_FILESIZEBITS {"PC_FILESIZEBITS", _PC_FILESIZEBITS}, #endif #ifdef _PC_LAST {"PC_LAST", _PC_LAST}, #endif #ifdef _PC_LINK_MAX {"PC_LINK_MAX", _PC_LINK_MAX}, #endif #ifdef _PC_MAX_CANON {"PC_MAX_CANON", _PC_MAX_CANON}, #endif #ifdef _PC_MAX_INPUT {"PC_MAX_INPUT", _PC_MAX_INPUT}, #endif #ifdef _PC_NAME_MAX {"PC_NAME_MAX", _PC_NAME_MAX}, #endif #ifdef _PC_NO_TRUNC {"PC_NO_TRUNC", _PC_NO_TRUNC}, #endif #ifdef _PC_PATH_MAX {"PC_PATH_MAX", _PC_PATH_MAX}, #endif #ifdef _PC_PIPE_BUF {"PC_PIPE_BUF", _PC_PIPE_BUF}, #endif #ifdef _PC_PRIO_IO {"PC_PRIO_IO", _PC_PRIO_IO}, #endif #ifdef _PC_SOCK_MAXBUF {"PC_SOCK_MAXBUF", _PC_SOCK_MAXBUF}, #endif #ifdef _PC_SYNC_IO {"PC_SYNC_IO", _PC_SYNC_IO}, #endif #ifdef _PC_VDISABLE {"PC_VDISABLE", _PC_VDISABLE}, #endif #ifdef _PC_ACL_ENABLED {"PC_ACL_ENABLED", _PC_ACL_ENABLED}, #endif #ifdef _PC_MIN_HOLE_SIZE {"PC_MIN_HOLE_SIZE", _PC_MIN_HOLE_SIZE}, #endif #ifdef _PC_ALLOC_SIZE_MIN {"PC_ALLOC_SIZE_MIN", _PC_ALLOC_SIZE_MIN}, #endif #ifdef _PC_REC_INCR_XFER_SIZE {"PC_REC_INCR_XFER_SIZE", _PC_REC_INCR_XFER_SIZE}, #endif #ifdef _PC_REC_MAX_XFER_SIZE {"PC_REC_MAX_XFER_SIZE", _PC_REC_MAX_XFER_SIZE}, #endif #ifdef _PC_REC_MIN_XFER_SIZE {"PC_REC_MIN_XFER_SIZE", _PC_REC_MIN_XFER_SIZE}, #endif #ifdef _PC_REC_XFER_ALIGN {"PC_REC_XFER_ALIGN", _PC_REC_XFER_ALIGN}, #endif #ifdef _PC_SYMLINK_MAX {"PC_SYMLINK_MAX", _PC_SYMLINK_MAX}, #endif #ifdef _PC_XATTR_ENABLED {"PC_XATTR_ENABLED", _PC_XATTR_ENABLED}, #endif #ifdef _PC_XATTR_EXISTS {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS}, #endif #ifdef _PC_TIMESTAMP_RESOLUTION {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION}, #endif }; static int conv_path_confname(PyObject *arg, int *valuep) { return conv_confname(arg, valuep, posix_constants_pathconf, sizeof(posix_constants_pathconf) / sizeof(struct constdef)); } #endif #ifdef HAVE_FPATHCONF /*[clinic input] os.fpathconf -> long fd: fildes name: path_confname / Return the configuration limit name for the file descriptor fd. If there is no limit, return -1. [clinic start generated code]*/ static long os_fpathconf_impl(PyObject *module, int fd, int name) /*[clinic end generated code: output=d5b7042425fc3e21 input=5b8d2471cfaae186]*/ { long limit; errno = 0; limit = fpathconf(fd, name); if (limit == -1 && errno != 0) posix_error(); return limit; } #endif /* HAVE_FPATHCONF */ #ifdef HAVE_PATHCONF /*[clinic input] os.pathconf -> long path: path_t(allow_fd='PATH_HAVE_FPATHCONF') name: path_confname Return the configuration limit name for the file or directory path. If there is no limit, return -1. On some platforms, path may also be specified as an open file descriptor. If this functionality is unavailable, using it raises an exception. [clinic start generated code]*/ static long os_pathconf_impl(PyObject *module, path_t *path, int name) /*[clinic end generated code: output=5bedee35b293a089 input=bc3e2a985af27e5e]*/ { long limit; errno = 0; #ifdef HAVE_FPATHCONF if (path->fd != -1) limit = fpathconf(path->fd, name); else #endif limit = pathconf(path->narrow, name); if (limit == -1 && errno != 0) { if (errno == EINVAL) /* could be a path or name problem */ posix_error(); else path_error(path); } return limit; } #endif /* HAVE_PATHCONF */ #ifdef HAVE_CONFSTR static struct constdef posix_constants_confstr[] = { #ifdef _CS_ARCHITECTURE {"CS_ARCHITECTURE", _CS_ARCHITECTURE}, #endif #ifdef _CS_GNU_LIBC_VERSION {"CS_GNU_LIBC_VERSION", _CS_GNU_LIBC_VERSION}, #endif #ifdef _CS_GNU_LIBPTHREAD_VERSION {"CS_GNU_LIBPTHREAD_VERSION", _CS_GNU_LIBPTHREAD_VERSION}, #endif #ifdef _CS_HOSTNAME {"CS_HOSTNAME", _CS_HOSTNAME}, #endif #ifdef _CS_HW_PROVIDER {"CS_HW_PROVIDER", _CS_HW_PROVIDER}, #endif #ifdef _CS_HW_SERIAL {"CS_HW_SERIAL", _CS_HW_SERIAL}, #endif #ifdef _CS_INITTAB_NAME {"CS_INITTAB_NAME", _CS_INITTAB_NAME}, #endif #ifdef _CS_LFS64_CFLAGS {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS}, #endif #ifdef _CS_LFS64_LDFLAGS {"CS_LFS64_LDFLAGS", _CS_LFS64_LDFLAGS}, #endif #ifdef _CS_LFS64_LIBS {"CS_LFS64_LIBS", _CS_LFS64_LIBS}, #endif #ifdef _CS_LFS64_LINTFLAGS {"CS_LFS64_LINTFLAGS", _CS_LFS64_LINTFLAGS}, #endif #ifdef _CS_LFS_CFLAGS {"CS_LFS_CFLAGS", _CS_LFS_CFLAGS}, #endif #ifdef _CS_LFS_LDFLAGS {"CS_LFS_LDFLAGS", _CS_LFS_LDFLAGS}, #endif #ifdef _CS_LFS_LIBS {"CS_LFS_LIBS", _CS_LFS_LIBS}, #endif #ifdef _CS_LFS_LINTFLAGS {"CS_LFS_LINTFLAGS", _CS_LFS_LINTFLAGS}, #endif #ifdef _CS_MACHINE {"CS_MACHINE", _CS_MACHINE}, #endif #ifdef _CS_PATH {"CS_PATH", _CS_PATH}, #endif #ifdef _CS_RELEASE {"CS_RELEASE", _CS_RELEASE}, #endif #ifdef _CS_SRPC_DOMAIN {"CS_SRPC_DOMAIN", _CS_SRPC_DOMAIN}, #endif #ifdef _CS_SYSNAME {"CS_SYSNAME", _CS_SYSNAME}, #endif #ifdef _CS_VERSION {"CS_VERSION", _CS_VERSION}, #endif #ifdef _CS_XBS5_ILP32_OFF32_CFLAGS {"CS_XBS5_ILP32_OFF32_CFLAGS", _CS_XBS5_ILP32_OFF32_CFLAGS}, #endif #ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS {"CS_XBS5_ILP32_OFF32_LDFLAGS", _CS_XBS5_ILP32_OFF32_LDFLAGS}, #endif #ifdef _CS_XBS5_ILP32_OFF32_LIBS {"CS_XBS5_ILP32_OFF32_LIBS", _CS_XBS5_ILP32_OFF32_LIBS}, #endif #ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS {"CS_XBS5_ILP32_OFF32_LINTFLAGS", _CS_XBS5_ILP32_OFF32_LINTFLAGS}, #endif #ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS {"CS_XBS5_ILP32_OFFBIG_CFLAGS", _CS_XBS5_ILP32_OFFBIG_CFLAGS}, #endif #ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS {"CS_XBS5_ILP32_OFFBIG_LDFLAGS", _CS_XBS5_ILP32_OFFBIG_LDFLAGS}, #endif #ifdef _CS_XBS5_ILP32_OFFBIG_LIBS {"CS_XBS5_ILP32_OFFBIG_LIBS", _CS_XBS5_ILP32_OFFBIG_LIBS}, #endif #ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS", _CS_XBS5_ILP32_OFFBIG_LINTFLAGS}, #endif #ifdef _CS_XBS5_LP64_OFF64_CFLAGS {"CS_XBS5_LP64_OFF64_CFLAGS", _CS_XBS5_LP64_OFF64_CFLAGS}, #endif #ifdef _CS_XBS5_LP64_OFF64_LDFLAGS {"CS_XBS5_LP64_OFF64_LDFLAGS", _CS_XBS5_LP64_OFF64_LDFLAGS}, #endif #ifdef _CS_XBS5_LP64_OFF64_LIBS {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS}, #endif #ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS {"CS_XBS5_LP64_OFF64_LINTFLAGS", _CS_XBS5_LP64_OFF64_LINTFLAGS}, #endif #ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS {"CS_XBS5_LPBIG_OFFBIG_CFLAGS", _CS_XBS5_LPBIG_OFFBIG_CFLAGS}, #endif #ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS", _CS_XBS5_LPBIG_OFFBIG_LDFLAGS}, #endif #ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS {"CS_XBS5_LPBIG_OFFBIG_LIBS", _CS_XBS5_LPBIG_OFFBIG_LIBS}, #endif #ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS", _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS}, #endif #ifdef _MIPS_CS_AVAIL_PROCESSORS {"MIPS_CS_AVAIL_PROCESSORS", _MIPS_CS_AVAIL_PROCESSORS}, #endif #ifdef _MIPS_CS_BASE {"MIPS_CS_BASE", _MIPS_CS_BASE}, #endif #ifdef _MIPS_CS_HOSTID {"MIPS_CS_HOSTID", _MIPS_CS_HOSTID}, #endif #ifdef _MIPS_CS_HW_NAME {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME}, #endif #ifdef _MIPS_CS_NUM_PROCESSORS {"MIPS_CS_NUM_PROCESSORS", _MIPS_CS_NUM_PROCESSORS}, #endif #ifdef _MIPS_CS_OSREL_MAJ {"MIPS_CS_OSREL_MAJ", _MIPS_CS_OSREL_MAJ}, #endif #ifdef _MIPS_CS_OSREL_MIN {"MIPS_CS_OSREL_MIN", _MIPS_CS_OSREL_MIN}, #endif #ifdef _MIPS_CS_OSREL_PATCH {"MIPS_CS_OSREL_PATCH", _MIPS_CS_OSREL_PATCH}, #endif #ifdef _MIPS_CS_OS_NAME {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME}, #endif #ifdef _MIPS_CS_OS_PROVIDER {"MIPS_CS_OS_PROVIDER", _MIPS_CS_OS_PROVIDER}, #endif #ifdef _MIPS_CS_PROCESSORS {"MIPS_CS_PROCESSORS", _MIPS_CS_PROCESSORS}, #endif #ifdef _MIPS_CS_SERIAL {"MIPS_CS_SERIAL", _MIPS_CS_SERIAL}, #endif #ifdef _MIPS_CS_VENDOR {"MIPS_CS_VENDOR", _MIPS_CS_VENDOR}, #endif }; static int conv_confstr_confname(PyObject *arg, int *valuep) { return conv_confname(arg, valuep, posix_constants_confstr, sizeof(posix_constants_confstr) / sizeof(struct constdef)); } /*[clinic input] os.confstr name: confstr_confname / Return a string-valued system configuration variable. [clinic start generated code]*/ static PyObject * os_confstr_impl(PyObject *module, int name) /*[clinic end generated code: output=bfb0b1b1e49b9383 input=18fb4d0567242e65]*/ { PyObject *result = NULL; char buffer[255]; size_t len; errno = 0; len = confstr(name, buffer, sizeof(buffer)); if (len == 0) { if (errno) { posix_error(); return NULL; } else { Py_RETURN_NONE; } } if (len >= sizeof(buffer)) { size_t len2; char *buf = PyMem_Malloc(len); if (buf == NULL) return PyErr_NoMemory(); len2 = confstr(name, buf, len); assert(len == len2); result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1); PyMem_Free(buf); } else result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1); return result; } #endif /* HAVE_CONFSTR */ #ifdef HAVE_SYSCONF static struct constdef posix_constants_sysconf[] = { #ifdef _SC_2_CHAR_TERM {"SC_2_CHAR_TERM", _SC_2_CHAR_TERM}, #endif #ifdef _SC_2_C_BIND {"SC_2_C_BIND", _SC_2_C_BIND}, #endif #ifdef _SC_2_C_DEV {"SC_2_C_DEV", _SC_2_C_DEV}, #endif #ifdef _SC_2_C_VERSION {"SC_2_C_VERSION", _SC_2_C_VERSION}, #endif #ifdef _SC_2_FORT_DEV {"SC_2_FORT_DEV", _SC_2_FORT_DEV}, #endif #ifdef _SC_2_FORT_RUN {"SC_2_FORT_RUN", _SC_2_FORT_RUN}, #endif #ifdef _SC_2_LOCALEDEF {"SC_2_LOCALEDEF", _SC_2_LOCALEDEF}, #endif #ifdef _SC_2_SW_DEV {"SC_2_SW_DEV", _SC_2_SW_DEV}, #endif #ifdef _SC_2_UPE {"SC_2_UPE", _SC_2_UPE}, #endif #ifdef _SC_2_VERSION {"SC_2_VERSION", _SC_2_VERSION}, #endif #ifdef _SC_ABI_ASYNCHRONOUS_IO {"SC_ABI_ASYNCHRONOUS_IO", _SC_ABI_ASYNCHRONOUS_IO}, #endif #ifdef _SC_ACL {"SC_ACL", _SC_ACL}, #endif #ifdef _SC_AIO_LISTIO_MAX {"SC_AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX}, #endif #ifdef _SC_AIO_MAX {"SC_AIO_MAX", _SC_AIO_MAX}, #endif #ifdef _SC_AIO_PRIO_DELTA_MAX {"SC_AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX}, #endif #ifdef _SC_ARG_MAX {"SC_ARG_MAX", _SC_ARG_MAX}, #endif #ifdef _SC_ASYNCHRONOUS_IO {"SC_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO}, #endif #ifdef _SC_ATEXIT_MAX {"SC_ATEXIT_MAX", _SC_ATEXIT_MAX}, #endif #ifdef _SC_AUDIT {"SC_AUDIT", _SC_AUDIT}, #endif #ifdef _SC_AVPHYS_PAGES {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES}, #endif #ifdef _SC_BC_BASE_MAX {"SC_BC_BASE_MAX", _SC_BC_BASE_MAX}, #endif #ifdef _SC_BC_DIM_MAX {"SC_BC_DIM_MAX", _SC_BC_DIM_MAX}, #endif #ifdef _SC_BC_SCALE_MAX {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX}, #endif #ifdef _SC_BC_STRING_MAX {"SC_BC_STRING_MAX", _SC_BC_STRING_MAX}, #endif #ifdef _SC_CAP {"SC_CAP", _SC_CAP}, #endif #ifdef _SC_CHARCLASS_NAME_MAX {"SC_CHARCLASS_NAME_MAX", _SC_CHARCLASS_NAME_MAX}, #endif #ifdef _SC_CHAR_BIT {"SC_CHAR_BIT", _SC_CHAR_BIT}, #endif #ifdef _SC_CHAR_MAX {"SC_CHAR_MAX", _SC_CHAR_MAX}, #endif #ifdef _SC_CHAR_MIN {"SC_CHAR_MIN", _SC_CHAR_MIN}, #endif #ifdef _SC_CHILD_MAX {"SC_CHILD_MAX", _SC_CHILD_MAX}, #endif #ifdef _SC_CLK_TCK {"SC_CLK_TCK", _SC_CLK_TCK}, #endif #ifdef _SC_COHER_BLKSZ {"SC_COHER_BLKSZ", _SC_COHER_BLKSZ}, #endif #ifdef _SC_COLL_WEIGHTS_MAX {"SC_COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX}, #endif #ifdef _SC_DCACHE_ASSOC {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC}, #endif #ifdef _SC_DCACHE_BLKSZ {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ}, #endif #ifdef _SC_DCACHE_LINESZ {"SC_DCACHE_LINESZ", _SC_DCACHE_LINESZ}, #endif #ifdef _SC_DCACHE_SZ {"SC_DCACHE_SZ", _SC_DCACHE_SZ}, #endif #ifdef _SC_DCACHE_TBLKSZ {"SC_DCACHE_TBLKSZ", _SC_DCACHE_TBLKSZ}, #endif #ifdef _SC_DELAYTIMER_MAX {"SC_DELAYTIMER_MAX", _SC_DELAYTIMER_MAX}, #endif #ifdef _SC_EQUIV_CLASS_MAX {"SC_EQUIV_CLASS_MAX", _SC_EQUIV_CLASS_MAX}, #endif #ifdef _SC_EXPR_NEST_MAX {"SC_EXPR_NEST_MAX", _SC_EXPR_NEST_MAX}, #endif #ifdef _SC_FSYNC {"SC_FSYNC", _SC_FSYNC}, #endif #ifdef _SC_GETGR_R_SIZE_MAX {"SC_GETGR_R_SIZE_MAX", _SC_GETGR_R_SIZE_MAX}, #endif #ifdef _SC_GETPW_R_SIZE_MAX {"SC_GETPW_R_SIZE_MAX", _SC_GETPW_R_SIZE_MAX}, #endif #ifdef _SC_ICACHE_ASSOC {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC}, #endif #ifdef _SC_ICACHE_BLKSZ {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ}, #endif #ifdef _SC_ICACHE_LINESZ {"SC_ICACHE_LINESZ", _SC_ICACHE_LINESZ}, #endif #ifdef _SC_ICACHE_SZ {"SC_ICACHE_SZ", _SC_ICACHE_SZ}, #endif #ifdef _SC_INF {"SC_INF", _SC_INF}, #endif #ifdef _SC_INT_MAX {"SC_INT_MAX", _SC_INT_MAX}, #endif #ifdef _SC_INT_MIN {"SC_INT_MIN", _SC_INT_MIN}, #endif #ifdef _SC_IOV_MAX {"SC_IOV_MAX", _SC_IOV_MAX}, #endif #ifdef _SC_IP_SECOPTS {"SC_IP_SECOPTS", _SC_IP_SECOPTS}, #endif #ifdef _SC_JOB_CONTROL {"SC_JOB_CONTROL", _SC_JOB_CONTROL}, #endif #ifdef _SC_KERN_POINTERS {"SC_KERN_POINTERS", _SC_KERN_POINTERS}, #endif #ifdef _SC_KERN_SIM {"SC_KERN_SIM", _SC_KERN_SIM}, #endif #ifdef _SC_LINE_MAX {"SC_LINE_MAX", _SC_LINE_MAX}, #endif #ifdef _SC_LOGIN_NAME_MAX {"SC_LOGIN_NAME_MAX", _SC_LOGIN_NAME_MAX}, #endif #ifdef _SC_LOGNAME_MAX {"SC_LOGNAME_MAX", _SC_LOGNAME_MAX}, #endif #ifdef _SC_LONG_BIT {"SC_LONG_BIT", _SC_LONG_BIT}, #endif #ifdef _SC_MAC {"SC_MAC", _SC_MAC}, #endif #ifdef _SC_MAPPED_FILES {"SC_MAPPED_FILES", _SC_MAPPED_FILES}, #endif #ifdef _SC_MAXPID {"SC_MAXPID", _SC_MAXPID}, #endif #ifdef _SC_MB_LEN_MAX {"SC_MB_LEN_MAX", _SC_MB_LEN_MAX}, #endif #ifdef _SC_MEMLOCK {"SC_MEMLOCK", _SC_MEMLOCK}, #endif #ifdef _SC_MEMLOCK_RANGE {"SC_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE}, #endif #ifdef _SC_MEMORY_PROTECTION {"SC_MEMORY_PROTECTION", _SC_MEMORY_PROTECTION}, #endif #ifdef _SC_MESSAGE_PASSING {"SC_MESSAGE_PASSING", _SC_MESSAGE_PASSING}, #endif #ifdef _SC_MMAP_FIXED_ALIGNMENT {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT}, #endif #ifdef _SC_MQ_OPEN_MAX {"SC_MQ_OPEN_MAX", _SC_MQ_OPEN_MAX}, #endif #ifdef _SC_MQ_PRIO_MAX {"SC_MQ_PRIO_MAX", _SC_MQ_PRIO_MAX}, #endif #ifdef _SC_NACLS_MAX {"SC_NACLS_MAX", _SC_NACLS_MAX}, #endif #ifdef _SC_NGROUPS_MAX {"SC_NGROUPS_MAX", _SC_NGROUPS_MAX}, #endif #ifdef _SC_NL_ARGMAX {"SC_NL_ARGMAX", _SC_NL_ARGMAX}, #endif #ifdef _SC_NL_LANGMAX {"SC_NL_LANGMAX", _SC_NL_LANGMAX}, #endif #ifdef _SC_NL_MSGMAX {"SC_NL_MSGMAX", _SC_NL_MSGMAX}, #endif #ifdef _SC_NL_NMAX {"SC_NL_NMAX", _SC_NL_NMAX}, #endif #ifdef _SC_NL_SETMAX {"SC_NL_SETMAX", _SC_NL_SETMAX}, #endif #ifdef _SC_NL_TEXTMAX {"SC_NL_TEXTMAX", _SC_NL_TEXTMAX}, #endif #ifdef _SC_NPROCESSORS_CONF {"SC_NPROCESSORS_CONF", _SC_NPROCESSORS_CONF}, #endif #ifdef _SC_NPROCESSORS_ONLN {"SC_NPROCESSORS_ONLN", _SC_NPROCESSORS_ONLN}, #endif #ifdef _SC_NPROC_CONF {"SC_NPROC_CONF", _SC_NPROC_CONF}, #endif #ifdef _SC_NPROC_ONLN {"SC_NPROC_ONLN", _SC_NPROC_ONLN}, #endif #ifdef _SC_NZERO {"SC_NZERO", _SC_NZERO}, #endif #ifdef _SC_OPEN_MAX {"SC_OPEN_MAX", _SC_OPEN_MAX}, #endif #ifdef _SC_PAGESIZE {"SC_PAGESIZE", _SC_PAGESIZE}, #endif #ifdef _SC_PAGE_SIZE {"SC_PAGE_SIZE", _SC_PAGE_SIZE}, #endif #ifdef _SC_AIX_REALMEM {"SC_AIX_REALMEM", _SC_AIX_REALMEM}, #endif #ifdef _SC_PASS_MAX {"SC_PASS_MAX", _SC_PASS_MAX}, #endif #ifdef _SC_PHYS_PAGES {"SC_PHYS_PAGES", _SC_PHYS_PAGES}, #endif #ifdef _SC_PII {"SC_PII", _SC_PII}, #endif #ifdef _SC_PII_INTERNET {"SC_PII_INTERNET", _SC_PII_INTERNET}, #endif #ifdef _SC_PII_INTERNET_DGRAM {"SC_PII_INTERNET_DGRAM", _SC_PII_INTERNET_DGRAM}, #endif #ifdef _SC_PII_INTERNET_STREAM {"SC_PII_INTERNET_STREAM", _SC_PII_INTERNET_STREAM}, #endif #ifdef _SC_PII_OSI {"SC_PII_OSI", _SC_PII_OSI}, #endif #ifdef _SC_PII_OSI_CLTS {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS}, #endif #ifdef _SC_PII_OSI_COTS {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS}, #endif #ifdef _SC_PII_OSI_M {"SC_PII_OSI_M", _SC_PII_OSI_M}, #endif #ifdef _SC_PII_SOCKET {"SC_PII_SOCKET", _SC_PII_SOCKET}, #endif #ifdef _SC_PII_XTI {"SC_PII_XTI", _SC_PII_XTI}, #endif #ifdef _SC_POLL {"SC_POLL", _SC_POLL}, #endif #ifdef _SC_PRIORITIZED_IO {"SC_PRIORITIZED_IO", _SC_PRIORITIZED_IO}, #endif #ifdef _SC_PRIORITY_SCHEDULING {"SC_PRIORITY_SCHEDULING", _SC_PRIORITY_SCHEDULING}, #endif #ifdef _SC_REALTIME_SIGNALS {"SC_REALTIME_SIGNALS", _SC_REALTIME_SIGNALS}, #endif #ifdef _SC_RE_DUP_MAX {"SC_RE_DUP_MAX", _SC_RE_DUP_MAX}, #endif #ifdef _SC_RTSIG_MAX {"SC_RTSIG_MAX", _SC_RTSIG_MAX}, #endif #ifdef _SC_SAVED_IDS {"SC_SAVED_IDS", _SC_SAVED_IDS}, #endif #ifdef _SC_SCHAR_MAX {"SC_SCHAR_MAX", _SC_SCHAR_MAX}, #endif #ifdef _SC_SCHAR_MIN {"SC_SCHAR_MIN", _SC_SCHAR_MIN}, #endif #ifdef _SC_SELECT {"SC_SELECT", _SC_SELECT}, #endif #ifdef _SC_SEMAPHORES {"SC_SEMAPHORES", _SC_SEMAPHORES}, #endif #ifdef _SC_SEM_NSEMS_MAX {"SC_SEM_NSEMS_MAX", _SC_SEM_NSEMS_MAX}, #endif #ifdef _SC_SEM_VALUE_MAX {"SC_SEM_VALUE_MAX", _SC_SEM_VALUE_MAX}, #endif #ifdef _SC_SHARED_MEMORY_OBJECTS {"SC_SHARED_MEMORY_OBJECTS", _SC_SHARED_MEMORY_OBJECTS}, #endif #ifdef _SC_SHRT_MAX {"SC_SHRT_MAX", _SC_SHRT_MAX}, #endif #ifdef _SC_SHRT_MIN {"SC_SHRT_MIN", _SC_SHRT_MIN}, #endif #ifdef _SC_SIGQUEUE_MAX {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX}, #endif #ifdef _SC_SIGRT_MAX {"SC_SIGRT_MAX", _SC_SIGRT_MAX}, #endif #ifdef _SC_SIGRT_MIN {"SC_SIGRT_MIN", _SC_SIGRT_MIN}, #endif #ifdef _SC_SOFTPOWER {"SC_SOFTPOWER", _SC_SOFTPOWER}, #endif #ifdef _SC_SPLIT_CACHE {"SC_SPLIT_CACHE", _SC_SPLIT_CACHE}, #endif #ifdef _SC_SSIZE_MAX {"SC_SSIZE_MAX", _SC_SSIZE_MAX}, #endif #ifdef _SC_STACK_PROT {"SC_STACK_PROT", _SC_STACK_PROT}, #endif #ifdef _SC_STREAM_MAX {"SC_STREAM_MAX", _SC_STREAM_MAX}, #endif #ifdef _SC_SYNCHRONIZED_IO {"SC_SYNCHRONIZED_IO", _SC_SYNCHRONIZED_IO}, #endif #ifdef _SC_THREADS {"SC_THREADS", _SC_THREADS}, #endif #ifdef _SC_THREAD_ATTR_STACKADDR {"SC_THREAD_ATTR_STACKADDR", _SC_THREAD_ATTR_STACKADDR}, #endif #ifdef _SC_THREAD_ATTR_STACKSIZE {"SC_THREAD_ATTR_STACKSIZE", _SC_THREAD_ATTR_STACKSIZE}, #endif #ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS}, #endif #ifdef _SC_THREAD_KEYS_MAX {"SC_THREAD_KEYS_MAX", _SC_THREAD_KEYS_MAX}, #endif #ifdef _SC_THREAD_PRIORITY_SCHEDULING {"SC_THREAD_PRIORITY_SCHEDULING", _SC_THREAD_PRIORITY_SCHEDULING}, #endif #ifdef _SC_THREAD_PRIO_INHERIT {"SC_THREAD_PRIO_INHERIT", _SC_THREAD_PRIO_INHERIT}, #endif #ifdef _SC_THREAD_PRIO_PROTECT {"SC_THREAD_PRIO_PROTECT", _SC_THREAD_PRIO_PROTECT}, #endif #ifdef _SC_THREAD_PROCESS_SHARED {"SC_THREAD_PROCESS_SHARED", _SC_THREAD_PROCESS_SHARED}, #endif #ifdef _SC_THREAD_SAFE_FUNCTIONS {"SC_THREAD_SAFE_FUNCTIONS", _SC_THREAD_SAFE_FUNCTIONS}, #endif #ifdef _SC_THREAD_STACK_MIN {"SC_THREAD_STACK_MIN", _SC_THREAD_STACK_MIN}, #endif #ifdef _SC_THREAD_THREADS_MAX {"SC_THREAD_THREADS_MAX", _SC_THREAD_THREADS_MAX}, #endif #ifdef _SC_TIMERS {"SC_TIMERS", _SC_TIMERS}, #endif #ifdef _SC_TIMER_MAX {"SC_TIMER_MAX", _SC_TIMER_MAX}, #endif #ifdef _SC_TTY_NAME_MAX {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX}, #endif #ifdef _SC_TZNAME_MAX {"SC_TZNAME_MAX", _SC_TZNAME_MAX}, #endif #ifdef _SC_T_IOV_MAX {"SC_T_IOV_MAX", _SC_T_IOV_MAX}, #endif #ifdef _SC_UCHAR_MAX {"SC_UCHAR_MAX", _SC_UCHAR_MAX}, #endif #ifdef _SC_UINT_MAX {"SC_UINT_MAX", _SC_UINT_MAX}, #endif #ifdef _SC_UIO_MAXIOV {"SC_UIO_MAXIOV", _SC_UIO_MAXIOV}, #endif #ifdef _SC_ULONG_MAX {"SC_ULONG_MAX", _SC_ULONG_MAX}, #endif #ifdef _SC_USHRT_MAX {"SC_USHRT_MAX", _SC_USHRT_MAX}, #endif #ifdef _SC_VERSION {"SC_VERSION", _SC_VERSION}, #endif #ifdef _SC_WORD_BIT {"SC_WORD_BIT", _SC_WORD_BIT}, #endif #ifdef _SC_XBS5_ILP32_OFF32 {"SC_XBS5_ILP32_OFF32", _SC_XBS5_ILP32_OFF32}, #endif #ifdef _SC_XBS5_ILP32_OFFBIG {"SC_XBS5_ILP32_OFFBIG", _SC_XBS5_ILP32_OFFBIG}, #endif #ifdef _SC_XBS5_LP64_OFF64 {"SC_XBS5_LP64_OFF64", _SC_XBS5_LP64_OFF64}, #endif #ifdef _SC_XBS5_LPBIG_OFFBIG {"SC_XBS5_LPBIG_OFFBIG", _SC_XBS5_LPBIG_OFFBIG}, #endif #ifdef _SC_XOPEN_CRYPT {"SC_XOPEN_CRYPT", _SC_XOPEN_CRYPT}, #endif #ifdef _SC_XOPEN_ENH_I18N {"SC_XOPEN_ENH_I18N", _SC_XOPEN_ENH_I18N}, #endif #ifdef _SC_XOPEN_LEGACY {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY}, #endif #ifdef _SC_XOPEN_REALTIME {"SC_XOPEN_REALTIME", _SC_XOPEN_REALTIME}, #endif #ifdef _SC_XOPEN_REALTIME_THREADS {"SC_XOPEN_REALTIME_THREADS", _SC_XOPEN_REALTIME_THREADS}, #endif #ifdef _SC_XOPEN_SHM {"SC_XOPEN_SHM", _SC_XOPEN_SHM}, #endif #ifdef _SC_XOPEN_UNIX {"SC_XOPEN_UNIX", _SC_XOPEN_UNIX}, #endif #ifdef _SC_XOPEN_VERSION {"SC_XOPEN_VERSION", _SC_XOPEN_VERSION}, #endif #ifdef _SC_XOPEN_XCU_VERSION {"SC_XOPEN_XCU_VERSION", _SC_XOPEN_XCU_VERSION}, #endif #ifdef _SC_XOPEN_XPG2 {"SC_XOPEN_XPG2", _SC_XOPEN_XPG2}, #endif #ifdef _SC_XOPEN_XPG3 {"SC_XOPEN_XPG3", _SC_XOPEN_XPG3}, #endif #ifdef _SC_XOPEN_XPG4 {"SC_XOPEN_XPG4", _SC_XOPEN_XPG4}, #endif #ifdef _SC_MINSIGSTKSZ {"SC_MINSIGSTKSZ", _SC_MINSIGSTKSZ}, #endif }; static int conv_sysconf_confname(PyObject *arg, int *valuep) { return conv_confname(arg, valuep, posix_constants_sysconf, sizeof(posix_constants_sysconf) / sizeof(struct constdef)); } /*[clinic input] os.sysconf -> long name: sysconf_confname / Return an integer-valued system configuration variable. [clinic start generated code]*/ static long os_sysconf_impl(PyObject *module, int name) /*[clinic end generated code: output=3662f945fc0cc756 input=279e3430a33f29e4]*/ { long value; errno = 0; value = sysconf(name); if (value == -1 && errno != 0) posix_error(); return value; } #endif /* HAVE_SYSCONF */ /* This code is used to ensure that the tables of configuration value names * are in sorted order as required by conv_confname(), and also to build * the exported dictionaries that are used to publish information about the * names available on the host platform. * * Sorting the table at runtime ensures that the table is properly ordered * when used, even for platforms we're not able to test on. It also makes * it easier to add additional entries to the tables. */ static int cmp_constdefs(const void *v1, const void *v2) { const struct constdef *c1 = (const struct constdef *) v1; const struct constdef *c2 = (const struct constdef *) v2; return strcmp(c1->name, c2->name); } static int setup_confname_table(struct constdef *table, size_t tablesize, const char *tablename, PyObject *module) { PyObject *d = NULL; size_t i; qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs); d = PyDict_New(); if (d == NULL) return -1; for (i=0; i < tablesize; ++i) { PyObject *o = PyLong_FromLong(table[i].value); if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) { Py_XDECREF(o); Py_DECREF(d); return -1; } Py_DECREF(o); } return PyModule_AddObject(module, tablename, d); } /* Return -1 on failure, 0 on success. */ static int setup_confname_tables(PyObject *module) { #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF) if (setup_confname_table(posix_constants_pathconf, sizeof(posix_constants_pathconf) / sizeof(struct constdef), "pathconf_names", module)) return -1; #endif #ifdef HAVE_CONFSTR if (setup_confname_table(posix_constants_confstr, sizeof(posix_constants_confstr) / sizeof(struct constdef), "confstr_names", module)) return -1; #endif #ifdef HAVE_SYSCONF if (setup_confname_table(posix_constants_sysconf, sizeof(posix_constants_sysconf) / sizeof(struct constdef), "sysconf_names", module)) return -1; #endif return 0; } /*[clinic input] os.abort Abort the interpreter immediately. This function 'dumps core' or otherwise fails in the hardest way possible on the hosting operating system. This function never returns. [clinic start generated code]*/ static PyObject * os_abort_impl(PyObject *module) /*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/ { abort(); /*NOTREACHED*/ #ifndef __clang__ /* Issue #28152: abort() is declared with __attribute__((__noreturn__)). GCC emits a warning without "return NULL;" (compiler bug?), but Clang is smarter and emits a warning on the return. */ Py_FatalError("abort() called from Python code didn't abort!"); return NULL; #endif } #ifdef MS_WINDOWS /* Grab ShellExecute dynamically from shell32 */ static int has_ShellExecute = -1; static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR, INT); static int check_ShellExecute() { HINSTANCE hShell32; /* only recheck */ if (-1 == has_ShellExecute) { Py_BEGIN_ALLOW_THREADS /* Security note: this call is not vulnerable to "DLL hijacking". SHELL32 is part of "KnownDLLs" and so Windows always load the system SHELL32.DLL, even if there is another SHELL32.DLL in the DLL search path. */ hShell32 = LoadLibraryW(L"SHELL32"); if (hShell32) { *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32, "ShellExecuteW"); has_ShellExecute = Py_ShellExecuteW != NULL; } else { has_ShellExecute = 0; } Py_END_ALLOW_THREADS } return has_ShellExecute; } /*[clinic input] os.startfile filepath: path_t operation: Py_UNICODE = NULL arguments: Py_UNICODE = NULL cwd: path_t(nullable=True) = None show_cmd: int = 1 Start a file with its associated application. When "operation" is not specified or "open", this acts like double-clicking the file in Explorer, or giving the file name as an argument to the DOS "start" command: the file is opened with whatever application (if any) its extension is associated. When another "operation" is given, it specifies what should be done with the file. A typical operation is "print". "arguments" is passed to the application, but should be omitted if the file is a document. "cwd" is the working directory for the operation. If "filepath" is relative, it will be resolved against this directory. This argument should usually be an absolute path. "show_cmd" can be used to override the recommended visibility option. See the Windows ShellExecute documentation for values. startfile returns as soon as the associated application is launched. There is no option to wait for the application to close, and no way to retrieve the application's exit status. The filepath is relative to the current directory. If you want to use an absolute path, make sure the first character is not a slash ("/"); the underlying Win32 ShellExecute function doesn't work if it is. [clinic start generated code]*/ static PyObject * os_startfile_impl(PyObject *module, path_t *filepath, const Py_UNICODE *operation, const Py_UNICODE *arguments, path_t *cwd, int show_cmd) /*[clinic end generated code: output=3baa4f9795841880 input=8248997b80669622]*/ { HINSTANCE rc; if(!check_ShellExecute()) { /* If the OS doesn't have ShellExecute, return a NotImplementedError. */ return PyErr_Format(PyExc_NotImplementedError, "startfile not available on this platform"); } if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) { return NULL; } if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation, arguments, cwd->object ? cwd->object : Py_None, show_cmd) < 0) { return NULL; } Py_BEGIN_ALLOW_THREADS rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide, arguments, cwd->wide, show_cmd); Py_END_ALLOW_THREADS if (rc <= (HINSTANCE)32) { win32_error_object("startfile", filepath->object); return NULL; } Py_RETURN_NONE; } #endif /* MS_WINDOWS */ #ifdef HAVE_GETLOADAVG /*[clinic input] os.getloadavg Return average recent system load information. Return the number of processes in the system run queue averaged over the last 1, 5, and 15 minutes as a tuple of three floats. Raises OSError if the load average was unobtainable. [clinic start generated code]*/ static PyObject * os_getloadavg_impl(PyObject *module) /*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/ { double loadavg[3]; if (getloadavg(loadavg, 3)!=3) { PyErr_SetString(PyExc_OSError, "Load averages are unobtainable"); return NULL; } else return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]); } #endif /* HAVE_GETLOADAVG */ /*[clinic input] os.device_encoding fd: int Return a string describing the encoding of a terminal's file descriptor. The file descriptor must be attached to a terminal. If the device is not a terminal, return None. [clinic start generated code]*/ static PyObject * os_device_encoding_impl(PyObject *module, int fd) /*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/ { return _Py_device_encoding(fd); } #ifdef HAVE_SETRESUID /*[clinic input] os.setresuid ruid: uid_t euid: uid_t suid: uid_t / Set the current process's real, effective, and saved user ids. [clinic start generated code]*/ static PyObject * os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid) /*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/ { if (setresuid(ruid, euid, suid) < 0) return posix_error(); Py_RETURN_NONE; } #endif /* HAVE_SETRESUID */ #ifdef HAVE_SETRESGID /*[clinic input] os.setresgid rgid: gid_t egid: gid_t sgid: gid_t / Set the current process's real, effective, and saved group ids. [clinic start generated code]*/ static PyObject * os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid) /*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/ { if (setresgid(rgid, egid, sgid) < 0) return posix_error(); Py_RETURN_NONE; } #endif /* HAVE_SETRESGID */ #ifdef HAVE_GETRESUID /*[clinic input] os.getresuid Return a tuple of the current process's real, effective, and saved user ids. [clinic start generated code]*/ static PyObject * os_getresuid_impl(PyObject *module) /*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/ { uid_t ruid, euid, suid; if (getresuid(&ruid, &euid, &suid) < 0) return posix_error(); return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid), _PyLong_FromUid(euid), _PyLong_FromUid(suid)); } #endif /* HAVE_GETRESUID */ #ifdef HAVE_GETRESGID /*[clinic input] os.getresgid Return a tuple of the current process's real, effective, and saved group ids. [clinic start generated code]*/ static PyObject * os_getresgid_impl(PyObject *module) /*[clinic end generated code: output=2719c4bfcf27fb9f input=517e68db9ca32df6]*/ { gid_t rgid, egid, sgid; if (getresgid(&rgid, &egid, &sgid) < 0) return posix_error(); return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid), _PyLong_FromGid(egid), _PyLong_FromGid(sgid)); } #endif /* HAVE_GETRESGID */ #ifdef USE_XATTRS /*[clinic input] os.getxattr path: path_t(allow_fd=True) attribute: path_t * follow_symlinks: bool = True Return the value of extended attribute attribute on path. path may be either a string, a path-like object, or an open file descriptor. If follow_symlinks is False, and the last element of the path is a symbolic link, getxattr will examine the symbolic link itself instead of the file the link points to. [clinic start generated code]*/ static PyObject * os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute, int follow_symlinks) /*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/ { Py_ssize_t i; PyObject *buffer = NULL; if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks)) return NULL; if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) { return NULL; } for (i = 0; ; i++) { void *ptr; ssize_t result; static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0}; Py_ssize_t buffer_size = buffer_sizes[i]; if (!buffer_size) { path_error(path); return NULL; } buffer = PyBytes_FromStringAndSize(NULL, buffer_size); if (!buffer) return NULL; ptr = PyBytes_AS_STRING(buffer); Py_BEGIN_ALLOW_THREADS; if (path->fd >= 0) result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size); else if (follow_symlinks) result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size); else result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size); Py_END_ALLOW_THREADS; if (result < 0) { Py_DECREF(buffer); if (errno == ERANGE) continue; path_error(path); return NULL; } if (result != buffer_size) { /* Can only shrink. */ _PyBytes_Resize(&buffer, result); } break; } return buffer; } /*[clinic input] os.setxattr path: path_t(allow_fd=True) attribute: path_t value: Py_buffer flags: int = 0 * follow_symlinks: bool = True Set extended attribute attribute on path to value. path may be either a string, a path-like object, or an open file descriptor. If follow_symlinks is False, and the last element of the path is a symbolic link, setxattr will modify the symbolic link itself instead of the file the link points to. [clinic start generated code]*/ static PyObject * os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute, Py_buffer *value, int flags, int follow_symlinks) /*[clinic end generated code: output=98b83f63fdde26bb input=c17c0103009042f0]*/ { ssize_t result; if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks)) return NULL; if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object, value->buf, value->len, flags) < 0) { return NULL; } Py_BEGIN_ALLOW_THREADS; if (path->fd > -1) result = fsetxattr(path->fd, attribute->narrow, value->buf, value->len, flags); else if (follow_symlinks) result = setxattr(path->narrow, attribute->narrow, value->buf, value->len, flags); else result = lsetxattr(path->narrow, attribute->narrow, value->buf, value->len, flags); Py_END_ALLOW_THREADS; if (result) { path_error(path); return NULL; } Py_RETURN_NONE; } /*[clinic input] os.removexattr path: path_t(allow_fd=True) attribute: path_t * follow_symlinks: bool = True Remove extended attribute attribute on path. path may be either a string, a path-like object, or an open file descriptor. If follow_symlinks is False, and the last element of the path is a symbolic link, removexattr will modify the symbolic link itself instead of the file the link points to. [clinic start generated code]*/ static PyObject * os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute, int follow_symlinks) /*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/ { ssize_t result; if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks)) return NULL; if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) { return NULL; } Py_BEGIN_ALLOW_THREADS; if (path->fd > -1) result = fremovexattr(path->fd, attribute->narrow); else if (follow_symlinks) result = removexattr(path->narrow, attribute->narrow); else result = lremovexattr(path->narrow, attribute->narrow); Py_END_ALLOW_THREADS; if (result) { return path_error(path); } Py_RETURN_NONE; } /*[clinic input] os.listxattr path: path_t(allow_fd=True, nullable=True) = None * follow_symlinks: bool = True Return a list of extended attributes on path. path may be either None, a string, a path-like object, or an open file descriptor. if path is None, listxattr will examine the current directory. If follow_symlinks is False, and the last element of the path is a symbolic link, listxattr will examine the symbolic link itself instead of the file the link points to. [clinic start generated code]*/ static PyObject * os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks) /*[clinic end generated code: output=bebdb4e2ad0ce435 input=9826edf9fdb90869]*/ { Py_ssize_t i; PyObject *result = NULL; const char *name; char *buffer = NULL; if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks)) goto exit; if (PySys_Audit("os.listxattr", "(O)", path->object ? path->object : Py_None) < 0) { return NULL; } name = path->narrow ? path->narrow : "."; for (i = 0; ; i++) { const char *start, *trace, *end; ssize_t length; static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 }; Py_ssize_t buffer_size = buffer_sizes[i]; if (!buffer_size) { /* ERANGE */ path_error(path); break; } buffer = PyMem_Malloc(buffer_size); if (!buffer) { PyErr_NoMemory(); break; } Py_BEGIN_ALLOW_THREADS; if (path->fd > -1) length = flistxattr(path->fd, buffer, buffer_size); else if (follow_symlinks) length = listxattr(name, buffer, buffer_size); else length = llistxattr(name, buffer, buffer_size); Py_END_ALLOW_THREADS; if (length < 0) { if (errno == ERANGE) { PyMem_Free(buffer); buffer = NULL; continue; } path_error(path); break; } result = PyList_New(0); if (!result) { goto exit; } end = buffer + length; for (trace = start = buffer; trace != end; trace++) { if (!*trace) { int error; PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start, trace - start); if (!attribute) { Py_SETREF(result, NULL); goto exit; } error = PyList_Append(result, attribute); Py_DECREF(attribute); if (error) { Py_SETREF(result, NULL); goto exit; } start = trace + 1; } } break; } exit: if (buffer) PyMem_Free(buffer); return result; } #endif /* USE_XATTRS */ /*[clinic input] os.urandom size: Py_ssize_t / Return a bytes object containing random bytes suitable for cryptographic use. [clinic start generated code]*/ static PyObject * os_urandom_impl(PyObject *module, Py_ssize_t size) /*[clinic end generated code: output=42c5cca9d18068e9 input=4067cdb1b6776c29]*/ { PyObject *bytes; int result; if (size < 0) return PyErr_Format(PyExc_ValueError, "negative argument not allowed"); bytes = PyBytes_FromStringAndSize(NULL, size); if (bytes == NULL) return NULL; result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes)); if (result == -1) { Py_DECREF(bytes); return NULL; } return bytes; } #ifdef HAVE_MEMFD_CREATE /*[clinic input] os.memfd_create name: FSConverter flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC [clinic start generated code]*/ static PyObject * os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags) /*[clinic end generated code: output=6681ede983bdb9a6 input=a42cfc199bcd56e9]*/ { int fd; const char *bytes = PyBytes_AS_STRING(name); Py_BEGIN_ALLOW_THREADS fd = memfd_create(bytes, flags); Py_END_ALLOW_THREADS if (fd == -1) { return PyErr_SetFromErrno(PyExc_OSError); } return PyLong_FromLong(fd); } #endif #if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC) /*[clinic input] os.eventfd initval: unsigned_int flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC Creates and returns an event notification file descriptor. [clinic start generated code]*/ static PyObject * os_eventfd_impl(PyObject *module, unsigned int initval, int flags) /*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/ { /* initval is limited to uint32_t, internal counter is uint64_t */ int fd; Py_BEGIN_ALLOW_THREADS fd = eventfd(initval, flags); Py_END_ALLOW_THREADS if (fd == -1) { return PyErr_SetFromErrno(PyExc_OSError); } return PyLong_FromLong(fd); } /*[clinic input] os.eventfd_read fd: fildes Read eventfd value [clinic start generated code]*/ static PyObject * os_eventfd_read_impl(PyObject *module, int fd) /*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/ { eventfd_t value; int result; Py_BEGIN_ALLOW_THREADS result = eventfd_read(fd, &value); Py_END_ALLOW_THREADS if (result == -1) { return PyErr_SetFromErrno(PyExc_OSError); } return PyLong_FromUnsignedLongLong(value); } /*[clinic input] os.eventfd_write fd: fildes value: unsigned_long_long Write eventfd value. [clinic start generated code]*/ static PyObject * os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value) /*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/ { int result; Py_BEGIN_ALLOW_THREADS result = eventfd_write(fd, value); Py_END_ALLOW_THREADS if (result == -1) { return PyErr_SetFromErrno(PyExc_OSError); } Py_RETURN_NONE; } #endif /* HAVE_EVENTFD && EFD_CLOEXEC */ /* Terminal size querying */ PyDoc_STRVAR(TerminalSize_docstring, "A tuple of (columns, lines) for holding terminal window size"); static PyStructSequence_Field TerminalSize_fields[] = { {"columns", "width of the terminal window in characters"}, {"lines", "height of the terminal window in characters"}, {NULL, NULL} }; static PyStructSequence_Desc TerminalSize_desc = { "os.terminal_size", TerminalSize_docstring, TerminalSize_fields, 2, }; #if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) /*[clinic input] os.get_terminal_size fd: int(c_default="fileno(stdout)", py_default="") = -1 / Return the size of the terminal window as (columns, lines). The optional argument fd (default standard output) specifies which file descriptor should be queried. If the file descriptor is not connected to a terminal, an OSError is thrown. This function will only be defined if an implementation is available for this system. shutil.get_terminal_size is the high-level function which should normally be used, os.get_terminal_size is the low-level implementation. [clinic start generated code]*/ static PyObject * os_get_terminal_size_impl(PyObject *module, int fd) /*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/ { int columns, lines; PyObject *termsize; /* Under some conditions stdout may not be connected and * fileno(stdout) may point to an invalid file descriptor. For example * GUI apps don't have valid standard streams by default. * * If this happens, and the optional fd argument is not present, * the ioctl below will fail returning EBADF. This is what we want. */ #ifdef TERMSIZE_USE_IOCTL { struct winsize w; if (ioctl(fd, TIOCGWINSZ, &w)) return PyErr_SetFromErrno(PyExc_OSError); columns = w.ws_col; lines = w.ws_row; } #endif /* TERMSIZE_USE_IOCTL */ #ifdef TERMSIZE_USE_CONIO { HANDLE handle; CONSOLE_SCREEN_BUFFER_INFO csbi; handle = _Py_get_osfhandle(fd); if (handle == INVALID_HANDLE_VALUE) return NULL; if (!GetConsoleScreenBufferInfo(handle, &csbi)) return PyErr_SetFromWindowsErr(0); columns = csbi.srWindow.Right - csbi.srWindow.Left + 1; lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; } #endif /* TERMSIZE_USE_CONIO */ PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType; termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType); if (termsize == NULL) return NULL; PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns)); PyStructSequence_SET_ITEM(termsize, 1, PyLong_FromLong(lines)); if (PyErr_Occurred()) { Py_DECREF(termsize); return NULL; } return termsize; } #endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */ /*[clinic input] os.cpu_count Return the number of CPUs in the system; return None if indeterminable. This number is not equivalent to the number of CPUs the current process can use. The number of usable CPUs can be obtained with ``len(os.sched_getaffinity(0))`` [clinic start generated code]*/ static PyObject * os_cpu_count_impl(PyObject *module) /*[clinic end generated code: output=5fc29463c3936a9c input=e7c8f4ba6dbbadd3]*/ { int ncpu = 0; #ifdef MS_WINDOWS ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS); #elif defined(__hpux) ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL); #elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN) ncpu = sysconf(_SC_NPROCESSORS_ONLN); #elif defined(__VXWORKS__) ncpu = _Py_popcount32(vxCpuEnabledGet()); #elif defined(__DragonFly__) || \ defined(__OpenBSD__) || \ defined(__FreeBSD__) || \ defined(__NetBSD__) || \ defined(__APPLE__) int mib[2]; size_t len = sizeof(ncpu); mib[0] = CTL_HW; mib[1] = HW_NCPU; if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0) ncpu = 0; #endif if (ncpu >= 1) return PyLong_FromLong(ncpu); else Py_RETURN_NONE; } /*[clinic input] os.get_inheritable -> bool fd: int / Get the close-on-exe flag of the specified file descriptor. [clinic start generated code]*/ static int os_get_inheritable_impl(PyObject *module, int fd) /*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/ { int return_value; _Py_BEGIN_SUPPRESS_IPH return_value = _Py_get_inheritable(fd); _Py_END_SUPPRESS_IPH return return_value; } /*[clinic input] os.set_inheritable fd: int inheritable: int / Set the inheritable flag of the specified file descriptor. [clinic start generated code]*/ static PyObject * os_set_inheritable_impl(PyObject *module, int fd, int inheritable) /*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/ { int result; _Py_BEGIN_SUPPRESS_IPH result = _Py_set_inheritable(fd, inheritable, NULL); _Py_END_SUPPRESS_IPH if (result < 0) return NULL; Py_RETURN_NONE; } #ifdef MS_WINDOWS /*[clinic input] os.get_handle_inheritable -> bool handle: intptr_t / Get the close-on-exe flag of the specified file descriptor. [clinic start generated code]*/ static int os_get_handle_inheritable_impl(PyObject *module, intptr_t handle) /*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/ { DWORD flags; if (!GetHandleInformation((HANDLE)handle, &flags)) { PyErr_SetFromWindowsErr(0); return -1; } return flags & HANDLE_FLAG_INHERIT; } /*[clinic input] os.set_handle_inheritable handle: intptr_t inheritable: bool / Set the inheritable flag of the specified handle. [clinic start generated code]*/ static PyObject * os_set_handle_inheritable_impl(PyObject *module, intptr_t handle, int inheritable) /*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/ { DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0; if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) { PyErr_SetFromWindowsErr(0); return NULL; } Py_RETURN_NONE; } #endif /* MS_WINDOWS */ #ifndef MS_WINDOWS /*[clinic input] os.get_blocking -> bool fd: int / Get the blocking mode of the file descriptor. Return False if the O_NONBLOCK flag is set, True if the flag is cleared. [clinic start generated code]*/ static int os_get_blocking_impl(PyObject *module, int fd) /*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/ { int blocking; _ from the command line via the ProjectBuilder tool 'pbxbuild'. * macosx/tkMacOSXAppInit.c (new): macosx specific AppInit looking for a AppMain.tcl file in its bundled Resources/Scripts folder. If present, argv[1] is set to that file and the Scripts folder is added to the auto_path. This allows tk apps to embed scripts within their bundle directory structure. * macosx/tkMacOSXInit.c (new): macosx adapted version of tkUnixInit.c: we initialize & cache the Carbon native encoding (e.g. 'macRoman') and try to find the tk script library files inside Tk packaged as a framework. * macosx/tkMacOSXNotify.c (new): new macosx specific merged Carbon/select-based notifier. * macosx/tkMacOSXEvent.c (new): * macosx/tkMacOSXEvent.h (new): * macosx/tkMacOSXKeyEvent.c (new): * macosx/tkMacOSXMouseEvent.c (new): * macosx/tkMacOSXWindowEvent.c (new): new macosx specific event handling functionality. * macosx/tkMacOSX.h (new): * macosx/tkMacOSXBitmap.c (new): * macosx/tkMacOSXButton.c (new): * macosx/tkMacOSXClipboard.c (new): * macosx/tkMacOSXColor.c (new): * macosx/tkMacOSXConfig.c (new): * macosx/tkMacOSXCursor.c (new): * macosx/tkMacOSXDefault.h (new): * macosx/tkMacOSXDialog.c (new): * macosx/tkMacOSXDraw.c (new): * macosx/tkMacOSXEmbed.c (new): * macosx/tkMacOSXFont.c (new): * macosx/tkMacOSXHLEvents.c (new): * macosx/tkMacOSXInt.h (new): * macosx/tkMacOSXKeyboard.c (new): * macosx/tkMacOSXMenu.c (new): * macosx/tkMacOSXMenubutton.c (new): * macosx/tkMacOSXMenus.c (new): * macosx/tkMacOSXPort.h (new): * macosx/tkMacOSXRegion.c (new): * macosx/tkMacOSXScale.c (new): * macosx/tkMacOSXScrlbr.c (new): * macosx/tkMacOSXSubwindows.c (new): * macosx/tkMacOSXTest.c (new): * macosx/tkMacOSXUtil.c (new): * macosx/tkMacOSXUtil.h (new): * macosx/tkMacOSXWm.c (new): * macosx/tkMacOSXWm.h (new): * macosx/tkMacOSXXStubs.c (new): macosx ports of classic mac Tk implementation in tk/mac. * macosx/tkMacOSXSend.c (new): only send to local interp implemented currently. * macosx/tkMacOSXDebug.h (new): * macosx/tkMacOSXDebug.c (new): new macosx specific functions for debugging MacOS events, regions, etc. * macosx/tkAboutDlg.r (new): * macosx/tkMacOSXApplication.r (new): * macosx/tkMacOSXCursors.r (new): * macosx/tkMacOSXLibrary.r (new): * macosx/tkMacOSXMenu.r (new): * macosx/tkMacOSXResource.r (new): * macosx/tkMacOSXXCursors.r (new): * macosx/tclets.r (new): sources for Rez resource compiler. * macosx/Wish.icns (new): Wish application icon. * generic/tk.h: * generic/default.h: * generic/tkBind.c: * generic/tkCmds.c: * generic/tkGrab.c: * generic/tkPointer.c: * generic/tkPort.h: * generic/tkSelect.c: * generic/tkStubLib.c: * generic/tkTest.c: * generic/tkText.c: * generic/tkWindow.c: * unix/tkUnix3d.c: * xlib/xgc.c: * xlib/X11/X.h: * xlib/X11/Xlib.h: * xlib/X11/Xutil.h: added #includes and #ifdefs for macosx * library/bgerror.tcl: * library/button.tcl: * library/console.tcl: * library/dialog.tcl: * library/entry.tcl: * library/listbox.tcl: * library/menu.tcl: * library/msgbox.tcl: * library/scrlbar.tcl: * library/spinbox.tcl: * library/text.tcl: * library/tk.tcl: * library/demos/menu.tcl: * library/demos/menubu.tcl: * library/demos/widget: check [tk windowingsystem] instead of and/or in addition to $tcl_platform(platform). * generic/tkInt.h: * mac/tkMacBitmap.c: * mac/tkMacWm.c: added missing CONSTification * generic/tkIntDecls.h: * generic/tkIntPlatDecls.h: * generic/tkIntXlibDecls.h: * generic/tkPlatDecls.h: * generic/tkStubInit.c: regen 2002-08-27 D. Richard Hipp <drh@hwaci.com> * doc/checkbutton.n: [Bug 582457] Fix the -offrelief option so * doc/radiobutton.n: that when -offrelief is flat and -relief is * mac/tkMacButton.c: sunken and -overrelief is raised, buttons * unix/tkUnixButton.c: work look toolbar buttons under Windows. * win/tkWinButton.c: See also: TIP #82. 2002-08-26 Don Porter <dgp@users.sf.net> * win/Makefile.in: Removed dependence on the (parts of) the * win/winMain.c: tcltest executable on Windows. It was not used, and the dependency complicated the Makefile. [Bug 592638]. 2002-08-20 Don Porter <dgp@users.sf.net> * README: Bumped version number to 8.4b3 to distinguish * generic/tk.h: HEAD from the 8.4b2 release. * unix/configure.in: * win/configure.in: * unix/tk.spec: * unix/configure: autoconf * win/configure: * generic/tk.h: Added compile-time check that the tcl.h header file #included by Tk 8.4 is one from Tcl 8.4. This is needed to be sure that new #defines like CONST84 are available. [Bug 597432]. 2002-08-16 Jeff Hobbs <jeffh@ActiveState.com> * unix/Makefile.in (install-binaries): simplified pkgIndex.tcl file created on installation. * win/Makefile.in (install-binaries): corrected and simplified creation of pkgIndex.tcl file on installation. 2002-08-14 Vince Darley <vincentdarley@users.sourceforge.net> * win/tkWinDialog.c: * win/makefile.vc: broken compilation and link from changes Hobbs-08-07 fixed. * win/tkWinTest.c: CONST problem resolved. 2002-08-13 Jeff Hobbs <jeffh@ActiveState.com> * library/button.tcl: change the bindings to use Priv($w,relief) instead of just Priv(relief). This ensures that neighboring buttons don't confuse (over)relief settings. 2002-08-13 Reinhard Max <max@suse.de> * unix/tkUnixSend.c (Tk_SetAppName): Fixed a compiler warning. 2002-08-12 Donal K. Fellows <fellowsd@cs.man.ac.uk> * library/demos/image2.tcl: Tweaked the behaviour of the directory box on resize, as resizing of the overall window tends to be common given the sample images. 2002-08-08 Mo DeJong <mdejong@users.sourceforge.net> * unix/tkUnixWm.c (WmTransientCmd): Apply fix for wm transient assertion error that was applied to tkWinWm.c for Tk Bug #592201. 2002-08-08 Mo DeJong <mdejong@users.sourceforge.net> * tests/wm.test: Add deleteWindows at start of new transient tests so they do not fail if the toplevels already exist. * unix/tkUnixWm.c: Revert patch for Tk Bug #592201 which incorrectly removed numTransients member. 2002-08-08 Joe English <jenglish@users.sourceforge.net> * unix/tkUnixWm.c: * win/tkWinWm.c: * tests/wm.test: Fix for Tk Bug #592201 "wm transient fails with two masters"; fixes panic after a transient window is reassigned to new master and either master is subsequently destroyed. 2002-08-08 Don Porter <dgp@users.sf.net> * tests/unixWm.test: Corrected packaging of unixWm-50.3 so that [setupbg] and [cleanupbg] always balance, no matter what tests are skipped. 2002-08-08 Reinhard Max <max@suse.de> * unix/Makefile.in: Fixed typos in DISTNAME, and ZIPNAME. 2002-08-08 Jeff Hobbs <jeffh@ActiveState.com> *** 8.4b2 TAGGED FOR RELEASE *** * generic/tkButton.c (TkButtonWorldChanged): added GCFont handling to the disabledGc of buttons when compound != none. The drawing appears to be incorrect across platforms still. [Bug #477740] * generic/tkImgGIF.c (FileReadGIF): fixed -from handling for gifs [Bug #467524] (obermeier) 2002-08-07 Jeff Hobbs <jeffh@ActiveState.com> * generic/tkCanvUtil.c (TkSmoothParseProc): recognize the built-in bezier method by name. [Bug #578654] * doc/canvas.n: update to note that -smooth really doesn't take or return just booleans. * win/tkWinMenu.c (TkpSetWindowMenuBar): fixed logic bug in when to idle call ReconfigureWindowsMenu. * doc/GetBitmap.3: removed doc refs to deprecated Tk_GetBitmapFromData. [Bug #590379] * generic/tkPanedWindow.c (Tk_PanedWindowObjCmd): * library/panedwindow.tcl: changed class from PanedWindow to Panedwindow to not conflict with existing bwidgets, but also to be more regular with other names used in the core. * tests/panedwindow.test: added -text foobar to some test buttons to enable correct testing of panedwindow across platforms. [Bug #582370] * win/tkWinDialog.c: enabled use of the updated native Windows directory browser (tk_chooseDirectory). This does require shell32.dll v4.71 or greater. [Patch #468139] * win/configure: * win/tcl.m4: added shell32 to libs for updated native Windows tk_chooseDirectory dialog. 2002-08-06 Donal K. Fellows <fellowsd@cs.man.ac.uk> * generic/tkPanedWindow.c (RESIZE_PENDING): Separated out flag for indicating that a resize needs to be issued. (PanedWindowReqProc): Do the old behaviour when the panedwindow is not mapped; easiest way of making the test suite pass while still preserving improved behaviour in the face of children whose size is not known immediately. 2002-08-06 Don Porter <dgp@users.sf.net> * tests/defs.tcl: removed file. No longer needed now that Tk is using the tcltest package to do its testing. 2002-08-05 Don Porter <dgp@users.sf.net> * win/tkWinFont.c: Additional changes to fix CONST warnings on * win/tkWinWM.c: Windows due to latest patch. Tks Vince Darley. * doc/3DBorder.3: Applied companion patch for Tcl Patch 585105, * doc/BindTable.3: updating Tk to use Tcl 8.4's fully CONST-ified * doc/ConfigWidg.3: interface, and fully CONSTifying Tk at the * doc/CrtImgType.3: same time. * doc/CrtWindow.3: * doc/DeleteImg.3: This patch includes purging Tk of its last * doc/FindPhoto.3: direct access to interp->result. [Bug 589853] * doc/GetAnchor.3: * doc/GetBitmap.3: The substantial changes include copying * doc/GetCapStyl.3: event sequence strings into Tcl_DStrings * doc/GetClrmap.3: in tkBind.c, and copying [text] indices into * doc/GetColor.3: Tcl_DStrings because parsing them involved * doc/GetCursor.3: overwriting them. If this causes performance * doc/GetFont.3: trouble, that can be resolved by further * doc/GetImage.3: converting them to Tcl_Obj's. * doc/GetJoinStl.3: * doc/GetJustify.3: The #defines USE_NON_CONST and USE_COMPAT_CONST * doc/GetOption.3: have the same effect for Tk as they do for Tcl. * doc/GetRelief.3: (They actually change tcl.h) * doc/GetScroll.3: * doc/GetVisual.3: * doc/InternAtom.3: * doc/NameOfImg.3: * doc/SetAppName.3: * doc/WindowId.3: * generic/tk.decls: * generic/tk.h: * generic/tk3d.c: * generic/tkAtom.c: * generic/tkBind.c: * generic/tkBitmap.c: * generic/tkButton.c: * generic/tkCanvArc.c: * generic/tkCanvBmap.c: * generic/tkCanvImg.c: * generic/tkCanvLine.c: * generic/tkCanvPoly.c: * generic/tkCanvPs.c: * generic/tkCanvText.c: * generic/tkCanvUtil.c: * generic/tkCanvWind.c: * generic/tkCanvas.c: * generic/tkCanvas.h: * generic/tkClipboard.c: * generic/tkCmds.c: * generic/tkColor.c: * generic/tkConfig.c: * generic/tkConsole.c: * generic/tkCursor.c: * generic/tkDecls.h: * generic/tkEntry.c: * generic/tkFont.c: * generic/tkFrame.c: * generic/tkGet.c: * generic/tkGrid.c: * generic/tkImage.c: * generic/tkImgBmap.c: * generic/tkImgPhoto.c: * generic/tkInt.decls: * generic/tkInt.h: * generic/tkIntDecls.h: * generic/tkIntPlatDecls.h: * generic/tkListbox.c: * generic/tkMenu.c: * generic/tkMenubutton.c: * generic/tkMessage.c: * generic/tkOldConfig.c: * generic/tkOption.c: * generic/tkRectOval.c: * generic/tkScale.c: * generic/tkScrollbar.c: * generic/tkSelect.c: * generic/tkStyle.c: * generic/tkTest.c: * generic/tkText.c: * generic/tkText.h: * generic/tkTextBTree.c: * generic/tkTextDisp.c: * generic/tkTextImage.c: * generic/tkTextIndex.c: * generic/tkTextMark.c: * generic/tkTextTag.c: * generic/tkTextWind.c: * generic/tkUtil.c: * generic/tkVisual.c: * generic/tkWindow.c: * mac/tkMacConfig.c: * mac/tkMacCursor.c: * mac/tkMacEmbed.c: * mac/tkMacSend.c: * unix/tkUnixConfig.c: * unix/tkUnixCursor.c: * unix/tkUnixEmbed.c: * unix/tkUnixFont.c: * unix/tkUnixSelect.c: * unix/tkUnixSend.c: * unix/tkUnixWm.c: * win/tkWinConfig.c: * win/tkWinCursor.c: * win/tkWinEmbed.c: * win/tkWinMenu.c: * win/tkWinSend.c: 2002-08-02 Donal K. Fellows <fellowsd@cs.man.ac.uk> * generic/tkPanedWindow.c (DestroyPanedWindow): Idle calls need to be deleted on destruction of the window, or things can *really* go pear-shaped. 2002-07-31 Donal K. Fellows <fellowsd@cs.man.ac.uk> * generic/tkPanedWindow.c (PanedWindowReqProc): Postpone pane arrangement until idle, as is done in other window managers, to fix problems with size calculations when the children don't already know their sizes anyway. * unix/configure: Regen. * unix/tcl.m4: Update from Tcl. 2002-07-29 Mo DeJong <mdejong@users.sourceforge.net> * unix/configure: Regen. * unix/configure.in: Remove code that was setting CC_SEARCH_FLAGS and LD_SEARCH_FLAGS to try to account for cc vs ld linking. Tcl now handles this. * unix/tcl.m4: Update from Tcl. 2002-07-27 Mo DeJong <mdejong@users.sourceforge.net> * unix/Makefile.in: Add MAJOR_VERSION, MINOR_VERSION, PATCH_LEVEL, INSTALL_LIBRARY, STUB_LIB_FILE, and LIB_FILE to support changes in tcl.m4 related to library builds. Use MAKE_LIB macro to avoid dealing with RANLIB issues. Rename TK_CC_SEARCH_FLAGS to CC_SEARCH_FLAGS and rename TK_LD_SEARCH_FLAGS to LD_SEARCH_FLAGS. Use new INSTALL_LIB and INSTALL_STUB_LIB substs to deal with ranlib issues when install libraries. * unix/configure: Regen. * unix/configure.in: Remove AC_PROG_RANLIB since this is done by tcl.m4 now. Define CC_SEARCH_FLAGS instead of TK_CC_SEARCH_FLAGS and so on. Use MAKE_LIB and MAKE_STUB_LIB from tcl.m4. Remove AC_SUBST calls that are no done in tcl.m4. * unix/tcl.m4: Update from Tcl. * unix/tkConfig.sh.in: Subst CC_SEARCH_FLAGS and LD_SEARCH_FLAGS. 2002-07-25 Peter Spjuth <peter.spjuth@space.se> * generic/tkInt.h: * generic/tkWindow.c: * mac/tkMacWm.c: * unix/tkUnixWm.c: * win/tkWinWm.c: * tests/wm.test: * tests/winWm.test: * tests/unixWm.test: Objectifed wm. [Patch #564521] Note: At this point the Mac file is completely untested and may not even compile. 2002-07-25 Jeff Hobbs <jeffh@ActiveState.com> * tests/spinbox.test: added spinbox-22.[1-3] * generic/tkEntry.c (ConfigureEntry): made the textvariable value take precedence over changed -from/-to values, unless it must be constrained. [Bug #559078] * library/spinbox.tcl (MouseSelect): when not in the entry, just return instead of invoking - ButtonUp handles invoking already. [Bug #499168] * library/tk.tcl (RestoreFocusGrab): handle the case where the FocusGrab info is not set. [Bug #553283] 2002-07-24 Jeff Hobbs <jeffh@ActiveState.com> * tests/canvas.test: added canvas-14.[1-6] * generic/tkCanvas.c (CanvasWidgetCmd): corrected handling of 'scan' subcommand args. Also removed early return cases to goto done instead where the canvasPtr would be Tcl_Release'd. This may solve other problems with unreleased canvasPtr's. [Bug #581560] * win/tkWinButton.c (TkpDisplayButton): corrected display of focus ring around the actual text when the button is a compound button. [Bug #583691] * unix/README: Corrected notes about running user interactive Tk tests. [Bug #462320] * generic/tkText.c (TextEditUndo): set isDirtyIncrement to -1 when reverting to note proper "dirtiness". [Bug #580362] (callewaert) * generic/tkEntry.c (DisplayEntry): correct cursor position before calling Tk_SetCaretPos. (yamamoto) 2002-07-23 Mo DeJong <mdejong@users.sourceforge.net> * unix/configure: Regen. * unix/tcl.m4: Update from Tcl. 2002-07-22 Mo DeJong <mdejong@users.sourceforge.net> * library/choosedir.tcl (tk::dialog::file::chooseDir): * library/clrpick.tcl (tk::dialog::file::chooseDir): * library/msgbox.tcl (tk::MessageBox): * library/tkfbox.tcl (tk::dialog::file): * library/xmfbox.tcl (tk::MotifFDialog): Revert [Tk patch 568278]. The transient window workaround is no longer needed since the fix for [Tk bug 570764] solved the problem for withdrawn transients. 2002-07-19 Mo DeJong <mdejong@users.sourceforge.net> * unix/configure: * unix/configure.in: * win/configure: * win/configure.in: Add AC_PREREQ(2.13) in an attempt to make it more clear that the configure scripts must be generated with autoconf version 2.13. [Tcl Bug 583573] 2002-07-19 D. Richard Hipp <drh@hwaci.com> * library/mkpsec.tcl: Fix a bug that was causing postscript generation to fail under Win2K. 2002-07-18 Reinhard Max <max@suse.de> * unix/tkUnixSend.c: Using Tcl_GetTime instead of TclpGetTime. 2002-07-17 Reinhard Max <max@suse.de> * library/unsupported.tcl: Extended ExposePrivateVariable, and ExposePrivateCommand to accept patterns as well. 2002-07-17 Don Porter <dgp@users.sf.net> * generic/tkFont.c: Corrected reversed logic in assert -> panic conversion. [Bug 582799] 2002-07-16 Mo DeJong <mdejong@users.sourceforge.net> * generic/tkFont.c (TkFontPkgFree): Call panic instead of assert since assert is not used in the rest of Tk. [Tk bug 579651] 2002-07-16 Mo DeJong <mdejong@users.sourceforge.net> * unix/Makefile.in: * win/Makefile.in: Add a more descriptive warning in the event `make genstubs` needs to be rerun. 2002-07-16 Vince Darley <vincentdarley@users.sourceforge.net> * win/tkWinWm.c: * doc/wm.n: fix for part of [Bug 581627], and made iconbitmap code on Windows more flexible about reading in icons [Bug 220800]. 2002-07-15 David Gravereaux <davygrvy@pobox.com> * win/makefile.bc (new): re-add of the borland makefile. Submitted by Helmut Giese <hgiese@ratiosoft.com>. This needs testing, still. 2002-07-15 Don Porter <dgp@users.sf.net> * Fixes for [Bug 581627, 581795]. * generic/tkTest.c: Test commands not supported on non-Unix platforms should not be defined there in the first place. * tests/constraints.tcl: Fixed "secureserver" constraint. * tests/unixWm.test: Some tests needed "unix" constraint. * win/tkWinWm.c: Typo in error message. 2002-07-14 Don Porter <dgp@users.sf.net> * tests/event.test: Fixes to enable testing of only userInteraction * tests/visual_bb.test: tests. * README: Bumped HEAD to version 8.4b2 in order to * generic/tk.h: distinguish it from the 8.4b1 release. * unix/configure*: Also extended LOCALES to cover all message * unix/tk.spec: catalogs. * win/configure*: * tests/focustTcl.test: Conversion bug: Corrected backwards logic. * tests/imgPhoto.test: Conversion bug: overwrote unix/README. * tests/all.tcl: Completed conversion of Tk test suite * tests/constraints.tcl: to use tcltest. * tests/[b-v]*.test: * unix/Makefile.in: 2002-07-12 Don Porter <dgp@users.sf.net> * tests/constraints.tcl: Converted more files to tcltest and * tests/[g-x]*.test: factored out common code. 2002-07-11 Don Porter <dgp@users.sf.net> * tests/canvPsImg.tcl: Converted several files in the * tests/constraints.tcl (new file): Tk test suite for testing by * tests/[r-x]*.test: tcltest 2.1. * unix/Makefile.in: 2002-07-11 Jeff Hobbs <jeffh@ActiveState.com> * win/tkWinDialog.c (Tk_ChooseDirectoryObjCmd): initialize utfTitle to NULL, add a few more notes about limitations of possible new Tk_ChooseDirectoryObjCmd function. 2002-07-11 Donal K. Fellows <fellowsd@cs.man.ac.uk> * tests/imgPhoto.test (imgPhoto-15.1): Added test of mem-alloc failure, but this is non-portable. * generic/tkImgPhoto.c (ImgPhotoSetSize): Allowed this function to fail when it can't allocate enough memory. Note that not all the places that call it can fail nicely without API changes; some still panic but at least some of the potential failures are now handled gracefully. * tests/visual_bb.test (lpr): Stopped this from relying on external files; direct piping is much more flexible for this application. 2002-07-09 Don Porter <dgp@users.sf.net> * generic/tkTest.c: Removed unused dependence on TclThread_Init() * tests/defs.tcl: and [testthread]. [Bug 578165, Tcl Bug 531413] 2002-07-08 David Gravereaux <davygrvy@pobox.com> * unix/Makefile.in: Added missing win/lamp.bmp to the dist target. 2002-07-05 Jeff Hobbs <jeffh@ActiveState.com> *** 8.4b1 TAGGED FOR RELEASE *** 2002-07-04 Donal K. Fellows <fellowsd@cs.man.ac.uk> * library/bgerror.tcl (bgerror): Stopped the bgerror dialog from getting wider than the screen; in theory really long messages could make it become taller than the screen now, but that's much less likely to happen. Also trimmed a little bit of internal space so that the icon-message gap is the same as the icon-frame and message-frame gaps. 2002-07-01 Don Porter <dgp@users.sf.net> * unix/configure: * unix/tcl.m4: Updated to latest tcl.m4 from Tcl. 2002-06-28 Donal K. Fellows <fellowsd@cs.man.ac.uk> * library/msgbox.tcl (MessageBox): Force all non-button widgets to have the same background as the containing toplevel. [Bug #552515] 2002-06-27 Andreas Kupries <andreas_kupries@users.sourceforge.net> * win/Makefile.in (install-binaries): Fix of troubled Makefile quoting introduced by [Patch 521356] causing the installed to fail. 2002-06-25 Don Porter <dgp@users.sf.net> * unix/tkUnixFont.c: (Tk_DrawChars) silence compiler warning. 2002-06-26 David Gravereaux <davygrvy@pobox.com> * generic/tkStyle.c: <eol> of the committing cvs client didn't match the <eol> of the file itself. Windows users where getting \r\r\n. Problem fixed. 2002-06-26 Anton Kovalenko <a_kovalenko@users.sourceforge.net> * generic/tkFont.c (TkTextLayoutToPostscript): fixed potential buffer overflow which could be intentionally triggered from within safe interpreter -- malicious applet could modify tk::psglyphs array. 2002-06-26 Anton Kovalenko <a_kovalenko@users.sourceforge.net> * tests/font.test (font-32.1): updated this test to expect the new behavior of canvas postscript. 2002-06-25 Don Porter <dgp@users.sf.net> * unix/Makefile.in: Expanded install-binaries target to create * win/Makefile.in: and install a pkgIndex.tcl file to enable Tk as a loadable package [Patch 521356] 2002-06-25 Anton Kovalenko <a_kovalenko@users.sourceforge.net> * library/mkpsenc.tcl: (added) utilities to generate Postscript prolog for current system encoding. * generic/tkCanvPs.c (TkCanvPostscriptCmd): now uses mkpsenc.tcl to generate Postscript prolog. * generic/tkFont.c (TkTextLayoutToPostscript): modified according to patch #546910. Now outputs system-encoded characters (for unibyte) or Adobe glyph names (for multibyte or outside-locale). * tests/canvText.test (canvText-17.1): updated this test to expect the new behavior of canvas postscript. 2002-06-25 Reinhard Max <max@suse.de> * unix/tcl.m4: New macro SC_CONFIG_MANPAGES. * unix/configure.in: Added support for symlinks and compression * unix/Makefile.in: when installing the manpages. [Patch 518052] Default is still hardlinks and no compression. * unix/mkLinks: generated * unix/configure: * unix/README: Added documentation for the new features. * unix/configure: Replaced ${exec_prefix}/lib * unix/tcl.m4 (SC_PATH_TCLCONFIG): by ${libdir}. 2002-06-24 Mo DeJong <mdejong@users.sourceforge.net> * tests/winWm.test: Verify that both an unmapped and already mapped toplevel are raised and receive the focus when deiconified. * tests/wm.test: Add wm deiconify tests. Check that a toplevel that has never been mapped is not mapped by the deiconify command since it should be done at idle by MapFrame. * win/tkWinWm.c (Tk_WmCmd): Check the WM_NEVER_MAPPED flag while processing the wm deiconify command. The WM_UPDATE_PENDING flag should never be set when WM_NEVER_MAPPED is set, but double check so that the implementation is more explicit and matches the comment just above. Return without invoking TkWmRestackToplevel or TkSetFocusWin on a toplevel that has never been mapped. This fixes a bug where a toplevel is mapped with the wrong size and is then resized by the idle call to MapFrame. [Tk bug 233150] 2002-06-23 Jeff Hobbs <jeffh@ActiveState.com> * win/tkWinWm.c (UpdateGeometryInfo): remove the check for a null wrapper introduced in r1.41 on 2002-06-15 because it prevented geometry setting from taking effect if the window was not on the screen. Another check may go in it's place as IsIconic and IsZoomed should not be passed NULL. 2002-06-22 Mo DeJong <mdejong@users.sourceforge.net> * tests/wm.test: Remove invalid minsize test. Add update calls to wm transient tests so that idle handlers get run. This is needed to get the tests to pass under Win32. * unix/tkUnixWm.c (WmWaitMapProc): Move the special transient withdrawn check into the if body to make it easier to set a breakpoint on this test inside a debugger. No functional changes. * win/tkWinWm.c (WmWaitVisibilityOrMapProc): Ditto. 2002-06-22 Jeff Hobbs <jeffh@ActiveState.com> * doc/wm.n: TIP #95 Windows implementation and * mac/tkMacWm.c (Tk_WmCmd): docs with mac and unix stubs. * unix/tkUnixWm.c (Tk_WmCmd): * win/tkWinWm.c (Tk_WmCmd): * tests/unixWm.test: * tests/winWm.test: more wm attr tests will be needed. * generic/tkGrid.c (GridReqProc): check that gridPtr is not NULL (may be when embedded). [Bug #548791] (halliday) * generic/tkFont.c (TkFontPkgFree): changed panic on freeing fonts to an assert, and wrapped panic in #ifdef PURIFY. [Bug #568701] * library/menu.tcl: corrected menus from being posted offscreen on Windows. [Bug #464451] (darley) * library/console.tcl: corrected the defaultPrompt substitution [Bug #553207] and made Tab a default expansion key (like Escape). * win/tkWinEmbed.c (EmbedWindowDeleted): added a check for a null containerPtr. The core of this bug is likely elsewhere. [Bug #476176] * doc/text.n: TIP #93 implementation that * generic/tkText.c (TextWidgetCmd): enhances the text get and * generic/tkTextIndex.c (TkTextGetIndex): delete methods to accept * tests/text.test: multiple range pairs. This handles the delete case in an atomic, fixed-index fashion. 2002-06-21 Mo DeJong <mdejong@users.sourceforge.net> * tests/wm.test: Add tests to make sure a withdrawn transient does not get remapped by state changes in the master. * unix/tkUnixWm.c (Tk_WmCmd, WmWaitMapProc): * win/tkWinWm.c (Tk_WmCmd, WmWaitVisibilityOrMapProc): Add a WM_TRANSIENT_WITHDRAWN flag that gets set by the withdraw, deiconify, or state wm subcommands. Check this flag before mapping a transient when processing a MapNotify event. [Tk bug 570764] 2002-06-21 Donal K. Fellows <fellowsd@cs.man.ac.uk> * unix/tk.spec (version), README, win/configure.in, unix/configure.in: * generic/tk.h (TK_RELEASE_*, TK_PATCH_LEVEL): Bumped to beta1. 2002-06-21 Jeff Hobbs <jeffh@ActiveState.com> * doc/text.n: TIP #104 implementation which generalizes the * generic/tkText.c: undo/redo stack to not be tied solely to the * generic/tkText.h: text widget. The APIs are still private. * generic/tkUndo.c: This also adds a stack limiting ability and * generic/tkUndo.h: a -maxundo option to the text widget (in * library/text.tcl: addition to the options from TIP #26) should * mac/tkMacDefault.h: users want to limit the undo/redo stack * tests/text.test: (should not be necessary in most cases). * unix/Makefile.in: [Patch #554763] (callewart) * unix/tkUnixDefault.h: * win/Makefile.in: * win/makefile.vc: * win/tkWinDefault.h: 2002-06-21 Don Porter <dgp@users.sf.net> * unix/Makefile.in: Removed unnecessary dependence of tktest * unix/tkAppInit.c: executable on the tcltest executable on Unix. If there are similar dependencies on other platforms, they can probably be removed as well. [Bug 572134]. 2002-06-20 Jeff Hobbs <jeffh@ActiveState.com> * doc/listbox.n: * generic/tkListbox.c (DisplayListbox): * mac/tkMacDefault.h: TIP #94 implementation adding -activestyle * tests/listbox.test: option to the listbox. This adds the ability * unix/tkUnixDefault.h: to have listboxes look native on Windows, and * win/tkWinDefault.h: "nicer" elsewhere using the 'dotbox' style. 2002-06-20 Peter Spjuth <peter.spjuth@space.se> * generic/tkGrid.c: Corrected the test for grid propagate change. [Bug #571433] 2002-06-19 Jeff Hobbs <jeffh@ActiveState.com> * tests/panedwindow.test: * generic/tkPanedWindow.c: ensure that sash index is lower bounds checked. [Bug #548727] 2002-06-19 Mo DeJong <mdejong@users.sourceforge.net> * generic/tkClipboard.c (TkClipCleanup): Add code to set dispPtr->clipWindow to NULL, this was accidently removed by last commit. Fixes a crash while running the tests under win32. 2002-06-19 Mo DeJong <mdejong@users.sourceforge.net> * generic/tkBind.c (TkBindDeadWindow): Handle case where Tk_DestroyWindow is invoked on clipboard and send windows. * generic/tkClipboard.c (TkClipCleanup): Invoke Tk_DestroyWindow to cleanup the dispPtr->clipWindow. Call Tcl_Preserve and Tcl_Release on the window to avoid an invalid memory ref on shutdown. * generic/tkEvent.c (Tk_HandleEvent): Panic if XCreateIC is invoked twice for the same window. This should never happen, the check were just added to make sure it does not since this could lead to crashes in XCloseIM. * generic/tkFocus.c (TkFocusDeadWindow): Handle case where Tk_DestroyWindow is invoked on clipboard and send windows. * generic/tkOption.c (TkOptionDeadWindow): Ditto. * generic/tkWindow.c (TkCloseDisplay): Move deletion of dispPtr->winTable after TkpCloseDisplay call since Tk_DestroyWindow uses it and could be called by TkpCloseDisplay for clipboard/send windows. Also invoke ckfree for the dispPtr instead of doing it in TkpCloseDisplay. (Tk_DestroyWindow): Check for a null winPtr->mainPtr before doing certain cleanup tasks so the we can invoke Tk_DestroyWindow on clipboard and send windows. We need to do this so that XDestroyIC will get invoked for the input contexts of each window. * mac/tkMacXStubs.c (TkpCloseDisplay): Don't free the displayPtr since this is now done in TkCloseDisplay. * unix/tkUnixEvent.c (TkpCloseDisplay, OpenIM): Remove conditional compilation around calls to XCloseIM since I am confident that the crashes related to input contexts has been fixed. Don't free the displayPtr since this is now done in TkCloseDisplay. * unix/tkUnixSend.c (TkSendCleanup): Invoke the Tk_DestroyWindow method to cleanup the special send window. This will call XDestroyIC and thereby avoid a crash in XCloseIM. The send window needs to be Tcl_Preserve and Tcl_Release to avoid an invalid memory ref on shutdown. * win/tkWinX.c (TkpCloseDisplay): Don't free the displayPtr since this is now done in TkCloseDisplay. [Tk patch 570902] 2002-06-19 Donal K. Fellows <fellowsd@cs.man.ac.uk> * generic/tkStyle.c: TIP#48 style engine. See http://purl.org/tcl/tip/48.html for details. * generic/tkConfig.c (GetOptionFromObj): Split to allow for access to option tables via name as well as via object. (TkGetOptionSpec): Semi-public interface to GetOption functionality. (DoObjConfig, Tk_RestoreSavedOptions, FreeResources) (GetObjectForOption): Basic style support for configure. * generic/tkWindow.c (TkCreateMainWindow, Tk_DestroyWindow): Added calls to set up and tear down the style subsystem. * generic/tk.decls, generic/tk.h: Many declarations forming TIP#48 public interface. * generic/tkInt.decls (TkStylePkgInit,TkStylePkgFree): * generic/tkInt.h (TkGetOptionSpec): Supporting declarations. * unix/Makefile.in, win/Makefile.in, win/makefile.vc: Added tkStyle.c to list of generic source files. 2002-06-18 Donal K. Fellows <fellowsd@cs.man.ac.uk> * tests/defs.tcl (makeFile): Defined the return value of this procedure to be the filename of the created file, as in the real tcltest package... 2002-06-17 Mo DeJong <mdejong@users.sourceforge.net> * generic/tkImage.c (Tk_ImageObjCmd, DeleteImage): Call Tcl_Preserve and Tcl_Release for the masterPtr->winPtr window to avoid accessing memory that had already been deallocated in DeleteImage. 2002-06-17 David Gravereaux <davygrvy@pobox.com> Trims to support the removal of RESOURCE_INCLUDED from rc scripts from Tcl's accepted FR #565088. * generic/tk.h: Changed RESOURCE_INCLUDED to be RC_INVOKED as the RC tool defines this already by default. * win/rc/tk.rc: * win/rc/wish.rc: removed the #define RESOURCE_INCLUDED lines. 2002-06-17 Jeff Hobbs <jeffh@ActiveState.com> * unix/Makefile.in (dist): correct installation of wish.exe.manifest to DISTDIR target directory. * generic/tkCmds.c (Tk_TkObjCmd): * generic/tkInt.h (struct TkCaret): * mac/tkMacXStubs.c (Tk_SetCaretPos): * unix/tkUnixKey.c (TkpGetString, Tk_SetCaretPos): * win/tkWinX.c (Tk_SetCaretPos): * tests/tk.test: Added 'tk caret' implementation of TIP#96 * doc/SetCaret.3 (new): which adds a TkCaret structure element to * doc/tk.n: TkDisplay for maintaining state. * unix/tkUnixSend.c (TkSendCleanup): special cleanup of inputContext to avoid bug in XCloseIM. (dejong) 2002-06-17 Don Porter <dgp@users.sf.net> * library/msgs/en_gb.msg: Added catalog for UK English. Currently includes only Color -> Colour translation. 2002-06-17 D. Richard Hipp <drh@hwaci.com> * doc/checkbutton.n: * doc/radiobutton.n: * generic/tkButton.c: * generic/tkButton.h: * mac/tkMacButton.c: * tests/button.test: * unix/tkUnixButton.c: * win/tkWinButton.c: Implementation of TIP#82 - Added the -offrelief option to checkbutton and radiobutton. 2002-06-14 Mo DeJong <mdejong@users.sourceforge.net> * generic/tkWindow.c (Tk_DestroyWindow): Set the pathName component of a window to NULL after its memory has been deallocated to avoid a possible illegal memory access as a result of a call to Tk_PathName() on a Tk_Window structure of a window that has already been destroyed. [Tk bug 521946] 2002-06-14 Mo DeJong <mdejong@users.sourceforge.net> * generic/tkOption.c (Tk_GetOption): Allocate memory with ckalloc not malloc. This keeps Tk from erroring out when built with TCL_MEM_DEBUG. 2002-06-14 Jeff Hobbs <jeffh@ActiveState.com> * generic/tkBind.c (HandleEventGenerate): * generic/tkInt.h: changed warpInProgress boolean from int to a bit in the flags variable (TK_DISPLAY_IN_WARP) * generic/tkCmds.c (Tk_TkObjCmd): * unix/tkUnixKey.c (TkpGetString): * generic/tkEvent.c (Tk_HandleEvent): * generic/tkInt.h: changed useInputMethods boolean from int to a bit in the flags variable (TK_DISPLAY_USE_IM) * generic/tkInt.h: * generic/tkCmds.c (Tk_WmObjCmd): * unix/tkUnixWm.c (Tk_WmCmd): * win/tkWinWm.c (Tk_WmCmd): changed wmTracing from being an int to just a bit in the flags variable (TK_DISPLAY_WM_TRACING) * generic/tkEvent.c (Tk_HandleEvent): * unix/tkUnixEvent.c (OpenIM): * unix/tkUnixKey.c (TkpGetString): * generic/tkInt.h: added TK_DISPLAY_XIM_SPOT flag bit for TkDisplay and used this to allow a runtime check to see if over-the-spot XIM is possible. If not it will try and fallback to the old-style input context, which handles things like dead keys input. * generic/tk.decls: added TIP #84 implementation that adds a * generic/tkDecls.h: Tk_CollapseMotionEvents API which controls * generic/tkEvent.c: Tk's collapsing of incoming motion events * generic/tkInt.h: on its windows. The default remains to do * generic/tkStubInit.c: collapsing. Added a flags parameter to the * generic/tkWindow.c: internal display structure to support this * doc/QWinEvent.3: and be used in the future for other bits. [Tk patch 564642] * unix/mkLinks: updated from current docs 2002-06-14 Mo DeJong <mdejong@users.sourceforge.net> * generic/tkEvent.c (TkXErrorHandler): Declare static function to avoid compiler error with VC++. * generic/tkBind.c (ExpandPercents): Cast argument to Tk_GetAtomName in order to avoid compiler warning. 2002-06-14 Joe English <jenglish@users.sf.net> * doc/bind.n: * generic/tk.h: * generic/tkBind.c: * generic/tkCanvWind.c: * generic/tkCmds.c: * generic/tkEvent.c: * generic/tkFocus.c: * generic/tkGrab.c: * generic/tkGrid.c: * generic/tkImage.c: * generic/tkPack.c: * generic/tkPlace.c: * generic/tkPointer.c: * generic/tkTextWind.c: * generic/tkWindow.c: * mac/tkMacSubwindows.c: * mac/tkMacWindowMgr.c * mac/tkMacWm.c: * unix/Makefile.in: * unix/tkUnixEmbed.c: * unix/tkUnixWm.c: * win/tkWinScrlbr.c: * win/tkWinWindow.c: * win/tkWinWm.c: Implementation of TIP #47 by Neil McKay "Modifying Tk to Allow Writing X Window managers". Add CirculateRequest, Create, MapRequest, ResizeRequest, and ConfigureRequest event types; Split TK_TOPLEVEL flag into TK_TOPLEVEL, TK_HAS_WRAPPER, TK_WIN_MANAGED, and TK_TOP_HIERARCHY. [Tk patch 572978] 2002-06-14 Andreas Kupries <andreas_kupries@users.sourceforge.net> * unix/tkAppInit.c: Removed now unneeded and erroneous reference to 'matherr'. See Tcl ChangeLog entry 2002-05-31 Don Porter. 2002-06-14 David Gravereaux <davygrvy@pobox.com> * win/rules.vc: The test for compiler optimizations was in error. Thanks goes to Roy Terry <royterry@earthlink.net> for his assistance with this. 2002-06-14 Donal K. Fellows <fellowsd@cs.man.ac.uk> Implement TIP 98 [Tk patch 566765] * doc/FindPhoto.3, generic/tk.h, generic/tk.decls: * generic/tkImgPhoto.c: Changed *_Old to *_NoComposite and USE_OLD_PHOTO_PUT_BLOCK to USE_COMPOSITELESS_PHOTO_PUT_BLOCK following a suggestion from Don Porter. * tests/imgPhoto.test: Added tests of -compositingrule * doc/photo.n: Added documentation for "-compositingrule". * generic/tkImgPhoto.c (ImgPhotoCmd, ParseSubcommandOptions): New "-compositingrule" option for [$photo copy] subcommand, using OPT_COMPOSITE flag and compositingRule field in SubcommandOptions structure. * doc/FindPhoto.3: Documented the extra argument for the compositing rule and the action to take if anyone wants to maintain total backward-compatability. * generic/tk.h (TK_PHOTO_COMPOSITE_*): Defined values for use as compositing rules. (USE_OLD_PHOTO_PUT_BLOCK): Added a way for users to select the old interface to Tk_PhotoPutBlock to provide an easier upgrade path. * generic/tk.decls: Alter Tk_PhotoPut*Block to Tk_PhotoPut*Block_Old and introduce new slots for the old name of function with an extra argument at the end for the compositing rule. * generic/tkImgPhoto.c (ImgPhotoCmd): Updated "transparency set" subcommand to use TkSubtractRegion(). * win/tkWinRegion.c (TkSubtractRegion): * mac/tkMacRegion.c (TkSubtractRegion): * generic/tkInt.decls (TkSubtractRegion): * unix/tkUnixPort.h (TkSubtractRegion): Added function to perform the set-difference operation on regions; it seems all platforms can support it, and it makes removing rectangular bits from regions much easier. * generic/tkImgPPM.c (FileReadPPM): Reading a PPM/PGM always uses the SET compositing rule because it is faster and the format does not have any transparency information. * generic/tkImgGIF.c (FileReadGIF): Reading a GIF always uses the SET compositing rule because GIF files model transparency as a single special colour. * generic/tkImgPhoto.c (Tk_PhotoPutBlock, Tk_PhotoPutZoomedBlock): Added a compositing rule to allow better control over what happens to transparent pixels when inserting data into a photo image. 2002-06-13 Mo DeJong <mdejong@users.sourceforge.net> * tests/winfo.test: Add basic tests for winfo ismapped. 2002-06-13 Mo DeJong <mdejong@users.sourceforge.net> * tests/unixWm.test: * tests/wm.test: Move wm minsize and wm maxsize usage tests into the cross platform wm tests. 2002-06-13 Don Porter <dgp@users.sf.net> * tests/cursor.test: corrected error after cursor-2.2. * tests/defs.tcl: Added enhancements to Tk's fake version of tcltest required by recent cursor.test changes. 2002-06-13 Donal K. Fellows <fellowsd@cs.man.ac.uk> * tests/cursor.test (cursor-2.[34]): Tests added to ensure that cursor specs really are well-behaved lists. Also some general clean-up... * win/tkWinCursor.c (TkGetCursorByName): Undone Jeff's back-off and fixed things so that they should work now. Cursor specs are lists first and foremost. 2002-06-12 Mo DeJong <mdejong@users.sourceforge.net> * changes: Clearly label wm transient changes as a POTENTIAL INCOMPATIBILITY. * doc/wm.n: Remove "some window managers will" text and explicitly state what behavior a transient window will display. Also mention that it is an error to make a window a transient of itself. 2002-06-12 Mo DeJong <mdejong@users.sourceforge.net> * library/choosedir.tcl (tk::dialog::file::chooseDir): * library/clrpick.tcl (tk::dialog::file::chooseDir): * library/msgbox.tcl (tk::MessageBox): * library/tkfbox.tcl (tk::dialog::file): * library/xmfbox.tcl (tk::MotifFDialog): Remove the transient property on dialogs after they have been dismissed to insulate them from further state changes in the master. This keeps a withdrawn dialog from being mapped when the master is deiconified. [Tk patch 568278] 2002-06-12 Jeff Hobbs <jeffh@ActiveState.com> * win/tkWinCursor.c (TkGetCursorByName): reverted fix from 2002-06-06 because it broke the ability to use built-in cursors like left_ptr. 2002-06-12 Mo DeJong <mdejong@users.sourceforge.net> * library/choosedir.tcl (tk::dialog::file::chooseDir): * library/clrpick.tcl (tk::dialog::color): * library/dialog.tcl (tk_dialog): * library/msgbox.tcl (tk::MessageBox): * library/tkfbox.tcl (tk::dialog::file): * library/xmfbox.tcl (tk::MotifFDialog_Create): Only make the dialog window a transient if the master is visible. This check already appeared in some of the dialogs. This patch just copies the check into those that were lacking. [Tk patch 568253] 2002-06-12 Mo DeJong <mdejong@users.sourceforge.net> * changes: Add note about new transient behavior. * tests/unixWm.test: Check that the WM_TRANSIENT_FOR property for a transient window is being cleared when the master is destroyed. * tests/wm.test: Source defs.tcl instead of using tcltest to match the rest of Tk's test files. Add new tests that ensure that a transient's state mirrors the state of the master. * unix/tkUnixWm.c (WmInfo, TkWmNewWindow, TkWmMapWindow, TkWmDeadWindow, Tk_WmCmd, WmWaitMapProc): Add numTransients member to WmInfo structure. Keep state of master and transient in sync using a callback that tracks MapNotify and UnmapNotify events. When the master is mapped, map the transient. When the master is unmapped or iconified, withdraw the transient. * win/tkWinWm.c (TkWmMapWindow, TkpWmSetState, TkWmDeadWindow, Tk_WmCmd, WmWaitVisibilityOrMapProc): Keep state of master and transient in sync using a callback that tracks MapNotify and UnmapNotify events. Move masterPtr check from TkpWmSetState into TkWmMapWindow to deal with WM_NEVER_MAPPED transients. Cleanup numTransients and the callback in TkWmDeadWindow. Cleanup numTransients and the callback only after deleting a master in wm transient command to avoid deleting the callback when an error is raised. Add support for MapNotify and UnmapNotify events to the master callback. [Tk patch 561708] 2002-06-11 Joe English <jenglish@users.sf.net> * library/menu.tcl: fix for bug report #530212 "Bad Window Path Name in tkMenuFind" 2002-06-10 David Gravereaux <davygrvy@pobox.com> * win/makefile.vc: Fixed a win98 issue where the /exclude option for xcopy is unsupported. Reported by Roy Terry <royterry@earthlink.net>. 2002-06-10 Anton Kovalenko <a_kovalenko@users.sourceforge.net> * library/tk.tcl: added utility functions to get "-underline" and "-text" for labels and buttons from translatable string containing "magic ampersand" [patch #566605] * library/clrpick.tcl: * library/msgbox.tcl: * library/tkfbox.tcl: * library/xmfbox.tcl: some places where msgcat is used to get translated label are modified to handle labels with magic ampersand. * library/msgs/ru.msg: russian translations added * library/msgs/cs.msg: * library/msgs/de.msg: * library/msgs/el.msg: * library/msgs/es.msg: * library/msgs/fr.msg: * library/msgs/it.msg: * library/msgs/nl.msg: all translation files now have labels with 'magic ampersand' where appropriate. In el.msg some ampersands are missing, as I don't know which underline positions seems natural to "el" users. 2002-06-09 Mo DeJong <mdejong@users.sourceforge.net> * library/bgerror.tcl (tk::dialog::error::bgerror): Don't set the bgerror dialog as a transient of itself since this operation is ill defined. 2002-06-06 Donal K. Fellows <fellowsd@cs.man.ac.uk> * win/tkWinCursor.c (TkGetCursorByName): Fixed so that the reading of cursors from a file with a cursor spec was built using [list] works when the file has a space in instead of requiring fiddling with backslashes. 2002-06-06 Anton Kovalenko <a_kovalenko@users.sourceforge.net> * library/msgbox.tcl (MessageBox): Add -default normal when creating non-default buttons for message box. They already get -default normal when they're unfocused, and dialog window size used to change suddenly in such cases. 2002-06-05 Anton Kovalenko <a_kovalenko@users.sourceforge.net> * unix/tkUnixFont.c (Tk_DrawChars): Don't assume that one char is always one byte, and that required subfont for the last character in any string is the same as for the previous character [Bug #559435] [Patch #559437] 2002-05-27 Mo DeJong <mdejong@users.sourceforge.net> * changes: Document [wm transient .t .t] error. * tests/wm.test: Check that setting a window as a transient of itself raises an error. Check that passing a non-toplevel window to the wm transient command uses the enclosing toplevel. * unix/tkUnixWm.c (Tk_WmCmd): Raise an error if the user tries to make a toplevel a transient of itself. * win/tkWinWm.c (Tk_WmCmd): Raise an error if the user tries to make a toplevel a transient of itself. Test for other error before checking for the transient self error. 2002-05-27 Mo DeJong <mdejong@users.sourceforge.net> * unix/tkUnixWm.c (WmInfo, TkWmCleanup, TkWmNewWindow, TkWmMapWindow, TkWmDeadWindow, Tk_WmCmd): Replace WmInfo's master and masterWindowName members with a masterPtr member. This implementation is much simpler and mirrors the Win32 implementation. This change makes it easy to check the flags of the master window. No user visible changes. 2002-05-27 Mo DeJong <mdejong@users.sourceforge.net> * generic/tkInt.decls: Add unix decl for TkpWmSetState. * generic/tkIntPlatDecls.h: Regen. * generic/tkStubInit.c: Regen. * tests/wm.test: Test state changes between iconic, normal, and withdrawn both before and after initial mapping. * unix/tkUnixWm.c (Tk_WmCmd, TkpWmSetState): Move state change code into TkpWmSetState to more closely match the Win32 implementation. No user visible changes. 2002-05-27 Mo DeJong <mdejong@users.sourceforge.net> * tests/embed.test: Added cross platform embed tests. Check that window passed to -use has the -container option set. * tests/wm.test: Remove useless catch call. Deiconify . just in case, stackorder tests will not pass unless it is in the normal state. Add -container flag to embedded stackorder test. * unix/tkUnixEmbed.c (TkpUseWindow): * win/tkWinEmbed.c (TkpUseWindow): Lookup Tk window based on the id passed in as the value for -use. Generate an error if the Tk window did not have the -container option set. 2002-05-26 Peter Spjuth <peter.spjuth@space.se> * generic/tkButton.c (ConfigureButton): When creating a radiobutton with -value "" it was not drawn properly if the -variable was created by the radiobutton. [Bug #548765] 2002-05-26 Peter Spjuth <peter.spjuth@space.se> * generic/tkCanvText.c (ComputeTextBbox): Negative coordinates were rounded badly causing a 1 pixel displacement. [Bug #556526] 2002-05-24 Mo DeJong <mdejong@users.sourceforge.net> * mac/tkMacWm.c (Tk_WmCmd): * tests/unixWm.test: Move wm transient checks over to wm.test so they will be run on all systems. * tests/wm.test: Add tests to check for error when an iconwindow is passed to the wm transient command. * unix/tkUnixWm.c (Tk_WmCmd): * win/tkWinWm.c (Tk_WmCmd): Raise an error if one of the windows passed to the wm transient command is an iconwindow for another toplevel. 2002-05-23 Mo DeJong <mdejong@users.sourceforge.net> * mac/tkMacWm.c (TkWmStackorderToplevelWrapperMap): * tests/wm.test: Add embedded Window test case for the stackorder command. * unix/tkUnixWm.c (TkWmStackorderToplevelWrapperMap): * win/tkWinWm.c (TkWmStackorderToplevelWrapperMap): Ignore embedded windows during wm stackorder command. 2002-05-21 Mo DeJong <mdejong@users.sourceforge.net> * unix/configure: Regen. * unix/configure.in: Invoke SC_ENABLE_SHARED before calling SC_CONFIG_CFLAGS so that the SHARED_BUILD variable can be checked inside SC_CONFIG_CFLAGS. * unix/tcl.m4: Update from Tcl. 2002-05-20 Don Porter <dgp@users.sourceforge.net> * library/tk.tcl: A little namespace cleanup on Daniel Steffen's latest revisions to avoid defining new global commands. 2002-05-20 Daniel Steffen <das@users.sourceforge.net> * mac/tkMacInit.c: * mac/tkMacTclCode.r: include msgcat package in resources as bgerror depends on it. Restores ability of mac static build to run standalone (except for encoding file issues). * mac/tkMacInit.c: * library/console.tcl: * library/tk.tcl: fix tk.tcl not sourcing library files that define bindings at startup on mac. (independent of tk library files being in resources or on auto_path) 2002-05-08 Don Porter <dgp@users.sourceforge.net> * library/bgerror.tcl: * library/tclIndex: Cleaned up namespace usage of the bgerror dialog. Completes soft dependence on msgcat. [FR 539309] 2002-05-07 David Gravereaux <davygrvy@pobox.com> * win/makefile.vc: Problem with TCLDIR macro not accepting forward slash path seperators resolved. Added the same logic to INSTALLDIR, too. [Bug #553208] 2002-04-26 Jeff Hobbs <jeffh@ActiveState.com> * unix/configure: * unix/tcl.m4: change HP-11 SHLIB_LD_LIBS from "" to ${LIBS} so that the .sl knows its dependent libs. 2002-04-24 Daniel Steffen <das@users.sourceforge.net> * mac/tkMacTclCode.r: * mac/tkMacResource.r: added check of TCLTK_NO_LIBRARY_TEXT_RESOURCES #define to allow disabling the inclusion of the tk library code in the resource fork of Tk executables and shared libraries. Moved tk library code inclusion to separate file like in tcl. Added 'panedwindow' resource. 2002-04-22 Jeff Hobbs <jeffh@ActiveState.com> * library/button.tcl (ButtonLeave): corrected the 3 implementations of ButtonLeave to check for Priv(relief) existing before trying to use it. [Patch #541849] * generic/tkTextDisp.c (DisplayLineBackground): * unix/tkUnix3d.c (Tk_3DHorizontalBevel): * unix/tkUnixFont.c (Tk_DrawChars): applied fixes to not overrun the X window 16-bit size limit. [Patch #541999] (bonfield) 2002-04-22 Donal K. Fellows <fellowsd@cs.man.ac.uk> * generic/tkTextDisp.c (GetXView, GetYView): Comparison with previous values of scrollbar range are now done in a way that is sensitive to the bizarreness of floating-point on architectures where IEEE-FP is not used on the processor. Also increased the size of the temporary buffer to take account of the fact that TCL_DOUBLE_SPACE is meant to only imply enough space to take a printed double and trailing '\0', and no more. [Bug #223739] (FP_EQUAL_SCALE): New macro to help compare floating-point numbers for equality in a sane way, used in GetXView and GetYView. 2002-04-12 Jeff Hobbs <jeffh@ActiveState.com> * generic/tkWindow.c (TkCloseDisplay): Added to centralize where a display was closed. This handles freeing memory associated with a display and closing it. (DeleteWindowsExitProc): actually close displays. This would also ideally be done in Tk_DestroyWindow when the last window on the display has been closed, but that still has unresolved order of cleanup problems. (Tk_DestroyWindow): added TkFocusFree call. * generic/tkStubInit.c: * generic/tkIntPlatDecls.h: * generic/tkIntDecls.h: * generic/tkInt.decls: added TkFocusFree, TkClipCleanup and TkGCCleanup generic private procs, and TkWmCleanup, TkSendCleanup and TkFreeXId unix private procs. * generic/tkInt.h: * unix/tkUnixXId.c (TkFreeXId): frees XID resources. Made idCleanupScheduled a Tcl_TimerToken (was int) in TkDisplay structure to allow us to delete the timer scheduled for it. * unix/tkUnixWm.c (TkWmStackorderToplevel): ensure children structure is freed. (ConfigureEvent, ComputeReparentGeometry): Add extra wm tracing info (TkWmRestackToplevel): initialize changes to 0 to prevent UMR. Use WaitForConfigureNotify on all windows. This part still requires fixing as it is the root of the 2 second raise delay on some window managers (those that use extra wrapper windows of their own). * unix/tkUnixSend.c (TkSendCleanup): free send-related resources * unix/tkUnixEvent.c (TkpCloseDisplay): call TkSendCleanup and TkWmCleanup. * unix/tkUnixSelect.c (SelRcvIncrProc): added missing Tcl_Release of interp * generic/tkGet.c (FreeUidThreadExitProc): free thread-specific resources on thread exit * generic/tkFocus.c (TkFocusFree): frees TkMainInfo data * generic/tkClipboard.c (TkClipCleanup): frees TkDisplay data * generic/tkGC.c (TkGCCleanup): frees TkDisplay data * unix/tkUnixFont.c (FontPkgCleanup): cleanup thread specific font resources on thread exit. * mac/tkMacXStubs.c (TkpOpenDisplay): memset the initial display structures to 0. * generic/tkOption.c (OptionThreadExitProc): freed tsd option stacks on thread exit. (Tk_GetOption): free mem used to get Tk_Uid * generic/tkMenu.c (ConfigureMenu): freed saved options in all error cases. * win/tkWinInt.h: declaration for TkWinGetUnicodeEncoding * win/tkWinDialog.c (GetFileNameW): use TkWinGetUnicodeEncoding * win/tkWinInit.c (TkpDisplayWarning): use TkWinGetUnicodeEncoding * win/tkWinFont.c: use TkWinGetUnicodeEncoding instead of static unicodeEncoding. * win/tkWinX.c (Tk_SetCaretPos): remove WM_IME_STARTCOMPOSITION and place the IME position within Tk_SetCaretPos. Cache results in Tk_SetCaretPos to reduce unnecessary repositioning. Also call DestroyCaret if we receive WM_KILLFOCUS. (TkpOpenDisplay): ZeroMemory the initial display structures. (TkWinGetUnicodeEncoding): Added so that Windows only needs to cache this value one, and then free it in TkWinXCleanup. (HandleIMEComposition): add support for Win98 and ATOK13 IME. (yamamoto) * generic/tkConsole.c (ConsoleCmd): correct return that should have just set result code. * generic/tkImgPhoto.c: Added PhotoFormatThreadExitProc to clean up on thread exit. (Tk_PhotoPutBlock) slight code updates * generic/tkPanedWindow.c (DestroyPanedWindow, ConfigureSlaves): fix mem leaks in not freeing slave info * win/configure: * win/tcl.m4: Enabled COFF as well as CV style debug info with --enable-symbols to allow Dr. Watson users to see function info. More info on debugging levels can be obtained at: http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp 2002-04-10 Mo DeJong <mdejong@users.sourceforge.net> * doc/wm.n: * mac/tkMacWm.c: * tests/wm.test: * unix/tkUnixWm.c: * win/tkWinWm.c: Update wm stackorder usage message to make it clear that either 1 or 3 arguments are required. [Bug 540013] 2002-04-08 Daniel Steffen <das@users.sourceforge.net> * mac/tkMacProjects.sea.hqx: added tkPanedWindow.c to projects * mac/tkMacAppInit.c: fixes to MSL stdin/stdout hookup to the TkConsole when using shared MSL libraries; fix for crashing bug on exit: writing to stdin/sterr when console has already been destroyed. (both fixes need support in MSL, see 'CW Pro6 changes' in tcl/mac/tcltkMacBuildSupport.sea.hqx) * mac/tkMacDialog.c: fixes to Navigation Services Dialog filter. * mac/tkMacDraw.c: add panic for overwide TkImages that would crash Tk on mac otherwise. 2002-04-05 Jeff Hobbs <jeffh@ActiveState.com> * mac/tkMacXStubs.c: added Tk_SetCaretPos stub (does nothing). * win/tkWinX.c: added Tk_SetCaretPos code to position IME windows correctly when WM_IME_STARTCOMPOSITION is received. * unix/tkUnixKey.c: added Tk_SetCaretPos and code for setting XIM caret in TkpGetString. * generic/tkStubInit.c: * generic/tkDecls.h: * generic/tk.decls: added Tk_SetCaretPos declaration. This command allows users to indicate the cursor position and is used by XIM (Unix) or IME (Windows) to place the caret box correctly. It is also part of correct Accessibility style on Windows to make the magnifier jump to the focus point. * win/tkWinButton.c (TkpDisplayButton): * generic/tkTextMark.c (TkTextInsertDisplayProc): * generic/tkCanvText.c (DisplayCanvText): * generic/tkEntry.c (DisplayEntry): added Tk_SetCaretPos calls * generic/tkInt.h: added TK_XIM_SPOT #define (default 1). Added XFontSet attribute to TkDisplay when TK_XIM_SPOT is true. * generic/tkEvent.c (Tk_HandleEvent): made sure inputContexts are not getting created on DestroyNotify events (for dead windows). Added over-the-spot support if TK_XIM_SPOT is defined (default). The is the nicer XIM behavior, but uses a bit more memory. * unix/tkUnixEvent.c: * generic/tkWindow.c: moved OpenIM over to tkUnixEvent.c. Removed setting inputContext to null in Tk_MakeWindowExist as it was redundant. * unix/tkUnixWm.c (CreateWrapper): Removed redundat setting of inputContext to null. * win/Makefile.in: changed gdb and shell targets to properly build all binaries before running (otherwise an error often occured). 2002-03-28 David Gravereaux <davygrvy@pobox.com> * win/.cvsignore (new): * win/lamp.bmp (new): * win/makefile.vc: * win/nmakehlp.c (new): * win/rules.vc: Brought the makefile up-to-date with Tcl's one. This now has support for Win9x issues and the winhelp target now exists. Color scheme can be changed. I'm just imparting a first suggestion using orange :) I'll have to think about the install portion of the helpfile as I'll need to do some tricks to insert tk's contents file into Tcl's using some special winhlp32.exe switches. [Bug 533862 527941] * win/makefile.vc: Tk helpfile is now installing itself into Tcl's contents file as part of the install target and rebuilding the contents table as desired. [Bug 527941] * doc/console.n: Changed topic from "Tcl Built-In Commands" to "Tk Built-In Commands" * win/buildall.vc.bat: Update to match Tcl. 2002-03-26 Andreas Kupries <andreask_kupries@users.sourceforge.net> * unix/tkUnixFont.c: Added inclusion of <arpa/inet.h>. This fixes a GCC/HPUX problem with missing a "htons". See also "tclUnixPort.h" for equivalent code. 2002-03-21 David Gravereaux <davygrvy@pobox.com> * win/makefile.vc: Changed optimize flag to -0ti instead of -02. [Bug 528441] 2002-03-20 Don Porter <dgp@users.sourceforge.net> * generic/tkButton.c (ButtonTextVarProc,ButtonVarProc): * generic/tkCmds.c (WaitVariableProc): * generic/tkEntry.c (EntryTextVarProc): * generic/tkListbox.c (ListboxListVarProc): * generic/tkMenu.c (MenuVarProc): * generic/tkMenubutton.c (MenuButtonTextVarProc): * generic/tkMessage.c (MessageTextVarProc): * generic/tkScale.c (ScaleVarProc): Updates to handle change in type of part2 argument of Tcl_VarTraceProc typedef. [TIP 27] [Patch 532644]. 2002-03-19 Jeff Hobbs <jeffh@ActiveState.com> * generic/tkOldConfig.c (Tk_ConfigureValue): prevent leaving interp->result as NULL. 2002-03-07 Donal K. Fellows <fellowsd@cs.man.ac.uk> * library/text.tcl (TextPasteSelection): Renaming of TextPaste to prevent confusion with tk_textPaste. Stopped code from inserting selections twice, which seems to have happened with TIP#26, and reorganized code to reduce amount of stuff protected by catch which is tricky to maintain. (tk_textPaste): Reduce amount of code protected by catch. 2002-03-06 Mo DeJong <mdejong@users.sourceforge.net> * win/tkWinX.c: Define _WIN32_IE as 0x0300 before including commctrl.h so that we can access the InitCommonControlsEx API when building Tk with mingw. 2002-03-06 Donal K. Fellows <fellowsd@cs.man.ac.uk> * README, generic/tk.h, unix/configure.in, unix/tk.spec: * win/configure.in: Bumped patchlevel; this might need to change in the future, but it will help us distinguish between the CVS version and the most recent released version. 2002-03-05 Jeff Hobbs <jeffh@ActiveState.com> *** 8.4a4 TAGGED FOR RELEASE *** * unix/README: updated --* options docs. * unix/tk.spec: fixed URL refs to use www.tcl.tk or SF. 2002-03-04 Jeff Hobbs <jeffh@ActiveState.com> * README: * mac/README: * unix/README: * win/README: updated to use www.tcl.tk URL. 2002-03-03 Jeff Hobbs <jeffh@ActiveState.com> * library/entry.tcl: added catch around Triple-1 binding use of sel.last 2002-02-28 Don Porter <dgp@users.sourceforge.net> * library/console.tcl (ConsoleBind): Corrected console <<Paste>> binding on Unix platforms. 2002-02-26 Jeff Hobbs <jeffh@ActiveState.com> * unix/configure: Regen. * unix/tcl.m4: Update from Tcl. * generic/tkWindow.c (Tk_MainWindow, Tk_GetNumMainWindows): protect against being called before Tcl stubs are init'ed. [Bug #220916] (porter) 2002-02-25 Jeff Hobbs <jeffh@ActiveState.com> * generic/tkText.c (ConfigureText): reenable the blinking cursor on state change where necessary. [Bug #503772] * tests/listbox.test: * generic/tkListbox.c: corrected error handling when setting to an invalid listvar value. [Bug #503613] * library/scale.tcl: mirror B2 bindings to B3 on Windows to better accomodate two button mice. [Patch #493145] * library/panedwindow.tcl: improved proxy sash handling. (boudaillier) 2002-02-25 Donal K. Fellows <fellowsd@cs.man.ac.uk> * tests/filebox.test: Reorganised and fixed so that tests are executed fewer times (!) and the automatic extension adding behaviour of tk_getSaveFile is tested. 2002-02-23 Mo DeJong <mdejong@users.sourceforge.net> * unix/configure: Regen. * unix/tcl.m4: Update from Tcl. 2002-02-22 Jeff Hobbs <jeffh@ActiveState.com> * generic/tkPanedWindow.c (PanedWindowWidgetObjCmd): fixed returns that should have been breaks instead. Corrected .pw configure handling for insufficient args. [Patch #521436] (boudaillier) * mac/tkMacDefault.h: * unix/tkUnixDefault.h: * win/tkWinDefault.h: changed panedwindow default relief to flat, a more natural outer relief. * library/panedwindow.tcl (ReleaseSash): changed to not pass x and y args at all (they aren't used). Added proc comments. Made configuring sash cursor more efficient. Added Cursor timer that restores the default cursor when pointer is no longer over the sash. This is necessary because Leave events won't be seen when moving into a paned child. 2002-02-22 Donal K. Fellows <fellowsd@cs.man.ac.uk> * library/demos/widget: New section "Paned Windows" * library/demos/paned2.tcl, library/demos/paned1.tcl: New files. * library/panedwindow.tcl (ReleaseSash): Added missing arguments. * library/tk.tcl: Bindings for paned window were not being loaded by default. * unix/tkUnixMenu.c (GetMenuLabelGeometry,DrawMenuEntryLabel): Stop meaningless GCC warnings. 2002-02-21 Jeff Hobbs <jeffh@ActiveState.com> * doc/panedwindow.n (new): * generic/tkPanedWindow.c (new): * generic/tkInt.h: * generic/tkWindow.c: * library/panedwindow.tcl (new): * mac/tkMacDefault.h: * tests/panedwindow.test (new): * unix/Makefile.in: * unix/tkUnixDefault.h: * win/Makefile.in: * win/makefile.vc: * win/tkWinDefault.h: added implementation of TIP #41, panedwindow widget. [Patch #512503] (melski) * generic/tkOption.c (ReadOptionFile): fixed Tcl_Seek casting to remove warnings (we expect no option files with be > 2GB). * unix/configure: regenerated * unix/tcl.m4: updated to sync with Tcl's tcl.m4 Added --enable-64bit support for AIX-4 using IBM's xlc (-q64 flag). 2002-02-19 Don Porter <dgp@users.sourceforge.net> * changes: First draft of updated changes for 8.4a4 release. 2002-02-19 Donal K. Fellows <fellowsd@cs.man.ac.uk> * generic/tkImgPhoto.c (MatchFileFormat): Tcl_Seek takes Tcl_WideInt offset (three places.) * generic/tkImgPPM.c (FileReadPPM): Tcl_Seek takes Tcl_WideInt offset. * generic/tkFrame.c (ConfigureFrame): Stop GCC warning. * generic/tkImgGIF.c: Made file meet the formatting rules from the Tcl Engineering Manual better; mostly differences in whitespace. 2002-02-18 Jeff Hobbs <jeffh@ActiveState.com> * unix/configure: regen'd * unix/tcl.m4: * unix/configure.in: added macros and calls to SC_TCL_EARLY_FLAGS and SC_TCL_64BIT_FLAGS, part of TIP #72. 2002-02-14 Mo DeJong <mdejong@users.sourceforge.net> * library/entry.tcl: * library/text.tcl: Adjust <Double-1> and <Triple-1> bindings so that no anchor point is set and the insertion cursor is set to the last character in the selection. [Bug 220943] * tests/event.test: Add test cases for double click and drag as well as triple click and drag in the text and entry widgets. 2002-02-14 Mo DeJong <mdejong@users.sourceforge.net> * tests/event.test (_text_ind_to_x_y, _get_selection): Fix incorrect use of results from bbox invocation so that y center point for a give index is calculated correctly. Add new method to return the selection and use it in test cases. Always lappend to the result list to avoid case where initial result includes a space. 2002-02-07 Don Porter <dgp@users.sourceforge.net> * generic/tkMain.c: * mac/tkMacInit.c: * mac/tkMacKeyboard.c: * win/tkWinDialog.c: * win/tkWinTest.c: modified some callers of Tcl routines that were restored to return (char *) pointing into Tcl_DStrings. 2002-02-03 eric melski <ericm@interwoven.com> * generic/tkImage.c (Tk_ImageObjCmd): Clean up bogus for loop in [image inuse] subcommand [Bug #485803]. 2002-02-01 Jeff Hobbs <jeffh@ActiveState.com> * generic/tkCmds.c (Tk_TkObjCmd): don't use 'bool' as an arg as it conflicts with the C99 spec. [Bug #511956] (ingham) 2002-02-01 David Gravereaux <davygrvy@pobox.com> * win/makefile.vc: unset macro located in the tktest target caused a failure to build. [Bug 511652] 2002-01-30 Don Porter <dgp@users.sourceforge.net> * win/stubs.c (XSetCommand): Overlooked CONSTification. 2002-02-01 Donal K. Fellows <fellowsd@cs.man.ac.uk> * doc/photo.n: Documented transparency subcommand. * tests/imgPhoto.test (imgPhoto-4.40...imgPhoto-4.68): Tests for the transparency subcommand. * generic/tkImgPhoto.c (ImgPhotoCmd): Added transparency subcommand (see TIP #14.) 2002-01-31 Todd Helfter <tmh@users.sourceforge.net> * generic/tkMenu.c (ConfigureMenuCloneEntries) * tests/menu.test (menu3.68) Correct and test for logic error when cloning menus. [Bug #508988] 2002-01-30 Don Porter <dgp@users.sourceforge.net> * generic/tk.decls: The POTENTIAL INCOMPATIBILITY in the changing interface of Tk_ParseArgv can now be removed by the -DUSE_NON_CONST compiler flag. * generic/tkDecls.h: make genstubs 2002-01-29 Andreas Kupries <andreas_kupries@users.sourceforge.net> * win/tkWinInit.c (TkpGetAppName): TIP 27 fixup. The code now does not write into the CONST path returned by "argv0" and Tcl_SplitPath anymore. 2002-01-28 Mo DeJong <mdejong@users.sourceforge.net> * unix/configure: Regen. * unix/configure.in: Don't set TCL_LIB_SPEC and TCL_STUB_LIB_SPEC variables since this breaks the AIX build. This was used in the past to support linking with Tcl from the build dir or the install dir, but it is no longer needed. 2002-01-28 Mo DeJong <mdejong@users.sourceforge.net> * unix/Makefile.in: Remove commented out vars. * unix/configure: Regen. * unix/configure.in: Don't subst vars that are already taken care of in SC_LOAD_TCLCONFIG. * unix/tcl.m4: Update from Tcl. * win/configure: Regen. * win/tcl.m4: Update from Tcl. 2001-01-27 Daniel Steffen <das@users.sourceforge.net> * generic/tkFileFilter.c: * mac/tkMacInit.c: * mac/tkMacKeyboard.c: * mac/tkMacMenus.c: TIP 27 CONSTification induced changes 2002-01-25 Don Porter <dgp@users.sourceforge.net> * All changes below are Patch 505159 * doc/AddOption.3: * doc/CanvTkWin.3: * doc/GetPixels.3: * doc/Name.3: * doc/ParseArgv.3: * generic/tk.decls (Tk_AddOption,Tk_CanvasGetCoord,Tk_GetPixels, Tk_GetScreenMM,Tk_NameToWindow,Tk_ParseArgv): * generic/tkArgv.c (Tk_ParseArgv): * generic/tkCanvLine.c (ParseArrowShape): * generic/tkCanvUtil.c (Tk_CanvasGetCoord,Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc,Tk_GetDash): * generic/tkCanvas.c (ConfigureCanvas): * generic/tkGet.c (Tk_GetPixels,Tk_GetScreenMM): * generic/tkImgPhoto.c (ImgPhotoCmd): * generic/tkMain.c (Tk_MainEx): * generic/tkOldConfig.c (FormatConfigInfo): * generic/tkOption.c (Tk_AddOption): * generic/tkText.c (TextWidgetCmd,TkTextGetTabs,DumpSegment): * generic/tkText.h (TkTextCreateTag): * generic/tkTextTag.c (TkTextCreateTag): * generic/tkWindow.c (Tk_NameToWindow,Initialize): * mac/tkMacCursor.c (FindCursorByName,TkGetCursorByName): * mac/tkMacWm.c (Tk_WmCmd): * unix/tkUnixCursor.c (TkGetCursorByName): * unix/tkUnixSend.c (ValidateName): * unix/tkUnixWm.c (Tk_WmCmd): * win/tkWinCursor.c (TkGetCursorByName): * win/tkWinWm.c (Tk_WmCmd): Updated callers of Tcl_SplitList and Tcl_Merge. * generic/tkDecls.h: make genstubs ***POTENTIAL INCOMPATIBILITY*** Includes a source incompatibility in the argv argument of Tcl_ParseArgv. * generic/tkBind.c (DeleteVirtualEvent): * generic/tkCanvas.c (ScrollFractions, CanvasWidgetCmd, CanvasUpdateScrollbars): * generic/tkTestTag.c (TkTextTagCmd): Updated callers of Tcl_GetStringResult. Rewrote PrintScrollFractions to ScrollFractions to stop scribbling directly on interp->result. * generic/tkInt.decls (TkGetDefaultScreenName, TkpDisplayWarning, TkpOpenDisplay): * generic/tkCanvPs.c (Tk_PostscriptColor, Tk_PostscriptFont): * generic/tkEntry.c (EntrySetValue, EntryValidateChange, ExpandPercents, EntryValueChanged, Tk_EntryObjCmd, DestroyEntry, ConfigureEntry, EntryComputeGeometry, InsertChars, DeleteChars, EntryFetchSelection, EntryTextVarProc, Tk_SpinBoxObjCmd, SpinboxWidgetObjCmd): * generic/tkMain.c (Prompt): * generic/tkMenu.c (MenuVarProc): * generic/tkMenubutton.c (ConfigureMenuButton, MenuButtonTextVarProc): * generic/tkMessage.c (ConfigureMessage, MessageTextVarProc): * generic/tkWindow.c (GetScreen, Initialize): * mac/tkMacInit.c (TkpInit, TkpDisplayWarning): * mac/tkMacXStubs.c (TkGetDefaultScreenName, TkpOpenDisplay): * unix/tkUnix.c (TkGetDefaultScreenName): * unix/tkUnixEvent.c (TkpOpenDisplay): * unix/tkUnixInit.c (TkpGetAppName, TkpDisplayWarning): * unix/tkUnixSend.c (SendEventProc): * win/tkWinInit.c (TkpGetAppName, TkpDisplayWarning): * win/tkWinX.c (TkGetDefaultScreenName,TkpOpenDisplay): Updated callers of Tcl_GetVar, Tcl_GetVar2 * generic/tkIntDecls.h: make genstubs * generic/tkCanvPs.c (TkCanvPostscriptCmd): * generic/tkImgBmap.c (TkGetBitmapData): * generic/tkOption.c (ReadOptionFile): * mac/tkMacInit.c (TkpInit, TkpGetAppName): * win/tkWinInit.c (TkpGetAppName): Updated callers of Tcl_SplitPath, Tcl_JoinPath, and Tcl_TranslateFileName. 2002-01-18 Mo DeJong <mdejong@users.sourceforge.net> * tests/wm.test: Rewrite stackorder tests that deal with toplevels that have the overrideredirect flag set. [Tk bug 492259] 2002-01-18 Don Porter <dgp@users.sourceforge.net> * win/tkWinDialog.c: Overlooked Tcl_GetIndexFromObj callers. 2001-01-18 Daniel Steffen <das@users.sourceforge.net> * mac/tkMacDialog.c: * mac/tkMacSend.c: TIP 27 CONSTification broke the mac build in a few places. 2002-01-16 Jeff Hobbs <jeffh@ActiveState.com> * generic/tkListbox.c (ChangeListboxOffset): improved tracking when scrolling on x axis with entry/text. [Bug #225025] (voskuil) 2002-01-16 Don Porter <dgp@users.sourceforge.net> * generic/tk3d.c (Tk_GetReliefFromObj): * generic/tkBind.c (Tk_EventObjCmd,HandleEventGenerate): * generic/tkButton.c (ButtonWidgetObjCmd): * generic/tkCanvas.c (CanvasWidgetCmd,FindItems): * generic/tkClipboard.c (Tk_ClipboardObjCmd): * generic/tkCmds.c (Tk_BellObjCmd, Tk_TkObjCmd, Tk_TkwaitObjCmd, Tk_UpdateObjCmd, Tk_WinfoObjCmd, Tk_WmObjCmd): * generic/tkConfig.c (DoObjConfig): * generic/tkEntry.c (EntryWidgetObjCmd, SpinboxWidgetObjCmd): * generic/tkFocus.c (Tk_FocusObjCmd): * generic/tkFont.c (Tk_FocusObjCmd, ConfigAttributesObj): * generic/tkFrame.c (Tk_FrameObjCmd): * generic/tkGet.c (Tk_GetAnchorFromObj, Tk_GetJustifyFromObj): * generic/tkGrab.c (Tk_GrabObjCmd): * generic/tkGrid.c (Tk_GridObjCmd,GridRowColumnConfigureCommand, GridSlavesCommand, ConfigureSlaves): * generic/tkImage.c (Tk_ImageObjCmd): * generic/tkImgBmap.c (ImgBmapCmd): * generic/tkImgGIF.c (FileReadGIF): * generic/tkImgPhoto.c (ImgPhotoCmd): * generic/tkListbox.c (ListboxWidgetObjCmd, ListboxSelectionSubCmd, GetListboxIndex): * generic/tkMenu.c (MenuWidgetObjCmd, MenuAddOrInsert, MenuCmd, ConfigureMenu, CloneMenu): * generic/tkMenubutton.c (MenuButtonWidgetObjCmd): * generic/tkMessage.c (MessageWidgetObjCmd): * generic/tkOption.c (Tk_OptionObjCmd): * generic/tkPack.c (Tk_PackObjCmd, ConfigureSlaves): * generic/tkPlace.c (Tk_PlaceObjCmd): * generic/tkScale.c (ScaleWidgetObjCmd): * generic/tkSelect.c (Tk_SelectionObjCmd): * generic/tkSquare.c (SquareWidgetObjCmd): * generic/tkTest.c (TestobjconfigObjCmd, TrivialConfigObjCmd, TestfontObjCmd): Updates to handle change in type of tablePtr argument of Tcl_GetIndexFromObj(Struct) from (char **) to (CONST char **). [TIP 27] [Patch 504705] * generic/tkCanvText.c (GetSelText): * generic/tkEntry.c (Entry{FetchSelection,Setvalue},ExpandPercents): * generic/tkSelect.c (HandleTclCommand): * generic/tkText.c (TextSearchCmd): * generic/tkTextIndex.c (TkTextMakeByteIndex, TkTextIndexBackChars): * mac/tkMacFont.c (Tk_MeasureChars, BreakLine): * unix/tkUnixMenu.c (DrawMenuUnderline): * win/tkWinMenu.c (GetEntryText, DrawMenuUnderline): Updated callers of Tcl_Utf* and Tcl_Regexp* APIs to reflect TIP 27 API changes (see Tcl Patch 471509). [Patch 471513] 2002-01-16 Mo DeJong <mdejong@users.sourceforge.net> * unix/configure: Regen. * unix/tcl.m4: Update from Tcl. * win/configure: Regen. * win/tcl.m4: Update from Tcl. 2002-01-04 Don Porter <dgp@users.sourceforge.net> * generic/tkMain.c (Tk_MainEx): Updated callers of CONSTified Tcl interfaces Tcl_EvalFile and TclGetStartupScriptFileName. * generic/tkConsole.c (ConsoleOutputProc, TkConsolePrint): * generic/tkInt.h (TkConsolePrint): * mac/tkMacAppInit.c (TkConsolePrint): Updated Tk's console to CONSTified channel driver interface. [Tcl Patch 503565, Tk Patch 503983] 2002-01-11 Mo DeJong <mdejong@users.sourceforge.net> Use ${libdir} instead of ${exec_prefix}/lib. [Tcl bug 489370] * unix/configure: Regen. * unix/configure.in: Define and use libdir. * win/configure: Regen. * win/configure.in: Define libdir. 2002-01-11 Mo DeJong <mdejong@users.sourceforge.net> * unix/Makefile.in: Burn Tcl and Tk build directories into tktest executable to avoid crashes caused by ld loading a previously installed version of the tcl or tk shared libraries. Remove setting of LD_LIBRARY_PATH, LIBPATH, and SHLIB_PATH before running tktest since it should no longer be required. 2002-01-11 Mo DeJong <mdejong@users.sourceforge.net> Enable use of Tcl stubs when building Tk as a shared library. This should fix the build under AIX. [Bugs 220858, 220955, 220921] * unix/Makefile.in: Add TCL_STUB_LIB_SPEC and TCL_STUB_LIB_FLAG variables. * unix/configure: Regen. * unix/configure.in: Pass TCL_STUB_LIB_SPEC into Makefile and use it when linking the tk shared library. Define USE_TCL_STUBS when building shared. Subst TCL_STUB_LIB_SPEC and TCL_STUB_LIB_FLAG. 2002-01-08 D. Richard Hipp <drh@hwaci.com> * win/tkWinMenu.c: Fix the following bug: If you select an entry on a cascade menu then the next time the parent menu is posted, the cascade entry was active. Also, if you traverse to a disabled entry using keystrokes and press ENTER on the disabled entry, then that entry appears active the next time the menu is posted. The same patch fixes both problems. 2002-01-04 Don Porter <dgp@users.sourceforge.net> * generic/tkBind.c (TkBindFree): * generic/tkGrid.c (ResolveConstraints,CheckSlotData,DestroyGrid): * generic/tkSelect.c (Tk_DeleteSelHandler,TkSelDeadWindow): Replaced Tcl_Free calls with ckfree so that memory debugging is fully supported. 2001-12-28 Jeff Hobbs <jeffh@ActiveState.com> * test/winButton.test: * win/tkWinButton.c: added updated patch #463234 which returns the default sizing behavior (not so native), but enables native L&F with negative sizing (-11 for example). * library/text.tcl (tk::TextButton1): made text receive focus even in disabled state for Windows to show selection and allow mouse-wheel scrolling. * win/tkWinInit.c (TkpDisplayWarning): added Tcl_DStringFree's * win/tkWinInt.h: * win/tkWinX.c: added TkWinProcs that represent a function table to switch between unicode and ansi procs on Windows. This is analogous to the TclWinProcs. Using Tcl_WinUtfToTChar, we can easily take advantage of using unicode functions where available without having to switch on the platform id each time. * win/tkWinWm.c (InitWindowClass): corrected init routines to allow unicode in window titles on Windows (for Win2K/XP). (TkWmStackorderToplevel): Corrected casts to enable debug compile * win/configure: regen'ed * win/tcl.m4: added shell32.lib to link libs, as these are necessary for new directory chooser (when enabled). * win/tkWinDialog.c (Tk_MessageBoxObjCmd): use MessageBoxW for proper display of unicode errors. Added patch which uses new OLE based directory chooser. This still has some issues, so is disabled by default. [Patch #468139] (ColorDlgHookProc) Corrected ability to use unicode chars in tk_chooseColor -title. 2001-12-27 Jeff Hobbs <jeffh@ActiveState.com> * win/tkWinInit.c (TkpDisplayWarning): Use MessageBoxW in case the error displayed has unicode chars. [Bug #485986] 2001-12-27 Daniel Steffen <das@users.sourceforge.net> * mac/tkMacInit.c: * mac/tkMacResource.r: synced up tkInit features to unix/win: use existing tkInit proc if defined. Added spinbox.tcl resource. Used TclGetEnv() instead of Tcl_GetVar2(interp, env) * mac/tkMacApplication.r: * mac/tkMacLibrary.r: minor version resources cleanup 2001-12-27 Jeff Hobbs <jeffh@ActiveState.com> * generic/tkButton.c (ButtonTextVarProc): guard against being called while the *button/label is being deleted. [Bug #490051] * library/entry.tcl: * library/spinbox.tcl: * library/text.tcl: added extra checks against bug #220269 and made spinbox reuse more of the entry procedure code. 2001-12-20 Mo DeJong <mdejong@users.sourceforge.net> * unix/configure: Regen. * unix/tcl.m4: Update from Tcl. 2001-12-19 Mo DeJong <mdejong@users.sourceforge.net> * unix/configure: Regen. * unix/tcl.m4: Update from Tcl. 2001-12-18 Mo DeJong <mdejong@users.sourceforge.net> * unix/configure: Regen. * unix/configure.in: Move EXP file changes over from Tcl configure script to fix AIX build with gcc. [Bug 220955] 2001-12-18 Mo DeJong <mdejong@users.sourceforge.net> * unix/Makefile.in: * win/Makefile.in: Use $(MAKE) instead of make in the tcltest rule. 2001-12-18 Don Porter <dgp@users.sourceforge.net> * tests/event.test (event-click-drag-1.2): Corrected test that failed on Solaris/CDE due to text scrolling. [Bug 413735] 2001-12-18 Jeff Hobbs <jeffh@ActiveState.com> * library/spinbox.tcl (ButtonDown): added catch to ignore possible error in after cancel when Priv(afterId) isn't defined. * doc/spinbox.n: corrected spin(up|down) -> button(up|down) 2001-12-14 Donal K. Fellows <fellowsd@cs.man.ac.uk> * doc/getOpenFile.n: Documented change. * library/tkfbox.tcl (SetFilter): Added code to guess the correct default extension from whatever value was selected in the filetypes option menu. Adapted from code by Chris Nelson submitted in Patch #492220. 2001-12-12 Jeff Hobbs <jeffh@ActiveState.com> * unix/tkUnixWm.c (TkWmStackorderToplevelWrapperMap): added static 2001-12-05 Jeff Hobbs <jeffh@ActiveState.com> * generic/tkText.c: * generic/tkText.h: changed TkTextEditType enums to be prefaced with TK_EDIT_ to prevent name collision. 2001-12-05 Daniel Steffen <das@users.sourceforge.net> * mac/tkMacWm.c: mac implementation of wm stackorder (patch 481148, TIP 74) 2001-12-03 Mo DeJong <mdejong@users.sourceforge.net> Add TK patch 481148 to implement TIP 74, the wm stackorder command. * doc/winfo.n: Update documentation for the winfo children command to indicate that top-level windows are not returned in stacking order. * doc/wm.n: Add documentation for wm stackorder. * generic/tkInt.decls (TkWmStackorderToplevel): Add decl for new function. * generic/tkIntDecls.h: Regen. * generic/tkStubInit.c: Regen. * tests/unixWm.test: Add stackorder command to test for wm command usage message. * tests/wm.test: Add new set of tests for generic window manager methods. * unix/tkUnixWm.c (Tk_WmCmd, TkWmStackorderToplevelWrapperMap, TkWmStackorderToplevel): Add unix implementation of new wm stackorder command. * win/tkWinWm.c (Tk_WmCmd, TkWmStackorderToplevelEnumProc, TkWmStackorderToplevelWrapperMap, TkWmStackorderToplevel): Add windows implementation of new wm stackorder command. 2001-12-03 David Gravereaux <davygrvy@pobox.com> * win/makefile.vc: install target changes by request from Ryan Casey <scfiead@hotmail.com>. 2001-11-30 Donal K. Fellows <fellowsd@cs.man.ac.uk> * library/demos/widget: Further overhauling; shrank fonts, made better use of fonts, added an icon, fixed the About box. Prompted by Bug #487442 from Vincent Wartelle. 2001-11-29 Donal K. Fellows <fellowsd@cs.man.ac.uk> * library/palette.tcl (tk_setPalette): Added heuristic to guess from the background whether to use black or white for the foreground when not told specifically. Suggested by Chris Nelson, this makes the command fit the documentation better! 2001-11-27 David Gravereaux <davygrvy@pobox.com> * win/makefile.vc: Fixed CAT32 target. cat.c is located in the Tcl source, not the Tk source. 2001-11-27 D. Richard Hipp <drh@hwaci.com> * library/menu.tcl: Do not allow keyboard traversal of torn-off menus to visit the (invisible) tearoff bar. 2001-11-26 D. Richard Hipp <drh@hwaci.com> * win/tkWinMenu.c: disabled menu items show the activebackground color in their background. This change makes menu behavior consistent with what native windows does. 2001-11-24 Mo DeJong <mdejong@users.sourceforge.net> * unix/Makefile.in: Add comments to better describe TCL_EXE and when it should be available. Add rule that prints message about running `make genstubs` when tkStubInit.c is out of date. * win/Makefile.in: Add TCL_TOOL_DIR and TCL_EXE variables to better match the Tcl Makefile. Add genstubs rule so tkSTubInit.c can be regenerated. 2001-11-24 Mo DeJong <mdejong@users.sourceforge.net> * win/configure: Regen. * win/configure.in: Don't AC_SUBST CFLAGS_DEBUG, CFLAGS_OPTIMIZE, or CFLAGS_WARNING since it is now done in SC_CONFIG_CFLAGS. * win/tcl.m4 (SC_CONFIG_CFLAGS): AC_SUBST DL_LIBS, CFLAGS_DEBUG, CFLAGS_OPTIMIZE, and CFLAGS_WARNING. 2001-11-23 Daniel Steffen <das@users.sourceforge.net> Up-port to 8.4 of mac code changes for 8.3.3 & various new changes for 8.4, some already backported to 8.3.4 (patch #435660) * library/tk.tcl: added <Key-F1> binding for <<Undo>> on the mac (TIP26) * library/button.tcl: fixed undefined $Priv(repeated) error for button without -repeatdelay support * generic/tkConsole.c: * library/console.tcl: * mac/tkMacInit.c: * mac/tkMacResource.r: corrected how mac deals with tcl library files present both in resources and in $tk_library directory. * generic/tkConsole.c: crashing bug fix when printing to console at program exit after the console has already been closed. Now setting gStdoutInterp=NULL in ConsoleClose(). * mac/tkMacInit.c: correct use of Tcl_JoinPath in tk_library initialization * mac/tkMacMenu.c: special MDEF_PROC_OFFSET only needed for exactly one specific version of the MWERKS 68k compiler . * mac/tkMacShLib.exp: removed file * unix/Makefile.in: removed reference to .exp files * mac/MWTkBuildLibHeader.h: * mac/MW_TkBuildLibHeader.pch: * mac/MW_TkHeaderCommon.h: * mac/MW_TkOldImgStaticHeader.h: * mac/MW_TkStaticHeader.h: * mac/MW_TkStaticHeader.pch: new precompiled header files * mac/MW_TkHeader.pch: * mac/MW_TkOldImgHeader.h: * mac/MW_TkTestHeader.pch: revised precompiled header handling: now include a common header file 'MW_TkHeaderCommon.h' from all .pch files, the .pch files themselves now only setup #defines (e.g. BUILD_tk, STATIC_BUILD, TCL_DEBUG, TCL_THREADS) like in makefiles on other platforms. * mac/tkMac.h: * mac/tkMacPort.h: * mac/tkMacInt.h: use of BUILD_tk and TCL_STORAGE_CLASS like on other platforms, standardize #include'd files to what's done on other platforms, removed use of #pragma export, changed extern to EXTERN where appropriate to enable DLL export via the TCL_STORAGE_CLASS mechanism. * mac/tkMacAppearanceStubs.c: removed use of #pragma export * mac/widget.r: new resource file for 'Widget Demos' * mac/tkMacProjects.sea.hqx: updated mac build project files: build support for CodeWarrior Pro6, UnivIntf 3.4 & shared runtime libraries (see Tcl ChangeLog for details). changed weak linking so that CFM68k binaries now work on all OS versions from the free 7.5.5 onwards, with or without AppearanceMgr and/or NavigationMgr installed. added target to automatically build 'Widget Demos' included XML versions of the projects for CW Pro5 or Pro7 users. use compat/strtod.c instead of MSL's strtod() * generic/tkInt.decls: * generic/tkIntDecls.h: * generic/tkIntPlatDecls.h: * generic/tkStubInit.c: * mac/tkMacInt.h: MAC_TCL tk stub support was badly broken due to multiply defined (mac specific) names in tk.decls and tkInt.decls, removed the duplicates from the internal unsupported interfaces "interface tkInt" and "interface tkIntPlat"; moved declaration of TkpIsWindowFloating from tkMacInt.h to tkInt.decls: interface tkIntPlat. - these changes to the stub tables might require you to recompile your Tk extensions if they turn out to reference one of the removed routines in the wrong table (should be unlikely). * generic/tkMain.c: MAC_TCL: workaround for broken/non-standard isatty on MW Pro6, #include <unistd.h> instead of defining isatty * generic/tkPointer.c: MAC_TCL: #include tkMacInt.h * generic/tkStubLib.c: MAC_TCL: removed obsolete special casing of mac headers, standardize #include'd files to what's done on other platforms * mac/tclets.r: * mac/tkMacWindowMgr.c: * mac/tkMacScrlbr.c: * mac/tkMacMenu.c: * mac/tkMacMenus.c: * mac/tkMacFont.c: * mac/tkMacDialog.c: * mac/tkMacButton.c: renamed obsolete apple API names to modern equivalents; UH3.4 support: added #include <ControlDefinitions.h>; fixed munged non-ASCII chars in sources due to bungled latin1<->mac roman encoding in CVS repository. * mac/tkMacDialog.c: added support for -filetypes option (fix for bug tcl #221636); added update event handling for background windows while in a NavigationMgr dialog; fixed nasty bug when calling CustomGetFile (missing addr operator) (fix for bug tk #220911 & tcl #219367); renamed routines conflicting with standard MoreFiles headers (see Tcl ChangeLog for details) * mac/tkMacApplication.r: * mac/tkMacLibrary.r: * mac/tkMacResource.r: fixed obsolete copyrights/dates in version strings, updated version strings to standard usage, added support for '(Support Libraries)' subfolder for shared runtime libraries in unmerged binaries, commented out demo setting of "Tcl Environment Variables"; reorganized resources among these files to avoid multiple copies in applications and shared libraries, the script libraries/Xcursors etc are now no longer duplicated in Wish but are only included in the resources of Tk.shlb. * mac/tkMacMenu.c: * mac/tkMacMDEF.r: changes to support MW Pro 6 68k (vers 0x2400 only) compiler producing different offset to start of MDEF; fix to static 68k presence testing when calling the custom MDEF * mac/tkMacWm.c.c: * mac/tkMacWindowMgr.c: added/fixed AppearanceMgr checks; override AppearanceMgr version detection on static 68k to ensure static 68k Wish runs on PPCs with recent AppearanceMgr * mac/tkMacButton.c: fixed misplaced/missing variable initialization. 2001-11-20 Jeff Hobbs <jeffh@ActiveState.com> * generic/tkText.c (TextGetText): reworked to use DString for improved speed. (callewaert, darley) (DestroyText): plugged mem leak when not clearing stack (callewaert) (TextGetText): more efficient string size calculation (darley) 2001-11-19 Donal K. Fellows <fellowsd@cs.man.ac.uk> * library/demos/entry3.tcl: New demo showing off validation and password entry. * library/demos/widget: Some reorganization to make the code simpler, plus a new entry demo. 2001-11-17 Jeff Hobbs <jeffh@ActiveState.com> * win/tkWinButton.c (TkpComputeButtonGeometry): corrected the default size of Windows buttons to conform to the Windows style. This changes the default size of buttons on Windows. [Patch #463234] (nelson) **** POTENTIAL VISUAL INCOMPATABILITY **** 2001-11-16 Jeff Hobbs <jeffh@ActiveState.com> * library/menu.tcl: corrected menu traversal code on Unix to better handle entering cascades. [Patch #481219] (oleinick) 2001-11-16 David Gravereaux <davygrvy@pobox.com> * win/makefile.vc: Install target repaired. 2001-11-15 Donal K. Fellows <fellowsd@cs.man.ac.uk> * library/demos/image2.tcl: Many improvements to this image-viewing demo; now uses labelframes and tk_chooseDirectory * library/palette.tcl (::tk::RecolorTree): Made this work better with CDE, which does some extremely annoying things with the option database that interact badly with Tk's way of handling options. * doc/text.n: Overhauled the documentation of undo to make it easier to understand. * library/tk.tcl (::tk::EventMotifBindings): Added Emacs-like undo binding, but not behaviour (we separate undo and redo.) * library/demos/text.tcl: Show off our undo capability! 2001-11-12 David Gravereaux <davygrvy@pobox.com> * win/mkd.bat: * win/rmd.bat: Removed -kb CVS attribute and added changes from Llyod Lim for better stability. [Patch #456761] * win/rules.vc(new): * win/buildall.vc.bat(new): * win/makefile.vc: large rewrite following Tcl's makefile.vc as a guide and Patch #456761. Appears BugFree(tm). 2001-11-12 Jeff Hobbs <jeffh@ActiveState.com> * doc/text.n: * generic/tkText.c: * generic/tkText.h: * generic/tkTextTag.c: * library/text.tcl: * library/tk.tcl: * mac/tkMacDefault.h: * tests/text.test: * unix/tkUnixDefault.h: * win/tkWinDefault.h: added TIP #26 implementation of simple built-in undo/redo of text editing in the text widget. [Patch #458879] (callewaert) 2001-11-12 Donal K. Fellows <fellowsd@cs.man.ac.uk> * library/demos/menu.tcl: Show off -compound support in menus. * library/demos/radio.tcl: Added some code to both show off the extra capabilities of the buttons and also show what can be done with compound images on the sly. 2001-11-10 Mo DeJong <mdejong@users.sourceforge.net> * unix/Makefile.in: * win/Makefile.in: Add "make gdb" target. This target can run wish inside either gdb or insight. 2001-11-09 Jeff Hobbs <jeffh@ActiveState.com> * library/clrpick.tcl: changed a few parameters so that the full 0..255 range could be accessed via the mouse. [Bug #478498] * unix/configure: * unix/tcl.m4: added -lc to AIX libs, fixed path to ldAix * win/configure: * win/tcl.m4: * win/makefile.vc: add comctl32.lib to build libs. * win/tkWinX.c (TkWinXInit): added InitCommonControlsEx call. * win/rc/tk.rc: * win/rc/wish.rc: * win/rc/wish.exe.manifest: added resources that specify using v6 of the MS Common Controls library when available (WinXP+). This enables use of the themeable widgets (like scrollbars) to be used in Tk. [Patch #478933] 2001-11-09 Mo DeJong <mdejong@users.sourceforge.net> * unix/configure: * unix/tcl.m4: Update from Tcl. 2001-11-08 Mo DeJong <mdejong@users.sourceforge.net> * unix/Makefile.in: Avoid adding libc to the LIBS and WISH_LIBS variables since it is not needed when linking with CC. If required when linking with LD it should be done on a case by case basis in tcl.m4. 2001-11-05 Donal K. Fellows <fellowsd@cs.man.ac.uk> * library/demos/dialog2.tcl: Typo-fix. * library/demos/browse, library/demos/ixset, library/demos/rolodex: Installation does version number fixup, so we shouldn't. Thanks to wohnivec@iol.cz for pointing these (thankfully minor) problems out. 2001-10-30 Donal K. Fellows <fellowsd@cs.man.ac.uk> * library/demos/widget: Integrated labelframe item into the labels section and added a spinbox demo to the (retitled) entry section. * library/demos/labelframe.tcl: Adjusted so as to show off the labelframe widget to better effect and have a better description. * library/demos/spin.tcl: New demo to show off spinbox capabilities. * library/demos/rolodex: Changes up-ported from core-8-3-1-branch to make the script use more 8.*-isms, but not menus due to the way the context help system works. * library/demos/ixset: Changed to use the labelframe widget and the grid geometry manager. 2001-10-29 Donal K. Fellows <fellowsd@cs.man.ac.uk> * library/demos/browse: Changes up-ported from core-8-3-1-branch to make the script much more robust, particularly when neither the current version of wish or the script are on the path. * library/demos/hello: Added emacs trailing tag-line. * library/demos/tcolor: Changes up-ported from core-8-3-1-branch to make the script compliant with current good practise, as well as extensive use of the new labelframe widget. * library/demos/timer: Changes up-ported from core-8-3-1-branch to make the script look and work better. * library/demos/rmt: Changes up-ported from core-8-3-1-branch to use more 8.* features and make the demo script more generally useful to people. 2001-10-23 Donal K. Fellows <fellowsd@cs.man.ac.uk> * generic/tkCursor.c (Tk_GetCursorFromData): Fixed uninit nextPtr field. [adapted from Patch 473875] (GetCursor): Removed double-assignment to nextPtr field. 2001-10-19 Jeff Hobbs <jeffh@ActiveState.com> * library/console.tcl: removed transpose ability until the console can get a proper rewrite of tag handling. 2001-10-18 Jeff Hobbs <jeffh@ActiveState.com> * tests/defs.tcl: removed threaded build warning under X. * library/console.tcl (ConsoleOutput): fixed undefined widget argument. 2001-10-16 Jeff Hobbs <jeffh@ActiveState.com> * library/xmfbox.tcl: fixed filtering in motif file dialog. [Patch #469670] (nelson) * generic/tkWindow.c (OpenIM): Added simple XIM patch to enable basic XIM input on Unix. [Patch #412727] (fabian) 2001-10-15 Jeff Hobbs <jeffh@ActiveState.com> * unix/configure: * unix/configure.in: * win/configure: * win/configure.in: * win/tkConfig.sh.in: reworked to be a little cleaner in comparison to each other, and to AC_SUBST even empty vars for win/tkConfig.sh 2001-10-12 Todd M. Helfter <tmh@purdue.edu> * ChangeLog: * doc/menu.n: * generic/tkMenu.c: * generic/tkMenu.h: * generic/tkMenubutton.c: * generic/tkMenubutton.h: * mac/tkMacDefault.h: * mac/tkMacMenu.c: * mac/tkMacMenubutton.c: * tests/menu.test: * unix/tkUnixDefault.h: * unix/tkUnixMenu.c: * win/makefile.vc: * win/tkWinDefault.h: * win/tkWinMenu.c: * win/tkWinWm.c: Implementation of TIP #63, the addition of a -compound option to menu entries allowing text and an image to be displayed at the same time. 2001-10-09 Jeff Hobbs <jeffh@ActiveState.com> * library/console.tcl: added more smarts extracted from tkcon to the default console. 2001-10-01 Jeff Hobbs <jeffh@ActiveState.com> * win/tkWinTest.c: better error reporting from testclipboard * win/tkWinDialog.c: minor cast changes to support Win64 * win/tkWinWindow.c: made use of standard Tk_GetHWND instead of older, private TkWinGetHWND. * win/configure: regen'ed * win/tcl.m4: * win/makefile.vc: updated for Win64 SDK RC1 compilation support 2001-09-30 Peter Spjuth <peter.spjuth@space.se> * doc/grid.n: * generic/tkGrid.c: * tests/grid.test: Added -uniform option to grid's row/column- configure. [TIP 37] [Patch 459343] 2001-09-26 Peter Spjuth <peter.spjuth@space.se> * win/tkWinFont.c (Tk_DrawChars): Added support for clipping text. * doc/frame.n: * doc/labelframe.n: * doc/toplevel.n: * generic/tkFrame.c: * generic/tkInt.h: * generic/tkWindow.c: * library/demos/radio.tcl: * library/demos/labelframe.tcl: * library/demos/widget: * mac/tkMacDefault.h: * tests/frame.test: * unix/tkUnixDefault.h: * win/tkWinDefault.h: Added labelframe widget. Added -padx/y options to frame and toplevel. * tests/grid.test: * tests/pack.test: * tests/place.test: Used labelframe to test geometry manager changes. [TIP 18] [Patch 429164] 2001-09-26 Peter Spjuth <peter.spjuth@space.se> * doc/GeomReq.3: * doc/WindowId.3: * generic/tk.decls: * generic/tk.h: * generic/tkDecls.h: * generic/tkGeometry.c: * generic/tkGrid.c (ArrangeGrid): * generic/tkInt.h: * generic/tkPack.c (ArrangePacking): * generic/tkPlace.c (RecomputePlacement): * generic/tkStubInit.c: * generic/tkUtil.c (TkComputeAnchor): * generic/tkWindow.c (TkAllocWindow): * unix/mkLinks: Geometry manager changes to support TIP#18. Allows a widget to set different internal border widths on different sides, and to set a minimum requested size. POTENTIAL INCOMPATIBILITY. [Patch 429164] 2001-09-25 Don Porter <dgp@users.sourceforge.net> * generic/tkBind.c: * generic/tkInt.decls (TkpScanWindowId): * unix/tkUnixPort.h (Tkp{Print,Scan}WindowId): * unix/tkUnixXId.c (TkpScanWindowId): * win/tkWinWindow.c (TkpScanWindowId): Corrected definition of TkpScanWindowId to handle situation where types Window and int do not have the same number of bits. CONST-ified too. * generic/tkIntPlatDecls.h: * generic/tkStubInit.c: make genstubs 2001-09-24 Don Porter <dgp@users.sourceforge.net> * generic/tkMain.c (StdinProc): Update to handle change in return type of Tcl_DStringAppend() from (char *) to (CONST char *). [TIP 27] 2001-09-23 Peter Spjuth <peter.spjuth@space.se> * generic/tkPack.c (ConfigureSlaves): * tests/pack.test: * tests/grid.test: Pack accepted asymmetric values for -ipadx/y. Only -padx/y supports asymmetry. [Bug #462348] 2001-09-21 Jeff Hobbs <jeffh@ActiveState.com> * win/tkWinWindow.c (TkpPrintWindowId, TkpScanWindowId): fixed to work on Win64 with 64bit XIDs. * generic/tkWindow.c (Tk_CreateAnonymousWindow): * generic/tkEntry.c (GetSpinboxElement): fixed unreachable returns. * win/tkWinX.c (TkGetServerInfo): added recognition of Win64. * xlib/X11/X.h: made XID __int64 type for Win64. * unix/tkUnixPort.h: * mac/tkMacPort.h: add (int*) cast to TkpScanWindowId. These may need to be changed to Window* (ulong). * generic/tkCmds.c (Tk_WinfoObjCmd): * generic/tkBind.c (NameToWindow): correct Window id's to be of type Window * generic/tkIntDecls.h: * generic/tkIntPlatDecls.h: * generic/tkInt.decls (TkpScanWindowId): changed decl to use Window* instead of int*. * xlib/xcolors.c: * generic/tkPack.c,tkWindow.c: * win/tkWinFont.c,tkWinMenu.c: * unix/tkUnixScale.c: minor cast fixes to prevent 64bit warnings. * tests/scrollbar.test (scrollbar-6.27): marked knownBug because it is skewed by bad dimensions returned by Windows. * tests/textDisp.test (textDisp-4.12): corrected test to work properly on Windows. * tests/id.test,macFont.test,macMenu.test,macscrollbar.test: * tests/send.test,winClipboard.test,winDialog.test,winFont.test: improved use of test constraints * win/tkWinWm.c (WinSetIcon): fixed SetClassLong for 64bit support. 2001-09-20 Jeff Hobbs <jeffh@ActiveState.com> * unix/configure: regen'ed * unix/tcl.m4: added --enable-64bit support for HP-11 with the 64-bit kernel. 2001-09-17 Don Porter <dgp@users.sourceforge.net> * generic/tkGrid.c (ConfigureSlaves): * generic/tkPack.c (PackAfter): Corrected type definition of argument passed to Tcl_GetStringFromObj() from size_t to int. Incorrect type broke [pack] and [grid] on systems where sizeof(size_t) != sizeof(int). [Bugs 462375, 462342, 462338] 2001-09-17 Donal K. Fellows <fellowsd@cs.man.ac.uk> * library/choosedir.tcl (DblClick): * library/tkfbox.tcl (OkCmd, ListInvoke): Rewrote so as to avoid the highly confusing string "text" and to be consistent about what is and what is not a list. [Bug 459895, reported by fandom] 2001-09-14 Andreas Kupries <andreas_kupries@users.sourceforge.net> * generic/tkImgGIF.c: * generic/tkImgPPM.c: * generic/tkImgPhoto.c: * generic/tkMenu.c: Applied patch [461578], provided by Vincent Darley. This fixes several memory leaks in the image code. They happen if there are errors during the initialization of the channel the image is supposed to be read from. 2001-09-12 Mo DeJong <mdejong@users.sourceforge.net> * unix/configure: * unix/tcl.m4: Update from Tcl. 2001-09-12 D. Richard Hipp <drh@hwaci.com> * library/tkfbox.tcl: fixed error that appeared when you would click on the canvas while viewing an empty directory. 2001-09-10 Mo DeJong <mdejong@users.sourceforge.net> * unix/configure: * unix/tcl.m4: Update from Tcl. 2001-09-09 Mo DeJong <mdejong@users.sourceforge.net> * win/Makefile.in: Fix Windows Makefile so that tcltest will automatically be compiled if the user tries to build tktest. 2001-09-09 Mo DeJong <mdejong@users.sourceforge.net> * win/Makefile.in: Use TKTEST variable directly instead of depending on the tktest alias. 2001-09-08 Mo DeJong <mdejong@users.sourceforge.net> * win/mkd.bat: * win/rmd.bat: Apply binary property (cvs admin -kb) to files and convert to CRLF linefeed format to fix the VC++ build. [Tcl Bug #219409] 2001-08-29 Jeff Hobbs <jeffh@ActiveState.com> * tests/menu.test: * tests/send.test: * tests/select.test: corrected to use testConfig constraints in the TK_ALT_DISPLAY case * tests/unixSend.test: removed test file completely identical to send.test. Removed platform specific named file in case somebody gets send working on Win/Mac in the future. * tests/config.test: added config-14.1 to test namespace import evaluation of widgets. * generic/tkButton.c (ButtonCreate): * generic/tkFrame.c (CreateFrame): * generic/tkMenubutton.c (Tk_MenubuttonObjCmd): * generic/tkPlace.c (Tk_PlaceObjCmd): * generic/tkScale.c (Tk_ScaleObjCmd): * generic/tkMessage.c (Tk_MessageObjCmd): * generic/tkEntry.c (Tk_EntryObjCmd, Tk_SpinboxObjCmd): * generic/tkSquare.c (SquareObjCmd): redid the handling of optionTables in widgets to allow them to be imported into other namespaces. [Bug #456632] 2001-08-28 Jeff Hobbs <jeffh@ActiveState.com> * win/tkWinDialog.c (ChooseDirectoryHookProc): work-around for MS bug that caused crashing in tk_chooseDirectory on Win95. [Bug #224936] (baker) * unix/tkUnixWm.c (TkWmRestackToplevel): reworked how ConfigureNotify requests were handled in relation to the parent to avoid the problem with potential 'raise' delays on some wms. [Bug #220260] (baker) wms that were affected should notice the difference in tests unixWm-51.* not failing that failed before. 2001-08-26 Don Porter <dgp@users.sourceforge.net> * library/text.tcl (<Shift-Up> binding): Corrected TIP 44 typo that broke binding. Thanks to "Michal" for the fix. [Bug 455468] 2001-08-23 Jeff Hobbs <jeffh@ActiveState.com> * unix/configure: * unix/tcl.m4: added QNX-6 build support. [Bug #219410] (loverso) * doc/CrtPhImgFmt.3: removed bogus note about including tkPhoto.h 2001-08-22 Peter Spjuth <peter.spjuth@space.se> * generics/tkGrid.c (ConfigureSlaves): * tests/grid.test: Fixed a bug where adjacent 'x' and '^' where not handled properly. [Bug #452040] 2001-08-22 Jeff Hobbs <jeffh@ActiveState.com> * generic/tkPack.c (TkParsePadAmount): added lint init for sepChar. * tests/dialog.test (HitReturn): fixed failing dialog-2.1 test because it wasn't always getting focus properly. 2001-08-21 Jeff Hobbs <jeffh@ActiveState.com> * tests/unixFont.test (unixFont-2.[234]): fixed to be more sensitive on systems that have more installed fonts. * library/dialog.tcl (tk_dialog): changed dialog to show bar on Windows as well and added some y padding between the buttons and the bar. [Patch #442835] (harrismh) 2001-08-20 Peter Spjuth <peter.spjuth@space.se> * generic/tkInt.h: * generic/tkWindow.c: * generic/tkGrid.c: * generic/tkPack.c: * tests/grid.test: * tests/oldpack.test: * tests/pack.test: Objectified grid and pack commands. 2001-08-20 Donal K. Fellows <fellowsd@cs.man.ac.uk> * generic/tkObj.c (TkGetWindowFromObj): Rewrote window code to reuse a previously worked-out set of window information exactly when the reference window is the same and no window deletions have occurred since the object was allocated (display has same epoch counter.) Required changing the internal rep of the window quite a bit as now need to save three words-worth of information in the internal rep (this window, reference window, display epoch.) * generic/tkObj.c (SetWindowFromAny, DupWindowInternalRep, FreeWindowInternalRep): Code to support new internal rep for window objects. * generic/tkInt.h: Added epoch counter to TkDisplay structure * generic/tkWindow.c (GetScreen, Tk_DestroyWindow): Epoch counter is incremented every time a window is deleted. 2001-08-18 Peter Spjuth <peter.spjuth@space.se> * doc/grid.n: * tests/grid.test: * generic/tkGrid.c: Grid configure rejected initial "x" and "^". [Bug #418664] 2001-08-17 Donal K. Fellows <fellowsd@cs.man.ac.uk> * generic/tkObj.c (TkGetWindowFromObj): Was failing to reuse cached window objects, forcing a call to Tcl_GetStringFromObj and Tk_NameToWindow every time. This fault has been in there for nearly three years... 2001-08-15 Don Porter <dgp@users.sourceforge.net> * changes: Labelled the TIP 44 changes as "POTENTIAL INCOMPATIBILITY". Although technically internal changes are not incompatible, they'll be perceived as such by those who get bitten, and this will help them find the cause of their trouble. 2001-08-14 Donal K. Fellows <fellowsd@cs.man.ac.uk> * generic/tk{Util,Font,Cursor,Color,Bitmap,3d}.c: Modified objtype declarations so that they can be picked up in tkObj.c and the names are now prefixed with "tk" too. * generic/tkObj.c (TkRegisterObjTypes): * generic/tkWindow.c (Initialize): * generic/tkInt.h: Added code to register Tk's object types with the Tcl runtime. [Tcl Bug 450545] 2001-08-12 Mo DeJong <mdejong@redhat.com> * unix/configure: Regen. * unix/tcl.m4: Update from Tcl. 2001-08-10 Donal K. Fellows <fellowsd@cs.man.ac.uk> * library/demos/image2.tcl (loadDir): Converted non-portable [glob [file join $dirName *]] to [glob -directory $dirName *] which is both fully portable and more reliable when directory names contain glob-significant characters. [Bug 223313] 2001-08-08 Don Porter <dgp@users.sourceforge.net> * tests/dialog.test: New file testing [tk_dialog]. * library/dialog.tcl: * library/tkfbox.tcl: Corrections to problems introduced by the TIP 44 changes. [Bug 449261] * README: * generic/tk.h: * unix/configure: * unix/configure.in: * unix/tk.spec: * win/configure: * win/configure.in: Bumped up patchlevel to 8.4a4 to distinguish CVS snapshots from the 8.4a3 release. This does not necessarily mean there will be an 8.4a4 release. [Bug 448938]. 2001-08-07 Jeff Hobbs <jeffh@ActiveState.com> * unix/Makefile.in (dist): added {unix,win}/tcl.m4 and library/msgs/*.msg to dist target. [Bug: #448802] 2001-08-06 Jeff Hobbs <jeffh@ActiveState.com> 8.4a3 RELEASE * changes: * README: updated for 8.4a3 release * unix/configure: regenerated * unix/tcl.m4: added GNU (HURD) configuration target. (brinkmann) [Patch: #442974] 2001-08-06 Don Porter <dgp@users.sourceforge.net> * generic/tkConsole.c: * generic/tkWindow.c: * library/bgerror.tcl: * library/dialog.tcl: * library/msgbox.tcl: * library/unsupported.tcl: * mac/tclets.tcl: * mac/tkMacHLEvents.c: * mac/tkMacWm.c: TIP 44 changes specific to the Mac and Windows platforms that were overlooked before: tkOpenDocument, tkConsoleExit, tkConsoleOutput, unsupported1 out of namespace :: . Thanks to Vince Darley for prompting another look. 2001-08-03 Jeff Hobbs <jeffh@ActiveState.com> * win/winMain.c (WishPanic): fixed CONST changes to go with CONST-ification in Tcl. * win/configure: regenerated * win/tcl.m4: fixed DLLSUFFIX definition to always be ${DBGX}.dll. This is necessary for TEA compliant builds that build shared against a static-built Tk. * win/Makefile.in ($(WISH)): added $(TK_STUB_LIB_FILE) to build target, otherwise it wouldn't get generated in a static build. 2001-08-01 Don Porter <dgp@users.sourceforge.net> * doc/console.n: * doc/menu.n: * doc/text.n: * doc/tkvars.n: * generic/tkBind.c: * generic/tkMenu.c: * library/bgerror.tcl: * library/button.tcl: * library/choosedir.tcl: * library/clrpick.tcl: * library/comdlg.tcl: * library/console.tcl: * library/dialog.tcl: * library/entry.tcl: * library/focus.tcl: * library/listbox.tcl: * library/menu.tcl: * library/msgbox.tcl: * library/optMenu.tcl: * library/palette.tcl: * library/scale.tcl: * library/scrlbar.tcl: * library/spinbox.tcl: * library/tclIndex: * library/tearoff.tcl: * library/text.tcl: * library/tk.tcl: * library/tkfbox.tcl: * library/unsupported.tcl: * library/xmfbox.tcl: * mac/tkMacMenu.c: * tests/clrpick.test: * tests/filebox.test: * tests/macMenu.test: * tests/menu.test: * tests/menuDraw.test: * tests/msgbox.test: * tests/text.test: * tests/unixMenu.test: * tests/winMenu.test: * tests/xmfbox.test: * unix/mkLinks: * unix/tkUnixDialog.c: Merged changes from feature branch dgp-privates-into-namespace, implementing TIP 44. All Tk commands and variables matching tk[A-Z]* are now in the ::tk namespace. See "BRANCH: dgp-privates-into-namespace" entries below for details. [FR 220936] 2001-07-24 Mo DeJong <mdejong@redhat.com> * generic/default.h: Include tkWinDefault.h when built with Cygwin or Mingw. 2001-07-18 Don Porter <dgp@users.sourceforge.net> BRANCH dgp-privates-into-namespace: * doc/console.n: Updated names of private console commands. 2001-07-16 Don Porter <dgp@users.sourceforge.net> BRANCH dgp-privates-into-namespace: * library/console.tcl: * library/unsupported.tcl: Renamed tk::histNum to tk::HistNum as directed by the Tcl Style Guide. 2001-07-10 Mo DeJong <mdejong@redhat.com> * unix/Makefile.in: Add AR and STLIB_LD variables. * unix/configure: * unix/configure.in: Use STLIB_LD when defining MAKE_LIB and MAKE_STUB_LIB. Subst STLIB_LD, RANLIB, and AR. * unix/tcl.m4: Update from Tcl. * win/configure: Regen. * win/tcl.m4: Update from Tcl. 2001-07-06 Mo DeJong <mdejong@redhat.com> * win/configure: Regen. * win/tcl.m4: Update from Tcl. 2001-07-05 Mo DeJong <mdejong@redhat.com> * win/Makefile.in: Subst DEPARG directly instead of relying on a variable. This will make Cygwin build faster since an extra exec will be avoided. * win/configure: Regen. * win/configure.in: Subst DEPARG. * win/tcl.m4: Update from Tcl. 2001-07-04 Jeff Hobbs <jeffh@ActiveState.com> * README: * mac/README: * unix/README: * win/README: updated READMEs with purls 2001-07-03 Jeff Hobbs <jeffh@ActiveState.com> * tests/canvas.test: * generic/tkCanvPoly.c (PolygonToArea): Added patch that respects the polygon difference of including points in the polygon even when fill is empty. [Bug #226357] 2001-07-03 Mo DeJong <mdejong@redhat.com> * win/Makefile.in: Remove PATHTYPE variable. * win/configure: Regen. * win/configure.in: Don't subst PATHTYPE. * win/tcl.m4: Update from Tcl. 2001-07-03 Mo DeJong <mdejong@redhat.com> * win/Makefile.in: Don't use VPSEP, instead just use : in the VPATH. * win/configure: Regen. * win/configure.in: Don't subst VPSEP. 2001-07-03 Donal K. Fellows <fellowsd@cs.man.ac.uk> * library/xmfbox.tcl (tkMotifFDialog_ActivateSEnt): Added missing backslash [Bug #438247] 2001-07-02 Jeff Hobbs <jeffh@ActiveState.com> * generic/tkWindow.c (Tk_DestroyWindow): changed to use Tcl_EventuallyFree instead of ckfree so that widgets that have references to a tkwin can use them. * generic/tkCanvArc.c: * generic/tkCanvBmap.c: * generic/tkCanvLine.c: * generic/tkCanvPoly.c: * generic/tkCanvText.c: * generic/tkCanvWind.c: * generic/tkRectOval.c: corrected argument handling in Create<Item> functions that could lead to ABRs or FMRs and corrected names of argc/argv to objc/objv. * generic/tkImgGIF.c (Mgetc): corrected screwy use of ternary operator and possible FMR. * generic/tkEntry.c: corrected missing Tcl_Release that caused font not freed complaints when trying valid cleanup calls. * generic/tkListbox.c: made use of Tcl_Preserve/Tcl_Release to prevent FMR errors in Display functions. * unix/tkUnixScale.c (TkpDisplayScale): corrected FMR when scale was deleted while calling its command. * library/console.tcl: * library/entry.tcl: * library/spinbox.tcl: * library/text.tcl: * library/tk.tcl: added private ::tk::GetSelection command to handle requesting selection. This is to support requesting UTF8_STRING before generic STRING on Unix. Changed Text, Spinbox, Entry and Console to use this command. * tests/select.test: * generic/tkSelect.c (Tk_CreateSelHandler, Tk_DeleteSelHandler): on Unix, a UTF8_STRING handler will be created when the user requests a STRING handler (in addition to the STRING handler). This provides implicit support for the new UTF8_STRING selection target. * unix/tkUnixSelect.c (TkSelEventProc, ConvertSelection): Added support for UTF8_STRING target. [RFE #418653, Patch #433283] * generic/tkInt.h: added utf8Atom to TkDisplay structure. * tests/listbox.test: changed 'darkblue' to 'white' in a test because it isn't a portable color name. * generic/tkEntry.c (DestroyEntry): used Tcl_EventuallyFree instead of ckfree for entryPtr to prevent FMRs. [Bug #413904] 2001-06-26 Mo DeJong <mdejong@redhat.com> * unix/Makefile.in: * win/Makefile.in: Add `make shell` target. This target will set the proper env vars before invoking wish from the build directory. 2001-06-26 Mo DeJong <mdejong@redhat.com> * win/configure: * win/configure.in: Revert cross compiling change accidently added during last checkin. 2001-06-26 Mo DeJong <mdejong@redhat.com> * unix/configure: Regen. * unix/configure.in: Fix last checkin by removing export since that only works in bash. * win/configure: Regen. * win/configure.in: Ditto. 2001-06-26 Mo DeJong <mdejong@redhat.com> * unix/configure: Regen. * unix/configure.in: Set CFLAGS to "" if the user did not set CFLAGS in the env. This keeps AC_PROG_CC from adding "-g -O2" to the CFLAGS by default. * win/configure: Regen. * win/configure.in: Ditto. 2001-06-22 Mo DeJong <mdejong@redhat.com> * win/configure: Regen. * win/configure.in: Use RC_DEFINE flag from tcl.m4. * win/tcl.m4: Update from Tcl. 2001-06-22 Mo DeJong <mdejong@redhat.com> * win/configure: Regen. * win/tcl.m4: Update from Tcl. 2001-06-22 Mo DeJong <mdejong@redhat.com> * win/configure: Regen. * win/tcl.m4 (SC_CONFIG_CFLAGS): Link to the imm32 library when building with mingw gcc. * win/tkWinX.c: Include the imm.h header to fix compiling with mingw gcc. 2001-06-22 Mo DeJong <mdejong@redhat.com> * win/configure: Regen. * win/configure.in: Add resource compiler fix from 8.3.3 to fix compiling with mingw. 2001-06-22 Mo DeJong <mdejong@redhat.com> * win/configure: Regen. * win/tcl.m4: Fix silly typo in last checkin. 2001-06-22 Mo DeJong <mdejong@redhat.com> * unix/Makefile.in: Set CFLAGS to @CFLAGS@ and @CFLAGS_DEFAULT@. Set LDFLAGS to @LDFLAGS@ and @LDFLAGS_DEFAULT@. Add LDFLAGS_DEBUG and LDFLAGS_OPTIMIZE to match the way CFLAGS_DEFAULT works. Use new LDFLAGS variable in the Makefile instead of @LDFLAGS@. * unix/configure: Regen. * unix/configure.in: Don't set CFLAGS to CFLAGS_DEFAULT, instead subst CFLAGS_DEFAULT into the Makefile. Add AC_SUBST for CFLAGS_DEBUG, CFLAGS_OPTIMIZE, LDFLAGS_DEFAULT, LDFLAGS_DEBUG, and LDFLAGS_OPTIMIZE. Remove unused LD_FLAGS subst. * unix/tcl.m4: Update from Tcl. * win/Makefile.in: Set CFLAGS to @CFLAGS@ and @CFLAGS_DEFAULT@. Set LDFLAGS to @LDFLAGS@ and @LDFLAGS_DEFAULT@. * win/configure: Regen. * win/configure.in: Don't set CFLAGS or LDFLAGS, instead subst CFLAGS_DEFAULT and LDFLAGS_DEFAULT into the Makefile. * win/tcl.m4: Update from Tcl. 2001-06-22 Mo DeJong <mdejong@redhat.com> * win/configure: * win/tcl.m4: Update From Tcl. 2001-06-21 eric melski <ericm@interwoven.com> * doc/colors.n: Corrected bogus documentation with respect to several shades of blue, all of which were listed as RGB 0 0 0. [Bug #432104]. 2001-06-14 Donal K. Fellows <fellowsd@cs.man.ac.uk> * library/demos/floor.tcl, library/demos/filebox.tcl, * library/demos/clrpick.tcl, library/demos/vscale.tcl, * library/demos/twind.tcl, library/demos/ruler.tcl, * library/demos/plot.tcl, library/demos/items.tcl, * library/demos/hscale.tcl, library/demos/ctext.tcl, * library/demos/cscroll.tcl, library/demos/arrow.tcl, * library/xmfbox.tcl, library/msgbox.tcl, * library/clrpick.tcl, library/bgerror.tcl: Braced expressions. 2001-06-06 Mo DeJong <mdejong@redhat.com> * win/configure: Regen. * win/configure.in: Handle the --prefix option correctly it should default to /usr/local like the unix version. 2001-06-03 Jeff Hobbs <jeffh@ActiveState.com> * doc/selection.n: * doc/clipboard.n: added SEE ALSOs to cross-reference selection and clipboard, with extra note for clipboard command in selection docs. [Patch #422256] * unix/tkUnixFont.c: Corrected support for iso10646 (X11 Unicode) fonts on Unix. This adds a ucs-2be (UCS-2 Big Endian) encoding in Tk on Unix that is used for those fonts (X11 requires big-endianness). (welch) [Patch #406411; Bug #220890 #220899] This differs from the 8.3.3 patch by not adding ucs-2be in the preferred encodingList (seems works fine without). Added alias for jisx0201* fonts to jis0201 encoding. [Bug #414033] 2001-05-30 Jeff Hobbs <jeffh@ActiveState.com> * win/tkWinKey.c (TkpSetKeycodeAndState): removed old debug info 2001-05-29 Jeff Hobbs <jeffh@ActiveState.com> * win/tkWinX.c: moved the initialization of tkPlatformId from TkWinXInit to TkWinGetPlatformId because static builds could call it before it was initialized. [Bug #427278] 2001-05-28 Peter Spjuth <peter.spjuth@space.se> * generic/tkFrame.c: * generic/tkWindow.c: * tests/frame.test: Upgraded frame to use the newer TK_OPTION style when processing configuration options. Some cleanup of bad comments and bad code. [part of patch #420861] 2001-05-23 Mo DeJong <mdejong@redhat.com> * unix/configure: * unix/tcl.m4: * win/configure: * win/tcl.m4: Sync from Tcl sources. 2001-05-21 Jeff Hobbs <jeffh@ActiveState.com> * unix/tcl.m4: sync'ed up wih Tcl tcl.m4. [Bug #419812] * doc/TkInitStubs.3: * generic/tk.h: * generic/tkStubLib.c: CONST'ified Tk_InitStubs to match CONST changes to Tcl_PkgRequireEx. 2001-05-21 Todd M. Helfter <tmh@purdue.edu> * doc/menubutton.n: * generic/tkMenubutton.c: * generic/tkMenubutton.h: * mac/tkMacMenubutton.c: * tests/menubut.test: * unix/tkUnixMenubu.c: Implementation of TIP #11, the addition of a -compound option to the menubutton allowing text and an image to be displayed at the same time. This behavior is identical to the behavior of the button widget. 2001-05-16 Donal K. Fellows <fellowsd@cs.man.ac.uk> * doc/console.n: Added - was erroneously placed in Tcl before... 2001-04-25 Mo DeJong <mdejong@redhat.com> * unix/configure: Regen. * unix/tcl.m4: Update from Tcl. * win/configure: Regen. * win/tcl.m4: Update from Tcl. 2001-04-25 Mo DeJong <mdejong@redhat.com> * unix/configure: Regen. * unix/configure.in: Use $@ in MAKE_LIB and MAKE_STUB_LIB commands instead of using a delayed subst variable. Replace instances of STUB_LIB_FILE with TK_STUB_LIB_FILE. 2001-04-25 Mo DeJong <mdejong@redhat.com> * unix/Makefile.in: Use TCL_STUB_LIB_FILE instead of STUB_LIB_FILE. * unix/configure: Regen. * unix/configure.in: Don't subst STUB_LIB_FILE, use TCL_STUB_LIB_FILE instead. 2001-04-12 Donal K. Fellows <fellowsd@cs.man.ac.uk> * generic/tkImage.c (Tk_ImageObjCmd,DeleteImage): Better detection of deletion when world is falling apart. [Bug #220819] 2001-04-04 Jeff Hobbs <jeffh@ActiveState.com> * win/tkWinMenu.c (TkWinHandleMenuEvent): corrected reseting of service mode to only occur when it was set. [Bug #220948] 2001-04-03 Jeff Hobbs <jeffh@ActiveState.com> * tests/winClipboard.test: improved results for understanding when tests fail. * tests/winDialog.test: string totitle'd some results that expected [pwd] to return a capital drive letter. * tests/cursor.test: changed tests to use 'heart' cursor because 'arrow' on windows has a pre-skewed use count. * win/tkWinDialog.c (GetFileNameA): initialize multi to 0. 2001-04-02 Jeff Hobbs <jeffh@ActiveState.com> * win/configure: * win/tcl.m4 (SHLIB_LD): added -incremental:no. [Bug #219381] * generic/tkMenu.c (TkInvokeMenu): checked for menu deletion before calling associated menu entry command. [Bug #220821] * doc/image.n: added warning about names chosen for images. * generic/tkImgPhoto.c (ImgPhotoCmd): corrected the src and dest values for $imageName put when -format and -to are used. [Bug #232741] * tests/listbox.test: added test listbox-27.1, delete during scrollbar update * generic/tkListbox.c (DestroyListbox, ListboxEventProc): corrected listbox to make proper use of Tcl_EventuallyFree and protect against unusual listbox deletion. * tests/entry.test: added tests entry-20.*, delete during widget activity * generic/tkEntry.c (DestroyEntry, EntryEventProc): fixed the entry widget to survive deletion while processing scrollbar updates and validation. * tests/canvas.test: test of canvas delete during event * generic/tkCanvas.c (DestroyCanvas, CanvasEventProc): fixed the canvas to survive deletion during event processing. [Bug #228024] 2001-04-01 Jeff Hobbs <jeffh@ActiveState.com> * README: * mac/README: updated patchlevel to 8.4a3 and corrected links and notes. * generic/tk.h: * unix/configure.in (TK_PATCH_LEVEL): * unix/configure: * unix/tk.spec: * win/configure.in (TK_PATCH_LEVEL): * win/configure: updated patchlevel to 8.4a3 2001-03-30 Jeff Hobbs <jeffh@ActiveState.com> * tests/safe.test: added note about correcting failures in safe.test. * library/tk.tcl: moved package require msgcat inside if case to not be used in safe interps. * win/makefile.vc: * win/configure: * win/tcl.m4: added imm32.lib to LIBS_GUI for Tk IME support. * win/tkWinInt.h: * win/tkWinKey.c: * win/tkWinX.c: added support for changing IME on the fly in Windows (2000). (lam) [Patch #402993] * tests/bind.test (bind-22.18): * generic/tkBind.c (NameToWindow): handled the error case where a valid-looking but invalid identifier could be passed in certain event generate options causing a crash. [Bug #411307] * win/tkWinWm.c (UpdateWrapper): ensured that the passed in winPtr had an existent window to operate on. [Bug #409172] * win/Makefile.in (install-*): improved install-* targets to use their base build dependency. * generic/tkImage.c (Tk_ImageObjCmd, EventuallyDeleteImage): added casts to allow compiling on Windows with debbuging. 2001-03-29 Jeff Hobbs <jeffh@ActiveState.com> * library/msgs/de.msg: fixed translations. [Patch #403525] * doc/canvas.n: Noted ability to specify coords as a list in the docs. (techentin) [Patch #403660] * tests/canvas.test: added test case to check obj conversion * generic/tkObj.c (UpdateStringOfMM, SetMMFromAny): better obj-aware screen distances. (pgbaum, hobbs) [Patch #403327] * library/bgerror.tcl (bgerror): allow focus into details window for Windows C&P to work. [Bug #220929] * library/tk.tcl: put a catch around adding <hpBackTab> to the <<PrevWindow>> virtual event as it doesn't seem to work on all HP systems. [Bug #411669] * library/tkfbox.tcl: fixed selecting directories and single files with spaces using tk_getOpenFile -multiple 1. [Bug #411640] * win/tkWinDialog.c (GetFileNameA): added support for -multiple to ascii-based tk_getOpenFile (Win9*). (haneef) [Patch #403047] (GetFileNameW): increased number of files that could be returned by tk_getOpenFile -multiple. [Patch #412042] 2001-03-29 Mo DeJong <mdejong@redhat.com> * library/entry.tcl (tkEntryMouseSelect): * library/text.tcl (tkTextSelectTo): When the mouse is dragged with the button down, move the insertion cursor to the current mouse position. * tests/event.test: Add a series of tests for event generation. Add tests for selection, check the position of the insertion cursor. 2001-03-28 Jeff Hobbs <jeffh@gimlet.activestate.com> * unix/configure: * unix/tcl.m4: corrected IRIX-5.x config to not use -n32. (english) [Patch 403626] 2001-03-28 Don Porter <dgp@users.sourceforge.net> * tests/focus.test (focus-6.1): * tests/macEmbed.test (unixEmbed-5.1): * tests/macMenu.test (macMenu-21.3): * tests/menu.test (menu-27.1): * tests/unixEmbed.test (unixEmbed-8.2): * tests/unixWm.test (unixWm-50.4): Replaced all [load {} tk] in Tk test suite with [load {} Tk]. [Bug 220940, Patch 411952] 2001-03-12 Don Porter <dgp@users.sourceforge.net> BRANCH dgp-privates-into-namespace: * doc/menu.n: * unix/mkLinks: Added documentation for [tk_menuSetFocus]. 2001-03-12 Don Porter <dgp@users.sourceforge.net> BRANCH dgp-privates-into-namespace: * doc/text.n: * doc/tkvars.n: * unix/mkLinks: Added documentation for commands and variables matching tk_text*. 2001-03-08 Don Porter <dgp@users.sourceforge.net> BRANCH dgp-privates-into-namespace: * generic/tkTextDisp.c: * library/unsupported.tcl: * tests/textDisp.test: Restored the global variables tk_textRedraw and tk_textRelayout. Since they match tk_*, they should remain publicly available until at least Tk 9. 2001-03-01 Don Porter <dgp@users.sourceforge.net> BRANCH dgp-privates-into-namespace: * library/unsupported.tcl: New file for Tk's unsupported interfaces. Contains [tk::unsupported::ExposePrivateCommand] and [tk::unsupported::ExposePrivateVariable] that restore the availability of an old public name of one of Tk's private commands and variables, respectively, for those applications and extensions that depend on the old names against advice. 2001-02-28 Don Porter <dgp@users.sourceforge.net> BRANCH dgp-privates-into-namespace: Feature branch to move all of Tk's private commands and variable into the ::tk namespace and its children. * doc/tkvars.n: Documented private variable tkPriv renamed tk::Priv. * generic/tkBind.c: * generic/tkMenu.c: * generic/tkTextDisp.c: * library/bgerror.tcl: * library/button.tcl: * library/choosedir.tcl: * library/clrpick.tcl: * library/comdlg.tcl: * library/console.tcl: * library/dialog.tcl: * library/entry.tcl: * library/focus.tcl: * library/listbox.tcl: * library/menu.tcl: * library/msgbox.tcl: * library/optMenu.tcl: * library/palette.tcl: * library/scale.tcl: * library/scrlbar.tcl: * library/spinbox.tcl: * library/tclIndex: * library/tearoff.tcl: * library/text.tcl: * library/tk.tcl: * library/tkfbox.tcl: * library/xmfbox.tcl: * mac/tkMacMenu.c: * tests/clrpick.test: * tests/filebox.test: * tests/macMenu.test: * tests/menu.test: * tests/menuDraw.test: * tests/msgbox.test: * tests/text.test: * tests/textDisp.test: * tests/unixMenu.test: * tests/winMenu.test: * tests/xmfbox.test: * unix/tkUnixDialog.c: All Tk commands matching ::tk[A-Z]* and all Tk private variables in the global namespace were renamed to live in the namespace ::tk or one of its children. 2001-02-13 Eric Melski <ericm@interwoven.com> * doc/photo.n: [Bug 132213] Added clarification on interpretation of ranges for "photoName data -from" subcommand. 2001-02-12 D. Richard Hipp <drh@hwaci.com> TIP #21: Asymmetric padding in the pack and grid geometry managers. With this changes, you can now say "-padx {10 20}" to put 10 pixels of padding on the left and 20 on the right. Similar rules apply for vertical padding. See the revised documentation for details. 2001-01-02 Andreas Kupries <a.kupries@westend.com> * Everything below belongs together and implements TIP #8 (SF patch #102833). * win/tkWinWm.c (line 56f): Added icon structures. * win/tkWinWm.c (struct WmInfo, line 242): Added reference to optional icon for titlebar. * win/tkWinWm.c (struct ThreadSpecificData, line 335): Added reference to optional default icon for toplevel windows. * win/tkWinWm.c (line 387 ... 1169): All the new functions required to deal with icon specifications, 'InitWm' changed. * win/tkWinWm.c (TkWmNewWindow, UpdateWrapper, TkWmDeadWindow, Tk_WmCmd): Added initialization and handling of the new fields. * doc/wm.n: Documentation updated to explain the newly available functionality. 2000-12-13 jeff hobbs <jhobbs@interwoven.com> * generic/tkObj.c (SetMMFromAny): Added ability to recognize double type object to speed up canvas coord calculations. [Patch 403327] 2000-12-12 Donal K. Fellows <fellowsd@cs.man.ac.uk> * doc/entry.n: Improved documentation of interplay between the -state and -textvariable options. 2000-11-29 Donal K. Fellows <fellowsd@cs.man.ac.uk> * tests/image.test (image-1.10): Improved this test, which previously only worked if the command failed to delete the root window, and caused *major* trouble otherwise... * generic/tkImage.c (EventuallyDeleteImage): Created this function so that images that get deleted during the creation of an image won't cause a nasty core dump. Properly fixes bug #120819. 2000-11-28 Donal K. Fellows <fellowsd@cs.man.ac.uk> * doc/image.n: * generic/tkImage.c (Tk_ImageObjCmd): Backed out previous change. Bug #120819 is back again in force. Left the test in there though. 2000-11-23 Donal K. Fellows <fellowsd@cs.man.ac.uk> * doc/image.n: * tests/image.test (image-1.10): * generic/tkImage.c (Tk_ImageObjCmd): Prohibited image names that start with "." since they can cause some really obscure crashes. Fixes Bug #120819. 2000-11-21 Eric Melski <ericm@ajubasolutions.com> Overall change: Implemented TIP 5, which exports TkClassProcs/TkSetClassProcs as Tk_ClassProcs/Tk_SetClassProcs, adding a size field to Tk_ClassProcs to allow for future expansion, and renaming the geometryProc to worldChangedProc, which is more in keeping with the actual use of the callback. * unix/mkLinks: Added link for Tk_SetClassProcs. * doc/SetClassProcs.3: Documentation for Tk_ClassProcs/Tk_SetClassProcs. * generic/tkCanvas.c: * generic/tkEntry.c: * generic/tkFrame.c: * generic/tkListbox.c: * generic/tkMenu.c: * generic/tkMessage.c: * generic/tkScale.c: * generic/tkText.c: Updated to use Tk_ClassProcs/Tk_SetClassProcs instead of TkClassProcs/TkSetClassProcs. * generic/tkMenubutton.c: * generic/tkScrollbar.c: * generic/tkButton.c: Updated to use Tk_SetClassProcs instead of TkSetClassProcs. * generic/tkMenubutton.h: * generic/tkScrollbar.h: * generic/tkButton.h: * win/tkWinButton.c: * win/tkWinScrlbr.c: * mac/tkMacButton.c: * mac/tkMacMenubutton.c: * mac/tkMacScrlbr.c: * unix/tkUnixButton.c: * unix/tkUnixMenubu.c: * unix/tkUnixScrlbr.c: Updated to use Tk_ClassProcs instead of TkClassProcs. * generic/tkDecls.h: * generic/tkStubInit.c: * generic/tkIntDecls.h: Regenned from tk.decls, tkInt.decls. * generic/tk.h: Added declaration of Tk_ClassProcs, with size field. Added typedef's for Tk_ClassCreateProc, Tk_ClassWorldChangedProc, Tk_ClassModalProc. Added definition of Tk_GetClassProc macro, shorthand for extracting a member of the Tk_ClassProcs structure. * generic/tkInt.h: Removed declaration of TkClassProcs, TkClassGeometryProc, etc. * generic/tkBind.c (Tk_BindEvent): Updated to use Tk_GetClassProc macro to extract modalProc; added check that the modalProc is non-NULL. * generic/tkFont.c (RecomputeWidgets): Updated to use Tk_GetClassProc macro to extract worldChangedProc; added comment about the choice of a recursive versus iterative algorithm for propagating world changed messages. * generic/tkWindow.c (Tk_MakeWindowExist): Updated to use Tk_GetClassProc macro to extract createProc from Tk_ClassProcs. * generic/tk.decls: Added declaration for Tk_SetClassProcs. * generic/tkInt.decls: Commented out declaration for TkSetClassProcs, which is made public by this change. The entry is left in place, but commented, so that future developers will know not to reuse it's stub number. 2000-11-21 Donal K. Fellows <fellowsd@cs.man.ac.uk> * doc/ConfigWidg.3: Added deprecation note from Bug #120944 - use Tk_SetOption() instead. * generic/tkImgPhoto.c (TkPhotoGetValidRegion): Applied patch to create this function and add it to tkInt stubs. Should now be possible to write an extension that accesses the transparency data in a photo image. Bug #120930 2000-11-03 Jeff Hobbs <hobbs@ajubasolutions.com> 8.4a2 RELEASE * generic/tkWindow.c (Initialize): added call to Tcl_SetMainLoop. This only has effect when tclsh is run (not wish), and then Tk is loaded in interactively. 2000-11-02 Jeff Hobbs <hobbs@ajubasolutions.com> * win/tkWinButton.c: * win/tkWinDialog.c: * win/tkWinScrlbr.c: * win/tkWinWm.c: fixed up code for Win64 support. This mostly remains in _WIN64 #ifdef's, until updated compilers are standard. * win/tcl.m4: * win/makefile.vc: updated for Win64 compile support * unix/configure: * win/configure: checked in configure scripts so people doing CVS checkouts aren't required to have autoconf. Changes to configure.in in the future will require the corresponding configure script to also be re-autoconf'ed and checked in. * doc/event.n: added note that key events require window focus. 2000-11-01 Jeff Hobbs <hobbs@ajubasolutions.com> * win/tkWinDialog.c (GetFileNameW, GetFileNameA, Tk_ChooseDirectoryObjCmd): created work-around for change in NT5.0/98 that caused no initialdir setting to open the browser up in the user's documents dir. * tests/color.test: marked color-2.6 nonPortable as we can't reliably assume what 'red' maps to. 2000-11-01 Eric Melski <ericm@ajubasolutions.com> * tests/winDialog.test: Corrected expected results for bad option tests (5.2, 5.5) to include -multiple option. * win/tkWinDialog.c: Added branch for 0 return from CommDlgExtendedError() switches; this was formerly treated as an error, but it actually is not, since it just means the user hit cancel or closed the dialog. (GetFileNameW): Added better smarts such that -multiple is not considered a valid option for tk_getSaveFile. Removed CommDlgExtendedError() checks for color and choosedir dialogs, and removed all except the explicit invalid filename checks for the file dialogs. 2000-10-30 David Gravereaux <davygrvy@ajubasolutions.com> * win/configure.in: * win/Makefile.in: * win/makefile.vc: * win/rc/tk.rc: * win/rc/tk_base.rc (new): * win/rc/wish.rc: Added logic to derive filenames better in the resource scripts based on compile options along with better support for building a static wish shell with cursor resources. 2000-10-27 Jeff Hobbs <hobbs@ajubasolutions.com> * unix/tcl.m4: added support for AIX-5. * tests/tk.test: * doc/tk.n: updated to reflect default on status of useinputmethods. * library/tk.tcl: tk useinputmethods is set to 1 by default. This enables Kanji and dead-char input by default. Intro'd in 1999-12-16 with default off to avoid some problems with older X servers that would slow down widget creation over time. * win/Makefile.in (test, winhelp, tktest): corrected the TCL_LIBRARY path specification. 2000-10-18 Eric Melski <ericm@ajubasolutions.com> * win/tkWinDraw.c (RenderObject): Applied patch from [Bug: 6368], which corrects rendering of 1-pixel wide stippled lines on Windows. * generic/tkCanvLine.c (DisplayLine): Applied patch from [Bug: 6368], corrects bugs relating to use of active- and disabledwidth values for displaying lines (disabledwidth was never used, and activewidth/disablewidths would only possibly be used when greater than default width, rather than when simply not equal to default width). * library/tkfbox.tcl (OkCmd): Applied patch from [Bug: 6365], which adds safety for directory names containing spaces or which are non-lists. * win/tkWinDialog.c (GetFileNameW, GetFileNameA, Tk_ChooseColorObjCmd, Tk_ChooseDirectoryObjCmd): Added error checking for the return value from the common dialog functions, so that the commands will not silently fail if the common dialog returns an error. [Bug: 6369]. 2000-10-10 Eric Melski <ericm@ajubasolutions.com> * generic/tkConfig.c (Tk_InitOptions): Added Tcl_IncrRefCount/Tcl_DecrRefCount calls on valuePtr, to prevent memory leaks when the value object comes from the option database. [Bug: 6275]. 2000-10-06 Jeff Hobbs <hobbs@ajubasolutions.com> * win/Makefile.in (cat32.${OBJEXT}): add win/ subdirectory to cat32 target to correctly find the source file. 2000-10-05 Eric Melski <ericm@ajubasolutions.com> * generic/tkCmds.c (Tk_WinfoObjCmd): Added check for TK_ANONYMOUS_WINDOW flag in the [winfo children] subcommand; if set, the window will not be printed in the list of children. * doc/CrtWindow.3: Added entry for Tk_CreateAnonymousWindow. * generic/tkWindow.c (Tk_CreateAnonymousWindow): New API for creating anonymous windows. These windows are manipulable from C, but not from Tcl, because they have no pathname associated with them. They are used initially by widgets that do rubber-band resizing (panedwindow, multi-column listbox, etc.), and may be useful for other widgets as well (dropbox, combobox). (Tk_DestroyWindow): Added check for TK_ANONYMOUS_WINDOW flag when determining whether to generate a DestroyNotify event. * generic/tkStubInit.c: * generic/tkDecls.h: Regen'd from tk.decls. * generic/tk.decls: Added Tk_CreateAnonymousWindow declaration. * generic/tk.h: Added TK_ANONYMOUS_WINDOW flag for Tk_Window's. 2000-10-04 Eric Melski <ericm@ajubasolutions.com> * doc/MaintGeom.3: Noted that Tk_MaintainGeometry handles direct descendants properly. * generic/tkGeometry.c (Tk_MaintainGeometry): Added a check for the case in which the slave window is a direct descendant of the master window. In this case, we need not set up the additional infrastructure normally provide by Tk_MaintainGeometry, because we can rely on the parent/child relationship to handle it for us implicitly. In this case, Tk_MaintainGeometry just calls directly to Tk_MoveResizeWindow. This allows geometry managers to simply always use Tk_MaintainGeometry to maintain geometry for slaves, and avoid doing the direct descendant check themselves. (Tk_UnmaintainGeometry): Added a matching check for the direct descendant case; in this case, Tk_UnmaintainGeometry simply returns immediately. 2000-10-01 Eric Melski <ericm@ajubasolutions.com> * generic/tkButton.c (ConfigureButton): Added tests for -compound option, so that when there is a textvariable and an image, and -compound is not none, the button will display both the textvariable and the image. * doc/SetOptions.3: Added note that restoreProc and freeProc may be NULL. * generic/tkConfig.c (Tk_RestoreSavedOptions): For custom options, added test that the restoreProc is not NULL, to allow for custom options that don't care about supporting Tk_RestoreSavedOptions. 2000-09-29 D. Richard Hipp <drh@hwaci.com> * generic/tkBitmap.c: Changes to prevent a BadMatch error from the Xserver when the same bitmap is used on two or more screens of the same display. * tests/menu.test: Print a warning if the TK_ALT_DISPLAY environment variable is not configured so as to test for the bug fix above. * library/tk.tcl (::tk::SetGrabFocus): "Catch" the grab in case another application already holds the grab and the "grab" command fails. 2000-09-29 Jeff Hobbs <hobbs@scriptics.com> * win/Makefile.in: commented use of TESTFLAGS * unix/Makefile.in: added TESTFLAGS to test and testlang targets to conform with Windows makefile and TEA style. 2000-09-29 Eric Melski <ericm@ajubasolutions.com> * generic/tkTest.c: Fixed tests to use updated API. * doc/SetOptions.3: * generic/tk.h: * generic/tkConfig.c: Changed interface for Tk_CustomOptionSetProc and Tk_CustomOptionGetProc; these now take a pointer to the start of the widget record, and an integer offset to the slot for the option value, instead of just a pointer to the slot. This allows more sophisticated options to do interesting things based on other data in the widget record. 2000-09-17 Eric Melski <ericm@ajubasolutions.com> * generic/tk.h: Added declaration of Tk_ObjCustomOption structure, used for TK_OPTION_CUSTOM, and typedef's of the functions Tk_CustomOptionSetProc, Tk_CustomOptionGetProc, Tk_CustomOptionRestoreProc, and Tk_CustomOptionFreeProc, used for TK_OPTION_CUSTOM. * doc/SetOptions.3: Added documentation of TK_OPTION_CUSTOM, and section "CUSTOM OPTION TYPES" explaining how to create and use custom options. * tests/config.test: Added tests for custom option type. * generic/tkTest.c: Added test support for TK_OPTION_CUSTOM to TestobjconfigObjCmd. Added CustomOption* functions to implement a test custom option. * generic/tkConfig.c: Added new option type TK_OPTION_CUSTOM, which allows the definition of custom option types by creating parsing, printing, freeing, and restoring procedures for a custom option. This is needed by the text and canvas widgets if they are to be fully objectified. 2000-09-07 Jeff Hobbs <hobbs@scriptics.com> * doc/Tk_Init.3: * doc/bell.n: * doc/loadTk.n: minor doc cleanup 2000-09-06 Eric Melski <ericm@ajubasolutions.com> * doc/HWNDToWindow.3: * doc/GetHWND.3: Changed synopsis to indicate the tkPlatDecls.h should be included, not tk.h. * generic/tkPlatDecls.h: Removed #include <windows.h> for Windows, a better solution for now is to update the docs and have extension authors #include <tkPlatDecls.h>. * generic/tk.h: Removed '#include "tkPlatDecls.h"', as the incorrect inclusion order between windows.h/tkPlatDecls.h causes build conflicts on Windows. * generic/tkPlatDecls.h: Added #include <windows.h> for Windows, so that HWND, etc., are defined properly. 2000-09-06 Jeff Hobbs <hobbs@scriptics.com> * doc/canvas.n: fixed doc bug (ellson). [Bug: 6218] * README: * generic/tk.h: * unix/configure.in: * unix/tk.spec: * win/configure.in: updated to patchlevel 8.4a2 * generic/tkMessage.c (MessageWidgetObjCmd): initialized result to avoid pedantic warning. * generic/tkGrab.c (Tk_GrabObjCmd): changed len arg from size_t to int to fix pedantic warning. 2000-09-01 Eric Melski <ericm@ajubasolutions.com> * win/makefile.vc (install-libraries): * win/Makefile.in (install-libraries): * unix/Makefile.in (install-libraries): Added tkPlatDecls.h to list of header files to install. * generic/tk.h: Added #include "tkPlatDecls.h", which declares the platform specific component of the public Tk stubs API's. 2000-08-29 Eric Melski <ericm@ajubasolutions.com> * win/tkWinMenu.c (DrawWindowsSystemBitmap): Use scratchDC for determining the source's logical coordinates. Patch from [Bug: 6134 (Markus Oberhumer)]. * win/tkWinMenu.c (SetDefaults): Compute the indicatorDimensions[] under Windows NT/2000 in the same way as under Windows 95/98. Patch from [Bug: 6134 (Markus Oberhumer)]. * win/tkWinFont.c (GetScreenFont): Added a memset() to pacify memory checkers. Patch from [Bug: 6134 (Markus Oberhumer)]. * library/tkfbox.tcl (::tk::dialog::file::Update): Corrected handling of multi-pattern filters (eg, "* *.*"), which was broken by the getOpenFile performance patches applied earlier. 2000-08-24 Eric Melski <ericm@ajubasolutions.com> * doc/toplevel.n: * doc/spinbox.n: * doc/scrollbar.n: * doc/scale.n: * doc/menubutton.n: * doc/menu.n: * doc/listbox.n: * doc/entry.n: * doc/frame.n: * doc/message.n: * doc/checkbutton.n: * doc/radiobutton.n: * doc/button.n: * doc/label.n: * doc/canvas.n: * doc/text.n: Fixed Standard Options section to make best use of new tab settings in man.macros. 2000-08-24 Mo DeJong <mdejong@redhat.com> * unix/README: Update to account for removal of --enable-gcc. * unix/configure.in: * unix/tcl.m4 (SC_ENABLE_GCC): Remove --enable-gcc option. * win/configure.in: * win/tcl.m4 (SC_ENABLE_GCC): Remove --enable-gcc option. Remove quick hack that provided cross compile support for windows builds. 2000-08-23 Jeff Hobbs <hobbs@scriptics.com> * generic/tkButton.c (ButtonTextVarProc): reversed change below, it was not correct. 2000-08-22 Jeff Hobbs <hobbs@scriptics.com> * generic/tkButton.c (ButtonTextVarProc): changed order of incr/decr of new value object, in case they are equal. 2000-08-18 Eric Melski <ericm@ajubasolutions.com> * generic/tkImgPhoto.c (ImgPhotoGet): Removed redundant call to DitherInstance; this call was formerly being made from ImgPhotoGet->ImgPhotoConfigureInstance->DitherInstance, and ImgPhotoGet->DitherInstance. The second call was removed. 2000-08-10 Jeff Hobbs <hobbs@scriptics.com> * doc/SetOptions.3: added missing ')'. 2000-08-09 Eric Melski <ericm@ajubasolutions.com> * doc/SetOptions.3: Updated documentation to reflect support for TK_OPTION_NULL_OK for TK_OPTION_DOUBLE and TK_OPTION_PIXELS. * generic/tkConfig.c: Added for TK_OPTION_NULL_OK support for TK_OPTION_DOUBLE and TK_OPTION_PIXELS. * doc/place.n: Updated, reformatted manual entry. * tests/place.test: Added many tests. * generic/tkPlace.c (Tk_PlaceObjCmd): Updated to use Tk widget-option management facilities to manage place options (-x, -y, etc.), which simplifies the placer code. Added support for [place configure pathName] and [place configure pathName -option], similar to the behavior of the configure subcommand supported by widgets. 2000-08-08 Eric Melski <ericm@ajubasolutions.com> * tests/place.test: Extended test suite to test error returns from [place]. * generic/tkInt.h: Replaced Tk_PlaceCmd prototype with Tk_PlaceObjCmd prototype. * generic/tkWindow.c: Updated [place] command entry to use new Tcl_Obj interface. * generic/tkPlace.c (Tk_PlaceObjCmd): Tcl_Obj'ified [place] command. 2000-08-07 Eric Melski <ericm@ajubasolutions.com> * generic/tkWindow.c: Updated [selection] command entry to use new Tcl_Obj interface. * generic/tkInt.h: Replaced Tk_SelectionCmd prototype with Tk_SelectionObjCmd prototype. * tests/select.test: Updated test suite to recognize standardized error messages. * generic/tkSelect.c (Tk_SelectionObjCmd): Tcl_Obj'ified [selection] command. 2000-08-07 Jeff Hobbs <hobbs@scriptics.com> * doc/cursors.n: changed .SS to more compatible macros. 2000-08-05 Jeff Hobbs <hobbs@scriptics.com> * library/safetk.tcl: rationalized the setting of tk_library when initialized Tk in a safe interpreter. 2000-08-03 Eric Melski <ericm@ajubasolutions.com> * generic/tkWindow.c: Updated "grab" command entry to use Tcl_Obj'ified command. * generic/tkInt.h: Replaced Tk_GrabCmd prototype with Tk_GrabObjCmd prototype. * tests/grab.test: Initial suite of tests for [grab] command. * generic/tkGrab.c (Tk_GrabObjCmd): Tcl_Obj'ified [grab] command. * generic/tkInt.h: Removed Tk_AfterCmd function prototype; the function does not exist (since 4.0p3). Cleaned up some line wrapping. * generic/tk.h: Removed "#define Tk_AfterCmd Tcl_AfterCmd"; nothing in the core uses Tk_AfterCmd, and Tcl_AfterCmd doesn't exist anymore anyway. * generic/tkInt.h: Replace Tk_BindCmd prototype with Tk_BindObjCmd prototype. * generic/tkWindow.c: Updated "bind" command entry to use Tcl_Obj'ified command. * generic/tkCmds.c (Tk_BindObjCmd): Tcl_Obj'ified [bind] command. * tests/bind.test: Tweaked expected error messages for [bindtags] to comply with updated error messages. * generic/tkMenu.c (CloneMenu): Replaced calls to Tk_BindtagsCmd with equivalent calls to Tk_BindtagsObjCmd. * generic/tkInt.h: Replace Tk_BindtagsCmd prototype with Tk_BindtagsObjCmd prototype. * generic/tkWindow.c: Updated "bindtags" command entry to use Tcl_Obj'ified command. * generic/tkCmds.c (Tk_BindtagsObjCmd): Tcl_Obj'ified [bindtags] command. 2000-08-02 Eric Melski <ericm@ajubasolutions.com> * generic/tkCmds.c (Tk_TkwaitObjCmd): Tcl_Obj'ified [tkwait] command. * generic/tkWindow.c: Updated "tkwait" command entry to use Tcl_Obj'ified command. * generic/tkInt.h: Replace Tk_TkwaitCmd prototype with Tk_TkwaitObjCmd prototype. * generic/tkGrid.c (Tk_GridCmd): Split [grid] subcommands into separate functions instead of inlining them all in Tk_GridCmd. 2000-08-01 Eric Melski <ericm@ajubasolutions.com> * generic/tkInt.h: Replaced prototype for Tk_MessageCmd with prototype for Tk_MessageObjCmd. * generic/tkWindow.c: Marked message command as using the new MessageObjCmd instead of the old MessageCmd. * tests/message.test: Added tests for the message widget. * generic/tkMessage.c: Obj'ified the message widget. * generic/tkInt.h: Removed prototype for Tk_ClipboardCmd, added prototype for Tk_ClipboardObjCmd. * generic/tkWindow.c: Updated function pointers for clipboard command to use Tcl_Obj version. * tests/clipboard.test: Updated tests to expect standard error messages. * generic/tkClipboard.c (Tk_ClipboardObjCmd): Obj'ified Tk_ClipboardCmd -> Tk_ClipboardObjCmd. 2000-07-28 Eric Melski <ericm@ajubasolutions.com> * unix/tkUnixButton.c (TkpDisplayButton): Added bits to change the indicator color when radio-/check-buttons are disabled. This reduces the visual incongruity when a group of these controls are disabled together. * win/tkWinMenu.c (ReconfigureWindowsMenu): Added MF_GRAYED bit for disabled menu entries, to ensure that those which are drawn by the system are shown grayed (such as entries on menubars) [Bug: 4372]. * doc/label.n: Added -disabledforeground to list of options [Bug: 6053]. * mac/tkMacDefault.h: * unix/tkUnixDefault.h: Added default values for listbox disabledforeground and state. * win/tkWinDefault.h: Changed default listbox background color to white and listbox selection borderwidth to 0, in keeping with the "Microsoft Windows User Experience"; added default values for listbox disabledforeground and listbox state. * doc/listbox.n: Added documentation for -state option. * generic/tkListbox.c: Added support for -state to listbox. [RFE: 6052]. * tests/listbox.test: Tests for listbox disabled state. 2000-07-27 Mo DeJong <mdejong@redhat.com> * win/configure.in: TCL_STUB_LIB_FLAG and TK_STUB_LIB_FLAG should not include ${TCL_DBGX} in win/tkConfig.sh, fix that. 2000-07-25 Joe English <jenglish@flightlab.com> * doc: CanvPsY.3, ConfigWidg.3, CrtImgType.3, CrtItemType.3, FontId.3, GetFont.3, canvas.n, font.n, options.n, text.n: Documentation fix: Replaced references to XFontStruct * and Tk_FontStruct with Tk_Font. 2000-07-24 Eric Melski <ericm@ajubasolutions.com> * tests/text.test: Added tests for -regexp -nocase searches with backslash character classes. * generic/tkText.c (TextSearchCmd): Text search did not work properly when -regexp and -nocase were used, in combination with backslash character classes represented by capital letters (ie, \W, \M); altered implementation of -regexp -nocase searches to use new regexp interfaces to fix this problem. [Bug: 5988]. 2000-07-21 Eric Melski <ericm@ajubasolutions.com> * tests/text.test: Added tests for searching when text is elided. * generic/tkText.c (TextSearchCmd): Text search was not returning the correct index when the search covered (but did not search) elided characters; corrected this by adjusting the match index by the number of elided characters preceeding the start of the match, just as is done with embedded windows, etc. [Bug: 5470]. 2000-07-21 Mo DeJong <mdejong@redhat.com> * win/configure.in: Add TK_STUB_LIB_FLAG and TK_BUILD_STUB_LIB_SPEC. These are needed to build a stub enabled extension. 2000-07-20 Eric Melski <ericm@ajubasolutions.com> * unix/tkUnixDraw.c (TkScrollWindow): Replaced a use of a trinary operator with an if/else, to avoid build problems on some platforms [Bug: 5819]. * win/makefile.vc: Applied patch from Don Porter to enhance nmake support on NT/Alpha [RFE: 5939]. 2000-07-19 Eric Melski <ericm@ajubasolutions.com> * library/text.tcl: Enhanced <Tab> binding to behave like normal <Tab> bindings when the text widget is disabled (ie, it advances focus to the next widget). * generic/tkText.c (TextSearchCmd): Added a test for a NULL segment pointer when doing backwards searches for "" on an empty text widget. [Bug: 6007]. 2000-07-18 Mo DeJong <mdejong@redhat.com> * unix/aclocal.m4: Use tcl.m4. * unix/configure.in: Properly quote LOCALES variable. Properly quote argument to m4 macro. * unix/tcl.m4: Add updated file from tcl. * win/tcl.m4: Updated file from tcl. 2000-07-18 Eric Melski <ericm@ajubasolutions.com> * library/tkfbox.tcl: Fixed keyboard navigation in the iconlist. * unix/configure.in (MAKE_LIB): Corrected definition of MAKE_LIB for shared builds, with patch from Mike Hopkirk. 2000-07-18 Mo DeJong <mdejong@redhat.com> * win/Makefile.in: Fix TCL_GENERIC_DIR variable so that it uses the TK_SRC_DIR in the same way as the unix version. 2000-07-17 David Gravereaux <davygrvy@ajubasolutions.com> * generic/tkConsole.c: Added comments for a Win2K OS bug with GetStdHandle(STD_OUTPUT_HANDLE). No change was done to the code as the resulting behaviour of ShouldUseConsoleChannel() was correct, anyways. [BUG: 5971] 2000-07-17 Eric Melski <ericm@scriptics.com> * generic/tkStubImg.c (Tk_InitImageArgs): Applied patch from [Bug: 5990], from Anselm Lingnau, which correctly sets the value of useNewImage to 0 when the new image system is not to be used, instead of leaving it at -1, which causes the check to be performed more times than is really necessary. * library/bgerror.tcl: Fixed a typo in one of the bgerror dialog label. * library/msgs/it.msg: Italian message catalog, from Paolo Brutti. [RFE: 6012]. 2000-07-07 Eric Melski <ericm@ajubasolutions.com> * library/msgs/el.msg: Greek message catalog, from George Petasis. 2000-07-07 Mo DeJong <mdejong@redhat.com> * win/configure.in: Fix subst of TK_SHARED_BUILD variable in tkConfig.sh.in. Fix definition of TK_SRC_DIR variable so that it matches the unix version. 2000-07-05 Mo DeJong <mdejong@redhat.com> * generic/tkFileFilter.c (AddClause): Cast to match function prototype. * win/stubs.c (_XInitImageFuncPtrs): Add return value for function. * win/tkWinButton.c (buttonStyles, ButtonBindProc, ComputeStyle): Remove unused declarations. * win/tkWinColor.c (GetColorByName, GetColorByValue): Remove unused function declarations. * win/tkWinDialog.c (TrySetDirectory): Remove unused function declaration. * win/tkWinEmbed.c (TkWinEmbeddedEventProc): Cast to match function prototype. * win/tkWinMenu.c (winMenuMutex, MenuExitProc): Remove unused declaration. * win/tkWinWindow.c (StackWindow): Remove unused declaration. * win/tkWinWm.c (ConfigureEvent): Remove unused declaration. * win/tkWinX.c (winXMutex): Remove unused declaration. * xlib/ximage.c (XCreateBitmapFromData): Cast to match function prototype. 2000-07-05 Eric Melski <ericm@ajubasolutions.com> * tests/imgPhoto.test: Added test for GIF writing code [Bug: 5823]. * generic/tkImgGIF.c: Applied patch from Jan Nijtmans to fix a problem with the GIF writing code [Bug: 5823]. * generic/tkCursor.c: Added initialization for nextPtr field of TkCursor, patch from Nijtmans/Howlett. 2000-07-05 Eric Melski <ericm@ajubasolutions.com> * library/msgs/nl.msg: Dutch message catalog for dialogs, from Jan Nijtmans. 2000-06-30 Eric Melski <ericm@scriptics.com> * doc/keysyms.n: * doc/colors.n: Added extra .CE/.CS pairs to break up the large text block, so that the generated Windows help file could accomodate the manual entry. [Bug: 5862] * tests/filebox.test: Adjusted tests to accomodate -multiple. * library/xmfbox.tcl: Adjusted arguments list construction such that -multiple is not presented as an option for tk_getSaveFile. * library/tk.tcl: Added test for safe interpreter status before attempting to load message catalogs (which is impossible in a standard safe interpreter). This means that SafeTk will not have localized dialogs, unless a means is found for loading the message catalog files. 2000-06-29 Eric Melski <ericm@scriptics.com> * library/msgs/de.msg: German message catalog. * library/msgs/en.msg: English message catalog. * library/msgs/es.msg: Spanish message catalog. * library/msgs/fr.msg: French message catalog. * unix/Makefile.in: * unix/configure.in: * library/tk.tcl: * library/clrpick.tcl: * library/choosedir.tcl: * library/console.tcl: * library/msgbox.tcl: * library/tkfbox.tcl: * library/xmfbox.tcl: * library/bgerror.tcl: Applied patches from Laurent Duperval to provide localization of Tk dialogs. [RFE: 2671]. 2000-06-27 Eric Melski <ericm@scriptics.com> * generic/tkMenu.c (DeleteMenuCloneEntries): Applied fix from [Bug: 5275], which corrected a segfault-causing indexing problem when deleting entries from torn-off menus. 2000-06-22 Eric Melski <ericm@ajubasolutions.com> * doc/getOpenFile.n: Updated with information about -multiple. * library/choosedir.tcl: Tweaked to handle modified tkIconList API's. * library/tkfbox.tcl: Preliminary implementation of multiple selection; based on patch from [RFE: 604]. Some of the tkIconList functions changed to support this and to make the dialog faster. * library/xmfbox.tcl: Added support for multiple selection, from patch in [RFE: 4999]. 2000-06-21 Eric Melski <ericm@scriptics.com> * library/text.tcl: Corrected behavior of text widget with respect to this sequence of events: click, shift-click. Previously, the shift-click just moved the cursor and anchor; now, the shift-click will select the text between the click and the shift-click, which is the behavior most users expect. [Bug: 5929]. 2000-06-19 Eric Melski <ericm@scriptics.com> * library/bgerror.tcl: Added auto-truncation for long error messages (more than 30 characters wide, or more than 4 lines long), so that the dialog remains a manageable size. [RFE: 5782] 2000-06-15 Eric Melski <ericm@scriptics.com> * win/tkWinDialog.c: Patched to support tk_getOpenFile -multiple. [RFE: 604]. 2000-06-13 Eric Melski <ericm@scriptics.com> * win/aclocal.m4: * win/configure.in: * win/Makefile.in: Applied patch from [RFE: 5844], to provide support for the mingw compile environment for Windows. 2000-06-06 Jeff Hobbs <hobbs@scriptics.com> 8.4a1 RELEASE 2000-06-03 Jeff Hobbs <hobbs@scriptics.com> * doc/CrtCmHdlr.3: new doc for ClientMessage handler procs * generic/tk.h: added typdef for Tk_ClientMessageProc * generic/tkStubInit.c: * generic/tkDecls.h: * generic/tk.decls: Added Tk_CreateClientMessageHandler and Tk_DeleteClientMessageHandler declarations. * generic/tkEvent.c (Tk_HandleEvent): Added Tk_CreateClientMessageHandler and Tk_DeleteClientMessageHandler to allow adding event handlers that invoke for ClientMessage events. This is necessary to support unix dnd protocols. 2000-06-02 Jeff Hobbs <hobbs@scriptics.com> * canvas.test: added test for 5783. * generic/tkCanvPoly.c (DisplayPolygon): added checks for the polygon fillGC not being empty to prevent segfault. [Bug: 5783] 2000-05-31 Eric Melski <ericm@scriptics.com> * library/bgerror.tcl: Improved bgerror based on work by Donal K. Fellows; no longer dependant on tk_dialog; features a Windows-esque "Details" button, and a customizable extra function button that allows the user to (for example) save the stack trace to a file. 2000-05-30 Eric Melski <ericm@scriptics.com> * generic/tkImgGIF.c: Changed defines for GIF87a/GIF89a to be static char arrays with integer initialization, to address EBCIDIC vs. ASCII encoding issues and to handle compilers that don't deal with "\xAB" syntax for specifying hex values in strings. 2000-05-28 Jeff Hobbs <hobbs@scriptics.com> * doc/spinbox.n: (new file) docs for spinbox widget * generic/tkInt.h: added Tk_SpinboxObjCmd declaration * generic/tkEntry.c: added 'spinbox' widget - an extension of the entry widget type. * generic/tkWindow.c: added 'spinbox' to core Tk commands * library/spinbox.tcl: (new file) binding and helper procs for spinbox * library/tk.tcl: added spinbox.tcl to list of files to source * tests/entry.test: updated changed error messages * tests/spinbox.test: (new file) test suite for spinbox * generic/tkPlace.c (Tk_PlaceCmd): reworked place master/slave table init'n to prevent seg fault when using place on multiple displays. * generic/tk.h: added comments ot Tk_FakeWin structure 2000-05-26 Eric Melski <ericm@scriptics.com> * generic/tkOption.c (Tk_GetOption): Extended Tk_GetOption to support a new syntax for option names in option tables. If the option name has an embedded ".", it indicates that the name field contains both an option name and an overriding widget class, in the form "class.option". The lookup for the option value will be performed as though the widget class is that specified, rather than the actual widget class. (SetupStacks): Replaced several lines of array element copying with a for loop for conciseness. 2000-05-25 Eric Melski <ericm@scriptics.com> * library/button.tcl: Tweaks for -overrelief handling on Windows. * doc/radiobutton.n: Added documentation for -overrelief option. * doc/checkbutton.n: Added documentation for -overrelief option. * doc/label.n: Added documentation for -state option. * generic/tkButton.c: Added -overrelief option for checkbuttons, and radiobuttons. * library/button.tcl (tkButtonDown, macintosh version): Added protection against querying the -repeatdelay option from a widget that doesn't support it (ie, checkbuttons, radiobuttons, etc). Other platforms use a different binding script for checkbuttons and radiobuttons, so they don't have this issue. (tkCheckRadioEnter, windows version): Added code to handle -overrelief for check/radiobuttons on windows. 2000-05-22 Eric Melski <ericm@scriptics.com> * generic/tkButton.c: Added -activeforeground, -activebackground for labels, for the -state option. * doc/label.n: Added documentation for -state option, -activeforeground, -activebackground. 2000-05-22 Jeff Hobbs <hobbs@scriptics.com> * win/Makefile.in (install-libraries): corrected to install X headers [Bug: 5516] * doc/bind.n: * doc/canvas.n: * doc/entry.n: * doc/listbox.n: * doc/photo.n: doc fix-ups [Bug: 5396] 2000-05-17 Jeff Hobbs <hobbs@scriptics.com> * doc/bell.n: * tests/bell.test: * generic/tkCmds.c (Tk_BellObjCmd): added -nice option to optionally avoid resetting screen saver [Bug: 4279] 2000-05-15 Jeff Hobbs <hobbs@scriptics.com> * win/tkWinWm.c (Tk_WmCmd): changed wm deiconify from using idle callback to calling restack and focus code immediately. 2000-05-17 Eric Melski <ericm@scriptics.com> Overall change: Added "-readonlybackground" option for entries, to enable a visual change when state goes to readonly. * mac/tkMacDefault.h (DEF_ENTRY_READONLY_BG_COLOR, DEF_ENTRY_READONLY_BG_COLOR): * win/tkWinDefault.h (DEF_ENTRY_READONLY_BG_COLOR, DEF_ENTRY_READONLY_BG_COLOR): * unix/tkUnixDefault.h (DEF_ENTRY_READONLY_BG_COLOR, DEF_ENTRY_READONLY_BG_COLOR): Added default values for entry -readonlybackground option. * generic/tkEntry.c: Added -readonlybackground option, cleaned up excessive use of graphics contexts. * tests/entry.test: Added configuration test for -readonlybackground option. * doc/entry.n: Added documentation for -readonlybackground option. Overall change: changed implementation of "link" relief for buttons. Instead of a new relief style (-relief link), there is a new option, -overrelief, which if set is used when the mouse is over the button. * doc/SetOptions.3: Added information about TK_OPTION_NULL_OK with TK_OPTION_RELIEF. * win/tkWinButton.c: Removed bits about TK_RELIEF_LINK. * tests/button.test: Added tests for -overrelief; removed tests for -relief link. * mac/tkMacButton.c: Removed bits about TK_RELIEF_LINK. * generic/tkOldConfig.c: Removed bits about TK_RELIEF_LINK. * generic/tkConfig.c: Removed bits about TK_RELIEF_LINK; added support for TK_OPTION_NULL_OK for TK_OPTION_RELIEF. * library/button.tcl: Added binding support for -overrelief. * generic/tk3d.c (Tk_GetRelief): Added branch for TK_RELIEF_NULL. * generic/tkButton.c: Added -overrelief option; removed Enter/Leave EventProc masks and handlers. * generic/tk.h: Added TK_RELIEF_NULL definition, removed TK_RELIEF_LINK. * mac/tkMacDefault.h (DEF_BUTTON_OVER_RELIEF): * win/tkWinDefault.h (DEF_BUTTON_OVER_RELIEF): * unix/tkUnixDefault.h (DEF_BUTTON_OVER_RELIEF): Added default value for the -overrelief option. 2000-05-16 Eric Melski <ericm@scriptics.com> * win/tkWinMenu.c (ReconfigureWindowsMenu): Added code to add the MF_SEPARATOR bit for SEPARATOR_ENTRY menu items. This causes separator entries on the system menu to be drawn correctly [Bug: 5451]. 2000-05-15 Eric Melski <ericm@scriptics.com> * doc/image.n: Added documentation for [image inuse] command. * tests/image.test: Added tests for [image inuse] command. * generic/tkImage.c (Tk_ImageObjCmd): Added [image inuse] command, which provides a means for programmers to determine if a given image is in use by any widgets. [RFE: 3327]. 2000-05-14 Eric Melski <ericm@scriptics.com> * doc/clipboard.n: Added documentation for "clipboard get". * generic/tkClipboard.c (Tk_ClipboardCmd): Added "clipboard get" subcommand [RFE: 4628]. * tests/clipboard.test: Updated to use "clipboard get" instead of "selection get -s CLIPBOARD". * library/entry.tcl: Adjusted Button-1 binding to set focus to the entry when it is readonly or normal. * doc/entry.n: Added documentation for readonly state, -disabledforeground, -disabledbackground. * tests/entry.test: Added tests for readonly state. * generic/tkEntry.c: Added support for "readonly" state, and redefined "disabled" state. A disabled entry will display its text in a dimmed color and possibly with a different background, and will be completely unusable (no selection, no editing). A readonly entry will look like a normal entry, but it will not be editable; selection is still allowed. [RFE: 4239]. To support the new disabled state properly, "-disabledforeground" and "-disabledbackground" options were added. *** THIS IS A BACKWARDS INCOMPATIBLE BEHAVIOR CHANGE *** * win/tkWinDefault.h: * mac/tkMacDefault.h: * unix/tkUnixDefault.h: Added DEF_ENTRY_DISABLED_FG, DEF_ENTRY_DISABLED_BG_COLOR, DEF_ENTRY_DISABLED_BG_MONO. 2000-05-12 Eric Melski <ericm@scriptics.com> * unix/tkUnixButton.c (TkpDisplayButton, TkpComputeButtonGeometry): * mac/tkMacButton.c (TkpDisplayButton, TkpComputeButtonGeometry): * win/tkWinButton.c (TkpDisplayButton, TkpComputeButtonGeometry): Added code for drawing compound buttons. * tests/button.test: Added configuration tests for -repeatdelay, -repeatinterval, -compound. * library/button.tcl: Added support for -repeatedelay, -repeatinterval options. * generic/tkOldConfig.c: Changed handling of link relief so that proper error messages are used. * generic/tkButton.h: Added -compound, -repeatdelay, -repeatinterval options. * generic/tkButton.c: Added event watchers for enter/leave events, for link relief support. * generic/tk3d.c: Changed handling of link relief so that proper error messages are used. * generic/tk.h: Changed values of TK_OPTION_LINK_OK/TK_CONFIG_LINK_OK for link relief support. 2000-05-12 Jeff Hobbs <hobbs@scriptics.com> * win/tkWinFont.c (LoadFontRanges): improved support for all chars in 0-255 range for bitmap ANSI fonts. May be improved to handle bitmap non-ANSI fonts in the future. [Bug: 2172] * win/tkWinWm.c (RaiseWinWhenIdle): added TK_DONT_DESTROY_WINDOW to flag check to prevent timing related core dump. [Bug: 5438] 2000-05-11 Jeff Hobbs <hobbs@scriptics.com> * win/tkWinTest.c (TestclipboardObjCmd): ensured CloseClipboard would always get called for each OpenClipboard. * tests/focus.test (focusSetupAlt): removed wm withdraw from proc as it would cause a hang for tkwait visibility * tests/menu.test: * generic/tk3d.c: * generic/tkColor.c: * generic/tkCursor.c: corrected handling of 3DBorder, Cursor and Color objects on multiple screens. [Bug: 5454] 2000-05-09 Eric Melski <ericm@scriptics.com> * doc/button.n: Added documentation for link relief. * tests/button.test: Added tests for link relief for buttons. * generic/tk.h (TK_CONFIG_LINK_OK): Added definition of TK_RELIEF_LINK, TK_OPTION_LINK_OK and TK_CONFIG_LINK_OK. [RFE: 4348] * generic/tk3d.c: Added support for link relief. [RFE: 4348] * mac/tkMacButton.c (TkpDisplayButton): * unix/tkUnixButton.c (TkpDisplayButton): Added support for link relief. [RFE: 4348] * generic/tkOldConfig.c (Tk_ConfigureWidget): * generic/tkConfig.c (DoObjConfig): Added understanding of link relief, which is allowed only for widgets that have TK_OPTION_LINK_OK or TK_CONFIG_LINK_OK set for the "-relief" option. [RFE: 4348] * generic/tkButton.c: Added TK_OPTION_LINK_OK to "-relief" option for buttons. [RFE: 4348] * win/tkWinWm.c (EX_TRANSIENT_STYLE): Removed WS_EX_TOOLWINDOW style bit, so that transient windows have full-size titlebars (like the tk_getOpenFile dialog). * win/tkWinMenu.c (GetMenuSeparatorGeometry): Tweaked height requested for separator bars to be (linespace - (2*descent)) instead of just (linespace); this makes the separator occupy a more correct amount of vertical space. [Bug: 5303]. 2000-05-09 Jeff Hobbs <hobbs@scriptics.com> * library/focus.tcl: fixed calling of takeFocus proc [Bug: 5372] 2000-05-02 Jeff Hobbs <hobbs@scriptics.com> * README: * generic/tk.h: * library/tk.tcl: * mac/README: * unix/README: * unix/configure.in: * unix/tk.spec: * win/README: * win/aclocal.m4: * win/configure.in: * win/makefile.vc: updated patchlevel to 8.4a1 * unix/Makefile.in: added tk.spec to dist target 2000-04-27 Eric Melski <ericm@scriptics.com> * doc/Tk_Init.3: Added Tk_SafeInit information [Bug: 1884]. * doc/keysyms.n: Man page enumerating keysyms [RFE: 1645]. * doc/colors.n: Man page enumerating valid color names [RFE: 1645]. * doc/cursors.n: Man page enumerating valid cursor values [RFE: 1645]. * library/msgbox.tcl: Corrected Unix tk_messageBox implementation to make the first button the default when no default is specified [Bug: 2218]. * doc/messageBox.n: Updated documentation with regards to selection of default button when none is specified (now it will use the first button as the default in that case) [Bug: 2218]. 2000-04-26 Jeff Hobbs <hobbs@scriptics.com> 8.3.1 RELEASE * README: * mac/README: * unix/README: * unix/tk.spec: * win/README: Updating URLs to reference dev.scriptics.com 2000-04-25 Jeff Hobbs <hobbs@scriptics.com> * unix/Makefile.in: * win/Makefile.in: makefile cleanup 2000-04-25 Eric Melski <ericm@scriptics.com> * generic/tkMain.c: Fixed function header comment for Tk_MainEx. * unix/mkLinks: * doc/GetScroll.3: Added information about Tk_GetScrollInfoObj [Bug: 1866]. 2000-04-24 Eric Melski <ericm@scriptics.com> * unix/mkLinks: * doc/Grab.3: Man page for Tk_Grab and Tk_Ungrab [Bug: 1868, 1889] * unix/mkLinks: * doc/MainWin.3: Added entry for Tk_GetNumMainWindows [Bug: 1865]. * unix/mkLinks: * doc/GetHINSTANCE.3: Man page for Tk_GetHINSTANCE [Bug: 1862]. 2000-04-24 Jeff Hobbs <hobbs@scriptics.com> * generic/tkImage.c (Tk_PostscriptImage): added check to create necessary prolog for photos * generic/tkCanvPs.c: added Tk_PostscriptPhoto that outputs PS for photo images * generic/tkImgPhoto.c: new func ImgPhotoPostscript and added that in as ps proc in tkPhotoImageType. * generic/tkStubInit.c: * generic/tkDecls.h: * generic/tk.decls: added Tk_PostscriptPhoto * generic/tkConfig.c (DoObjConfig): removed direct setting of interp->result. * mac/tkMacWm.c (Tk_WmCmd): initialized gotToplevel in colormapwindows case (bug found by Reasoning, Inc's automated code testing). 2000-04-24 Eric Melski <ericm@scriptics.com> * unix/mkLinks: * doc/GetHWND.3: Man page for Tk_GetHWND [Bug: 1863]. * unix/mkLinks: * doc/HWNDToWindow.3: Man page for Tk_HWNDToWindow [Bug: 1869]. * unix/mkLinks: * doc/AddOption.3: Man page for Tk_AddOption [Bug: 1854] 2000-04-22 Jim Ingham <jingham@cygnus.com> * mac/tkMacDialog.c (Tk_MacGetOpenFile): Add empty bodies for the "-initialfile" and "-defaultextension" options. * mac/tkMacDialog.c (NavServicesGetFile): Only cons the result up into a list if multiple is true. * mac/tkMacMenus.c (SourceDialog): Use the "tk_getOpenFile" instead of hand-coding the dialog with StandardGetFile. This way we get the Navigation dialogs for free. * doc/getOpenFile.n: Document the -multiple and -message flags which are only implemented on the Mac. Also note that the -title works on the Mac with Nav Services installed. 2000-04-19 Eric Melski <ericm@scriptics.com> * doc/WinViewable.3: * unix/mkLinks: Removed docs for Tk_IsViewable. * win/tkWinDialog.c: Removed calls to Tk_IsViewable. * generic/tkUtil.c: * generic/tkStubInit.c: * generic/tkDecls.h: * generic/tkCmds.c: * generic/tk.decls: Removed Tk_IsViewable function (it was not actually needed). 2000-04-19 Jeff Hobbs <hobbs@scriptics.com> * win/aclocal.m4: made SC_PROG_TCLSH search specifically for tclsh*.exe type files to find an executable. * win/Makefile.in: fixed up cleanup, winhelp, cat32 targets * library/console.tcl: made console use systemfixed font on Win * generic/tkEntry.c: removed unnecessary ENTRY_VALIDATE #define 2000-04-19 Eric Melski <ericm@scriptics.com> * generic/tkRectOval.c (ConfigureRectOval): Added checks for valid outline settings before creating of outline GC; this means that it is really possible now to have an oval or rectangle with no outline. [Bug: 5029]. 2000-04-19 Jeff Hobbs <hobbs@scriptics.com> * library/choosedir.tcl (::tk::dialog::file::chooseDir::Config): * library/tkfbox.tcl (::tk::dialog::file::Config): removed the extraneous glob on -initialdir after file isdir already returned 1 and moved cd trick into this case as the else already uses [pwd]. [Bug: 5181] * win/winMain.c: moved extern call out of WinMain func * README: * generic/tk.h: * unix/configure.in: * unix/tk.spec: * win/configure.in: bumped to version 8.3.1 * library/msgbox.tcl (tkMessageBox): changed to use grid in some places, realign icon to anchor nw. * mac/tkMacScale.c: reverted tkMacScale.c to 1.5 equivalent (it was accidentally bumped forward). 2000-04-18 Eric Melski <ericm@scriptics.com> * win/tkWinPointer.c: Changed Mod2Mask in TkWinGetModifierState to ALT_MASK, to fix some event problems [Bugs: 1160, 5088]. * win/tkWinX.c: Changed Mod2Mask in GetState to ALT_MASK, to fix some event problems [Bugs: 1160, 5088]. * generic/tkInt.h: Moved definition of ALT_MASK and META_MASK here so that it would be accessible from other modules than tkBind.c. * generic/tkBind.c: Added code in BindEvent to check for ALT_MASK and META_MASK in the event state field, as this field may not be set up with the correct display modifier mask bits if the XEvent structure was created by [event generate] or by the Windows X emulation. [Bugs: 1160, 5088]. 2000-04-18 Scott Redman <redman@HILO> * win/tk.rc: * win/wish.rc: * win/wish.ico: Modified copyright dates in Windows resource files. Updated the icon for wish.exe. 2000-04-17 Eric Melski <ericm@scriptics.com> * win/tkWinDialog.c: Added checks for visibility of parent window before creating MessageBox and ChooseColor dialogs; this prevents the application from locking when the parent is withdrawn and the message box is created. In these cases, the window will be created without a parent. * unix/mkLinks: Added WinViewable.3. * tests/msgbox.test: Added tests for patch from [Bug: 4997]. * library/msgbox.tcl: * library/dialog.tcl: Applied patch from [Bug: 4997]; detaches dialog window from parent if parent is not viewable. * library/bgerror.tcl: Removed workaround from [Bug: 4370]; this is superceeded by patches to dialog.tcl. * generic/tkCmds.c: Changed WinfoObjCmd to use Tk_IsViewable function to determine visibility of windows instead of inlining the code. * generic/tkStubInit.c: * generic/tkDecls.h: * generic/tk.decls: Added Tk_IsViewable declaration. 2000-04-17 Eric Melski <ericm@scriptics.com> * library/text.tcl: Tweaked double-/triple-click selection; previously, anchor and insert marks were placed in unexpected locations following a double or triple click. Now they are placed logically. Also tweaked the extension of selection via shift-double-clicks so that it no longer selects the contiguous whitespace on the side of the selection opposite the double-click. [RFE: 4253]. * doc/menu.n: Added note regarding rendering of checkbuttons/radiobuttons in menubars on different platforms -- some systems do not draw indicators for check/radiobuttons in menubars. * library/menu.tcl: Corrected behavior of checkbuttons/commands/radiobuttons in menubars [Bug: 630]. * tests/grid.test: Added test for [grid propagate . 0] to not toggle. * generic/tkGrid.c: Fixed bogus logic in [grid propagate] that caused [grid propagate . 0] to act as a toggle instead of an absolute set. [Bug: 2286]. 2000-04-16 Jeff Hobbs <hobbs@scriptics.com> * win/tkWinColor.c (FindSystemColor): correct calculation of colors when shifting value. [Bug: 4919] 2000-04-16 Jim Ingham <jingham@cygnus.com> * mac/tkMacPort.h: protect against strncasecmp already defined - it is in the Pro5 version of MSL. * mac/tkMacWindowMgr.c (GenerateKeyEvent): Check for a null tkWin. If the hidden window we use for double-buffering controls manages to percolate to the top (should never happen, but...) this will keep us from crashing. * mac/tkMacButton.c (InitSampleControls): Hide the double-buffering window BEHIND the first "." window you can find. This will keep it from ever being the front window, and thus a black hole for events. * mac/tkMacButton.c (ButtonEventProc): Disable the controls when the window is in the background. This is required by the MacOS HIG. This doesn't always get called when it should, it still needs more work. * mac/tkMacDialog.c: Pretty substantial rewrite to include Navigation Services support for systems which have it. 2000-04-14 Eric Melski <ericm@scriptics.com> * win/tkWinKey.c: Added check for ASCII delete character in KeycodeToKeysym, to fix [Bug: 5090]. See comment in code for more information. * generic/ks_names.h: Added Scroll_Lock and Sys_Req definitions. * win/tkWinKey.c: Changed implementation of KeycodeToKeysym, et. al., to use a keycode table for lookups; this will result in faster keycode -> keysym translations for non-ASCII keys like Control, Alt, etc. 2000-04-14 Jeff Hobbs <hobbs@scriptics.com> * win/tkWinWm.c (WmProc): added check in WM_MOUSEACTIVATE so we correctly activate native menus when clicking in when we didn't have focus [Bug: 2272] * generic/tkCanvas.c (CanvasEventProc:2451): corrected cast * generic/tkEntry.c (Tk_EntryObjCmd): adjusted finishing error cases and changed TK_CONFIG_NULL_OK to TK_OPTION_NULL_OK * tests/scale.test: * generic/tkScale.c: * generic/tkScale.h: * unix/tkUnixScale.c: * mac/tkMacScale.c: moved (PixelToValue|ValueToPixel|SetScaleValue) to tkScale.c. Caused an associated variable to be immediately set [Bug: 4833] * library/scale.tcl (tkScaleActivate): reduced number of scale redisplays by checking current value of state before setting it again. [Bug: 4191] * tests/winDialog.test: tk_chooseDirectory seems to get a noop from GetOpenFileName in the static build, hanging some tests. The tests were fixed to timeout (noop cause unknown). * unix/aclocal.m4 (SC_ENABLE_THREADS): enhanced the detection of pthread_mutex_init [Bug: 4359] and (SC_CONFIG_CFLAGS) added --enable-64bit-vis switch for Sparc VIS compilation [Bug: 4995] 2000-04-13 Eric Melski <ericm@scriptics.com> * win/tkWinKey.c: Added smarts to check whether the left or right Control, Shift, or Alt key was pressed. [Bug: 870]. * win/tkWinMenu.c: Corrected code that created separator items on menus; originally, it requested that the system be responsible for drawing those items, so it would ignore configuration items like the widget background. Now, we draw the separators ourselves (as we do with every other kind of menu item already). [Bug: 1166]. * win/tkWin3d.c: * unix/tkUnix3d.c: Applied patch from [RFE: 2501]: adds more sophisticated smarts to TkpGetShadows, so that the highlight of a very bright color is actually distinguishable from the color, and the shadow of a very dark color is similarly distinguishable from the color. * generic/tkCanvas.c: Applied patch from [Bug: 4202]; adds a check for NULL tkwin in Tk_CanvasEventuallyRedraw. 2000-04-12 Jeff Hobbs <hobbs@scriptics.com> * test/winClipboard.test: * win/tkWinInt.h: * win/tkWinClipboard.c (UpdateClipboard): * win/tkWinX.c (GenerateXEvent): added updatingClipboard tsd and TkWinUpdatingClipboard accessor function to allow us to flag ourselves when we are the ones updating the clipboard. This corrected inability to create our own clipboard types within a Tk application. [Bug: 2338 4318] * win/tkWinTest.c (TestclipboardCmd): improved TestclipboardCmd with better error handling and obj'ification 2000-04-11 Eric Melski <ericm@scriptics.com> * msgcat.n: Added docs for new behavior from patch in [Bug: 4158]. * msgcat.test: Added tests for new behavior from patch in [Bug: 4158]. * msgcat.tcl: Applied patch from [Bug: 4158], which enables msgcat::mc to search the entire namespace ancestry chain for message translations (ie, first it checks the current namespace, then the parent, then the parent's parent, etc). Also allows the specification of additional args for msgcat::mc; if extra args are given, the [format] command is used to substitute the additional args in the translated message. * library/bgerror.tcl: Moved check for withdrawn state after check for tkerror; this was causing problems when tkerror was used. 2000-04-10 Eric Melski <ericm@scriptics.com> * library/bgerror.tcl: Added check for withdrawn state of . and unsetting of transient bit for .bgerrorDialog if . is not viewable; this protects against the application hanging on systems like Windows, where transient windows are withdrawn with their parents. [Bug: 4370]. * tests/event.test: Added test for [event generate $widget <Alt-z>] [Bug: 4611]. * tests/choosedir.test: Changed "namespace import ::tcltest" to "namespace import -force ::tcltest". * win/tkWinKey.c: * unix/tkUnixKey.c: * mac/tkMacKeyboard.c: Changed InitKeymapInfo to TkpInitKeymapInfo. [Bug: 4611]. * generic/tkStubInit.c: * generic/tkIntDecls.h: Re-gen'd from tkInt.decls. * generic/tkInt.decls: Added TkpInitKeymapInfo to list of function decls. * generic/tkBind.c (HandleEventGenerate): Added code to initialize keymap info if necessary, and to correctly set modifier bits in XEvent structure create to handle [event generate] calls. Previously, the alt/meta bits were not set correctly, so [event generate $widget <Alt-z>] would always fail. [Bug: 4611] 2000-04-07 Jeff Hobbs <hobbs@scriptics.com> * generic/tkGrid.c (InitMasterData): fixed uninit'd data in GridMaster struct [Bug: 4387] * library/safetk.tcl (disallowTk): made disallowTk work in the simple case. * library/comdlg.tcl (tkFocusGroup_In): fixed key navigation problems in dialogs under CDE [Bug: 2960] * tests/winDialog.test: removed knownBug constraint from 5.16 * win/tkWinFont.c (GetScreenFont): corrected adjustment against LC_FACESIZE limitation for NT [Bug: 4931] * win/makefile.vc (TKTEST_OBJS): * win/Makefile.in (TKTEST_OBJS): moved tkWinTest.c from normal objs to TKTEST_OBJS where it belonged. 2000-04-03 Jeff Hobbs <hobbs@scriptics.com> * generic/tkTest.c: fixed incorrect platform inclusion for TkplatformtestInit (it would never get called). * unix/Makefile.in (MAN_INSTALL_DIR): patch to accept --mandir correctly [Bug: 4085] * library/clrpick.tcl (tkColorDialog_Config): error now thrown when -initialcolor "" specified. [Bug: 4198] 2000-03-31 Jeff Hobbs <hobbs@scriptics.com> * doc/DrawFocHlt.3: doc name correction * generic/tkEntry.c: set TK_OPTION_NULL_OK bit on -invcmd option and removed #ifdef ENTRY_VALIDATE expressions * library/menu.tcl (tkMenuInvoke): corrected naming of tearoffs [Bug: 4506] * library/tkfbox.tcl (tkIconList_Goto): caused browsecmd to be called in tkIconList_Select. This causes the entry to be set properly when using the type-in-name-in-listbox bindings. * win/tkWinDialog.c: added unicode-aware open/save file dialogs * win/tkWinFont.c (TkpFontPkgInit): move private ref to platformId to TkWinGetPlatformId * win/tkWinMenu.c (SetDefaults): moved private use of versionInfo to TkWinGetPlatformId and removed all code for (versionInfo.dwMajorVersion < 4) (== Win32s) * win/tkWinX.c: * win/tkWin32Dll.c: moved TkWinGetPlatformId to tkWinX.c * win/tkWinInit.c: added TkWinXInit to TkpInit to ensure that its called for static Windows shells. [Bug: 3647] * win/tkWinInt.h: * win/tkWinX.c: * win/tkWinDraw.c (SetUpGraphicsPort): * win/tkWinScrlbr.c (UpdateScrollbar): removed use of tkpIsWin32s * win/tkWinInt.h (TkWinDCState struct): added bkmode value * win/tkWinDraw.c (TkWinGetDrawableDC, et al): added support for properly transparent dashed lines on Windows. [Bug: 4617] 2000-03-30 Eric Melski <ericm@scriptics.com> * generic/tkImgGIF.c: Fixed some ANSI specific bits to avoid compile problems with non-ANSI compilers (ie, replace const with CONST, etc). [Bug: 4223]. * unix/configure.in: Applied patch from [Bug: 4237]; ensures that srcdir is fully qualified. * unix/Makefile.in: Applied patch from [Bug: 4237]; if tcltest was not compiled, make test/tktest failed. Now it has a rule to build tcltest if it has not been built. 2000-03-28 Eric Melski <ericm@scriptics.com> * library/tkfbox.tcl: Moved an overlooked tkFDialog* function in ::tk::dialog::file namespace. * tests/unixWm.test: Added tests for memory leak conditions in tkUnixWm.c. * tests/canvas.test: Added test for bad configuration options on empty and non-empty canvas. * generic/tkCanvas.c: Removed bad code in CANV_CONFIGURE block of CanvasWidgetCmd; this was causing non-empty canvases to improperly handle bad configuration options [Bug: 4456]. 2000-03-27 Eric Melski <ericm@scriptics.com> * unix/tkUnixWm.c: Applied patch from [Bug: 4405]; fixes memory leak in Unix wm command. 2000-03-24 Eric Melski <ericm@scriptics.com> * tests/filebox.test: * tests/choosedir.test: Updated tests. * library/xmfbox.tcl: Updated to stash data array in ::tk::dialog::file namespace instead of in global namespace. * library/tkfbox.tcl: Extended some functions to support creation of a choosedir dialog, to allow greater code reuse between the two dialogs. Moved tkFDialog* functions into a namespace (::tk::dialog::file). Because these are private Tk functions (and should thus not be used directly by users), this should not impact anybody (the tk_getOpenFile and tk_getSaveFile commands still exist at the global scope). * library/tk.tcl: * library/tclIndex: Updated function names for tkFDialog* functions and choosedir functions. * library/choosedir.tcl: New and improved implementation of tk_chooseDirectory dialog. Based on tk_getOpenFile dialog. 2000-03-23 Eric Melski <ericm@scriptics.com> * generic/tkWindow.c: * generic/tkInt.h: Updated Tcl_OptionCmd -> Tcl_OptionObjCmd * generic/tkOption.c: Tcl_Obj'ectified the "option" command. 2000-03-22 Eric Melski <ericm@scriptics.com> * library/listbox.tcl (tkListboxCancel): Added a check for empty string value for tkPriv(listboxPrev). Without this check, it's possible to get a stack trace under certain conditions. [Bug: 4373]. 2000-03-15 Sven Delmas <sven@scriptics.com> * win/tkWinDialog.c: Changed the behavior for the tk_chooseDirectory dialog under Windows. Instead of trying to return the currently selected listbox entry (which didn't work in case the user selected the initial directory anyway), we now return the value shown in the entry. This seems to be in accordance with the expected behavior for this dialog. 2000-03-14 Eric Melski <ericm@scriptics.com> * tests/choosedir.test: Marked test 3.1 and 3.2 as bad until the issue with those tests on IRIX can be determined. 2000-03-10 Eric Melski <ericm@scriptics.com> * library/menu.tcl: Applied patch from [Bug: 4155]; protects against grabs on non-viewable windows. 2000-03-08 Eric Melski <ericm@scriptics.com> * tests/choosedir.test: Modified test 3.1 (-mustexist works) to be more careful about cleaning up its potentially troublesome after events. 2000-03-07 Eric Melski <ericm@scriptics.com> * tests/button.test: * generic/tkButton.c: Added -disabledforeground/-state to labels. 2000-03-07 Jeff Hobbs <hobbs@scriptics.com> * tests/entry.test: * generic/tkEntry.c (EntrySetValue): malloc the value when validating because validation could cause the pointer to become invalid. Also fixed configure to not trigger focus-based validation. Improved use of Tcl_WrongNumArgs. [Bug: 4320] 2000-03-06 Eric Melski <ericm@scriptics.com> * library/menu.tcl: Added a check in tkMenuFirstEntry that changes menu behavior to only auto-post an immediate child cascade if we are currently on a menubar menu. This prevents massive auto-cascading in cases where the first entry of the cascade is itself a cascade, and the first entry of that cascade is a cascade, and the first entry of that cascade is a cascade ... [Bug: 676]. * generic/tkOldConfig.c: Added check for NULL tkwin value in Tk_ConfigureWidget [Bug: 4079] * generic/tkWindow.c: Added check for NULL tkwin value in Tk_NameToWindow [Bug: 4079] 2000-03-02 Jeff Hobbs <hobbs@scriptics.com> * tests/color.test: * xlib/xcolors.c (XParseColor FindColor): * win/tkWinColor.c (XAllocColor): Fixed bit fiddling for colors to return "correct" values for color mapping. [Bug: 4282] * unix/Makefile.in (SCRIPT_INSTALL_DIR): removed extraneous '/' * unix/aclocal.m4: corrected TCL_NEEDS_EXP_FILE to be 1 for AIX * win/tkWinInt.h: change extern to EXTERN for TkWinChildProc declaration with extra #defs. [Bug: 4240] * library/focus.tcl: fixed tkFocusOK to protect $w in uplevel with list. [Bug: 4208] * doc/CrtItemType.3: fixed docs for Tk_CreateItemType to reflect changes made in 8.3.0 (but old style would still work as well). [Bug: 4252] * tests/config.test: extra test to check object cleanup when destroying the widget * generic/tkListbox.c (DestroyListbox): fixed crash in DestroyListbox due to null tkwin. [Bug: 4207] * tests/entry.test: added test suite for entry validation * doc/entry.n: improved docs discussing caveats and gotchas when mixing textvar with widget validation * generic/tkEntry.c (EntryValidateChange): improved handling of validation with relation to -textvariable. Previously, it would turn off whenever the textvar was set. Now it will it will turn off only when the textvar is set and validation returns 0. Added %V (type of validation occuring) to %-subs to help work with trickier validation. 2000-03-01 Eric Melski <ericm@scriptics.com> * tests/clrpick.test: * library/clrpick.tcl: Added code to make color chooser dialog inherit screen setting from parent (bug #2334) 2000-02-25 Jeff Hobbs <hobbs@scriptics.com> * win/tkWinWm.c (RaiseWinWhenIdle): Checked for the possibility that the window could be destroyed (can occur with wm deiconify .toplevel; destroy .toplevel). 2000-02-25 Eric Melski <ericm@scriptics.com> * generic/tkImgGIF.c: Applied "spirit of" the patch in 1605 (the submitted patch was more complicated than necessary and did not extend to writing GIF's, only reading), to allow reading/writing of GIF files on EBCDIC and other non-ASCII based systems. 2000-02-14 Eric Melski <ericm@scriptics.com> * unix/tk.spec: RPM specification for producing a binary Tk RPM for Linux. * unix/Makefile.in: Added rpm target to generate Tk binary RPM. 2000-02-10 Jeff Hobbs <hobbs@scriptics.com> 8.3.0 RELEASE * changes: updated for 8.3.0 release * generic/tkImgGIF.c (FileReadGIF): added cast for trashBuffer * generic/tkIntXlibDecls.h: * generic/tkInt.decls: declared some Xlib emulation calls for the Mac * generic/tkFrame.c (TkInstallFrameMenu): added extra panic to inform user of bad call when framePtr is NULL [Bug: 2530] * generic/tkMenu.c (DestroyMenuInstance): Placed checks around menu name objects before trying to incr the ref. [Bug: 3402] * generic/tkTest.c: removed USE_OLD_IMAGE def for Mac * library/listbox.tcl: * library/text.tcl: added support for <4> and <5> for mousewheel style scrolling on Unix for mice that map to these buttons. * tests/scrollbar.test: fixed check of testmetrics command to allow unix tests to run (testmetrics is mac/pc only) * unix/tkUnixWm.c (Tk_CoordsToWindow): qualified delete of error handler as the goto label is reached from above and below. * unix/configure.in: * unix/aclocal.m4: cleaned up macros to coincide with tcl.m4, added -export-dynamic to LDFLAGS for FreeBSD-3+ [Bug: 2998] * unix/README: * unix/Makefile.in (dist): removed porting.notes and porting.old from distribution and CVS. The information was very outdated. Now refer to http://dev.scriptics.com/services/support/platforms.html * xlib/xgc.c: #def'd out XDrawSegments for the Mac, and added some extra include info for the Mac 2000-02-09 Jim Ingham <jingham@cygnus.com> * mac/tkMacButton.c: Stop removing the appearance window from the Window List. It is not clear why Ray did this, and it causes the Appearance manager to crash at random times. * mac/tkMacWM.c: Add support in unsupported1 style for the Appearance specification of window styles, including floating window support. * mac/tkMacWindowMgr.c: Operate on the front non-floating window, unless the mouse is directly over the floating window. Also, keystrokes go to the front non-floating window. * mac/tkMacAppInit.c: Initialize floating window support. * mac/tkMacScrlbr.c: * mac/tkMacmenu.c: Fixes for floating windows - operate on the FrontNonFloatingWindow. * mac/tkMacLibrary.r: Fix typo in File info string. * mac/tkMacApplication.r: Fix typo in file info string. Add Finder balloon help for no apparent reason. * mac/tkMacSubwindows.c: Change panic in tkMacGetDrawablePort to Debugger. This is only a temporary fix. The panic is only triggered when a safeTk interpreter is torn down, and ignoring it does no harm. I haven't figured out how to avoid it yet, however. Also use the Appearance MoveWindowStructure call when available. New Files: * MW_TkOldImageHeader.h: Handle #defining USE_OLD_IMAGE for tkImgPPM.c. * MW_TkTestHeader.h: * MW_TkTestHeader.pch: * MW_TkHeader.h: Add separate prefix files for test & release versions of Tk, so we can just have separate targets w/o having to edit files. * tclets.r: The D&D Tclets icon in rez form so we can have a target for this. The above are curtesy of Daniel Steffen (steffen@math.mq.edu.au) * tkMacAppearanceStubs.c: Stubs of the Mac Appearance calls I use so I can link the static 68K Shell without putting ifdef's all over the code. 2000-02-08 Jeff Hobbs <hobbs@scriptics.com> * generic/tk.decls: * generic/tkBind.c: * generic/tkInt.decls: * generic/tkIntDecls.h: * generic/tkStubInit.c: * mac/tkMacKeyboard.c: * unix/tkUnixKey.c: * win/tkWinKey.c: Fix for keyboard handling of "dead" keys and caps lock from Peter Spjuth. [Bug: 4105 3359 2493] Split functions into platform specific files: Static functions GetKeySym(), SetKeycodeAndState() and InitKeymapInfo() from tkBind.c moved into platform files tkWinKey.c tkUnixKey.c and tkMacKeyboard.c. GetKeySym() and SetKeycodeAndState() renamed to Tkp* and made public (as private functions) in tkInt.decls. Step 2, fixes in tkWinKey.c New static function: KeycodeToKeysym(), based on XKeycodeToKeysym() but with different arguments, and a lot of improvements. TkpGetString() changed to use KeycodeToKeysym() + other fixes. TkpGetKeySym() changed to use KeycodeToKeysym() + other fixes. InitKeymapInfo() changed to use KeycodeToKeysym(). TkpSetKeycodeAndState() rewritten, mostly by copying code from XKeysymToKeycode(). XKeycodeToKeysym() rewritten. Preferably it should be removed. EXPLANATION: The main problem is ToAscii() which has a lot of side effects, and also that XKeycodeToKeysym() is not provided enough input to do a proper job. The changes' main goal is to avoid calling ToAscii() if not necessary, and to provide it with as correct information as possible when called. Also some attempts to clean up what ToAscii() did are done. See the code for details. BUGS FIXED: Typing shifted (and AltGr) dead keys did not work. Keyboard lock lamps did not work on Win98. Events regarding AltGr-keys behaved badly. Example: On a Swedish keyboard, $ is typed with AltGr-4. That keyboard event would get the keysym '4' not 'dollar'. Also, doing [event generete . <Key-dollar>] would send keysym '4'. Translation to ascii in TkpGetString did not handle return and tab correctly. I.e. [event generate . <Key-Return>] gave wrong %A * generic/tkDecls.h: * generic/tk.decls: * generic/tk.h: moved new public functions created in dash patch to the stubs interface [Bug: 4062] * generic/tk.h: * doc/CrtImgType.3: * doc/CrtPhImgFmt.3: * generic/tk.h: * generic/tkImgGIF.c: * generic/tkImgPhoto.c: * generic/tkStubImg.c (new file): * generic/tkTest.c: * unix/Makefile.in: * win/Makefile.in: * win/makefile.vc: improved support for moving from the old style image C API to the new obj'ified one with new Tk_InitImageArgs command and stub'ing of image code. See docs for how to make the transition. [Bug: 4060] * library/tk.tcl: wrapped check for tcl_platform(os) around info exists because it won't in safe interpreters * win/tkWinFont.c: corrected symbol font use to only work on 8-bit characters [Bug: 2406] * unix/aclocal.m4: changed all -fpic to -fPIC * README: * unix/configure.in: * win/configure.in: * generic/tk.h (TK_RELEASE_SERIAL): Moved to 8.3.0 patchlevel 2000-02-07 Eric Melski <ericm@scriptics.com> * library/tkfbox.tcl: Applied patch from bug #4117, tk_getOpenFile/getSaveFile doesn't do the right thing when user types a directory name in the entry and a default extension is specified. 2000-02-05 Jeff Hobbs <hobbs@scriptics.com> * unix/tkUnixScale.c (TkpDestroyScale): changed ckfree to Tcl_EventuallyFree to behave with Tcl_Preserve in TkpDisplayScale (prevents possible segfault). 2000-02-03 Eric Melski <ericm@scriptics.com> * tests/canvText.test: test for fix for bug #2525. * generic/tkFont.c (Tk_ComputeTextLayout): Was erroneously setting the width of newline-only text display chunks to some arbitrary huge number, instead of 0; this was interfering with things like the canvas find enclosed feature. (bug #2525). * tests/text.test: * generic/tkText.c (DumpLine/DumpSegment): Changed DumpSegment to take a TkTextIndex instead of two integer offsets, so that it could use TkTextPrintIndex to format the offsets into an index, which makes it UTF smart (bug #2582). 2000-02-01 Eric Melski <ericm@scriptics.com> * library/tk.tcl: * library/tclIndex: * library/choosedir.tcl: Moved choosedir functions into the ::tk::dialog::chooseDir namespace instead of a toplevel ::tkChooseDirectory namespace. Additional cleanup on the chooseDir dialog. 2000-02-01 Jeff Hobbs <hobbs@scriptics.com> * doc/text.n: clarified docs on what happens during a search with -count when images/windows are embedded * win/Makefile.in (install-*): reduced verbosity of install * win/tkWinPixmap.c (XGetGeometry): added support for windows in XGetGeometry [Bug: 4069] * win/tkWinFont.c (GetScreenFont): fixed possible mem overrun with long font names [Bug: 4108] * win/tkWinDialog.c: added EnableWindow calls to dialogs to correct for possible loss of control in parent Tk toplevel [Bug: 1212 et al] * generic/tkRectOval.c (ConfigureRectOval): * generic/tkCanvLine.c (ConfigureLine): * generic/tkCanvPoly.c (ConfigurePoly): * generic/tkCanvArc.c (Configure/DisplayArc): fixed handling for negative dash values [Bug: 4104] * generic/tkScale.c (TkRoundToResolution): fixed incorrect assumption that (N+1)*delta = N*delta + delta with floating point math [Bug: 3689, 4099] (DestroyScale) Fixed check for cancelling TkpDisplayScale (was REDRAW_ALL, is now REDRAW_PENDING) * tests/listbox.test: corrected test case for listbox itemconfigure * unix/aclocal.m4: added *BSD ELF recognition for SHARED_LIB_SUFFIX determination (from Tcl's tcl.m4) 2000-01-27 Eric Melski <ericm@scriptics.com> * generic/tkImgPhoto.c: Removed unneccesary object translation in MatchStringFormat (bug #4103). 2000-01-27 Eric Melski <ericm@scriptics.com> * generic/tkImgGIF.c: Additional code cleanup (now we only have one decoder! neat!) 2000-01-26 Eric Melski <ericm@scriptics.com> * doc/getOpenFile.n: * doc/chooseDirectory.n: Man page/cross links for tk_chooseDirectory (bug #1786). * library/tk.tcl: * library/tclIndex: Added hooks for tk_chooseDirectory. (bug #1786) * library/choosedir.tcl: tk_chooseDirectory implementation for Unix/Mac (bug #1786). * generic/tkImgPhoto.c: Added some comments regarding slow processing of transparent images. * generic/tkImgGIF.c: Improved GIF decoder for ~60% speed increase. Added some comments on how to further improve the implementation, time permitting. * doc/photo.n: Added a description of what the -data string can contain (base64 or binary data). * generic/tkImgPhoto.c: Fixed bug with use of binary data for "-data" option to "image create" command. 2000-01-21 Eric Melski <ericm@scriptics.com> * library/tkfbox.tcl: Fixed bug relating to incorrect parent values for error message boxes displayed by the file dialog (bug #3616). * tests/text.test: * generic/tkText.c: Fixed bug relating to regexp searching for empty lines; previously, the starting line was ignored. (bug #1643). 2000-01-20 Jeff Hobbs <hobbs@scriptics.com> * library/text.tcl: fixed double-click selection behavior where there were embedded windows/widgets in the same line. [Bug: 3989] * win/tkWinWm.c (TkWmProtocolEventProc): cached atom name as the window could get destroyed during eval [Bug: 2513] * generic/tkCanvLine.c (LineCoords): fixed segfault when too few coords were passed to a line with certain options set (it should always have thrown an error anyway). [Bug: 4042] * tests/text.test: * generic/tkText.c: fixed missing " in error case and missing 'dump' in subcommand listing [Bug: 4036] * generic/tkListbox.c: adjusted use of basic string concatenation in (non-K&R behavior) [Bug: 4027] Swapped bg/fg class for -select(bg|fg) for listbox and their items [Bug: 4039] * unix/mkLinks: * doc/WindowId.3: added docs for Tk_IsContainer and Tk_IsEmbedded * doc/text.n: clarified mark gravity definition and usage of ``word'' in binding definitions. [Bug: 2004 2277 1388] * generic/tkInt.h: moved new TkDisplay useInputMethods structure element to end to not disturb position of previous elements in the structure (as compared to Tk <=8.2). 2000-01-20 Eric Melski <ericm@scriptics.com> * tests/grid.test: Added a test for the consecutive ^ and multiple widget case (bug #1386). * generic/tkGrid.c: Fixed interpretation of consecutive ^ characters in grid command. Previously, ^ ^ was interpreted as meaning that there must be a 2-column widget above to extend, neglecting the case where there was actually 2 1-column widgets above. Now, ^ ^ is interpreted as a possible width; the gridder will consume as many ^'s as there are columns in the widget, and leave the rest for the extension of other widgets. (bug #1386). 2000-01-19 Eric Melski <ericm@scriptics.com> * library/tk.tcl: Created a virtual event <<PrevWindow>> for reverse tab traversals, with one default binding <Shift-Tab>, and OS specific bindings for Linux, HP-UX, and IRIX. (bug #3163) 2000-01-13 Jeff Hobbs <hobbs@scriptics.com> * changes: updated changes file to reflect 8.3b2 mods * README: * generic/tk.h: * unix/configure.in: * win/configure.in: updated to patchlevel 8.3b2 * win/tkWinWm.c: added visibility event handler to make sure that transient window wrappers would be updated when the master was initially mapped. 2000-01-12 Jeff Hobbs <hobbs@scriptics.com> * tests/text.test: changed test to reflect change of -hidden to -elide in search options. * win/tkWinScrlbr.c: added check for valid hwnd in ModalLoopProc to avoid crash when building statically * doc/event.n: * generic/tkBind.c: prevented core with event -warp on Windows when window wasn't mapped [Bug: 4004] and added docs stating the requirement for mapped windows. * generic/tkCanvas.c: fixed mem leak with TagSearchExprInit [Bug: 3977] * generic/tkStubInit.c: * generic/tkDecls.h: remove non-existent Tk_(Get|Create)CanvasVisitor prototypes * generic/tkText.c: * generic/tkEntry.c: fixed cursor to not blink when widget was disabled [Bug: 1807] * generic/tkRectOval.c: added note about change to bloat for RectOval bounds calculation for WIN32 only * library/dialog.tcl: improved handling of $default arg to allow for name of given button, as well as bounds checking * doc/wm.n: * tests/winWm.test: * tests/unixWm.test: * mac/tkMacWm.c: * unix/tkUnixWm.c: fixed possible X error being raised [Bug: 3377] * win/tkWinWm.c: wm deiconify in zoom state [Bug: 2077], fixed possible flashing of unmapped toplevel in deiconify [Bug: 3338] and fixed mapping of transient window [Bug: 572] Also, for all wm's, extended 'wm state' command to allow setting of the state, and added official support of 'zoomed' state on Win. * unix/aclocal.m4: strtod bug on Tru64 [Bug: 3378] * unix/Makefile.in: added tests to prevent unnecessary chmod +x in source dirs while installing [Bug: 3367] * unix/configure.in: properly sub'ed in TK_SHARED_BUILD [Bug: 3385] 2000-01-05 Jeff Hobbs <hobbs@scriptics.com> * doc/text.n: * generic/tkText.c: * generic/tkText.h: * generic/tkTextBTree.c: * generic/tkTextDisp.c: * generic/tkTextTag.c: removed the -state option for text tags, and reoriented it around -elide, as -state disabled was never implemented, and -state hidden is better as -elide. * mac/tkMacClipboard.c: fixed i18n problems with clipboard [Bug: 3544] * library/entry.tcl: * library/focus.tcl: * library/listbox.tcl: * library/scale.tcl: * library/scrlbar.tcl: * library/tearoff.tcl: * library/text.tcl: * library/tkfbox.tcl: * library/xmfbox.tcl: fixed unprotected arg parsing through eval/after [Bug: 3943] * unix/Makefile.in: added unix/aclocal.m4 to distribution [Bug: 3938] * unix/aclocal.m4: changed NetBSD SHLIB_CFLAGS from -fpic to -fPIC * win/tkWinImage.c: added static declaration to function 1999-12-22 Jeff Hobbs <hobbs@scriptics.com> * changes: updated changes file * generic/tkScale.c: * generic/tkScale.h: * mac/tkMacScale.c: * unix/tkUnixScale.c: fixed potential segv from patch in 3897 * tests/unixWm.test: nonPOrtable -> nonPortable 1999-12-21 Jeff Hobbs <hobbs@scriptics.com> * generic/tk.h: * unix/configure.in: * win/configure.in: * win/aclocal.m4: * README: updated for patch level 8.3b1 * unix/tkUnixWm.c: fixed panic in Tk_CoordsToWindow to print error and continue instead (for Tix) [Bug: 716 et al] * scale.test: * generic/tkScale.c: * generic/tkScale.h: fixed possible core when freeing options (cursor) associated with scale widget [Bug: 3897] * doc/MeasureChar.3: fixed docs for Tk_MeasureChars to reflect code * doc/listbox.n: fixed formatting problem * generic/tk3d.c: added extra calculations to ensure that thin frames get refreshed too [Bug: 3596] * unix/tkUnixMenu.c: * unix/tkUnixFont.c: * generic/tkCanvText.c: * generic/tkEntry.c: * generic/tkFont.c: * generic/tkImgPPM.c: removed extranneous vars that were set but never used. * mac/tclMacHLEvents.c: fixed applescript for I18N [Bug: 3644] * unix/aclocal.m4: removed -O flag for AIX when using the IBM compiler (several versions have a bug that crops up in the text widget). [Bug: 2316] * unix/Makefile.in: removed extra slash in SCRIPT_INSTALL_DIR [Bug: 3896] * library/listbox.tcl: added extra checks for existence of tkPriv(listboxSelection) before it was used. [Bug: 3892] 1999-12-16 Jeff Hobbs <hobbs@scriptics.com> * doc/GetCursor.3: * win/tkWinCursor.c: added support for Windows cursors to TkGetCursorByName (.ani, .cur) using -cursor @<filename> (Ascher) [Bug: 1350] * win/tkWinWm.c: fixed 'wm deiconify' to update position of the toplevel if event is waiting before mapping. (Mao) [Bug: 3687] This removes the need for 'update idle' before 'wm deiconify' on Windows. * doc/listbox.n: added doc for <<ListboxSelect>> [Bug: 3500] * doc/getOpenFile.n: removed note that -initialfile didn't work for tk_getOpenFile * library/tkfbox.tcl: updated tk_get*File to better match the Windows file box it emulates, give proper support to -initialfile, and fixes lack of global tkPriv call. [Bug: 3735 3882] * doc/tk.n: added doc for 'tk useinputmethods ...' * tests/tk.test: * unix/tkUnixKey.c: * generic/tkCmds.c: * generic/tkEvent.c: * generic/tkWindow.c: * generic/tkInt.h: add 'tk useinputmethods ?-display win? ?bool?' call to provide support for disabling/enabling the use of XIM on X. This was previously all done at compile time, and always on. Now it is turned off by default, even when available, and the user must turn it on to use XIM (per display). * generic/tkCanvUtil.c: fixed bug in Tk_CanvasPsOutline that freed mem it shouldn't. * generic/tkFont.c: added "bitstream cyberbit" (popular Windows CJK font) to list of font fallbacks. (kenny) [Bug: 2407] * mac/tkMacMenu.c: finished bug 3075 by changing the char values of what was checked (verified correctness on Mac). 1999-12-13 Jeff Hobbs <hobbs@scriptics.com> * doc/canvas.n: added docs for items added by dash patch (-*dash*, -state, -active*, -disabled*, -offset, essentially rewrote the man patch for completely updated 8.3 canvas widget. * doc/entry.n: added docs for entry widget validation * doc/event.n: added docs for -warp * doc/text.n: doc'ed new -state value 'hidden' * doc/GetDash.3: (new file) man page explaining Tk_GetDash * generic/tkStubInit.c: * generic/tkDecls.h: * generic/tkIntXlibDecls.h: * generic/tkInt.decls: added XSetDashes and XWarpPointer * generic/tk.decls: added Tk_CreateSmoothMethod, and reserved two spots * generic/tk.h: added Tk_SmoothMethod struct, state item to canvas record, #defines for item state, support for using old char*-based canvas item C creation procedures with -DUSE_OLD_CANVAS, Tk_Dash, Tk_TSOffset (-offsets) & Tk_Outline structs and #defs, decls for dash, outline and postscript routines * generic/tkBind.c: added support for Quadruple clicks, and added the -warp option to 'event' with pointer warping routines * xlib/xgc.c: * generic/tkRectOval.c: * generic/tkCanvArc.c: * generic/tkCanvBmap.c: * generic/tkCanvImg.c: * generic/tkCanvLine.c: * generic/tkCanvPoly.c: * generic/tkCanvPs.c: * generic/tkCanvText.c: * generic/tkCanvUtil.c: * generic/tkCanvWind.c: * generic/tkCanvas.c: * generic/tkCanvas.h: Canvas and items received overhaul to with the addition of the dash patch (Nijtmans, et al) This includes objectification of the 'canvas' command, as well as support for (where appropriate) dashes in items, extended stipple support, state for all items, and postscript generation of images and windows. See the new canvas man page for related docs. * generic/tkEntry.c: added entry widget validation, see entry.n * generic/tkEvent.c: on simulated events, ButtonPress should be matched with ButtonRelease to be correct * generic/tkFont.c: corrected possible null reference * generic/tkFrame.c: made frame a Tcl_Obj based command * generic/tkGet.c: added TkGetDoublePixels * generic/tkImage.c: bug fixes from Img patch and new Tk_PostscriptImage and Tk_SetTSOrigin functions * generic/tkImgBmap.c: new ImgBmapPostscript function * generic/tkImgPhoto.c: new Tk_CreatePhotoOption, Tk_DitherPhoto * generic/tkInt.h: declarations for some new functions * generic/tkMessage.c: reworked relief drawing * generic/tkOldConfig.c: added TK_CONFIG_OBJS so old style ConfigureWidget calls can pass in Tcl_Obj arrays * generic/tkScrollbar.c: * generic/tkScrollbar.h: made -orient use an option table * generic/tkText.c: * generic/tkText.h: made -wrap and -state use option tables * generic/tkTextBTree.c: * generic/tkTextDisp.c: * generic/tkTextImage.c: * generic/tkTextMark.c: * generic/tkTextTag.c: * generic/tkTextWind.c: added support for -elide and -state hidden * generic/tkTrig.c: changed TkMakeBezierCurve to support returning the upper limit of points needed for spline * generic/tkUtil.c: new option table parsing routines * generic/tkWindow.c: init'ing of warp stuff, mouseButtonState related bug ids for the fixes: [Bug: 648 1541 1540 1779 2168 2311 2297 2340 2348 2578 3386] * tests/bind.test: * tests/canvImg.test: * tests/canvPsArc.tcl: * tests/canvPsImg.tcl: (new file) * tests/canvRect.test: * tests/canvText.test: * tests/canvas.test: * tests/defs.tcl: * tests/entry.test: * tests/event.test: * tests/font.test: * tests/frame.test: * tests/imgPhoto.test: * tests/safe.test: * tests/scale.test: * tests/scrollbar.test: * tests/select.test: * tests/text.test: * tests/textDisp.test: * tests/textTag.test: * tests/unixFont.test: * tests/unixWm.test: * tests/visual_bb.test: * tests/winClipboard.test: tests for the dash patch changes * unix/mkLinks: added GetDash.3 into the mkLink step * mac/tkMacDraw.c: mac still needs pointer warping routine * mac/tkMacXStubs.c: * win/tkWinDraw.c: * win/tkWinPointer.c: added support for pointer warping and platform specific support for dash patch items 1999-12-12 Jeff Hobbs <hobbs@scriptics.com> * generic/tkText.c: fixed bug in TextSearchCmd for multibyte chars (Darley) [Bug: 3839] * unix/aclocal.m4: added warning when configuring with --enable-threads that Tk may have problems 1999-12-09 Jeff Hobbs <hobbs@scriptics.com> * generic/tkImgGIF.c: updated casting * win/makefile.vc: removed 16bit stuff, simplified makefile. 1999-12-06 Scott Redman <redman@scriptics.com> * generic/tkMain.c: need to include tclInt.h for new hook functions that are internal-use-only. 1999-12-06 Jeff Hobbs <hobbs@scriptics.com> * library/comdlg.tcl: removed tclVerifyInteger and tclSortNoCase, they weren't used, and were not actually correct * mac/tkMacFont.c: * mac/tkMacMenu.c: * mac/tkMacWindowMgr.c: fixed greyed out menu items, handling of ... elipsis, font mapping problem, and enabled generated menu posting [Bug: 3705] 1999-12-02 Jeff Hobbs <hobbs@scriptics.com> * generic/tkInt.h: * generic/tkWindow.c: * generic/tkCmds.c: converted Tk_DestroyCmd, Tk_LowerCmd and Tk_RaiseCmd to their ObjCmd equivalent. * library/msgbox.tcl: added color icons for tk_messageBox on Unix and Mac when tk_strictMotif isn't set. (Hipp) * library/tk.tcl: added window bounds checking to ::tk::PlaceWindow * tests/imgPPM.test: fixed test 2.2 to use -format ppm (since we know have GIF write capability) 1999-12-01 Scott Redman <redman@scriptics.com> * generic/tkMain.c : * unix/tkAppInit.c: * win/winMain.c: Added added hooks into the main() code for supporting TclPro and other "big" shells more easily without requiring a copy of the main() code. 1999-11-29 Jeff Hobbs <hobbs@scriptics.com> * generic/tkImgGIF.c: added GIF writing that uses miGIF RLE [Bug: 2039, new patch] * library/entry.tcl: fixed up tkEntrySeeInsert (Nemthi) * generic/tkListbox.c: fixed 'get' of listbox to return a string when only one item is requested. * tests/clrpick.test: * tests/filebox.test: minor whitespace cleanup * library/tk.tcl: fixed missing $w in ::tk::PlaceWindow 1999-11-24 Jeff Hobbs <hobbs@scriptics.com> * library/clrpick.tcl: * library/msgbox.tcl: * library/tk.tcl: * library/tkfbox.tcl: * library/xmfbox.tcl: fixed dialogs to center over -parent, added utility functions ::tk::PlaceWindow, ::tk::SetFocusGrab, ::tk::RestoreFocusGrab to tk.tcl to help 1999-11-23 Eric Melski <ericm@scriptics.com> * tests/listbox.test: Added a test to check that the topIndex is update when items are removed from the listvar variable. * generic/tkListbox.c: Added a check the updates the topIndex when items are removed from the listvar variable. * tests/listbox.test: Added a test to check that the vertical scrollbar is updated when the listvar changes. * generic/tkListbox.c (ListboxListVarProc): added a check that sets the UPDATE_V_SCROLLBAR flag if the length of the listvar has changed. 1999-11-23 Jeff Hobbs <hobbs@scriptics.com> * generic/tk.h: * generic/tkConfig.c: added support for TK_OPTION_DONT_SET_DEFAULT as equiv for TK_CONFIG_DONT_SET_DEFAULT * generic/tkListbox.c: added TK_OPTION_DONT_SET_DEFAULT to the item specs 1999-11-19 Jeff Hobbs <hobbs@scriptics.com> * generic/tkColor.c: * generic/tkColor.h: fixed Tk_NameOfColor to work correctly, with minor change to TkColor struct. * generic/tkConsole.c: added static declaration to ConsoleDeleteProc function (proto already had it) * win/tkWinInt.h: removed TkFontAttributes typedef (was redundant with tkFont.h). * win/tkWinPort.h: put #ifndef __GNUC__ around redefinition of str[n]casecmp, as cygwin uses the originals. * win/tkWinX.c: changed GetCurrentTime to GetTickCount (the former is deprecated). [Bug: 2053] 1999-11-19 Eric Melski <ericm@scriptics.com> * tests/listbox.test: Added tests for itemcget and itemconfigure. * doc/listbox.n: Added documentation for -listvar option and for itemconfigure and itemcget commands. * generic/tkListbox.c: Added support for itemconfigure/itemcget listbox subcommands (addresses rfe #936) 1999-11-17 Eric Melski <ericm@scriptics.com> * tests/listbox.test: Updated tests for new error messages. * generic/tkListbox.c: Improved error messages for bad -listvar's. * tests/listbox.test: Added tests for bad -listvar's. * generic/tkListbox.c: Added handlers for bad -listvar's (ie, bad lists) * tests/listbox.test: Added tests for ListboxUpdateHScrollbar. * generic/tkListbox.c: Changed some old static buffers to base size on TCL_DOUBLLE_SPACE instead of (completely) hardcoding the size. * tests/listbox.test: New tests for -listvar functionality, and an odd extra case that wasn't covered before. * generic/tkListbox.c: Tests exposed some bugs, now fixed. 1999-11-16 Eric Melski <ericm@scriptics.com> * tests/listbox.test: Fixed tests to comply with new objectified error messages. No -listvar specific tests yet. * win/tkWinDefault.h: * unix/tkUnixDefault.h: * mac/tkMacDefault.h: Added default value for -listvar option. * generic/tkWindow.c: Changed "listbox" mapping from old-school to new-school objectified command. * generic/tkListbox.c: Objectified listbox; added support for -listvar option. Converted internal structure to use a Tcl list object to store the data. * generic/tkInt.h: Changed reference to Tk_ListboxCmd to Tk_ListboxObjCmd. 1999-11-09 Jeff Hobbs <hobbs@scriptics.com> * generic/tkGrid.c: changed Tcl_Alloc to ckalloc * generic/tkEntry.c: fixed C expr error in destroy of entry that could lead to 'malformed bucket chain' error * win/winMain.c: corrected winMain to not do a DebugBreak when returning an error message from the top level 1999-10-30 Jeff Hobbs <hobbs@scriptics.com> * win/tkWinKey.c: fixed XKeysymToKeycode to handle mapping of symbolic keysyms (Left, Home, ...) with event generate * library/entry.tcl: change tkEntrySeeInsert to avoid the use of a while loop that could eat CPU tremendously. Behavior of moving the cursor at the right edge changes slightly (previously it tried to keep the cursor at the right edge, now it moves the cursor to a "central right" location - better IMHO). 1999-10-28 Jeff Hobbs <hobbs@scriptics.com> * doc/CrtImgType.3: * doc/CrtPhImgFmt.3: * doc/FindPhoto.3: * doc/photo.n: * generic/tk.h: * generic/tkCmds.c: * generic/tkImage.c: * generic/tkImgBmap.c: * generic/tkImgGIF.c: * generic/tkImgPPM.c: * generic/tkImgPhoto.c: * generic/tkInt.h: * generic/tkTest.c: * generic/tkWindow.c: * tests/imgPhoto.test: added Img patch (Nijtmans) with docs, headers #def'd with USE_OLD_IMAGE. Upgrades image stuff to Tcl_Obj API, adds alpha channel (images are now 32 bpp) * makefile.vc: changed 'c:/program files' to c:/progra~1 1999-10-19 Jeff Hobbs <hobbs@scriptics.com> * library/scrlbar.tcl: changed tkScrollButtonUp to check for existence of tkPriv(relief) in order to avoid spurious release events * unix/Makefile.in: added ChangeLog to dist archive 1999-09-24 Jeff Hobbs <hobbs@scriptics.com> * */README: * win/makefile.vc: * */configure.in: * generic/tk.h: * library/tk.tcl: up'd to 8.3a1 * unix/Makefile.in: changed 'mkdir' to 'mkdir -p' * library/dialog.tcl: changed {Times 18} to {Times 12} for dialog font. 1999-09-16 Jeff Hobbs <hobbs@scriptics.com> * generic/tkFont.c: fixed processing of font options and error returned [Bug: 2075] * win/tkWinWm.c: fixed bug in 'wm deiconify' that raised the wrong toplevel, and changed it to not set focus on overridden toplevels 1999-09-15 Jeff Hobbs <hobbs@scriptics.com> * unix/aclocal.m4: added fix for FreeBSD-[1-2] recognition [Bug: 2070] and fix to AIX-* to get ldAix right [Bug: 2624], fixed AIX version check (readjust from 8-21 fix) and several other config fixes for AIX * mac/tkMacMenubutton.c: * unix/tkUnixMenubu.c: fixed permanently stippled menubutton image * win/tkWinButton.c: fixed possible pointer smash [Bug: 2733] 1999-09-14 Jeff Hobbs <hobbs@scriptics.com> * win/tkWinMenu.c: fix for stack overrun in GetTextFace [Bug: 909] 1999-09-01 Jeff Hobbs <hobbs@scriptics.com> * win/tkWinDraw.c: * unix/tkUnixDraw.c: fixed header style for TkpDrawHighlightBorder * generic/tkCanvas.c: fixed GC error (bg <> fg) in tkCanvas.c (from code added to support TkpDrawHighlightBorder) [Bug: 2676] * unix/aclocal.m4: added -bnoentry to the AIX-* flags * library/msgbox.tcl: changed the behavior of tk_messageBox on Unix to be more Windows like in handling of <Return> and the default button * library/button.tcl: * library/clrpick.tcl: * library/comdlg.tcl: * library/console.tcl: * library/dialog.tcl: * library/entry.tcl: * library/focus.tcl: * library/listbox.tcl: * library/menu.tcl: * library/msgbox.tcl: * library/palette.tcl: * library/safetk.tcl: * library/scale.tcl: * library/scrlbar.tcl: * library/tearoff.tcl: * library/text.tcl: * library/tk.tcl: * library/tkfbox.tcl: * library/xmfbox.tcl: updated commands to use [string] ops instead of expr equality operators 1999-08-21 Jeff Hobbs <hobbs@scriptics.com> * unix/aclocal.m4: Changed AIX-4.[2-9] check to AIX-4.[1-9] [Bug: 1909] 1999-08-20 Jeff Hobbs <hobbs@scriptics.com> * generic/tkCursor.c: fixed bug in GetCursorFromObj that caused panic [Bug: 2562] * TK 8.2.0 RELEASED 1999-08-13 Jim Ingham <jingham@cygnus.com> * mac/tkMacMenu.c: Tk_DrawChars ends up setting the menu background wrong. There is no clean way to stop it, so I use lower level routines here to draw the text. * mac/tkMacProjects.sea.hqx: Rearrange the projects so that the build directory is separate from the sources. Much more convenient! 1999-08-10 Jeff Hobbs <hobbs@scriptics.com> * win/tkWinWm.c: changed "wm deiconify" on Windows to raise and force the focus on the deiconified window (behavioral change from 8.1 to comply better with Windows style) [Bug: 1609] * doc/wm.n: clarified behavior of "wm deiconify". * generic/tkInt.decls: added TkSetFocusWin * generic/tkFocus.c: changed static SetFocus to TkSetFocusWin * library/clrpick.tcl: * library/console.tcl: * library/tk.tcl: fixed code where abbreviations where used in calling widget methods (confuses iWidgets) [Bug: 2422] 1999-08-09 Jeff Hobbs <hobbs@scriptics.com> * library/button.tcl: cleaned up programming (config -> configure) and fixed Windows relief bug [Bug: 664] * library/entry.tcl: changed Entry C/C/P to not use global data (now uses tkPriv(data)) [Bug: 1475] * library/listbox.tcl: fixed extended mode script error [Bug: 866] * doc/options.n: clarified that -troughcolor doesn't work on Windows * doc/wm.n: fixed wm positionfrom docs [Bug: 2284] 1999-08-01 Jeff Hobbs <hobbs@scriptics.com> * mac/tkMacPort.h: wrapped panic in #ifndef panic to avoid compiler errors when used with stubs-#defines, from Vince Darley. [Bug: 2389] 1999-07-31 Scott Redman <redman@scriptics.com> * xlib/X11/Xlib.h: Remove XFillRectangle since it is now in the stub tables. 1999-07-30 Jeff Hobbs <hobbs@scriptics.com> * generic/tkInt.decls: Added stub entry for XFillRectangle [Bug: 2446] 1999-07-30 <redman@scriptics.com> * win/makefile.vc: Corrected building threaded tktest.exe on Windows. Needed to link in .obj files from Tcl, needs to change later so that code is in Tk and doesn't require a Tcl build. Also added runtest target. 1999-07-29 <redman@scriptics.com> * generic/tkConsole.c: Allow tcl to open CON and NUL, even for std channels. Checking for bad/unusable std channels was moved to Tk since its only purpose was to check whether to use the Tk Console Window for the std channels. [Bug: 2393 2392 2209 2458] * win/Makefile.in: Corrected building threaded tktest.exe on Windows. Needed to link in .obj files from Tcl, needs to change later so that code is in Tk and doesn't require a Tcl build. 1999-07-22 <redman@scriptics.com> * Changed version to 8.2b2 * win/tkWinPort.h: Block out include of sys/stat.h in order to build extensions with MetroWerks compiler for Win32. [Bug: 2385] * unix/Makefile.in: Need to make install-sh executable before calling (with chmod +x). [Bug: 2413] * library/menu.tcl: Applied patch from Jeff Hobbs to fix typo. [Bug: 2425] 1999-07-21 <redman@scriptics.com> * unix/Makefile.in: Add Windows configure script to distribution. 1999-07-16 <redman@scriptics.com> * unix/Makefile.in: * win/Makefile.in: Copy the prolog.ps from the generic directory for install-libraries. * unix/aclocal.m4: Check for Alpha/Linux to set the IEEE flag to the compiler to be -mieee. Patch from Don Porter. 1999-07-08 <stanton@scriptics.com> * tests/unixSelect.test: Fixed broken test. * win/makefile.vc: Added special case target to ensure that tkStubLib.obj is built with -DSTATIC_BUILD. * win/tkWinX.c (TkWinChildProc): Changed to pass WM_WINDOWPOSCHANGED through to DefWindowProc to make OpenGL sub-windows happy. This allows Windows to generate the WM_SIZE and WM_MOVE messages. 1999-07-08 <redman@scriptics.com> * unix/configure.in: Fix Tk stub lib file names and flags. 1999-06-30 <redman@scriptics.com> * generic/tkGrid.c: removed deprecated functions (applied patch from Jan Nijtmans). [Bug: 2080] * generic/tkImgGIF.c: * generic/tkImgPPM.c: * generic/tkImgPhoto.c: Applied patch to allow Img extension to work with 8.2, from Jan Nijtmans. [Bug: 2068] * win/tkWinWm.c: Applied patch from Don Porter to prevent the windows code from calling the Tcl functions when the stub table has not been initialized in TkWinWmCleanup. [Bug: 2269] 1999-06-16 <wart@scriptics.com> * unix/configure.in: * unix/Makefile.in: * unix/aclocal.m4: Numerous build changes to make Tk conform to the proposed TEA spec * tkConsole.c: changed some variable types from (int) to (size_t) to prevent compiler warnings. Cast return value from strlen() to (int) in one place for the same reason. 1999-06-03 <stanton@scriptics.com> * unix/tkUnixSelect.c: * tests/unixSelect.test: * generic/tkSelect.c: Fixed selection code to handle Unicode data in COMPOUND_TEXT and STRING selections. [Bug: 1791] 1999-06-02 <stanton@scriptics.com> * generic/tkIntXlibDecls.h: * xlib/X11/Xlib.h: Added Mac specific defines to help with compilation. * generic/tkFont.c: lint 1999-06-01 <stanton@scriptics.com> * unix/tkUnixSelect.c: Improved I18N selection support. COMPOUND_TEXT is converted to/from iso2022, and STRING is converted to/from iso8859-1. There are still a few loose ends to tie up before this is completely done. * unix/tkUnixFont.c: Eliminated redundant case folding code. * generic/tkFont.c: Eliminated use of isupper/tolower in favor of Unicode variants. 1999-05-24 <stanton@scriptics.com> * generic/tkStubLib.c: * generic/tkStubInit.c: * generic/tkIntXlibDecls.h: * generic/tkIntPlatDecls.h: * generic/tkIntDecls.h: * generic/tkInt.decls: * generic/tkConsole.c: Various changes to try to get the Mac builds working. 1999-05-21 <stanton@scriptics.com> * win/tkWinClipboard.c: Fixed clipboard code to handle lack of CF_LOCALE information (e.g. from command.com). 1999-05-20 <redman@scriptics.com> * library/console.tcl: Changed copyright string to read 1999 Scriptics Corp. in wish console about box. 1999-05-19 <redman@scriptics.com> * generic/tk.h: Add extern "C" block around entire header file for C++ compilers to fix linkage issues. Submitted by Don Porter and Paul Duffin. 1999-05-18 <stanton@scriptics.com> * tests/winClipboard.test: * win/tkWinClipboard.c: Fixed clipboard code so it handles Unicode data properly on Windows NT and 95. [Bug: 1791] 1999-05-07 <stanton@scriptics.com> * library/menu.tcl: Fixed bug where tk_popup fails when called too quickly. [Bug: 2009] 1999-04-30 <stanton@scriptics.com> * Changed version number to 8.1.1. 1999-04-30 <stanton@scriptics.com> * Merged changes from 8.1.0 branch: * generic/tkDecls.h: * generic/tkIntDecls.h: * generic/tkIntPlatDecls.h: * generic/tkIntXlibDecls.h: * generic/tkPlatDecls.h: * generic/tkStubInit.c: Changed to avoid the need for forward declarations in stub initializers. Added extern "C" blocks around stub table pointer declarations so the stubs can be used from C++ code. [Bug: 1934] * generic/tkInt.decls: Added TkClipBox, XDrawSegments, and XForceScreenSaver to stubs. * generic/tkStubLib.c: Reordered declarations to avoid circularities and forward references. * generic/tkStubInit.c: Added includes for Mac. * generic/tkMenubutton.c: lint * generic/tkEntry.c: Fixed bad option table entry. * generic/tkImgBmap.c: * generic/tkImgPPM.c: * generic/tkImgPhoto.c: Set the -translation and -encoding options to binary for image files. (reported by Marco Gazzetta) 1999-04-23 <stanton@scriptics.com> * generic/tkInt.decls: Added TkClipBox, XDrawSegments, and XForceScreenSaver to stubs. * generic/tkStubLib.c: Reordered declarations to avoid circularities and forward references. * generic/tkStubInit.c: Added includes for Mac. * generic/tkMenubutton.c: lint * generic/tkEntry.c: Fixed bad option table entry. 1999-04-22 <redman@scriptics.com> * generic/tkImgBmap.c: * generic/tkImgPPM.c: * generic/tkImgPhoto.c: Set the -translation and -encoding options to binary for image files. (reported by Marco Gazzetta) 1999-04-20 <redman@scriptics.com> * xlib/X11/Xlib.h: changed definition of Status type to use a typedef instead of a #define to avoid conflicting with the cygwin win32 headers [Bug 1804] 1999-04-15 <stanton@scriptics.com> * Merged 8.1 branch into the main trunk 1999-04-09 <redman@scriptics.com> * generic/tkWindow.c: Fixed deadlock situation when the Initialize() function returns without releasing the mutex. Found while testing Bug 1700, during safe.test (tk). 1999-04-06 <stanton@scriptics.com> * generic/tkMain.c (Tk_MainEx): Changed to reset result before calling Tcl_EvalFile. The ensures that error messages will be generated cleanly. * tests/winfo.test: Enabled tests that previously failed. 1999-04-05 <stanton@scriptics.com> * library/bgerror.tcl: * library/button.tcl: * library/clrpick.tcl: * library/console.tcl: * library/dialog.tcl: * library/entry.tcl: * library/focus.tcl: * library/listbox.tcl: * library/menu.tcl: * library/msgbox.tcl: * library/palette.tcl: * library/scale.tcl: * library/scrlbar.tcl: * library/tearoff.tcl: * library/text.tcl: * library/tk.tcl: Lots of minor performance improvements contributed by Jeffrey Hobbs. [Bug: 1118] * win/tkWinWm.c (Tk_WmCmd): Fixed bad code in tracing suboption. [Bug: 1519] * library/tkfbox.tcl: Change to restore button text after an action to avoid the sticky "Open" button in a save dialog. [Bug: 1640] * library/entry.tcl: Fixed so selection is returned using the -show character during cut and paste operations. [Bug: 1687] 1999-04-5 <redman@scriptics.com> * generic/tkInt.decls: * generic/tkIntXlibDecls.h: * generic/tkStubInit.c: * xlib/xgc.c: * xlib/X11/Xlib.h: * xlib/X11/Xutil.h: Added more X functions to the Win & Mac stubs tables. 1999-04-05 <stanton@scriptics.com> * unix/configure.in: * generic/tkCanvPs.c: Added configure test for pw_gecos field in pwd to support OS/390. [Bug: 1724] 1999-04-02 <stanton@scriptics.com> * tests/text.test: * generic/tkText.c: Fixed handling of Unicode in text searches. The -count option was returning byte counts instead of character counts. [Bug: 1056, 1148, 1666] 1999-04-01 <redman@scriptics.com> * generic/tk.decls: * generic/tk.h: * generic/tkStubInit.c: * generic/tkWindow.c: * unix/Makefile.in: * win/makefile.vc: Tk now uses its own stub library to store pointers to its own stubs table. * doc/dde.n: (removed) * doc/send.n: * generic/tk.decls: * tests/winSend.test: * generic/tkPlatDecls.h: * win/tkWinSend.c: Removed the DDE-based send and dde commands, they were causing Tk to lock up when any window on the system was not processing its message queue (more importantly, windows in Tcl and Tk). The send command needs to be rewritten to prevent the deadlock situation (soon). The dde command is being pushed into its own package and will provide almost all of the capabilities that send did before (using a "dde eval" command), not yet completed. 1999-03-31 <redman@scriptics.com> * win/tkWinSend.c: Modified dde/send code to work properly on Win95/Win98. String lengths are not returned properly by DDE, so NULL terminate all strings going in and ignore the string length coming back out. Do not destroy handles until all necessary work on those handles (and child handles) is done. 1999-03-30 <stanton@scriptics.com> * generic/tkWindow.c (Tk_DestroyWindow): Image handlers are now finalized before the font subsystem since complex image handlers may contain references to fonts (e.g. Tix compound images). [Bug: 1603] 1999-03-29 <stanton@scriptics.com> * doc/MeasureChar.3: * doc/TextLayout.3: * generic/tk.decls: * generic/tkCanvText.c: * generic/tkEntry.c: * generic/tkFont.c: * generic/tkListbox.c: * generic/tkMessage.c: * mac/tkMacFont.c: * unix/tkUnixButton.c: * unix/tkUnixFont.c: * unix/tkUnixMenu.c: * win/tkWinFont.c: * win/tkWinMenu.c: Standardized text layout and font interfaces so they are consistent with respect to byte versus character oriented indices. The layout functions all manipulate character oriented values while the lower level measurement functions all operate on byte oriented values. This distinction was not clear and so the functions were being used improperly in a number of places. [Bug: 1053, 747, 749, 1646] * generic/tk.decls: Eliminated uses of C++ STL types string and list from declarations. * generic/tkFont.c: Changes to named fonts were not being propagated in some cases. [Bug: 1144] * xlib/X11/Xlib.h: * generic/tkInt.decls: Added XParseColor to xlib stub tables. [Bug: 1574] * doc/GetBitmap.3: * generic/tkBitmap.c (BitmapInit): Eliminated use of Tk_Uid's in bitmaps. Added a few CONST declarations. 1999-03-29 <redman@scriptics.com> * unix/configure.in: * unix/Makefile.in: * win/makefile.vc: * generic/tkDecls.h: * generic/tkIntDecls.h: * generic/tkIntPlatDecls.h: * generic/tkPlatDecls.h: * generic/tkIntXlibDecls.h: Removed stub functions. Always use the Tcl stubs when building with --enable-shared. 1999-03-26 <redman@scriptics.com> * generic/tkTextIndex.c: * tests/testIndex.test: Avoid looking past the beginning of the array storing data for the text widget (.t index end-2c). Added test case to check for the bug. [Bug 991] * generic/tkConsole.c: Copy static strings into a Tcl_DString before passing to Tcl_Eval, in case the compiler puts static strings into read-only memory. 1999-03-26 <suresh@scriptics.com> * unix/configure.in: --nameble-shared is now the default and builds Tk as a shared library; specify --disable-shared to build a static Tk library and shell. 1999-03-26 <surles@scriptics.com> * library/menu.tcl: Fixed bug reported by Bryan Oakley in the menubutton bindings. There was a false assumption that there was always a menu attached to the button. [Bug 1116] 1999-03-26 <redman@scriptics.com> * unix/configure.in: Removed --enable-tcl-stub. Linking Tk to Tcl stubs is causing too many problems when linking executables like wish. Until the Tk is a fully loadable extension, linking against the Tcl stubs is not supported in Tk. 1999-03-19 <redman@scriptics.com> * generic/tkBitmap.c: * generic/tkCursor.c: * generic/tkGC.c: When creating hash tables that key off of XID handles, make sure to pass TCL_ONE_WORD_KEYS. XIDs are guaranteed to be 32bit numbers, although on some 64bit systems (including 64bit Solaris 7) they are packed into a 64bit value where the upper 32bits are zero. The normal method of sizeof(XID)/sizeof(int) causes the hash table code to assume that the XID is a pointer to an array of two ints, which it is not. Tk now supports 64bit Solaris 7. 1999-03-17 <stanton@scriptics.com> * win/makefile.vc: * generic/tk.h: Changed to use TCL_BETA_RELEASE macro, and fixed so this works in rc files. * win/makefile.vc: * win/makefile.bc: * win/README: * unix/configure.in: * generic/tk.h: * README: Updated version to 8.1b3. 1999-03-14 <stanton@GASPODE> * unix/configure.in: Added missing stub related definitions. * unix/Makefile.in: Install tkDecls.h in addition to tk.h. * generic/tkStubLib.c: Added flags to ensure we are using Tcl stub macros. 1999-03-11 <stanton@GASPODE> * generic/tkInt.decls: Added reserved slot for XSetDashes for use by the dash patch. 1999-03-10 <redman@scriptics.com> * xlib/xdraw.c: * xlib/X11/Xlib.h: * mac/tkMac.h: * mac/tkMacInt.h: * mac/tkMacPort.h: * mac/tkMacXStubs.c: * mac/tkMacAppInit.c: * mac/tkMacCursor.c: * win/makefile.vc: * win/tkWin.h: * win/tkWinInt.h: * win/tkWinPort.h: * win/winMain.c: * generic/tk.h: * generic/tkInt.h: * generic/tk.decls: * generic/tkInt.decls: * generic/tkDecls.h: * generic/tkPlatDecls.h: * generic/tkIntDecls.h: * generic/tkIntPlatDecls.h: * generic/tkIntXlibDecls.h: * generic/tkStubs.c: * generic/tkPlatStubs.c: * generic/tkIntStubs.c: * generic/tkIntPlatStubs.c: * generic/tkIntXlibStubs.c: * generic/tkStubInit.c: * generic/tkStubLib.c: * generic/tkBind.c: * generic/tkCmds.c: * generic/tkConfig.c: * generic/tkConsole.c: * generic/tkCursor.c: * generic/tkGrab.c: * generic/tkImgPhoto.c: * generic/tkMain.c: * generic/tkMenu.c: * generic/tkPointer.c: * generic/tkTextDisp.c: * generic/tkWindow.c: * unix/tkUnixInt.h: * unix/tkUnixPort.h: * unix/Makefile.in: * unix/configure.in: * unix/tkConfig.sh.in: * unix/tkUnix.c: * unix/tkUnix3d.c: * unix/tkUnixDraw.c: * unix/tkUnixFont.c: * unix/tkUnixMenubu.c: Stubs implementation for 8.1. Tk_Main() is replaced with a macro which calls Tk_MainEx(). Tk can link to the Tcl stubs library, wish links directly to Tcl and Tk. Use --enable-tcl-stubs to link Tk to the Tcl stubs library (Unix), on by default on Windows. Exported all public functions through the stubs mechanism (see the *.decls files) and many of the internal functions. Most of the changes dealt with shifting around the function declarations in the header files. Mac code may not compile, but it shouldn't take much work to fix this. * mac/tkMacMenu.c: Added dummy TkpMenuThreadInit for Mac to be consistent with Unix and Windows versions. 1999-03-08 <lfb@scriptics.com> * win/tkWinWm.c: Toplevel class no longer shared between threads. * win/tkWinX.c: Multiple threads no longer share the same TkDisplay structure. Required because TkDisplay stores much thread-specific data for a given thread. * win/tkWinSend.c: Moved application instance handle out out thread-local storage. DDE was failing to initialize when the instance handles were different between threads. * win/makefile.vc: Added THREADDEFINES for building with threads enabled. * generic/tkMenu.c: * win/tkWinMenu.c: * unix/tkUnixMenu.c: Added TkpMenuThreadInit for initializing thread-specific Menu state. 1999-03-01 <redman@scriptics.com> * win/tkWinWm.c: * win/tkWinPointer.c: * win/tkWinInt.h: Fix "focus -force" for Windows. The Win32 API function SetForegroundWindow() does not work unless the window handle is a toplevel window (a Windows toplevel). The handle being passed was a Tk toplevel, which is a child of the Windows toplevel. 1999-02-26 <redman@scriptics.com> * win/cat.c: Remove this file, use the one in the Tcl source directory. * win/makefile.vc: Remove the wishc.exe from the default targets. Add a separate console-wish target to build it. The need for a console-wish will go away soon, so we don't want to encourage its use. 1999-02-25 <redman@scriptics.com> * win/tkWinWm.c: Properly initialize the tsdPtr->firstWindow field. * win/cat.c: Code for cat32.exe, copied from the Tcl sources. Required in order to run the test suite from the makefile * win/winMain.c: Add main() for a console-based wishc.exe, which meant adding code to disable the call to Tk_ConsoleInit(). * generic/tkConsole.c: Check the standard handles before creating the new standard channels. This allows a windows app that has stdin, stdout, or stderr to correctly connect to them. * generic/tkMain.c: Add a proper check for the interactive mode, since the standard channels may actually be connected in windows mode or even in the console-based wish. * win/makefile.vc: Add targets for wishc.exe (console-based wish) and cat32.exe (for testing). Fix the test suite target so it can be run from the makefile (which can happen since the standard handles have been fixed). 1999-02-12 <lfb@scriptics.com> * generic/tkMenuButton.h: * generic/tkMenuButton.c: * mac/tkMacMenubutton.c: * mac/tkMacDefault.h * unix/tkUnixMenubu.c: Eliminated Tk_Uids used by -state option. * unix/tkUnixDefault.h * win/tkWinDefault.h * generic/tk.h: * generic/tkScale.h: * generic/tkScale.c: * generic/tkWindow.c: * unix/tkUnixScale.c: * unix/tkUnixDefault.h: * unix/tkWinDefault.h: * mac/tkMacDefault.h: Objectified scale widget. * win/tkWinX.c: Removed Thread-specific data from process initialization code that was stopping the Tk Dll from loading. 1999-02-11 <stanton@GASPODE> * README: * generic/tk.h: * unix/configure.in: * win/README: * win/makefile.bc: * win/makefile.vc: Updated version to 8.1b2. * unix/tkUnixSend.c: Fixed one more Tcl_*ObjVar instance. 1999-02-04 <stanton@GASPODE> * Various cleanup related to the Tcl_Eval and Tcl_ObjSetVar changes in Tcl. INTEGRATED PATCHES FROM 8.0.5b2: * win/tkWinMenu.c (TkpDestroyMenu): Changed so modalMenuPtr is cleared when it is being destroyed. * generic/tkImgPhoto.c: Changed so color tables are freed immediately instead of being delayed. This ensures that color tables are properly disposed at process exit. * library/prolog.ps: Changed string that determines font height to include European character with an umlaut. * generic/tkImgBmap.c (ImgBmapConfigureInstance): If an image mask changed but ended up with the same XID, the GC failed to be updated and so the new mask was not used. [Bug: 970] * generic/tkFocus.c (SetFocus): Changed so focus window is always set if -force is specified. This fixes the problem on Windows where Tk does not activate the window if it already has focus. * generic/tkConsole.c: Fixed so errors in console eval are reported properly. Eliminated duplicate result messages. [Bug: 973] * win/tkWinWm.c: Changed so windows that aren't resizable don't have resize handles and the zoom box is disabled. * win/tkWinInt.h: * win/tkWinPointer.c: Changed to cancel the mouse timer when a user initiated move/resize loop begins. * unix/configure.in: TK_LD_SEARCH_FLAGS was set incorrectly if SHLIB_LD_LIBS='${LIBS}', and shared linking is performed through the C compiler. Systems affected are Linux, MP-RAS and NEXTSTEP, but also with gcc on many more systems. [Bug: 908] * win/makefile.vc: First stab at install target. Fixed quoting so paths with spaces work. * tests/main.test: * tests/unixWm.test: Better cleanup of temporary files. * mac/tkMacAppInit.c: * generic/tkTest.c: * generic/tkAppInit.c: * win/winMain.c: Changed some EXTERN declarations to extern since they are not defining exported interfaces. This avoids generating useless declspec() attributes and makes the windows makefile simpler. * library/menu.tcl (tkMenuFind): Changed so keyboard shortcuts will only be found in the current toplevel. Previously, they might be found in menus attached to other toplevels that might not even be mapped. [Bug: 924] * generic/tkCanvLine.c: Changed to treat zero width lines like they have width 1 for purposes of selection. [Bug: 925] * win/tkWinFont.c (Tk_MeasureChars): Added a workaround for a bug in GetTextExtentExPoint on Win NT 4.0/Japanese. [Bug: 1006] * unix/tkUnixSend.c (Tk_SetAppName): Fixed uninitialized memory access bug. [Bug: 919] 1999-1-28 <stanton@GASPODE> * generic/tkGrid.c: Fixed bug in "grid forget" that failed to cancel pending idle handlers, resulting in a crash in a few odd cases. 1999-01-06 <lfb@JUSTICE> * generic/tk.h, generic/tkGet.c, generic/tkConfig.c, * generic/tkOldConfig.c, generic/tkEntry.c, generic/tkMenubutton.c, * generic/tkMenubutton.h, generic/tkScale.c, generic/tkScale.h, * generic/tkTextDisplay.c, generic/tkText.c, unix/tkUnixMenubu.c, * unix/tkUnixScale.c, mac/tkMacMenu.c, mac/tkMacMenubutton.c, Removed global Tk_Uids dealing with "-state" configuration option and added new TK_CONFIG_STATE configSpec that doesn't use Tk_Uids. 1998-12-11 === Tk 8.1b1 Release === 1998-12-11 <stanton@GASPODE> * generic/tkMain.c (Tk_Main): Fixed improper command line encoding handling. 1998-12-08 <stanton@GASPODE> * win/tkWinClipboard.c (TkSelGetSelection, TkWinClipboardRender): Changed to handle multibyte characters properly. [Bug: 935] 1998-12-07 <stanton@GASPODE> * library/xmfbox.tcl (tkMotifFDialog_Create): In the cached case, the data array was not being initialized with the correct set of widgets. 1998-12-4 <welch@SAGE> * Changed patchLevel to 8.1b1 * generic/tkMenu.c (ConfigureMenuCloneEntries): The -menu configuration option was being incorrectly specified as just "menu". 1998-11-30 <stanton@GASPODE> * generic/tkButton.c (ConfigureButton): The error result was getting lost when restoring configuration options. [Bug: 619] 1998-11-25 <stanton@GASPODE> * unix/tkUnixFont.c (GetFontAttributes): Initialize an unspecified family to an empty string. (FontMapLoadPage): if the font included characters below 32, the index computation was incorrect because the range was shifted up to 32. (CreateClosestFont): check for empty locale as well as NULL. * generic/tkFont.c (TkFontParseXLFD): initialize charset to iso8859-1 if no charset is specified. * mac/tkMacHLEvents.c (OdocHandler): added conversion from external string to UTF [Bug: 869] * integrated tk8.0.4 changes. * generic/tkBind.c: fixed deletion order bug where a crash would result if a binding deleted "." * generic/tkMenu.c (MenuWidgetObjCmd): disabled menu entries were getting reenabled whenever the mouse passed over the entry [Bug: 860] * unix/tkUnixMenu.c (TkpComputeStandardMenuGeometry): hidemargin option was not honored properly in menus [Bug: 859] 1998-11-24 <stanton@GASPODE> * tkMacMenu.c, tkUnixMenu.c, tkWinMenu.c, tkMenuDraw.c, tkMenu.h, * tkMenu.c: Backed out the previous fix for bug 620 and eliminated a bunch of code that created unnecessary objects. Changed back to using internal types instead of objects for many configuration options. There are many more fixes like this that could be made, but some require a little restructuring of the code. In any case the leaks are fixed and there is a lot less allocation happening. [Bug: 620] 1998-11-19 <stanton@GASPODE> * tkMenu.c (DestroyMenuEntry): fixed memory leaks [Bug: 620] * tkWinX.c (GetTranslatedKey): fixed bad code merge * tkWinWm.c, tkWinMenu.c: fixed titles and menus so they properly display Unicode [Bug: 819]