Browse Source

blib wip

master
Mathieu Serandour 6 months ago
parent
commit
108d40c65b
  1. 11
      blib/Makefile
  2. 6
      blib/include/alloc.h
  3. 2
      blib/include/sprintf.h
  4. 7
      blib/include/stdio.h
  5. 33
      blib/include/stdio_printf.h
  6. 20
      blib/include/stdlib.h
  7. 13
      blib/include/string.h
  8. 68
      blib/include/unistd.h
  9. 3
      blib/src/alloc.c
  10. 64
      blib/src/crt0.c
  11. 4
      blib/src/dirent.c
  12. 5
      blib/src/sprintf.c
  13. 339
      blib/src/stdio.c
  14. 111
      blib/src/stdlib.c
  15. 31
      blib/src/string.c
  16. 152
      blib/src/unistd.c

11
blib/Makefile

@ -1,6 +1,6 @@
.PHONY: all clean
.PHONY: all clean debug release
BIN_FILE:=blib.a
@ -11,7 +11,7 @@ ASM:=nasm
CFLAGS := -O3 -mgeneral-regs-only \
CFLAGS := -O3 -mgeneral-regs-only -Wall -Wextra \
-ffreestanding -Iinclude/ -fno-pie -fno-stack-protector
LDFLAGS := -shared -fno-pie
@ -29,6 +29,13 @@ OBJ := $(SFILES:.s=.s.o) \
$(CFILES:.c=.c.o)
debug: CFLAGS += -g
debug: LDFLAGS += -g
debug: all
release: all
all: $(BIN_FILE)
%.c.o: %.c

6
blib/include/alloc.h

