Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
emscripten-core
GitHub Repository: emscripten-core/emscripten
Path: blob/main/system/lib/libc/emscripten_libc_stubs.c
6162 views
1
/*
2
* Copyright 2021 The Emscripten Authors. All rights reserved.
3
* Emscripten is available under two separate licenses, the MIT license and the
4
* University of Illinois/NCSA Open Source License. Both these licenses can be
5
* found in the LICENSE file.
6
*
7
* Fake/stub implementations of libc functions.
8
* See emscripten_syscall_stubs.c for fake/stub implementations of syscalls.
9
*/
10
11
#include <errno.h>
12
#include <grp.h>
13
#include <pwd.h>
14
#include <string.h>
15
#include <time.h>
16
#include <signal.h>
17
#include <spawn.h>
18
#include <stdio.h>
19
#include <sys/times.h>
20
#include <sys/wait.h>
21
#include <unistd.h>
22
23
#ifndef weak
24
#define weak __attribute__((__weak__))
25
#endif
26
27
// ==========================================================================
28
// sys/wait.h
29
// ==========================================================================
30
31
weak int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options) {
32
errno = ECHILD;
33
return -1;
34
}
35
36
// ==========================================================================
37
// sys/times.h
38
// ==========================================================================
39
40
clock_t times(struct tms *buf) {
41
// clock_t times(struct tms *buffer);
42
// http://pubs.opengroup.org/onlinepubs/009695399/functions/times.html
43
// NOTE: This is fake, since we can't calculate real CPU time usage in JS.
44
if (buf) {
45
memset(buf, 0, sizeof(*buf));
46
}
47
return 0;
48
}
49
50
struct tm *getdate(const char *string) {
51
// struct tm *getdate(const char *string);
52
// http://pubs.opengroup.org/onlinepubs/009695399/functions/getdate.html
53
// TODO: Implement.
54
return 0;
55
}
56
57
weak int stime(const time_t *t) {
58
errno = EPERM;
59
return -1;
60
}
61
62
weak int clock_getcpuclockid(pid_t pid, clockid_t *clockid) {
63
if (pid < 0) {
64
return ESRCH;
65
}
66
if (pid != 0 && pid != getpid()) {
67
return ENOSYS;
68
}
69
if (clockid) {
70
*clockid = CLOCK_PROCESS_CPUTIME_ID;
71
}
72
return 0;
73
}
74
75
// ==========================================================================
76
// pwd.h
77
// ==========================================================================
78
79
struct passwd *getpwnam(const char *name) {
80
errno = ENOENT;
81
return 0;
82
}
83
84
struct passwd *getpwuid(uid_t uid) {
85
errno = ENOENT;
86
return 0;
87
}
88
89
weak int getpwnam_r(const char *name, struct passwd *pwd,
90
char *buf, size_t buflen, struct passwd **result) {
91
return ENOENT;
92
}
93
94
weak int getpwuid_r(uid_t uid, struct passwd *pwd,
95
char *buf, size_t buflen, struct passwd **result) {
96
return ENOENT;
97
}
98
99
weak void setpwent(void) {
100
}
101
102
weak void endpwent(void) {
103
}
104
105
struct passwd *getpwent(void) {
106
errno = EIO;
107
return NULL;
108
}
109
110
// ==========================================================================
111
// grp.h
112
// ==========================================================================
113
114
weak struct group *getgrnam(const char *name) {
115
errno = ENOENT;
116
return 0;
117
}
118
119
weak struct group *getgrgid(gid_t gid) {
120
errno = ENOENT;
121
return 0;
122
}
123
124
weak int getgrnam_r(const char *name, struct group *grp,
125
char *buf, size_t buflen, struct group **result) {
126
return ENOENT;
127
}
128
129
weak int getgrgid_r(gid_t gid, struct group *grp,
130
char *buf, size_t buflen, struct group **result) {
131
return ENOENT;
132
}
133
134
weak struct group *getgrent(void) {
135
errno = EIO;
136
return NULL;
137
}
138
139
weak void endgrent(void) {
140
}
141
142
weak void setgrent(void) {
143
}
144
145
// ==========================================================================
146
// sys/file.h
147
// ==========================================================================
148
149
weak int flock(int fd, int operation) {
150
// Pretend that the locking is successful. These are process-level locks,
151
// and Emscripten programs are a single process. If we supported linking a
152
// filesystem between programs, we'd need to do more here.
153
// See https://github.com/emscripten-core/emscripten/issues/23697
154
return 0;
155
}
156
157
weak int chroot(const char *path) {
158
// int chroot(const char *path);
159
// http://pubs.opengroup.org/onlinepubs/7908799/xsh/chroot.html
160
errno = EACCES;
161
return -1;
162
}
163
164
weak int execve(const char *pathname, char *const argv[],
165
char *const envp[]) {
166
// int execve(const char *pathname, char *const argv[],
167
// char *const envp[]);
168
// http://pubs.opengroup.org/onlinepubs/009695399/functions/exec.html
169
// We don't support executing external code.
170
errno = ENOEXEC;
171
return -1;
172
}
173
174
weak pid_t fork(void) {
175
// pid_t fork(void);
176
// http://pubs.opengroup.org/onlinepubs/000095399/functions/fork.html
177
// We don't support multiple processes.
178
errno = ENOSYS;
179
return -1;
180
}
181
182
weak pid_t vfork(void) {
183
errno = ENOSYS;
184
return -1;
185
}
186
187
weak int posix_spawn(pid_t *pid, const char *path,
188
const posix_spawn_file_actions_t *file_actions,
189
const posix_spawnattr_t *attrp,
190
char *const argv[], char *const envp[]) {
191
errno = ENOSYS;
192
return -1;
193
}
194
195
// ==========================================================================
196
// stdio.h
197
// ==========================================================================
198
199
weak FILE *popen(const char *command, const char *type) {
200
errno = ENOSYS;
201
return NULL;
202
}
203
204
weak int pclose(FILE *stream) {
205
errno = ENOSYS;
206
return -1;
207
}
208
209
weak int setgroups(size_t size, const gid_t *list) {
210
// int setgroups(int ngroups, const gid_t *gidset);
211
// https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man2/setgroups.2.html
212
if (size < 1 || size > sysconf(_SC_NGROUPS_MAX)) {
213
errno = EINVAL;
214
return -1;
215
}
216
// We have just one process/user/group, so it makes no sense to set groups.
217
errno = EPERM;
218
return -1;
219
}
220
221
weak int sigaltstack(const stack_t *restrict ss, stack_t *restrict old_ss) {
222
errno = ENOSYS;
223
return -1;
224
}
225
226
// ==========================================================================
227
// dlfcn.h
228
// ==========================================================================
229
230
#ifndef EMSCRIPTEN_DYNAMIC_LINKING
231
void __dl_seterr(const char*, ...);
232
233
weak void *__dlsym(void *restrict p, const char *restrict s, void *restrict ra) {
234
__dl_seterr("dynamic linking not enabled");
235
return NULL;
236
}
237
238
weak void* dlopen(const char* file, int flags) {
239
__dl_seterr("dynamic linking not enabled");
240
return NULL;
241
}
242
#endif
243
244
// ==========================================================================
245
// stdlib.h
246
// ==========================================================================
247
248
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
249
250
weak int getloadavg(double loadavg[], int nelem) {
251
// http://linux.die.net/man/3/getloadavg
252
int limit = MIN(nelem, 3);
253
for (int i = 0; i < limit; i++) {
254
loadavg[i] = 0.1;
255
}
256
return limit;
257
}
258
259