Luna/libc/src/unistd.cpp

239 lines
5.3 KiB
C++
Raw Normal View History

2023-04-07 13:39:10 +00:00
#include <luna/StringBuilder.h>
2023-03-30 19:28:39 +00:00
#include <luna/Vector.h>
#include <bits/errno-return.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdint.h>
2023-04-07 13:39:10 +00:00
#include <stdlib.h>
#include <sys/syscall.h>
#include <unistd.h>
extern "C" long arch_invoke_syscall(long, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t);
extern char** environ;
extern "C"
{
2023-03-18 22:58:56 +00:00
pid_t fork(void)
{
long rc = syscall(SYS_fork);
__errno_return(rc, int);
}
2023-03-11 21:19:58 +00:00
pid_t getpid(void)
{
return (pid_t)syscall(SYS_getpid);
}
pid_t getppid(void)
{
return (pid_t)syscall(SYS_getppid);
}
uid_t getuid(void)
{
return (uid_t)syscall(SYS_getuid);
}
uid_t geteuid(void)
{
return (uid_t)syscall(SYS_geteuid);
}
gid_t getgid(void)
{
return (gid_t)syscall(SYS_getgid);
}
gid_t getegid(void)
{
return (gid_t)syscall(SYS_getegid);
}
int setuid(uid_t uid)
{
long rc = syscall(SYS_setuid, uid);
__errno_return(rc, int);
}
int seteuid(uid_t uid)
{
long rc = syscall(SYS_seteuid, uid);
__errno_return(rc, int);
}
int setgid(gid_t gid)
{
long rc = syscall(SYS_setgid, gid);
__errno_return(rc, int);
}
int setegid(gid_t gid)
{
long rc = syscall(SYS_setegid, gid);
__errno_return(rc, int);
}
2023-04-08 12:47:34 +00:00
int chmod(const char* path, mode_t mode)
{
long rc = syscall(SYS_chmod, path, mode);
__errno_return(rc, int);
}
int chown(const char* path, uid_t uid, gid_t gid)
{
long rc = syscall(SYS_chown, path, uid, gid);
__errno_return(rc, int);
}
2023-03-18 21:31:16 +00:00
int execv(const char* path, char* const* argv)
{
return execve(path, argv, environ);
}
int execve(const char* path, char* const* argv, char* const* envp)
{
long rc = syscall(SYS_execve, path, argv, envp);
2023-03-18 21:31:16 +00:00
__errno_return(rc, int);
}
2023-04-07 13:39:10 +00:00
int execvpe(const char* name, char* const* argv, char* const* envp)
{
if (strchr(name, '/')) return execve(name, argv, envp);
char* path = getenv("PATH");
if (!path) path = const_cast<char*>("/bin:/sbin");
Vector<String> paths;
bool ok = StringView { path }.split(":").try_move_value_or_error(paths, errno);
if (!ok) return -1;
for (const auto& dir : paths)
{
// FIXME: Check for errors.
StringBuilder sb;
sb.add(dir);
sb.add('/');
sb.add(StringView { name });
String file;
ok = sb.string().try_move_value_or_error(file, errno);
if (!ok) return -1;
int err = errno;
execve(file.chars(), argv, envp);
if (errno != ENOENT && errno != EACCES && errno != ENOEXEC) return -1;
if (errno == ENOEXEC)
{
Vector<char*> shell_argv;
shell_argv.try_append(const_cast<char*>("sh"));
char* const* arg = argv;
do {
shell_argv.try_append(*arg);
} while (*(arg++));
execve("/bin/sh", shell_argv.data(), envp);
errno = ENOEXEC;
return -1;
}
2023-04-07 13:39:10 +00:00
if (err == EACCES) errno = err;
}
return -1;
}
int execvp(const char* name, char* const* argv)
{
return execvpe(name, argv, environ);
}
2023-03-30 19:28:39 +00:00
int execl(const char* path, const char* arg, ...)
{
va_list ap;
va_start(ap, arg);
Vector<char*> args;
if (args.try_append(const_cast<char*>(arg)).has_error()) return -1;
while (true)
{
char* str = va_arg(ap, char*);
if (args.try_append(str).has_error()) return -1;
if (!str) break;
}
va_end(ap);
return execv(path, args.data());
}
long syscall(long num, ...)
{
va_list ap;
va_start(ap, num);
uintptr_t arg0 = va_arg(ap, uintptr_t);
uintptr_t arg1 = va_arg(ap, uintptr_t);
uintptr_t arg2 = va_arg(ap, uintptr_t);
uintptr_t arg3 = va_arg(ap, uintptr_t);
uintptr_t arg4 = va_arg(ap, uintptr_t);
long rc = arch_invoke_syscall(num, arg0, arg1, arg2, arg3, arg4);
va_end(ap);
return rc;
}
int usleep(useconds_t us)
{
long rc = syscall(SYS_usleep, us);
__errno_return(rc, int);
}
unsigned long sleep(unsigned long seconds)
{
syscall(SYS_usleep, seconds * 1000000);
return 0;
}
int close(int fd)
{
long rc = syscall(SYS_close, fd);
__errno_return(rc, int);
}
2023-03-11 17:02:50 +00:00
ssize_t read(int fd, void* buf, size_t size)
{
long rc = syscall(SYS_read, fd, buf, size);
__errno_return(rc, ssize_t);
}
ssize_t write(int fd, const void* buf, size_t size)
{
long rc = syscall(SYS_write, fd, buf, size);
__errno_return(rc, ssize_t);
}
off_t lseek(int fd, off_t offset, int whence)
{
long rc = syscall(SYS_lseek, fd, offset, whence);
__errno_return(rc, off_t);
}
int dup(int fd)
{
return fcntl(fd, F_DUPFD, 0);
}
2023-04-11 20:15:21 +00:00
int chdir(const char* path)
{
long rc = syscall(SYS_chdir, path);
__errno_return(rc, int);
}
}