@ -1,5 +1,9 @@
#pragma once
#ifndef BLIB_STDLIB_H
#error "Include <stdlib.h> instead of this file directly."
#endif
#include <stddef.h>
/**
@ -13,3 +17,5 @@
void* malloc(size_t size);
void free(void* p);
void* realloc(void* ptr, size_t size);
#define alloca(size) __builtin_alloca(size)

2
blib/include/sprintf.h

@ -12,4 +12,4 @@ extern int vsprintf(char *str, const char *format, va_list ap);
extern int vsnprintf(char *str, size_t size, const char *format, va_list ap);
extern int snprintf (char *__restrict __s, size_t __maxlen,
const char *__restrict __format, ...)
const char *__restrict __format, ...);

7
blib/include/stdio.h

@ -71,7 +71,7 @@ extern FILE *stdout; /* Standard output stream. */
extern FILE *stderr; /* Standard error output stream. */
/* C89/C99 say they're macros. Make them happy. */
#define stdin stdin
#define stdin stdin
#define stdout stdout
#define stderr stderr
@ -245,7 +245,6 @@ extern void setbuf (FILE *__restrict __stream, char *__restrict __buf);
extern int setvbuf (FILE *__restrict __stream, char *__restrict __buf,
int __modes, size_t __n);
#ifdef __USE_MISC
/* If BUF is NULL, make STREAM unbuffered.
Else make it use SIZE bytes of BUF for buffering. */
extern void setbuffer (FILE *__restrict __stream, char *__restrict __buf,
@ -253,7 +252,6 @@ extern void setbuffer (FILE *__restrict __stream, char *__restrict __buf,
/* Make STREAM line-buffered. */
extern void setlinebuf (FILE *__stream);
#endif
#include <stdio_printf.h>
@ -261,7 +259,8 @@ extern void setlinebuf (FILE *__stream);
These functions are possible cancellation points and therefore not
marked with __THROW. */
extern int fgetc (FILE *__stream);
extern int getc (FILE *__stream);
#define getc fgetc

33
blib/include/stdio_printf.h

@ -5,6 +5,7 @@
#endif
/* Write formatted output to STREAM.
This function is a possible cancellation point and therefore not
@ -18,35 +19,32 @@ extern int fprintf (FILE *__restrict __stream,
extern int printf (const char *__restrict __format, ...);
/* Write formatted output to S. */
extern int sprintf (char *__restrict __s,
const char *__restrict __format, ...)NL;
const char *__restrict __format, ...);
#include "sprintf.h"
extern int vfprintf (FILE *__restrict __s, const char *__restrict __format,
__gnuc_va_list __arg);
va_list __arg);
/* Write formatted output to stdout from argument list ARG.
This function is a possible cancellation point and therefore not
marked with __THROW. */
extern int vprintf (const char *__restrict __format, __gnuc_va_list __arg);
extern int vprintf (const char *__restrict __format, va_list __arg);
/* Write formatted output to S from argument list ARG. */
/* Maximum chars of output to write in MAXLEN. */
extern int snprintf (char *__restrict __s, size_t __maxlen,
const char *__restrict __format, ...)
__THROWNL __attribute__ ((__format__ (__printf__, 3, 4)));
const char *__restrict __format, ...);
extern int vsnprintf (char *__restrict __s, size_t __maxlen,
const char *__restrict __format, __gnuc_va_list __arg)
__THROWNL __attribute__ ((__format__ (__printf__, 3, 0)));
const char *__restrict __format, va_list __arg)
__attribute__ ((__format__ (__printf__, 3, 0)));
/* Write formatted output to a file descriptor. */
extern int vdprintf (int __fd, const char *__restrict __fmt,
__gnuc_va_list __arg)
__attribute__ ((__format__ (__printf__, 2, 0)));
extern int dprintf (int __fd, const char *__restrict __fmt, ...)
__attribute__ ((__format__ (__printf__, 2, 3)));
va_list __arg);
extern int dprintf (int __fd, const char *__restrict __fmt, ...);
/* Read formatted input from STREAM.
@ -54,12 +52,12 @@ extern int dprintf (int __fd, const char *__restrict __fmt, ...)
This function is a possible cancellation point and therefore not
marked with __THROW. */
extern int fscanf (FILE *__restrict __stream,
const char *__restrict __format, ...) __wur;
const char *__restrict __format, ...);
/* Read formatted input from stdin.
This function is a possible cancellation point and therefore not
marked with __THROW. */
extern int scanf (const char *__restrict __format, ...) __wur;
extern int scanf (const char *__restrict __format, ...);
/* Read formatted input from S. */
extern int sscanf (const char *__restrict __s,
const char *__restrict __format, ...);
@ -69,17 +67,14 @@ extern int sscanf (const char *__restrict __s,
This function is a possible cancellation point and therefore not
marked with __THROW. */
extern int vfscanf (FILE *__restrict __s, const char *__restrict __format,
__gnuc_va_list __arg)
__attribute__ ((__format__ (__scanf__, 2, 0))) __wur;
va_list __arg);
/* Read formatted input from stdin into argument list ARG.
This function is a possible cancellation point and therefore not
marked with __THROW. */
extern int vscanf (const char *__restrict __format, __gnuc_va_list __arg)
__attribute__ ((__format__ (__scanf__, 1, 0))) __wur;
extern int vscanf (const char *__restrict __format, va_list __arg);
/* Read formatted input from S into argument list ARG. */
extern int vsscanf (const char *__restrict __s,
const char *__restrict __format, __gnuc_va_list __arg)
__THROW __attribute__ ((__format__ (__scanf__, 2, 0)));
const char *__restrict __format, va_list __arg);

20
blib/include/stdlib.h

@ -0,0 +1,20 @@
#pragma once
#define BLIB_STDLIB_H
extern int atexit(void (*func)(void));
extern void __attribute__((noreturn)) exit(int status);
extern int putenv(char *string);
extern int setenv(const char *name, const char *value, int overwrite);
extern int unsetenv(const char *name);
extern char* getenv(const char *name);
extern int system(const char *command);
// malloc, free, realloc, alloca
#include <alloc.h>
#undef BLIB_STDLIB_H

13
blib/include/string.h

