libc: split up large .c files, slimming down small binaries a bit
This commit is contained in:
parent
fd80c0b227
commit
a492c6ec11
|
@ -0,0 +1,3 @@
|
|||
int main(void) {
|
||||
return 0;
|
||||
}
|
|
@ -36,7 +36,7 @@ _Noreturn void _start2(struct execdata *ed) {
|
|||
|
||||
_sys_intr_set(intr_trampoline);
|
||||
intr_set(intr_default);
|
||||
__setinitialcwd(ed->cwd);
|
||||
__initialcwd = ed->cwd;
|
||||
|
||||
exit(main(ed->argc, ed->argv, ed->envp));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
#pragma once
|
||||
|
||||
void intr_set(void (*fn)(void));
|
||||
void intr_default(void);
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include <camellia/types.h> // TODO only needed because of hid_t
|
||||
#include <camellia/intr.h> // TODO only included for backwards compat
|
||||
#include <sys/types.h>
|
||||
#include <getopt.h>
|
||||
|
||||
|
@ -64,8 +65,5 @@ unsigned int sleep(unsigned int seconds);
|
|||
* @return 0 on failure, length of the path otherwise */
|
||||
size_t absolutepath(char *out, const char *in, size_t size);
|
||||
|
||||
// TODO put in an internal libc header
|
||||
void __setinitialcwd(const char *c);
|
||||
|
||||
void intr_set(void (*fn)(void));
|
||||
void intr_default(void);
|
||||
/* used internally */
|
||||
extern const char *__initialcwd;
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
#include <camellia/intr.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static void intr_null(void) { }
|
||||
|
||||
extern void (*volatile _intr)(void);
|
||||
void intr_set(void (*fn)(void)) {
|
||||
_intr = fn ? fn : intr_null;
|
||||
}
|
||||
|
||||
void intr_default(void) {
|
||||
exit(-1);
|
||||
}
|
|
@ -1,27 +1,10 @@
|
|||
#include <camellia/syscalls.h>
|
||||
#include <shared/printf.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
static void backend_file(void *arg, const char *buf, size_t len) {
|
||||
fwrite(buf, 1, len, arg);
|
||||
}
|
||||
|
||||
int vfprintf(FILE *restrict f, const char *restrict fmt, va_list ap) {
|
||||
return __printf_internal(fmt, ap, backend_file, f);
|
||||
}
|
||||
|
||||
|
||||
int printf(const char *restrict fmt, ...) {
|
||||
int ret;
|
||||
va_list argp;
|
||||
va_start(argp, fmt);
|
||||
ret = vprintf(fmt, argp);
|
||||
va_end(argp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int fprintf(FILE *restrict f, const char *restrict fmt, ...) {
|
||||
int ret;
|
||||
va_list argp;
|
||||
|
@ -31,11 +14,15 @@ int fprintf(FILE *restrict f, const char *restrict fmt, ...) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
int sprintf(char *restrict s, const char *restrict fmt, ...) {
|
||||
int vfprintf(FILE *restrict f, const char *restrict fmt, va_list ap) {
|
||||
return __printf_internal(fmt, ap, backend_file, f);
|
||||
}
|
||||
|
||||
int printf(const char *restrict fmt, ...) {
|
||||
int ret;
|
||||
va_list argp;
|
||||
va_start(argp, fmt);
|
||||
ret = vsnprintf(s, ~0, fmt, argp);
|
||||
ret = vprintf(fmt, argp);
|
||||
va_end(argp);
|
||||
return ret;
|
||||
}
|
||||
|
@ -43,18 +30,3 @@ int sprintf(char *restrict s, const char *restrict fmt, ...) {
|
|||
int vprintf(const char *restrict fmt, va_list ap) {
|
||||
return vfprintf(stdout, fmt, ap);
|
||||
}
|
||||
|
||||
int vsprintf(char *restrict s, const char *restrict fmt, va_list ap) {
|
||||
return vsnprintf(s, ~0, fmt, ap);
|
||||
}
|
||||
|
||||
int _klogf(const char *fmt, ...) {
|
||||
char buf[256];
|
||||
int ret;
|
||||
va_list argp;
|
||||
va_start(argp, fmt);
|
||||
ret = vsnprintf(buf, sizeof buf, fmt, argp);
|
||||
va_end(argp);
|
||||
_sys_debug_klog(buf, ret);
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
#include <camellia/syscalls.h>
|
||||
#include <shared/mem.h>
|
||||
#include <shared/printf.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int sprintf(char *restrict s, const char *restrict fmt, ...) {
|
||||
int ret;
|
||||
va_list argp;
|
||||
va_start(argp, fmt);
|
||||
ret = vsnprintf(s, ~0, fmt, argp);
|
||||
va_end(argp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int vsprintf(char *restrict s, const char *restrict fmt, va_list ap) {
|
||||
return vsnprintf(s, ~0, fmt, ap);
|
||||
}
|
||||
|
||||
int _klogf(const char *fmt, ...) {
|
||||
char buf[256];
|
||||
int ret;
|
||||
va_list argp;
|
||||
va_start(argp, fmt);
|
||||
ret = vsnprintf(buf, sizeof buf, fmt, argp);
|
||||
va_end(argp);
|
||||
_sys_debug_klog(buf, ret);
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
#include <_proc.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static const char *progname;
|
||||
const char *getprogname(void) {
|
||||
return progname;
|
||||
}
|
||||
void setprogname(const char *pg) {
|
||||
progname = pg;
|
||||
setproctitle(NULL);
|
||||
}
|
||||
|
||||
void setproctitle(const char *fmt, ...) {
|
||||
// TODO bounds checking
|
||||
if (!fmt) {
|
||||
strcpy(_psdata_loc->desc, progname);
|
||||
return;
|
||||
}
|
||||
sprintf(_psdata_loc->desc, "%s: ", progname);
|
||||
|
||||
va_list argp;
|
||||
va_start(argp, fmt);
|
||||
vsnprintf(_psdata_loc->desc + strlen(_psdata_loc->desc), 128, fmt, argp);
|
||||
va_end(argp);
|
||||
}
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
#include <_proc.h>
|
||||
#include <bits/panic.h>
|
||||
#include <camellia.h>
|
||||
#include <camellia/syscalls.h>
|
||||
|
@ -10,29 +9,6 @@ _Noreturn void abort(void) {
|
|||
_sys_exit(1);
|
||||
}
|
||||
|
||||
static const char *progname;
|
||||
const char *getprogname(void) {
|
||||
return progname;
|
||||
}
|
||||
void setprogname(const char *pg) {
|
||||
progname = pg;
|
||||
setproctitle(NULL);
|
||||
}
|
||||
|
||||
void setproctitle(const char *fmt, ...) {
|
||||
// TODO bounds checking
|
||||
if (!fmt) {
|
||||
strcpy(_psdata_loc->desc, progname);
|
||||
return;
|
||||
}
|
||||
sprintf(_psdata_loc->desc, "%s: ", progname);
|
||||
|
||||
va_list argp;
|
||||
va_start(argp, fmt);
|
||||
vsnprintf(_psdata_loc->desc + strlen(_psdata_loc->desc), 128, fmt, argp);
|
||||
va_end(argp);
|
||||
}
|
||||
|
||||
char *mktemp(char *tmpl) {
|
||||
// TODO mktemp mkstemp
|
||||
return tmpl;
|
|
@ -0,0 +1,105 @@
|
|||
/** String functions that don't depend on any external functions. */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
char *strchr(const char *s, int c) {
|
||||
for (; *s || c == 0; s++) {
|
||||
if (*s == c) return (char *)s;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *strrchr(const char *s, int c) {
|
||||
for (int i = strlen(s) + 1; i >= 0; i--) {
|
||||
if (s[i] == c) return (char *)s + i;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t strspn(const char *s, const char *accept) {
|
||||
size_t l = 0;
|
||||
for (; s[l] && strchr(accept, s[l]); l++);
|
||||
return l;
|
||||
}
|
||||
|
||||
size_t strcspn(const char *s, const char *reject) {
|
||||
size_t l = 0;
|
||||
for (; s[l] && !strchr(reject, s[l]); l++);
|
||||
return l;
|
||||
}
|
||||
|
||||
char *strpbrk(const char *s1, const char *s2) {
|
||||
for (; *s1; s1++) {
|
||||
if (strchr(s2, *s1)) return (char*)s1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *strtok(char *restrict s, const char *restrict sep) {
|
||||
static char *state;
|
||||
return strtok_r(s, sep, &state);
|
||||
}
|
||||
|
||||
char *strtok_r(char *restrict s, const char *restrict sep, char **restrict state) {
|
||||
char *end;
|
||||
if (!s) s = *state;
|
||||
s += strspn(s, sep); /* beginning of token */
|
||||
if (!*s) return NULL;
|
||||
|
||||
end = s + strcspn(s, sep);
|
||||
if (*end) {
|
||||
*end = '\0';
|
||||
*state = end + 1;
|
||||
} else {
|
||||
*state = end;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
int strncmp(const char *s1, const char *s2, size_t n) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
if (s1[i] < s2[i]) return -1;
|
||||
if (s1[i] > s2[i]) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int strcoll(const char *s1, const char *s2) {
|
||||
return strcmp(s1, s2);
|
||||
}
|
||||
|
||||
char *strstr(const char *s1, const char *s2) {
|
||||
size_t l1 = strlen(s1), l2 = strlen(s2);
|
||||
for (; l2 <= l1; s1++, l1--) {
|
||||
if (memcmp(s1, s2, l2) == 0) return (char*)s1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *strcat(char *restrict dst, const char *restrict src) {
|
||||
return strcpy(dst + strlen(dst), src);
|
||||
}
|
||||
|
||||
char *strcpy(char *restrict s1, const char *restrict s2) {
|
||||
char *ret = s1;
|
||||
while (*s2) *s1++ = *s2++;
|
||||
*s1 = *s2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *strncpy(char *restrict dst, const char *restrict src, size_t n) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
dst[i] = src[i];
|
||||
if (dst[i] == '\0') return dst + i; // TODO fill with null bytes
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
size_t strnlen(const char *s, size_t len) {
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (!s[i]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
/** String functions that don't fit into any of the other .c files */
|
||||
|
||||
#include <bits/panic.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
|
@ -5,107 +7,14 @@
|
|||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
char *strchr(const char *s, int c) {
|
||||
for (; *s || c == 0; s++) {
|
||||
if (*s == c) return (char *)s;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *strrchr(const char *s, int c) {
|
||||
for (int i = strlen(s) + 1; i >= 0; i--) {
|
||||
if (s[i] == c) return (char *)s + i;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t strspn(const char *s, const char *accept) {
|
||||
size_t l = 0;
|
||||
for (; s[l] && strchr(accept, s[l]); l++);
|
||||
return l;
|
||||
}
|
||||
|
||||
size_t strcspn(const char *s, const char *reject) {
|
||||
size_t l = 0;
|
||||
for (; s[l] && !strchr(reject, s[l]); l++);
|
||||
return l;
|
||||
}
|
||||
|
||||
char *strpbrk(const char *s1, const char *s2) {
|
||||
for (; *s1; s1++) {
|
||||
if (strchr(s2, *s1)) return (char*)s1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *strtok(char *restrict s, const char *restrict sep) {
|
||||
static char *state;
|
||||
return strtok_r(s, sep, &state);
|
||||
}
|
||||
|
||||
char *strtok_r(char *restrict s, const char *restrict sep, char **restrict state) {
|
||||
char *end;
|
||||
if (!s) s = *state;
|
||||
s += strspn(s, sep); /* beginning of token */
|
||||
if (!*s) return NULL;
|
||||
|
||||
end = s + strcspn(s, sep);
|
||||
if (*end) {
|
||||
*end = '\0';
|
||||
*state = end + 1;
|
||||
} else {
|
||||
*state = end;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
int strncmp(const char *s1, const char *s2, size_t n) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
if (s1[i] < s2[i]) return -1;
|
||||
if (s1[i] > s2[i]) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int strcoll(const char *s1, const char *s2) {
|
||||
return strcmp(s1, s2);
|
||||
}
|
||||
|
||||
// TODO implement strstr using Boyer-Moore
|
||||
char *strstr(const char *s1, const char *s2) {
|
||||
size_t l1 = strlen(s1), l2 = strlen(s2);
|
||||
for (; l2 <= l1; s1++, l1--) {
|
||||
if (memcmp(s1, s2, l2) == 0) return (char*)s1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *strcat(char *restrict dst, const char *restrict src) {
|
||||
return strcpy(dst + strlen(dst), src);
|
||||
}
|
||||
|
||||
char *strcpy(char *restrict s1, const char *restrict s2) {
|
||||
char *ret = s1;
|
||||
while (*s2) *s1++ = *s2++;
|
||||
*s1 = *s2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *strncpy(char *restrict dst, const char *restrict src, size_t n) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
dst[i] = src[i];
|
||||
if (dst[i] == '\0') return dst + i; // TODO fill with null bytes
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
char *strncat(char *restrict dst, const char *restrict src, size_t n) {
|
||||
(void)dst; (void)src; (void)n;
|
||||
__libc_panic("unimplemented");
|
||||
}
|
||||
|
||||
char *stpncpy(char *restrict dst, const char *restrict src, size_t n) {
|
||||
return stpncpy(dst, src, n) + n;
|
||||
(void)dst; (void)src; (void)n;
|
||||
__libc_panic("unimplemented");
|
||||
}
|
||||
|
||||
char *strdup(const char *s) {
|
||||
|
@ -115,15 +24,6 @@ char *strdup(const char *s) {
|
|||
return buf;
|
||||
}
|
||||
|
||||
size_t strnlen(const char *s, size_t len) {
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (!s[i]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
char *strsignal(int sig) {
|
||||
static char buf[32];
|
||||
snprintf(buf, sizeof(buf), "signal %d", sig);
|
||||
|
|
|
@ -1,315 +0,0 @@
|
|||
#include <bits/panic.h>
|
||||
#include <camellia.h>
|
||||
#include <camellia/path.h>
|
||||
#include <camellia/syscalls.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <elfload.h>
|
||||
|
||||
int errno = 0;
|
||||
static char *_environ[] = {NULL};
|
||||
char **environ = _environ;
|
||||
|
||||
int fork(void) {
|
||||
return _sys_fork(0, NULL);
|
||||
}
|
||||
|
||||
pid_t vfork(void) {
|
||||
// TODO vfork is implemented improperly and will break stuff
|
||||
return _sys_fork(0, NULL);
|
||||
}
|
||||
|
||||
int close(hid_t h) {
|
||||
return _sys_close(h);
|
||||
}
|
||||
|
||||
_Noreturn void exit(int c) {
|
||||
_sys_exit(c);
|
||||
}
|
||||
_Noreturn void _exit(int c) { exit(c); };
|
||||
|
||||
ssize_t readlink(const char *restrict path, char *restrict buf, size_t bufsize) {
|
||||
(void)path; (void)buf; (void)bufsize;
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int link(const char *path1, const char *path2) {
|
||||
(void)path1; (void)path2;
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int unlink(const char *path) {
|
||||
hid_t h = camellia_open(path, OPEN_WRITE);
|
||||
if (h < 0) return errno = -h, -1;
|
||||
long ret = _sys_remove(h);
|
||||
if (ret < 0) return errno = -ret, -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rmdir(const char *path) {
|
||||
(void)path;
|
||||
__libc_panic("unimplemented");
|
||||
}
|
||||
|
||||
int symlink(const char *path1, const char *path2) {
|
||||
(void)path1; (void)path2;
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// TODO isatty
|
||||
int isatty(int fd) {
|
||||
return fd <= 2 ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
int execv(const char *path, char *const argv[]) {
|
||||
return execve(path, argv, NULL);
|
||||
}
|
||||
|
||||
int execvp(const char *path, char *const argv[]) {
|
||||
// TODO execvp
|
||||
return execve(path, argv, NULL);
|
||||
}
|
||||
|
||||
int execvpe(const char *path, char *const argv[], char *const envp[]) {
|
||||
if (path[0] != '/') {
|
||||
char *exp = malloc(strlen(path) + 6);
|
||||
int ret;
|
||||
strcpy(exp, "/bin/");
|
||||
strcat(exp, path);
|
||||
ret = execve(exp, argv, envp);
|
||||
free(exp);
|
||||
return ret;
|
||||
}
|
||||
return execve(path, argv, envp);
|
||||
}
|
||||
|
||||
int execve(const char *path, char *const argv[], char *const envp[]) {
|
||||
FILE *file = fopen(path, "e");
|
||||
char hdr[4] = {0};
|
||||
if (!file)
|
||||
return -1;
|
||||
|
||||
fread(hdr, 1, 4, file);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
|
||||
if (!memcmp("\x7f""ELF", hdr, 4)) {
|
||||
elf_execf(file, (void*)argv, (void*)envp);
|
||||
fclose(file);
|
||||
} else if (!memcmp("#!", hdr, 2)) {
|
||||
char buf[256];
|
||||
fseek(file, 2, SEEK_SET);
|
||||
if (fgets(buf, sizeof buf, file)) {
|
||||
const char *argv [] = {buf, path, NULL};
|
||||
char *endl = strchr(buf, '\n');
|
||||
if (endl) *endl = '\0';
|
||||
execve(buf, (void*)argv, envp);
|
||||
}
|
||||
}
|
||||
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static const char *__initialcwd;
|
||||
static char *cwd = NULL, *cwd2 = NULL;
|
||||
static size_t cwdcapacity = 0;
|
||||
|
||||
static const char *getrealcwd(void) {
|
||||
/* __initialcwd can't just be initialized with "/" because ld has seemingly
|
||||
* started to revolt against humanity and not process half the relocations
|
||||
* it sees. */
|
||||
if (cwd) return cwd;
|
||||
if (__initialcwd) return __initialcwd;
|
||||
return "/";
|
||||
}
|
||||
|
||||
int chdir(const char *path) {
|
||||
hid_t h;
|
||||
char *tmp;
|
||||
size_t len = absolutepath(NULL, path, 0) + 1; /* +1 for the trailing slash */
|
||||
if (cwdcapacity < len) {
|
||||
cwdcapacity = len;
|
||||
if (cwd) {
|
||||
cwd = realloc(cwd, len);
|
||||
cwd2 = realloc(cwd2, len);
|
||||
} else {
|
||||
size_t initlen = strlen(__initialcwd) + 1;
|
||||
if (len < initlen)
|
||||
len = initlen;
|
||||
cwd = malloc(initlen);
|
||||
cwd2 = malloc(initlen);
|
||||
memcpy(cwd, __initialcwd, initlen);
|
||||
}
|
||||
}
|
||||
absolutepath(cwd2, path, cwdcapacity);
|
||||
len = strlen(cwd2);
|
||||
if (cwd2[len - 1] != '/') {
|
||||
cwd2[len] = '/';
|
||||
cwd2[len + 1] = '\0';
|
||||
}
|
||||
|
||||
/* check if exists */
|
||||
h = camellia_open(cwd2, OPEN_READ);
|
||||
if (h < 0) return errno = ENOENT, -1;
|
||||
close(h);
|
||||
|
||||
tmp = cwd;
|
||||
cwd = cwd2;
|
||||
cwd2 = tmp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *getcwd(char *buf, size_t capacity) {
|
||||
const char *realcwd = getrealcwd();
|
||||
size_t len = strlen(realcwd) + 1;
|
||||
if (capacity < len) {
|
||||
errno = capacity == 0 ? EINVAL : ERANGE;
|
||||
return NULL;
|
||||
}
|
||||
memcpy(buf, realcwd, len);
|
||||
return buf;
|
||||
}
|
||||
|
||||
uid_t getuid(void) { return 0; }
|
||||
uid_t geteuid(void) { return 0; }
|
||||
gid_t getgid(void) { return 0; }
|
||||
gid_t getegid(void) { return 0; }
|
||||
|
||||
int access(const char *path, int mode) {
|
||||
// TODO impl access()
|
||||
(void)path; (void)mode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int chown(const char *path, uid_t owner, gid_t group) {
|
||||
(void)path; (void)owner; (void)group;
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int setpgid(pid_t pid, pid_t pgid) {
|
||||
(void)pid; (void)pgid;
|
||||
return errno = ENOSYS, -1;
|
||||
}
|
||||
|
||||
pid_t tcgetpgrp(int fd) {
|
||||
(void)fd;
|
||||
return errno = ENOSYS, -1;
|
||||
}
|
||||
|
||||
int tcsetpgrp(int fd, pid_t pgrp) {
|
||||
(void)fd; (void)pgrp;
|
||||
return errno = ENOSYS, -1;
|
||||
}
|
||||
|
||||
pid_t getpgrp(void) {
|
||||
__libc_panic("unimplemented");
|
||||
}
|
||||
|
||||
pid_t getpid(void) {
|
||||
return _sys_getpid();
|
||||
}
|
||||
|
||||
pid_t getppid(void) {
|
||||
return _sys_getppid();
|
||||
}
|
||||
|
||||
int getgroups(int size, gid_t list[]) {
|
||||
(void)size; (void)list;
|
||||
__libc_panic("unimplemented");
|
||||
}
|
||||
|
||||
ssize_t read(int fd, void *buf, size_t count) {
|
||||
// TODO real file descriptor emulation - store offsets
|
||||
return _sys_read(fd, buf, count, -1);
|
||||
}
|
||||
|
||||
ssize_t write(int fd, const void *buf, size_t count) {
|
||||
// TODO real file descriptor emulation - store offsets
|
||||
return _sys_write(fd, buf, count, -1, 0);
|
||||
}
|
||||
|
||||
int pipe(int pipefd[2]) {
|
||||
// TODO pipe buffering
|
||||
int ret = _sys_pipe(pipefd, 0);
|
||||
if (ret < 0) {
|
||||
errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dup(int oldfd) {
|
||||
(void)oldfd;
|
||||
__libc_panic("unimplemented");
|
||||
}
|
||||
|
||||
int dup2(int oldfd, int newfd) {
|
||||
int ret = _sys_dup(oldfd, newfd, 0);
|
||||
if (ret < 0) {
|
||||
errno = -ret;
|
||||
ret = -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned int sleep(unsigned int seconds) {
|
||||
_sys_sleep(seconds * 1000);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t absolutepath(char *out, const char *in, size_t size) {
|
||||
const char *realcwd = getrealcwd();
|
||||
size_t len, pos = 0;
|
||||
if (!in) return strlen(realcwd) + 1;
|
||||
|
||||
if (!(in[0] == '/')) {
|
||||
len = strlen(realcwd);
|
||||
if (pos + len <= size && out != realcwd)
|
||||
memcpy(out + pos, realcwd, len);
|
||||
pos += len;
|
||||
|
||||
if (realcwd[len - 1] != '/') {
|
||||
if (pos + 1 <= size) out[pos] = '/';
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
len = strlen(in);
|
||||
if (pos + len <= size)
|
||||
memcpy(out + pos, in, len);
|
||||
pos += len;
|
||||
|
||||
if (pos <= size) {
|
||||
pos = path_simplify(out, out, pos);
|
||||
if (pos == 0) return 0;
|
||||
}
|
||||
|
||||
if (pos + 1 <= size) out[pos] = '\0';
|
||||
pos++;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
void __setinitialcwd(const char *s) {
|
||||
__initialcwd = s;
|
||||
}
|
||||
|
||||
static void intr_null(void) { }
|
||||
|
||||
extern void (*volatile _intr)(void);
|
||||
void intr_set(void (*fn)(void)) {
|
||||
_intr = fn ? fn : intr_null;
|
||||
}
|
||||
|
||||
void intr_default(void) {
|
||||
exit(-1);
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
#include <camellia.h>
|
||||
#include <camellia/path.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static char *cwd = NULL, *cwd2 = NULL;
|
||||
static size_t cwdcapacity = 0;
|
||||
|
||||
static const char *getrealcwd(void) {
|
||||
if (cwd) return cwd;
|
||||
if (__initialcwd) return __initialcwd;
|
||||
return "/";
|
||||
}
|
||||
|
||||
int chdir(const char *path) {
|
||||
hid_t h;
|
||||
char *tmp;
|
||||
size_t len = absolutepath(NULL, path, 0) + 1; /* +1 for the trailing slash */
|
||||
if (cwdcapacity < len) {
|
||||
cwdcapacity = len;
|
||||
if (cwd) {
|
||||
cwd = realloc(cwd, len);
|
||||
cwd2 = realloc(cwd2, len);
|
||||
} else {
|
||||
size_t initlen = strlen(__initialcwd) + 1;
|
||||
if (len < initlen)
|
||||
len = initlen;
|
||||
cwd = malloc(initlen);
|
||||
cwd2 = malloc(initlen);
|
||||
memcpy(cwd, __initialcwd, initlen);
|
||||
}
|
||||
}
|
||||
absolutepath(cwd2, path, cwdcapacity);
|
||||
len = strlen(cwd2);
|
||||
if (cwd2[len - 1] != '/') {
|
||||
cwd2[len] = '/';
|
||||
cwd2[len + 1] = '\0';
|
||||
}
|
||||
|
||||
/* check if exists */
|
||||
h = camellia_open(cwd2, OPEN_READ);
|
||||
if (h < 0) return errno = ENOENT, -1;
|
||||
close(h);
|
||||
|
||||
tmp = cwd;
|
||||
cwd = cwd2;
|
||||
cwd2 = tmp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *getcwd(char *buf, size_t capacity) {
|
||||
const char *realcwd = getrealcwd();
|
||||
size_t len = strlen(realcwd) + 1;
|
||||
if (capacity < len) {
|
||||
errno = capacity == 0 ? EINVAL : ERANGE;
|
||||
return NULL;
|
||||
}
|
||||
memcpy(buf, realcwd, len);
|
||||
return buf;
|
||||
}
|
||||
|
||||
size_t absolutepath(char *out, const char *in, size_t size) {
|
||||
const char *realcwd = getrealcwd();
|
||||
size_t len, pos = 0;
|
||||
if (!in) return strlen(realcwd) + 1;
|
||||
|
||||
if (!(in[0] == '/')) {
|
||||
len = strlen(realcwd);
|
||||
if (pos + len <= size && out != realcwd)
|
||||
memcpy(out + pos, realcwd, len);
|
||||
pos += len;
|
||||
|
||||
if (realcwd[len - 1] != '/') {
|
||||
if (pos + 1 <= size) out[pos] = '/';
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
len = strlen(in);
|
||||
if (pos + len <= size)
|
||||
memcpy(out + pos, in, len);
|
||||
pos += len;
|
||||
|
||||
if (pos <= size) {
|
||||
pos = path_simplify(out, out, pos);
|
||||
if (pos == 0) return 0;
|
||||
}
|
||||
|
||||
if (pos + 1 <= size) out[pos] = '\0';
|
||||
pos++;
|
||||
|
||||
return pos;
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
/** Functions from unistd.h that are either just a syscall or a return. */
|
||||
|
||||
#include <camellia/syscalls.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int errno = 0;
|
||||
static char *_environ[] = {NULL};
|
||||
char **environ = _environ;
|
||||
const char *__initialcwd = NULL;
|
||||
|
||||
int fork(void) {
|
||||
return _sys_fork(0, NULL);
|
||||
}
|
||||
|
||||
pid_t vfork(void) {
|
||||
// TODO vfork is implemented improperly and will break stuff
|
||||
return _sys_fork(0, NULL);
|
||||
}
|
||||
|
||||
int close(hid_t h) {
|
||||
return _sys_close(h);
|
||||
}
|
||||
|
||||
_Noreturn void exit(int c) {
|
||||
_sys_exit(c);
|
||||
}
|
||||
_Noreturn void _exit(int c) {
|
||||
exit(c);
|
||||
};
|
||||
|
||||
ssize_t readlink(const char *restrict path, char *restrict buf, size_t bufsize) {
|
||||
(void)path; (void)buf; (void)bufsize;
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int link(const char *path1, const char *path2) {
|
||||
(void)path1; (void)path2;
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int symlink(const char *path1, const char *path2) {
|
||||
(void)path1; (void)path2;
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// TODO isatty
|
||||
int isatty(int fd) {
|
||||
return fd <= 2 ? 1 : 0;
|
||||
}
|
||||
|
||||
uid_t getuid(void) { return 0; }
|
||||
uid_t geteuid(void) { return 0; }
|
||||
gid_t getgid(void) { return 0; }
|
||||
gid_t getegid(void) { return 0; }
|
||||
|
||||
int access(const char *path, int mode) {
|
||||
// TODO impl access()
|
||||
(void)path; (void)mode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int chown(const char *path, uid_t owner, gid_t group) {
|
||||
(void)path; (void)owner; (void)group;
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int setpgid(pid_t pid, pid_t pgid) {
|
||||
(void)pid; (void)pgid;
|
||||
return errno = ENOSYS, -1;
|
||||
}
|
||||
|
||||
pid_t tcgetpgrp(int fd) {
|
||||
(void)fd;
|
||||
return errno = ENOSYS, -1;
|
||||
}
|
||||
|
||||
int tcsetpgrp(int fd, pid_t pgrp) {
|
||||
(void)fd; (void)pgrp;
|
||||
return errno = ENOSYS, -1;
|
||||
}
|
||||
|
||||
pid_t getpid(void) {
|
||||
return _sys_getpid();
|
||||
}
|
||||
|
||||
pid_t getppid(void) {
|
||||
return _sys_getppid();
|
||||
}
|
||||
|
||||
ssize_t read(int fd, void *buf, size_t count) {
|
||||
// TODO real file descriptor emulation - store offsets
|
||||
// TODO errno
|
||||
return _sys_read(fd, buf, count, -1);
|
||||
}
|
||||
|
||||
ssize_t write(int fd, const void *buf, size_t count) {
|
||||
// TODO real file descriptor emulation - store offsets
|
||||
return _sys_write(fd, buf, count, -1, 0);
|
||||
}
|
||||
|
||||
int pipe(int pipefd[2]) {
|
||||
// TODO pipe buffering
|
||||
int ret = _sys_pipe(pipefd, 0);
|
||||
if (ret < 0) {
|
||||
errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dup2(int oldfd, int newfd) {
|
||||
int ret = _sys_dup(oldfd, newfd, 0);
|
||||
if (ret < 0) {
|
||||
errno = -ret;
|
||||
ret = -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned int sleep(unsigned int seconds) {
|
||||
_sys_sleep(seconds * 1000);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
#include <bits/panic.h>
|
||||
#include <camellia.h>
|
||||
#include <camellia/syscalls.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <elfload.h>
|
||||
|
||||
int unlink(const char *path) {
|
||||
hid_t h = camellia_open(path, OPEN_WRITE);
|
||||
if (h < 0) return errno = -h, -1;
|
||||
long ret = _sys_remove(h);
|
||||
if (ret < 0) return errno = -ret, -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rmdir(const char *path) {
|
||||
(void)path;
|
||||
__libc_panic("unimplemented");
|
||||
}
|
||||
|
||||
int execv(const char *path, char *const argv[]) {
|
||||
return execve(path, argv, NULL);
|
||||
}
|
||||
|
||||
int execvp(const char *path, char *const argv[]) {
|
||||
// TODO execvp
|
||||
return execve(path, argv, NULL);
|
||||
}
|
||||
|
||||
int execvpe(const char *path, char *const argv[], char *const envp[]) {
|
||||
if (path[0] != '/') {
|
||||
char *exp = malloc(strlen(path) + 6);
|
||||
int ret;
|
||||
strcpy(exp, "/bin/");
|
||||
strcat(exp, path);
|
||||
ret = execve(exp, argv, envp);
|
||||
free(exp);
|
||||
return ret;
|
||||
}
|
||||
return execve(path, argv, envp);
|
||||
}
|
||||
|
||||
int execve(const char *path, char *const argv[], char *const envp[]) {
|
||||
FILE *file = fopen(path, "e");
|
||||
char hdr[4] = {0};
|
||||
if (!file)
|
||||
return -1;
|
||||
|
||||
fread(hdr, 1, 4, file);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
|
||||
if (!memcmp("\x7f""ELF", hdr, 4)) {
|
||||
elf_execf(file, (void*)argv, (void*)envp);
|
||||
fclose(file);
|
||||
} else if (!memcmp("#!", hdr, 2)) {
|
||||
char buf[256];
|
||||
fseek(file, 2, SEEK_SET);
|
||||
if (fgets(buf, sizeof buf, file)) {
|
||||
const char *argv [] = {buf, path, NULL};
|
||||
char *endl = strchr(buf, '\n');
|
||||
if (endl) *endl = '\0';
|
||||
execve(buf, (void*)argv, envp);
|
||||
}
|
||||
}
|
||||
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
pid_t getpgrp(void) {
|
||||
__libc_panic("unimplemented");
|
||||
}
|
||||
|
||||
int getgroups(int size, gid_t list[]) {
|
||||
(void)size; (void)list;
|
||||
__libc_panic("unimplemented");
|
||||
}
|
||||
|
||||
int dup(int oldfd) {
|
||||
(void)oldfd;
|
||||
__libc_panic("unimplemented");
|
||||
}
|
Loading…
Reference in New Issue