blob: d7743c81ef5a771f4bd6f989d156606d7ba61d19 [file]
/*
* Copyright 2021 The Emscripten Authors. All rights reserved.
* Emscripten is available under two separate licenses, the MIT license and the
* University of Illinois/NCSA Open Source License. Both these licenses can be
* found in the LICENSE file.
*
* Unimplemented/dummy syscall implementations. These fall into 3 categories.
*
* 1. Fake it, use dummy/placeholder values and return success.
* 2. Fake it, as above but warn at runtime if called.
* 3. Return ENOSYS and warn at runtime if called.
*/
#define _GNU_SOURCE // for struct mmsghdr
#include <errno.h>
#include <string.h>
#include <emscripten/syscalls.h>
#include <emscripten/console.h>
#include <emscripten/version.h>
#include <emscripten/stack.h>
static pid_t g_pid = 42;
static pid_t g_pgid = 42;
static pid_t g_ppid = 1;
static pid_t g_sid = 42;
#ifdef NDEBUG
#define REPORT(name)
#else
#define REPORT(name) \
emscripten_err("warning: unsupported syscall: __syscall_" #name);
#endif
#define UNIMPLEMENTED(name, args) \
weak int __syscall_##name args { \
REPORT(name); \
return -ENOSYS; \
}
#define STRINGIFY(s) #s
#define STR(s) STRINGIFY(s)
weak int __syscall_uname(struct utsname *buf) {
if (!buf) {
return -EFAULT;
}
const char* full_version = STR(__EMSCRIPTEN_MAJOR__) "." \
STR(__EMSCRIPTEN_MINOR__) "." \
STR(__EMSCRIPTEN_TINY__);
strcpy(buf->sysname, "Emscripten");
strcpy(buf->nodename, "emscripten");
strcpy(buf->release, full_version);
strcpy(buf->version, "#1");
#ifdef __wasm64__
strcpy(buf->machine, "wasm64");
#else
strcpy(buf->machine, "wasm32");
#endif
return 0;
}
weak int __syscall_setpgid(pid_t pid, pid_t pgid) {
if (pid && pid != g_pid) {
return -ESRCH;
}
if (pgid && pgid != g_pgid) {
return -EPERM;
}
return 0;
}
weak int __syscall_sync() {
return 0;
}
weak pid_t __syscall_getsid(pid_t pid) {
if (pid && pid != g_pid) {
return -ESRCH;
}
return g_sid;
}
weak pid_t __syscall_getpgid(pid_t pid) {
if (pid && pid != g_pid) {
return -ESRCH;
}
return g_pgid;
}
weak pid_t __syscall_getpid() {
return g_pid;
}
weak pid_t __syscall_getppid() {
return g_ppid;
}
weak int __syscall_getgroups32(int count, gid_t list[]) {
if (count < 1) {
return -EINVAL;
}
list[0] = 0;
return 1;
}
weak pid_t __syscall_setsid() {
return 0; // no-op
}
weak int __syscall_getrusage(int who, struct rusage *usage) {
REPORT(getrusage);
usage->ru_utime = (struct timeval)
{ .tv_sec = 1, .tv_usec = 2 };
usage->ru_stime = (struct timeval)
{ .tv_sec = 3, .tv_usec = 4 };
return 0;
}
weak int __syscall_getpriority(int which, id_t who) {
return 0;
}
weak int __syscall_setpriority(int which, id_t who, int prio) {
return -EPERM;
}
weak int __syscall_setdomainname(const char *name, size_t len) {
return -EPERM;
}
weak int __syscall_getresuid32(uid_t *ruid, uid_t *euid, uid_t *suid) {
*ruid = 0;
*euid = 0;
*suid = 0;
return 0;
}
weak int __syscall_getresgid32(gid_t *rgid, gid_t *egid, gid_t *sgid) {
REPORT(getresgid32);
*rgid = 0;
*egid = 0;
*sgid = 0;
return 0;
}
weak int __syscall_madvise(void *addr, size_t length, int advice) {
REPORT(madvise);
// advice is welcome, but ignored
return 0;
}
weak int __syscall_mlock(const void *addr, size_t len) {
REPORT(mlock);
return 0;
}
weak int __syscall_munlock(const void *addr, size_t len) {
REPORT(munlock);
return 0;
}
weak int __syscall_mprotect(size_t start, size_t len, int prot) {
REPORT(mprotect);
return 0; // let's not and say we did
}
weak int __syscall_mremap(void *old_addr, size_t old_size, size_t new_size, int flags, void *new_addr) {
REPORT(mremap);
return -ENOMEM; // never succeed
}
weak int __syscall_mlockall(int flags) {
REPORT(mlockall);
return 0;
}
weak int __syscall_munlockall() {
REPORT(munlockall);
return 0;
}
weak int __syscall_prlimit64(pid_t pid, int resource, const struct rlimit *new_limit, struct rlimit *old_limit) {
REPORT(prlimit64);
if (new_limit) {
return -EPERM;
}
if (old_limit) {
if (resource == RLIMIT_NOFILE) {
// See FS.MAX_OPEN_FDS in src/lib/libfs.js
old_limit->rlim_cur = 4096;
old_limit->rlim_max = 4096;
} else if (resource == RLIMIT_STACK) {
uintptr_t end = emscripten_stack_get_end();
uintptr_t base = emscripten_stack_get_base();
old_limit->rlim_cur = base - end;
// we can not change the stack size, so the maximum is the same as the current
old_limit->rlim_max = base - end;
} else {
// Just report no limits
old_limit->rlim_cur = RLIM_INFINITY;
old_limit->rlim_max = RLIM_INFINITY;
}
}
return 0;
}
weak pid_t __syscall_wait4(pid_t pid, int *wstatus, int options, struct rusage *rusage) {
REPORT(wait4);
return -1;
}
UNIMPLEMENTED(acct, (const char *filename))
UNIMPLEMENTED(mincore, (void *addr, size_t length, unsigned char *vec))
UNIMPLEMENTED(recvmmsg, (int sockfd, struct mmsghdr *msgvec, unsigned int vlen, unsigned int flags, struct timespec *timeout))
UNIMPLEMENTED(sendmmsg, (int sockfd, struct mmsghdr *msgvec, unsigned int vlen, unsigned int flags))
UNIMPLEMENTED(socketpair, (int domain, int type, int protocol, int fd[2], int unused1, int unused2))