@ -11,7 +11,7 @@
void * memccpy (void * __restrict__, const void * __restrict__, int, size_t);
const void * memchr (const void *, int, size_t) __ATTR_PURE__;
const void * __ATTR_PURE__ memchr (const void *, int, size_t) __ATTR_PURE__;
int memcmp (const void *, const void *, size_t) __ATTR_PURE__;
void * memcpy (void * __restrict__, const void * __restrict__, size_t);
void * memset (void *, int, size_t);
@ -20,6 +20,9 @@ void * memmove (void *, const void *, size_t);
//void * memrchr (const void *, int, size_t) __ATTR_PURE__;
char *strdup(const char *s);
char *strndup(const char *s, size_t n);
size_t strlen (const char* str) __ATTR_PURE__;
size_t strnlen(const char* str, size_t n) __ATTR_PURE__;
@ -40,12 +43,4 @@ char* strtok(char* __restrict__ str, const char* __restrict__ delim);
char* strtok_r(char* __restrict__ str, const char* __restrict__ delim, char** __restrict__ saveptr);
// return 0 if the check sum is 0
// this is equivalent to memsum(table, size) == 0
int checksum(const void* table, size_t size);
int memsum(const void* ptr, size_t size);
#endif//KSTRING_H

68
blib/include/unistd.h

