OILS / cpp / stdlib.h View on Github | oilshell.org

177 lines, 89 significant
1// cpp/stdlib.h: Replacement for pyext/posixmodule.c
2
3#ifndef LEAKY_STDLIB_H
4#define LEAKY_STDLIB_H
5
6#include <errno.h>
7#include <sys/types.h> // mode_t
8#include <unistd.h>
9
10#include "mycpp/runtime.h"
11
12namespace math {
13
14bool isinf(double f);
15bool isnan(double f);
16
17} // namespace math
18
19namespace fcntl_ {
20
21// for F_GETFD
22int fcntl(int fd, int cmd);
23int fcntl(int fd, int cmd, int arg);
24
25} // namespace fcntl_
26
27namespace posix {
28
29mode_t umask(mode_t mask);
30
31inline bool access(BigStr* pathname, int mode) {
32 // No error case: 0 is success, -1 is error AND false.
33 return ::access(pathname->data_, mode) == 0;
34}
35
36inline BigStr* getcwd() {
37 BigStr* result = OverAllocatedStr(PATH_MAX);
38 char* p = ::getcwd(result->data_, PATH_MAX);
39 if (p == nullptr) {
40 throw Alloc<OSError>(errno);
41 }
42 // Important: set the length of the string!
43 result->MaybeShrink(strlen(result->data_));
44 return result;
45}
46
47// No error cases: the man page says these get*() functions always succeed
48
49inline int getegid() {
50 return ::getegid();
51}
52
53inline int geteuid() {
54 return ::geteuid();
55}
56
57inline int getpid() {
58 return ::getpid();
59}
60
61inline int getppid() {
62 return ::getppid();
63}
64
65inline int getuid() {
66 return ::getuid();
67}
68
69inline bool isatty(int fd) {
70 // No error case: false is the same as error (e.g. in pyext/posixmodule.c)
71 return ::isatty(fd);
72}
73
74inline BigStr* strerror(int err_num) {
75 // No error case: returns an appropriate string if err_num is invalid
76 return StrFromC(::strerror(err_num));
77}
78
79inline Tuple2<int, int> pipe() {
80 int fd[2];
81 if (::pipe(fd) < 0) {
82 throw Alloc<OSError>(errno);
83 }
84 return Tuple2<int, int>(fd[0], fd[1]);
85}
86
87inline void close(int fd) {
88 if (::close(fd) < 0) {
89 throw Alloc<OSError>(errno);
90 }
91}
92
93void putenv(BigStr* name, BigStr* value);
94
95inline int fork() {
96 int result = ::fork();
97 if (result < 0) {
98 throw Alloc<OSError>(errno);
99 }
100 return result;
101}
102
103inline void _exit(int status) {
104 // No error case: does not return
105 ::_exit(status);
106}
107
108inline void write(int fd, BigStr* s) {
109 //
110 // IMPORTANT TODO: Write in a loop like posix_write() in pyext/posixmodule.c
111 //
112
113 if (::write(fd, s->data_, len(s)) < 0) {
114 throw Alloc<OSError>(errno);
115 }
116}
117
118inline void setpgid(pid_t pid, pid_t pgid) {
119 int ret = ::setpgid(pid, pgid);
120 if (ret < 0) {
121 throw Alloc<OSError>(errno);
122 }
123}
124
125inline int getpgid(pid_t pid) {
126 pid_t ret = ::getpgid(pid);
127 if (ret < 0) {
128 throw Alloc<OSError>(errno);
129 }
130 return ret;
131}
132
133inline void tcsetpgrp(int fd, pid_t pgid) {
134 int ret = ::tcsetpgrp(fd, pgid);
135 if (ret < 0) {
136 throw Alloc<OSError>(errno);
137 }
138}
139
140inline int tcgetpgrp(int fd) {
141 pid_t ret = ::tcgetpgrp(fd);
142 if (ret < 0) {
143 throw Alloc<OSError>(errno);
144 }
145 return ret;
146}
147
148// Can we use fcntl instead?
149void dup2(int oldfd, int newfd);
150
151int open(BigStr* path, int flags, int perms);
152
153mylib::File* fdopen(int fd, BigStr* c_mode);
154
155void execve(BigStr* argv0, List<BigStr*>* argv,
156 Dict<BigStr*, BigStr*>* environ);
157
158void kill(int pid, int sig);
159void killpg(int pgid, int sig);
160
161List<BigStr*>* listdir(BigStr* path);
162
163} // namespace posix
164
165namespace time_ {
166
167void tzset();
168time_t time();
169// Note: This is translated in a weird way, unlike Python's API. Might want to
170// factor out our own API with better types.
171time_t localtime(time_t ts);
172BigStr* strftime(BigStr* s, time_t ts);
173void sleep(int seconds);
174
175} // namespace time_
176
177#endif // LEAKY_STDLIB_H