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

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