@ -82,43 +82,12 @@ extern int pause (void);
extern int fchdir (int __fd) __THROW __wur;
/* Replace the current process, executing PATH with arguments ARGV and
environment ENVP. ARGV and ENVP are terminated by NULL pointers. */
extern int execve (const char *__path, char *const __argv[],
char *const __envp[]) __THROW __nonnull ((1, 2));
/* Execute the file FD refers to, overlaying the running program image.
ARGV and ENVP are passed to the new program, as for `execve'. */
extern int fexecve (int __fd, char *const __argv[], char *const __envp[])
__THROW __nonnull ((2));
/* Execute PATH with arguments ARGV and environment from `environ'. */
extern int execv (const char *__path, char *const __argv[])
__THROW __nonnull ((1, 2));
/* Execute PATH with all arguments after PATH until a NULL pointer,
and the argument after that for environment. */
extern int execle (const char *__path, const char *__arg, ...)
__THROW __nonnull ((1, 2));
/* Execute PATH with all arguments after PATH until
a NULL pointer and environment from `environ'. */
extern int execl (const char *__path, const char *__arg, ...)
__THROW __nonnull ((1, 2));
/* Execute FILE, searching in the `PATH' environment variable if it contains
no slashes, with arguments ARGV and environment from `environ'. */
extern int execvp (const char *__file, char *const __argv[])
__THROW __nonnull ((1, 2));
/* Execute FILE, searching in the `PATH' environment variable if
it contains no slashes, with all arguments after FILE until a
NULL pointer and environment from `environ'. */
extern int execlp (const char *__file, const char *__arg, ...)
__THROW __nonnull ((1, 2));
/* Get file-specific configuration information about PATH. */
extern long int pathconf (const char *__path, int __name)
__THROW __nonnull ((1));
@ -574,12 +543,40 @@ extern void *sbrk (uint64_t __delta);
/*
return 0 if successfull, -1 if error
*/
extern int forkexec(const char* cmdline);
extern int forkexec(char* const cmdline[]);
/* Execute PATH with arguments ARGV and environment from `environ'. */
extern int execv (const char *__path, char *const __argv[]);
/* Replace the current process, executing PATH with arguments ARGV and
environment ENVP. ARGV and ENVP are terminated by NULL pointers. */
extern int execve (const char *__path, char *const __argv[],
char *const __envp[]);
/* Execute PATH with all arguments after PATH until a NULL pointer,
and the argument after that for environment. */
extern int execle (const char *__path, const char *__arg, ...);
/* Execute PATH with all arguments after PATH until
a NULL pointer and environment from `environ'. */
extern int execl (const char *__path, const char *__arg, ...);
/* Execute FILE, searching in the `PATH' environment variable if it contains
no slashes, with arguments ARGV and environment from `environ'. */
extern int execvp (const char *__file, char *const __argv[]);
extern int execvpe(const char *file, char *const argv[],
char *const envp[]);
/* Execute FILE, searching in the `PATH' environment variable if
it contains no slashes, with all arguments after FILE until a
NULL pointer and environment from `environ'. */
extern int execlp (const char *__file, const char *__arg, ...);
/* Change the process's working directory to PATH. */
extern int chdir (const char *__path);
@ -591,6 +588,9 @@ extern int chdir (const char *__path);
an array is allocated with `malloc'; the array is SIZE
bytes long, unless SIZE == 0, in which case it is as
big as necessary. */
// Bincows implementation of getcwd is similar to GNU:
// if buf == 0 && size == 0, return a malloced buffer
// with the right size.
extern char *getcwd (char *__buf, size_t __size);
@ -616,7 +616,7 @@ typedef enum open_flags {
O_NOATIME = 1024,
O_CLOEXEC = 2048,
O_DIR = 4096,
} open_flags_t;
} open_flags_t;
/* Invoke `system call' number SYSNO, passing it the remaining arguments.
@ -649,4 +649,6 @@ typedef enum mode_t {
int open (const char *pathname, int flags, mode_t mode);
#endif /* unistd.h */

3
blib/src/alloc.c

@ -1,8 +1,7 @@
#include "alloc.h"
#include <unistd.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#define MIN_EXPAND_SIZE 4096

64
blib/src/crt0.c

@ -0,0 +1,64 @@
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
char** __environ = NULL;
extern int main(int argc, char** argv);
// defined in stdio.c
extern void stio_init(void);
static void init_argv(int argc, void* args, char** argv) {
char* p = args;
int i = 0;
while(*p) {
if(i >= argc)
break;
argv[i++] = p;
while(*p) p++;
p++;
}
if(argc != i) {
printf("bad argc\n");
exit(1);
}
}
void __attribute__((noreturn))
_start(int argc, char* args, int envrionc, char* input_environ) {
// compute argv and argc
char** argv = alloca(argc * sizeof(char*));
init_argv(argc, args, argv);
// compute environ
char** environ;
__environ = environ = malloc(envrionc);
char** p = environ;
while(p) {
for(unsigned i = 0; i < envrionc; i++) {
*p++ = strdup(input_environ);
input_environ += strlen(input_environ) + 1;
}
}
stio_init();
int ret = main(argc, argv);
exit(ret);
}

4
blib/src/dirent.c

@ -1,6 +1,6 @@
#include <dirent.h>
#include <alloc.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct DIR {
int fd;

5
blib/src/sprintf.c

@ -1,7 +1,6 @@
#include <string.h>
#include "sprintf.h"
#include "math.h"
#include "string.h"
#include "../drivers/terminal/terminal.h"
#define SIGN(X) X > 0 ? 1 : -1
#define ARG(TYPE) (TYPE)va_arg(ap, TYPE)

339
blib/src/stdio.c

@ -1,21 +1,87 @@
#include <stdio.h>
#include <unistd.h>
#include <alloc.h>
#include <stdlib.h>
#include <string.h>
struct FILE {
int fd;
int flags;
int mode;
int ungetc;
int error;
int eof;
int pos;
int size;
char* buffer;
int fd;
int flags;
int mode;
int ungetc;
int error;
int eof;
int pos;
size_t size;
size_t bufsize;
char* buffer;
size_t buf_off;
// 0 if the buffer was not read/written
// 1 if the buffer was read to
// 2 if the buffer was written to
int buff_state;
};
FILE *stdin;
FILE *stdout;
FILE *stderr;
void stio_init(void) {
FILE* std = (FILE*)malloc(sizeof(FILE) * 3);
stdin = std + 0;
stdout = std + 1;
stderr = std + 2;
*stdin = (FILE){
.fd = STDIN_FILENO,
.flags = 0,
.mode = 0,
.ungetc = -1,
.error = 0,
.eof = 0,
.pos = 0,
.size = 0,
.bufsize = 0,
.buffer = NULL,
.buf_off = 0,
.buff_state = 0,
};
*stdout = (FILE){
.fd = STDOUT_FILENO,
.flags = 0,
.mode = 0,
.ungetc = -1,
.error = 0,
.eof = 0,
.pos = 0,
.size = 0,
.bufsize = 0,
.buffer = NULL,
.buf_off = 0,
.buff_state = 0,
};
*stderr = (FILE){
.fd = STDERR_FILENO,
.flags = 0,
.mode = 0,
.ungetc = -1,
.error = 0,
.eof = 0,
.pos = 0,
.size = 0,
.bufsize = 0,
.buffer = NULL,
.buf_off = 0,
.buff_state = 0,
};
}
#define BUF_NONE 0
#define BUF_RD 1
#define BUF_WR 2
FILE *fopen (const char *restrict filename,
const char *restrict modes
@ -40,6 +106,7 @@ FILE *fopen (const char *restrict filename,
file->eof = 0;
file->pos = 0;
file->size = 0;
file->bufsize = BUFSIZ;
file->buf_off = 0;
file->buffer = malloc(BUFSIZ);
@ -47,13 +114,21 @@ FILE *fopen (const char *restrict filename,
}
int fflush (FILE *stream) {
int fflush (FILE * restrict stream) {
if(stream->buf_off) {
write(stream->fd, stream->buffer, stream->buf_off);
if(stream->buff_state == BUF_WR)
write(stream->fd, stream->buffer, stream->buf_off);
else if(stream->buff_state == BUF_RD)
stream->bufsize = read(stream->fd, stream->buffer, stream->buf_off);
stream->buf_off = 0;
}
return 0;
}
int fclose (FILE* stream) {
fflush(stream);
close(stream->fd);
@ -75,10 +150,242 @@ int fclose (FILE* stream) {
return stream;
}
void setbuf (FILE *restrict stream, char *restrict buf) {
free(stream->buffer);
stream->buffer = buf;
int fgetc(FILE* stream) {
if(stream->flags & O_WRONLY) {
return EOF;
}
switch(stream->mode) {
case _IOFBF:
return EOF;
case _IOLBF:
return EOF;
case _IONBF: {
char c;
stream->pos++;
int n = read(stream->fd, &c, 1);
if(n == 1) {
return c;
}
return EOF;
}
default:
return EOF;
}
}
int fputc (int c, FILE* stream) {
char s[2];
s[0] = c;
s[1] = '\0';
return fputs(s, stream);
}
int putchar(int c) {
return fputc(c, stdout);
}
int puts (const char *s) {
if(write(STDOUT_FILENO, s, strlen(s)) < 0) {
return EOF;
}
else if(write(STDOUT_FILENO, "\n", 1) < 0) {
return EOF;
}
return 0;
}
size_t fread (void *restrict ptr, size_t size,
size_t n, FILE *restrict stream
) {
if(stream->flags & O_WRONLY) {
return 0;
}
int64_t rd = read(stream->fd, ptr, size * n);
if(rd < 0) {
return 0;
}
if(rd != size * n)
stream->eof = 1;
stream->pos += n;
return rd / size;
}
size_t fwrite (const void *restrict ptr, size_t size,
size_t _n, FILE *restrict stream
) {
if(stream->flags & O_RDONLY) {
return 0;
}
int64_t n = write(stream->fd, ptr, size * _n);
if(n < 0) {
return 0;
}
if(n != size * n)
stream->eof = 1;
stream->pos += n;
return n / size;
}
int fseek (FILE* stream, long offset, int whence) {
int seeked = lseek(stream->fd, offset, whence);
stream->pos = seeked;
return seeked;
}
long ftell (FILE* stream) {
return stream->pos;
}
void rewind (FILE* stream) {
fseek(stream, 0, SEEK_SET);
}
int fgetpos (FILE *restrict stream, fpos_t *restrict pos) {
*pos = stream->pos;
return 0;
}
int fileno (FILE *stream) {
return stream->fd;
}
int feof (FILE *stream) {
return stream->eof;
}
int fputs(const char* restrict s, FILE* restrict stream) {
if(stream->flags & O_RDONLY) {
return EOF;
}
switch(stream->mode) {
case _IOFBF: {
return EOF;
}
case _IOLBF: {
return EOF;
}
case _IONBF: {
int n = write(stream->fd, s, strlen(s));
if(n == strlen(s)) {
return 0;
}
stream->eof = 1;
return EOF;
}
default:
return EOF;
}
}
char* fgets(char* restrict s, int n, FILE* restrict stream) {
if(stream->flags & O_WRONLY) {
return NULL;
}
switch(stream->mode) {
case _IOFBF: {
return NULL;
}
case _IOLBF: {
return NULL;
}
case _IONBF: {
int i = 0;
while(i < n) {
char c = fgetc(stream);
if(c == EOF) {
return NULL;
}
s[i] = c;
i++;
}
return s;
}
default:
return NULL;
}
}
int fprintf (FILE* restrict stream, const char* restrict format, ...) {
va_list args;
va_start(args, format);
int n = vfprintf(stream, format, args);
va_end(args);
return n;
}
int vfprintf(FILE* stream, const char* restrict format, va_list arg) {
char* buf = malloc(BUFSIZ);
if(!buf) {
return -1;
}
int n = vsprintf(buf, format, arg);
if(n < 0) {
return -1;
}
write(stream->fd, buf, n);
stream->pos += n;
return n;
}
int vprintf(const char* restrict format, va_list arg) {
char* buf = malloc(BUFSIZ);
if(!buf) {
return -1;
}
int n = vsprintf(buf, format, arg);
write(1, buf, strlen(buf));
free(buf);
return n;
}
int printf(const char* restrict format, ...) {
va_list args;
va_start(args, format);
int n = vprintf(format, args);
va_end(args);
return n;
}

111
blib/src/stdlib.c

@ -0,0 +1,111 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static void (**atexit_funs)(void);
size_t n_atexit_funs = 0;
void exit(int status) {
for(size_t i = 0; i < n_atexit_funs; i++)
atexit_funs[i]();
_exit(status);
}
int atexit(void (*func)(void)) {
atexit_funs = realloc(atexit_funs, (n_atexit_funs + 1) * sizeof(void*));
if(atexit_funs == NULL)
return -1;
atexit_funs[n_atexit_funs++] = func;
return 0;
}
extern char** __environ;
int putenv(char *string) {
char* name = string;
size_t envs = 0;
for(char** p = __environ; *p; p++) {
if(strcmp(name, *p) == 0) {
*p = string;
return 0;
}
envs++;
}
// add a new environment variable
__environ = realloc(__environ, (envs + 2) * sizeof(char*));
if(__environ == NULL)
return -1;
__environ[envs] = string;
__environ[envs + 1] = NULL;
return 0;
}
int setenv(const char *name, const char *value, int overwrite) {
if(!overwrite) {
char* env = getenv(name);
if(env != NULL)
return -1;
}
char* env = malloc(strlen(name) + strlen(value) + 2);
strcpy(env, name);
strcat(env, "=");
strcat(env, value);
putenv(env);
return 0;
}
int unsetenv(const char *name) {
char* env = getenv(name);
if(env == NULL)
return -1;
char* p = env;
while(*p) {
*p = *(p + strlen(name) + 1);
p++;
}
return 0;
}
char* getenv(const char *name) {
for(char** p = __environ; *p; p++) {
if(strncmp(name, *p, strlen(name)) == 0) {
return *p;
}
}
return NULL;
}
int system(const char *command) {
return forkexec((char*[]){"/bin/sh", "-c", command, NULL});
}

31
blib/src/string.c

@ -1,5 +1,7 @@
#include "string.h"
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
size_t strlen(const char* str) {
const char* ptr = str;
@ -334,20 +336,23 @@ char* strtok(char* restrict str, const char* restrict delim) {
}
int memsum(const void* ptr, size_t size) {
uint8_t sum = 0;
const uint8_t* raw = ptr;
for(size_t i = 0;size > 0; --size) {
sum += raw[i++];
}
return sum;
}
char *strdup(const char *s) {
size_t len = strlen(s);
char* ret = malloc(len+1);
if(!ret)
return NULL;
int checksum(const void* table, size_t size) {
return ~memsum(table,size);
memcpy(ret, s, len+1);
return ret;
}
char *strndup(const char *s, size_t n) {
size_t len = strnlen(s, n);
char* ret = malloc(len+1);
if(!ret)
return NULL;
memcpy(ret, s, len+1);
return ret;
}

152
blib/src/unistd.c

@ -1,10 +1,10 @@
#include <stdarg.h>
#include <alloc.h>
#include "unistd.h"
#include "string.h"
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
// for system call numbers
#include "../../kernel/int/syscall.h"
#include "../../kernel/int/syscall_interface.h"
@ -41,11 +41,6 @@ void *sbrk (uint64_t delta) {
}
void exit (int status) {
syscall(SC_EXIT, &status, sizeof(status));
}
int open (const char *pathname, int flags, mode_t _mode) {
open_mode_t mode = (open_mode_t)_mode;
@ -120,62 +115,100 @@ size_t pread (int fd, void* buf, size_t nbytes, off_t offset) {
size_t pwrite (int fd, const void* buf, size_t n, off_t offset);
int execv (const char* path, char *const argv[]) {
if(strcmp(path, argv[0]) != 0) {
return -1;
};
size_t size = 0;
/**
* @brief create a string list:
* strings separated by '\0'
* with double '\0' at the end
*
* @param len number of null-terminated strings in arr
* @param arr null terminated array of null terminated
* strings
* @param size (output) size of the resulting string
* list buffer
* @return mallocated string list
*/
static char* create_string_list(char* const* arr, size_t* size) {
// first compute the needed buffer size
// and the number of strings
size_t len = 0;
size_t bufsize = 1; // for the last '\0'
while(arr[len])
bufsize += strlen(arr[len++]);
for(int i = 0; argv[i] != NULL; i++) {
size += strlen(argv[i]) + 1;
}
char* prog_args = malloc(size);
bufsize += len; // for the '\0' between each string
char* ptr = prog_args;
for(int i = 0; argv[i] != NULL; i++) {
strcpy(ptr, argv[i]);
ptr += strlen(argv[i]) + 1;
*size = bufsize;
// allocate the buffer
char* list = malloc(bufsize);
// fill the buffer
char* p = list;
for(size_t i = 0; i < len; i++) {
int slen = strlen(arr[i]);
memcpy(p, arr[i], slen);
p += slen;
*p++ = '\0';
}
*p++ = '\0';
return list;
}
// base function for all exec* functions
static
int exec(const char* file, char* const argv[], char* const envp[], int new_process) {
size_t args_sz = 0, env_sz = 0;
char* args = create_string_list(argv, &args_sz);
char* env = create_string_list(envp, &env_sz);
struct sc_exec_args args = {
.args = prog_args,
.args_sz = 0,
.new_process = 0,
struct sc_exec_args sc_args = {
.args = args,
.args_sz = args_sz,
.env = env,
.env_sz = env_sz,
.new_process = new_process,
};
syscall(SC_EXEC, &args, sizeof(args));
int r = syscall(SC_EXEC, &sc_args, sizeof(sc_args));
free(args);
free(env);
free(prog_args);
return r;
}
int forkexec(const char* cmdline) {
int execvpe(const char* file, char* const argv[], char* const envp[]) {
if(strcmp(file, argv[0]) != 0) {
return -1;
};
exec(file, argv, envp, 0);
}
char* cmdline_cpy = malloc(strlen(cmdline) + 1);
strcpy(cmdline_cpy, cmdline);
struct sc_exec_args args = {
.args = cmdline_cpy,
.args_sz = strlen(cmdline)+1,
.new_process = 1,
};
int execv (const char* path, char* const argv[]) {
// @todo search in $PATH
return execvp(path, argv);
}
while(strrchr(cmdline_cpy, ' ') != NULL) {
*(char *)strrchr(cmdline_cpy, ' ') = '\0';
}
int execvp (const char *le, char *const argv[]) {
return exec(le, argv, __environ, 0);
}
syscall(SC_EXEC, &args, sizeof(args));
free(cmdline_cpy);
return 0;
int forkexec(char* const cmdline[]) {
return exec(cmdline[0], cmdline, __environ, 1);
}
@ -196,6 +229,20 @@ char *getcwd (char *buf, size_t size) {
.buf_sz = size,
};
if(size == 0 && buf == NULL) {
// reaquest cwd size first
size = syscall(SC_GETCWD, &args, sizeof(args));
if(size == -1) {
return NULL;
}
args.buf = malloc(size);
args.buf_sz = size;
}
return (char *)syscall(SC_GETCWD, &args, sizeof(args));
}
@ -243,20 +290,3 @@ void __attribute__ ((__noreturn__)) _exit (int status) {
syscall(SC_EXIT, &status, sizeof(status));
__builtin_unreachable();
}
int fopen(const char* path, const char* mode) {
int flags = 0;
if(strcmp(mode, "r") == 0) {
flags = O_RDONLY;
} else if(strcmp(mode, "w") == 0) {
flags = O_WRONLY;
} else if(strcmp(mode, "rw") == 0) {
flags = O_RDWR;
} else {
return -1;
}
return open(path, flags, 0);
}

Loading…
Cancel
Save