C · 2541 bytes Raw Blame History
1 #include <fcntl.h>
2 #include <unistd.h>
3 #include <errno.h>
4 #include <string.h>
5 #include <sys/stat.h>
6 #include <sys/types.h>
7
8 // macOS kernel bug workaround: set S_CTTYREF on the controlling terminal.
9 // On macOS, PTY slave output is discarded when the child process exits unless
10 // /dev/tty was opened (which sets S_CTTYREF). Without this, pexpect-based tests
11 // lose output from commands that fork short-lived child processes.
12 // See: https://github.com/pexpect/pexpect/issues/662
13 void fortsh_set_cttyref(void) {
14 #ifdef __APPLE__
15 int fd = open("/dev/tty", O_WRONLY);
16 if (fd >= 0) close(fd);
17 #endif
18 }
19
20 // Wrapper for open() that takes mode as a separate parameter
21 // This works around a bug in Fortran's C binding where mode_t is not passed correctly
22 int fortsh_open(const char *pathname, int flags, int mode) {
23 return open(pathname, flags, (mode_t)mode);
24 }
25
26 int fortsh_close(int fd) {
27 return close(fd);
28 }
29
30 int fortsh_dup(int fd) {
31 return dup(fd);
32 }
33
34 int fortsh_dup2(int oldfd, int newfd) {
35 return dup2(oldfd, newfd);
36 }
37
38 int fortsh_get_errno(void) {
39 return errno;
40 }
41
42 const char *fortsh_strerror(int errnum) {
43 return strerror(errnum);
44 }
45
46 // Portable file type checks — bypasses Fortran struct stat layout issues
47 // across architectures (x86_64 vs aarch64 have different struct stat layouts)
48 int fortsh_stat_mode(const char *path) {
49 struct stat st;
50 if (stat(path, &st) != 0) return -1;
51 return (int)st.st_mode;
52 }
53
54 int fortsh_lstat_mode(const char *path) {
55 struct stat st;
56 if (lstat(path, &st) != 0) return -1;
57 return (int)st.st_mode;
58 }
59
60 long long fortsh_stat_size(const char *path) {
61 struct stat st;
62 if (stat(path, &st) != 0) return -1;
63 return (long long)st.st_size;
64 }
65
66 int fortsh_stat_uid(const char *path) {
67 struct stat st;
68 if (stat(path, &st) != 0) return -1;
69 return (int)st.st_uid;
70 }
71
72 long long fortsh_stat_mtime(const char *path) {
73 struct stat st;
74 if (stat(path, &st) != 0) return -1;
75 #ifdef __APPLE__
76 return (long long)st.st_mtimespec.tv_sec;
77 #else
78 return (long long)st.st_mtim.tv_sec;
79 #endif
80 }
81
82 long long fortsh_stat_dev(const char *path) {
83 struct stat st;
84 if (stat(path, &st) != 0) return -1;
85 return (long long)st.st_dev;
86 }
87
88 long long fortsh_stat_ino(const char *path) {
89 struct stat st;
90 if (stat(path, &st) != 0) return -1;
91 return (long long)st.st_ino;
92 }
93
94 // Access environ array by index
95 // Returns NULL when idx is beyond the end
96 extern char **environ;
97 char *get_environ_ptr(int idx) {
98 return environ[idx];
99 }