mirror of
https://github.com/JannisHeydemann/BoredOS.git
synced 2026-05-30 02:16:58 +00:00
Merge branch 'BoredDevNL:main' into terminal-fix
This commit is contained in:
@@ -59,7 +59,7 @@ $(BIN_DIR)/screenshot.elf: $(LIBC_OBJS) $(BIN_DIR)/screenshot.o $(BIN_DIR)/stb_i
|
||||
$(LD) $(LDFLAGS) $^ -o $@
|
||||
|
||||
$(BIN_DIR)/%.o: games/doom/%.c | $(BIN_DIR)
|
||||
$(CC) $(CFLAGS) -Wno-error -Igames/doom -c $< -o $@
|
||||
$(CC) $(CFLAGS) -Wno-error -DBOREDOS -Igames/doom -c $< -o $@
|
||||
|
||||
$(BIN_DIR)/doom.elf: $(LIBC_OBJS) $(DOOM_OBJS) $(BIN_DIR)/stb_image.o
|
||||
$(LD) $(LDFLAGS) $^ -o $@
|
||||
|
||||
@@ -564,7 +564,7 @@ static void history_add(const char *line) {
|
||||
|
||||
static void get_time_string(char *out, int max_len) {
|
||||
int dt[6] = {0};
|
||||
sys_system(11, (uint64_t)dt, 0, 0, 0);
|
||||
sys_system(SYSTEM_CMD_RTC_GET, (uint64_t)dt, 0, 0, 0);
|
||||
char hh[4], mm[4];
|
||||
itoa(dt[3], hh);
|
||||
itoa(dt[4], mm);
|
||||
|
||||
@@ -6,6 +6,6 @@
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
(void)argc; (void)argv;
|
||||
sys_system(10, 0, 0, 0, 0);
|
||||
sys_system(SYSTEM_CMD_CLEAR_SCREEN, 0, 0, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
int main(int argc, char **argv) {
|
||||
(void)argc; (void)argv;
|
||||
int dt[6];
|
||||
if (sys_system(11, (uint64_t)dt, 0, 0, 0) == 0) {
|
||||
if (sys_system(SYSTEM_CMD_RTC_GET, (uint64_t)dt, 0, 0, 0) == 0) {
|
||||
printf("Current Date: %d-%d-%d %d:%d:%d\n", dt[0], dt[1], dt[2], dt[3], dt[4], dt[5]);
|
||||
} else {
|
||||
printf("Error: Could not retrieve date.\n");
|
||||
|
||||
@@ -85,7 +85,7 @@ int main(void) {
|
||||
if (!fb) return 1;
|
||||
|
||||
// Seed PRNG with system time (ticks)
|
||||
my_srand((unsigned int)sys_system(16, 0, 0, 0, 0));
|
||||
my_srand((unsigned int)sys_system(SYSTEM_CMD_GET_TICKS, 0, 0, 0, 0));
|
||||
|
||||
// Initialize perfect slope
|
||||
int max_h = WIN_H - 40; // max height
|
||||
|
||||
1026
src/userland/cli/third_party/lua/boredos_stubs.h
vendored
1026
src/userland/cli/third_party/lua/boredos_stubs.h
vendored
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,9 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifndef BOREDOS_LIBC_TIME_H
|
||||
#define BOREDOS_LIBC_TIME_H
|
||||
|
||||
typedef long long time_t;
|
||||
typedef unsigned long long clock_t;
|
||||
|
||||
@@ -28,3 +31,5 @@ size_t strftime(char *s, size_t max, const char *fmt, const struct tm *tm);
|
||||
time_t mktime(struct tm *tm);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,219 +0,0 @@
|
||||
#include "boredos_libc.h"
|
||||
#include <syscall.h>
|
||||
|
||||
int errno = 0;
|
||||
|
||||
static FILE _stderr = {2, 0, 0};
|
||||
static FILE _stdout = {1, 0, 0};
|
||||
static FILE _stdin = {0, 0, 0};
|
||||
|
||||
FILE* stderr = &_stderr;
|
||||
FILE* stdout = &_stdout;
|
||||
FILE* stdin = &_stdin;
|
||||
|
||||
FILE *fopen(const char *path, const char *mode) {
|
||||
int fd = sys_open(path, mode);
|
||||
if (fd < 0) return NULL;
|
||||
FILE *f = malloc(sizeof(FILE));
|
||||
f->fd = fd;
|
||||
f->eof = 0;
|
||||
f->error = 0;
|
||||
return f;
|
||||
}
|
||||
|
||||
int fclose(FILE *stream) {
|
||||
if (!stream) return EOF;
|
||||
if (stream != stderr && stream != stdout && stream != stdin) {
|
||||
sys_close(stream->fd);
|
||||
free(stream);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) {
|
||||
if (!stream) return 0;
|
||||
int bytes = sys_read(stream->fd, ptr, size * nmemb);
|
||||
if (bytes < 0) {
|
||||
stream->error = 1;
|
||||
return 0;
|
||||
}
|
||||
if (bytes == 0) stream->eof = 1;
|
||||
return bytes / size;
|
||||
}
|
||||
|
||||
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) {
|
||||
if (!stream) return 0;
|
||||
if (stream == stdout || stream == stderr) {
|
||||
sys_write(stream->fd, ptr, size * nmemb);
|
||||
return nmemb;
|
||||
}
|
||||
int bytes = sys_write_fs(stream->fd, ptr, size * nmemb);
|
||||
if (bytes < 0) {
|
||||
stream->error = 1;
|
||||
return 0;
|
||||
}
|
||||
return bytes / size;
|
||||
}
|
||||
|
||||
int fseek(FILE *stream, long offset, int whence) {
|
||||
if (!stream) return -1;
|
||||
stream->eof = 0;
|
||||
return sys_seek(stream->fd, offset, whence);
|
||||
}
|
||||
|
||||
long ftell(FILE *stream) {
|
||||
if (!stream) return -1;
|
||||
return sys_tell(stream->fd);
|
||||
}
|
||||
|
||||
int remove(const char *pathname) {
|
||||
return sys_delete(pathname);
|
||||
}
|
||||
|
||||
int rename(const char *oldpath, const char *newpath) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int fputc(int c, FILE *stream) {
|
||||
unsigned char ch = c;
|
||||
if (fwrite(&ch, 1, 1, stream) != 1) return EOF;
|
||||
return ch;
|
||||
}
|
||||
|
||||
int fputs(const char *s, FILE *stream) {
|
||||
size_t len = strlen(s);
|
||||
if (fwrite(s, 1, len, stream) != len) return EOF;
|
||||
return 0;
|
||||
}
|
||||
|
||||
long filelength(FILE *f) {
|
||||
if (!f) return -1;
|
||||
return sys_size(f->fd);
|
||||
}
|
||||
|
||||
int mkdir(const char *pathname, int mode) {
|
||||
return sys_mkdir(pathname);
|
||||
}
|
||||
|
||||
int access(const char *pathname, int mode) {
|
||||
if (sys_exists(pathname)) return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int stat(const char *pathname, struct stat *statbuf) {
|
||||
if (sys_exists(pathname)) {
|
||||
if (statbuf) {
|
||||
statbuf->st_size = 0;
|
||||
statbuf->st_mode = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int strncasecmp(const char *s1, const char *s2, size_t n) {
|
||||
while (n--) {
|
||||
char c1 = tolower(*s1++);
|
||||
char c2 = tolower(*s2++);
|
||||
if (c1 != c2) return c1 - c2;
|
||||
if (!c1) break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int strcasecmp(const char *s1, const char *s2) {
|
||||
while (1) {
|
||||
char c1 = tolower(*s1++);
|
||||
char c2 = tolower(*s2++);
|
||||
if (c1 != c2) return c1 - c2;
|
||||
if (!c1) break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
char *strncpy(char *dest, const char *src, size_t n) {
|
||||
char *ret = dest;
|
||||
while (n && *src) { *dest++ = *src++; n--; }
|
||||
while (n) { *dest++ = 0; n--; }
|
||||
return ret;
|
||||
}
|
||||
int strncmp(const char *s1, const char *s2, size_t n) {
|
||||
while (n--) {
|
||||
if (*s1 != *s2) return *s1 - *s2;
|
||||
if (!*s1) break;
|
||||
s1++; s2++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
char *strrchr(const char *s, int c) {
|
||||
const char *last = NULL;
|
||||
while (*s) { if (*s == c) last = s; s++; }
|
||||
if (c == 0) last = s;
|
||||
return (char*)last;
|
||||
}
|
||||
char *strdup(const char *s) {
|
||||
size_t len = strlen(s) + 1;
|
||||
char *dup = malloc(len);
|
||||
if (dup) memcpy(dup, s, len);
|
||||
return dup;
|
||||
}
|
||||
|
||||
int toupper(int c) { return (c >= 'a' && c <= 'z') ? c - 32 : c; }
|
||||
int tolower(int c) { return (c >= 'A' && c <= 'Z') ? c + 32 : c; }
|
||||
int isspace(int c) { return c == ' ' || c == '\n' || c == '\t' || c == '\r' || c == '\v' || c == '\f'; }
|
||||
int isdigit(int c) { return c >= '0' && c <= '9'; }
|
||||
int isprint(int c) { return c >= 32 && c <= 126; }
|
||||
int isalpha(int c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
|
||||
int isalnum(int c) { return isalpha(c) || isdigit(c); }
|
||||
int isgraph(int c) { return c > 32 && c <= 126; }
|
||||
int ispunct(int c) { return isprint(c) && !isspace(c) && !isalnum(c); }
|
||||
int isupper(int c) { return c >= 'A' && c <= 'Z'; }
|
||||
|
||||
void _exit(int status) {
|
||||
exit(status);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int fflush(FILE *stream) { return 0; }
|
||||
int abs(int x) { return x < 0 ? -x : x; }
|
||||
int putchar(int c) { return fputc(c, stdout); }
|
||||
int system(const char *command) { return -1; }
|
||||
#define STB_SPRINTF_IMPLEMENTATION
|
||||
#define STB_SPRINTF_NOFLOAT
|
||||
#include "stb_sprintf.h"
|
||||
|
||||
int vfprintf(FILE *stream, const char *format, va_list ap) {
|
||||
char buf[1024];
|
||||
int len = stbsp_vsnprintf(buf, sizeof(buf), format, ap);
|
||||
if (len > 0) fwrite(buf, 1, len, stream);
|
||||
return len;
|
||||
}
|
||||
|
||||
int fprintf(FILE *stream, const char *format, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
int len = vfprintf(stream, format, ap);
|
||||
va_end(ap);
|
||||
return len;
|
||||
}
|
||||
|
||||
int sprintf(char *str, const char *format, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
int len = stbsp_vsprintf(str, format, ap);
|
||||
va_end(ap);
|
||||
return len;
|
||||
}
|
||||
|
||||
int snprintf(char *str, size_t size, const char *format, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
int len = stbsp_vsnprintf(str, size, format, ap);
|
||||
va_end(ap);
|
||||
return len;
|
||||
}
|
||||
|
||||
int vsnprintf(char *str, size_t size, const char *format, va_list ap) {
|
||||
return stbsp_vsnprintf(str, size, format, ap);
|
||||
}
|
||||
|
||||
int sscanf(const char *str, const char *format, ...) { return 0; }
|
||||
@@ -5,6 +5,9 @@
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#define SEEK_SET 0
|
||||
#define SEEK_CUR 1
|
||||
@@ -12,12 +15,6 @@
|
||||
|
||||
#define EOF (-1)
|
||||
|
||||
typedef struct {
|
||||
int fd;
|
||||
int eof;
|
||||
int error;
|
||||
} FILE;
|
||||
|
||||
extern FILE* stderr;
|
||||
extern FILE* stdout;
|
||||
extern FILE* stdin;
|
||||
@@ -34,6 +31,14 @@ extern FILE* stdin;
|
||||
#define W_OK 2
|
||||
#define X_OK 1
|
||||
|
||||
int open(const char *pathname, int flags, ...);
|
||||
int close(int fd);
|
||||
ssize_t read(int fd, void *buf, size_t count);
|
||||
ssize_t write(int fd, const void *buf, size_t count);
|
||||
off_t lseek(int fd, off_t offset, int whence);
|
||||
int unlink(const char *pathname);
|
||||
int isatty(int fd);
|
||||
|
||||
FILE *fopen(const char *path, const char *mode);
|
||||
int fclose(FILE *stream);
|
||||
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
|
||||
@@ -73,11 +78,6 @@ int isupper(int c);
|
||||
|
||||
int mkdir(const char *pathname, int mode);
|
||||
int access(const char *pathname, int mode);
|
||||
|
||||
struct stat {
|
||||
int st_size;
|
||||
int st_mode;
|
||||
};
|
||||
int stat(const char *pathname, struct stat *statbuf);
|
||||
|
||||
char *strstr(const char *haystack, const char *needle);
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "deh_main.h"
|
||||
#include "i_swap.h"
|
||||
#include "i_system.h"
|
||||
#include "i_video.h"
|
||||
|
||||
#include "hu_stuff.h"
|
||||
@@ -288,14 +289,47 @@ void HU_Init(void)
|
||||
|
||||
int i;
|
||||
int j;
|
||||
int fallback_lump = -1;
|
||||
char buffer[9];
|
||||
|
||||
// load the heads-up font
|
||||
j = HU_FONTSTART;
|
||||
for (i=0;i<HU_FONTSIZE;i++)
|
||||
{
|
||||
DEH_snprintf(buffer, 9, "STCFN%.3d", j++);
|
||||
hu_font[i] = (patch_t *) W_CacheLumpName(buffer, PU_STATIC);
|
||||
int lump;
|
||||
DEH_snprintf(buffer, 9, "STCFN%.3d", j++);
|
||||
lump = W_CheckNumForName(buffer);
|
||||
|
||||
if (lump < 0 && fallback_lump < 0)
|
||||
{
|
||||
int probe;
|
||||
for (probe = HU_FONTSTART; probe <= HU_FONTEND; ++probe)
|
||||
{
|
||||
DEH_snprintf(buffer, 9, "STCFN%.3d", probe);
|
||||
fallback_lump = W_CheckNumForName(buffer);
|
||||
if (fallback_lump >= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fallback_lump < 0)
|
||||
{
|
||||
fallback_lump = W_CheckNumForName("STTNUM0");
|
||||
}
|
||||
}
|
||||
|
||||
if (lump < 0)
|
||||
{
|
||||
lump = fallback_lump;
|
||||
}
|
||||
|
||||
if (lump < 0)
|
||||
{
|
||||
I_Error("HU_Init: no usable HUD font lumps (missing STCFNxxx/STTNUM0)");
|
||||
}
|
||||
|
||||
hu_font[i] = (patch_t *) W_CacheLumpNum(lump, PU_STATIC);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -264,7 +264,7 @@ void I_Quit (void)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined(_WIN32) && !defined(__MACOSX__) && !defined(__DJGPP__)
|
||||
#if !defined(_WIN32) && !defined(__MACOSX__) && !defined(__DJGPP__) && !defined(BOREDOS)
|
||||
#define ZENITY_BINARY "/usr/bin/zenity"
|
||||
|
||||
// returns non-zero if zenity is available
|
||||
@@ -347,7 +347,7 @@ static int ZenityErrorBox(char *message)
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* !defined(_WIN32) && !defined(__MACOSX__) && !defined(__DJGPP__) */
|
||||
#endif /* !defined(_WIN32) && !defined(__MACOSX__) && !defined(__DJGPP__) && !defined(BOREDOS) */
|
||||
|
||||
|
||||
//
|
||||
@@ -456,7 +456,9 @@ void I_Error (char *error, ...)
|
||||
|
||||
#else
|
||||
{
|
||||
#if !defined(BOREDOS)
|
||||
ZenityErrorBox(msgbuf);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1 +1,15 @@
|
||||
#include "../boredos_libc.h"
|
||||
#ifndef DOOM_COMPAT_SYS_STAT_H
|
||||
#define DOOM_COMPAT_SYS_STAT_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
struct stat {
|
||||
int st_size;
|
||||
int st_mode;
|
||||
};
|
||||
|
||||
int stat(const char *pathname, struct stat *statbuf);
|
||||
int fstat(int fd, struct stat *statbuf);
|
||||
int mkdir(const char *pathname, int mode);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1 +1,8 @@
|
||||
#include "../boredos_libc.h"
|
||||
#ifndef DOOM_COMPAT_SYS_TYPES_H
|
||||
#define DOOM_COMPAT_SYS_TYPES_H
|
||||
|
||||
typedef long ssize_t;
|
||||
typedef long off_t;
|
||||
typedef unsigned int mode_t;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -313,7 +313,7 @@ static int fetch_content(const char *url, char *dest_buf, int max_len, bool prog
|
||||
int total = 0;
|
||||
int last_render = 0;
|
||||
if (progressive) inc_parse_offset = 0;
|
||||
long long last_data_tick = sys_system(16, 0, 0, 0, 0);
|
||||
long long last_data_tick = sys_system(SYSTEM_CMD_GET_TICKS, 0, 0, 0, 0);
|
||||
|
||||
while (1) {
|
||||
int len = sys_tcp_recv_nb(dest_buf + total, max_len - 1 - total);
|
||||
@@ -321,7 +321,7 @@ static int fetch_content(const char *url, char *dest_buf, int max_len, bool prog
|
||||
if (len == -2) break;
|
||||
|
||||
if (len == 0) {
|
||||
long long now = sys_system(16, 0, 0, 0, 0);
|
||||
long long now = sys_system(SYSTEM_CMD_GET_TICKS, 0, 0, 0, 0);
|
||||
if (now > last_data_tick + 1800) break; // 30 sec timeout
|
||||
|
||||
gui_event_t ev;
|
||||
@@ -353,7 +353,7 @@ static int fetch_content(const char *url, char *dest_buf, int max_len, bool prog
|
||||
continue;
|
||||
}
|
||||
|
||||
last_data_tick = sys_system(16, 0, 0, 0, 0);
|
||||
last_data_tick = sys_system(SYSTEM_CMD_GET_TICKS, 0, 0, 0, 0);
|
||||
total += len;
|
||||
if (total >= max_len - 1) break;
|
||||
|
||||
@@ -461,7 +461,7 @@ static void decode_image(unsigned char *data, int len, RenderElement *el) {
|
||||
el->img_delays = malloc(frame_count * sizeof(int));
|
||||
el->img_frame_count = frame_count;
|
||||
el->img_current_frame = 0;
|
||||
el->next_frame_tick = sys_system(16, 0, 0, 0, 0) + (delays[0] * 60 / 1000);
|
||||
el->next_frame_tick = sys_system(SYSTEM_CMD_GET_TICKS, 0, 0, 0, 0) + (delays[0] * 60 / 1000);
|
||||
|
||||
uint32_t step_x = (img_w_orig << 16) / fit_w;
|
||||
uint32_t step_y = (img_h_orig << 16) / fit_h;
|
||||
@@ -2116,7 +2116,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
// Animated GIF progress
|
||||
bool gif_updated = false;
|
||||
long long now = sys_system(16, 0, 0, 0, 0);
|
||||
long long now = sys_system(SYSTEM_CMD_GET_TICKS, 0, 0, 0, 0);
|
||||
for (int i = 0; i < element_count; i++) {
|
||||
if (elements[i].tag == TAG_IMG && elements[i].img_frames && elements[i].img_frame_count > 1) {
|
||||
if (now >= elements[i].next_frame_tick) {
|
||||
|
||||
@@ -769,14 +769,14 @@ static void control_panel_paint(ui_window_t win) {
|
||||
}
|
||||
|
||||
static void save_desktop_config(void) {
|
||||
sys_system(4 /*SET_DESKTOP_PROP*/, 1, desktop_snap_to_grid, 0, 0);
|
||||
sys_system(4, 2, desktop_auto_align, 0, 0);
|
||||
sys_system(4, 3, desktop_max_rows_per_col, 0, 0);
|
||||
sys_system(4, 4, desktop_max_cols, 0, 0);
|
||||
sys_system(SYSTEM_CMD_SET_DESKTOP_PROP, 1, desktop_snap_to_grid, 0, 0);
|
||||
sys_system(SYSTEM_CMD_SET_DESKTOP_PROP, 2, desktop_auto_align, 0, 0);
|
||||
sys_system(SYSTEM_CMD_SET_DESKTOP_PROP, 3, desktop_max_rows_per_col, 0, 0);
|
||||
sys_system(SYSTEM_CMD_SET_DESKTOP_PROP, 4, desktop_max_cols, 0, 0);
|
||||
}
|
||||
|
||||
static void save_mouse_config(void) {
|
||||
sys_system(5 /*SET_MOUSE_SPEED*/, mouse_speed, 0, 0, 0);
|
||||
sys_system(SYSTEM_CMD_SET_MOUSE_SPEED, mouse_speed, 0, 0, 0);
|
||||
}
|
||||
|
||||
static int parse_ip(const char* str, net_ipv4_address_t* ip) {
|
||||
@@ -802,11 +802,11 @@ static int parse_ip(const char* str, net_ipv4_address_t* ip) {
|
||||
}
|
||||
|
||||
static void fetch_kernel_state(void) {
|
||||
desktop_snap_to_grid = sys_system(7 /*GET_DESKTOP_PROP*/, 1, 0, 0, 0);
|
||||
desktop_auto_align = sys_system(7, 2, 0, 0, 0);
|
||||
desktop_max_rows_per_col = sys_system(7, 3, 0, 0, 0);
|
||||
desktop_max_cols = sys_system(7, 4, 0, 0, 0);
|
||||
mouse_speed = sys_system(8 /*GET_MOUSE_SPEED*/, 0, 0, 0, 0);
|
||||
desktop_snap_to_grid = sys_system(SYSTEM_CMD_GET_DESKTOP_PROP, 1, 0, 0, 0);
|
||||
desktop_auto_align = sys_system(SYSTEM_CMD_GET_DESKTOP_PROP, 2, 0, 0, 0);
|
||||
desktop_max_rows_per_col = sys_system(SYSTEM_CMD_GET_DESKTOP_PROP, 3, 0, 0, 0);
|
||||
desktop_max_cols = sys_system(SYSTEM_CMD_GET_DESKTOP_PROP, 4, 0, 0, 0);
|
||||
mouse_speed = sys_system(SYSTEM_CMD_GET_MOUSE_SPEED, 0, 0, 0, 0);
|
||||
|
||||
net_ipv4_address_t kip;
|
||||
if (sys_network_get_ip(&kip) == 0) {
|
||||
@@ -889,7 +889,7 @@ static void control_panel_handle_mouse(int x, int y, bool is_down, bool is_click
|
||||
if (disp_sel_color == 3) { bpp = 8; mode = 1; }
|
||||
if (disp_sel_color == 4) { bpp = 8; mode = 2; }
|
||||
|
||||
sys_system(47 /*SET_RESOLUTION*/, w, h, bpp, mode);
|
||||
sys_system(SYSTEM_CMD_SET_RESOLUTION, w, h, bpp, mode);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -912,28 +912,28 @@ static void control_panel_handle_mouse(int x, int y, bool is_down, bool is_click
|
||||
uint32_t c = 0;
|
||||
if (i==0) c = COLOR_COFFEE; else if(i==1) c = COLOR_TEAL; else if(i==2) c = COLOR_GREEN;
|
||||
else if(i==3) c = COLOR_BLUE_BG; else if(i==4) c = COLOR_PURPLE; else if(i==5) c = COLOR_GREY;
|
||||
sys_system(1, c, 0, 0, 0); btn_wp_colors[i].pressed=false;
|
||||
sys_system(SYSTEM_CMD_SET_BG_COLOR, c, 0, 0, 0); btn_wp_colors[i].pressed=false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (widget_button_handle_mouse(&btn_wp_patterns[0], x, y, is_down, is_click, NULL)) {
|
||||
if (is_click) { sys_system(2, (uint64_t)pattern_lumberjack, 0, 0, 0); btn_wp_patterns[0].pressed=false;} return;
|
||||
if (is_click) { sys_system(SYSTEM_CMD_SET_BG_PATTERN, (uint64_t)pattern_lumberjack, 0, 0, 0); btn_wp_patterns[0].pressed=false;} return;
|
||||
}
|
||||
if (widget_button_handle_mouse(&btn_wp_patterns[1], x, y, is_down, is_click, NULL)) {
|
||||
if (is_click) { sys_system(2, (uint64_t)pattern_blue_diamond, 0, 0, 0); btn_wp_patterns[1].pressed=false;} return;
|
||||
if (is_click) { sys_system(SYSTEM_CMD_SET_BG_PATTERN, (uint64_t)pattern_blue_diamond, 0, 0, 0); btn_wp_patterns[1].pressed=false;} return;
|
||||
}
|
||||
if (widget_button_handle_mouse(&btn_wp_apply, x, y, is_down, is_click, NULL)) {
|
||||
if (is_click) {
|
||||
uint32_t cust = parse_rgb_separate(rgb_r, rgb_g, rgb_b);
|
||||
sys_system(1, cust, 0, 0, 0);
|
||||
sys_system(SYSTEM_CMD_SET_BG_COLOR, cust, 0, 0, 0);
|
||||
btn_wp_apply.pressed=false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (int i=0; i<wallpaper_count; i++) {
|
||||
if (wallpapers[i].valid && widget_button_handle_mouse(&btn_wp_thumbs[i], x, y, is_down, is_click, NULL)) {
|
||||
if (is_click) { sys_system(31, (uint64_t)wallpapers[i].path, 0, 0, 0); btn_wp_thumbs[i].pressed=false;} return;
|
||||
if (is_click) { sys_system(SYSTEM_CMD_SET_WALLPAPER_PATH, (uint64_t)wallpapers[i].path, 0, 0, 0); btn_wp_thumbs[i].pressed=false;} return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -948,7 +948,7 @@ static void control_panel_handle_mouse(int x, int y, bool is_down, bool is_click
|
||||
|
||||
if (widget_button_handle_mouse(&btn_net_init, x, y, is_down, is_click, NULL)) {
|
||||
if (is_click) {
|
||||
if (sys_system(6, 0, 0, 0, 0) == 0) {
|
||||
if (sys_system(SYSTEM_CMD_NETWORK_INIT, 0, 0, 0, 0) == 0) {
|
||||
net_status[0] = 'I'; net_status[1] = 'n'; net_status[2] = 'i';
|
||||
net_status[3] = 't'; net_status[4] = 'e'; net_status[5] = 'd'; net_status[6] = 0;
|
||||
} else {
|
||||
@@ -993,7 +993,7 @@ static void control_panel_handle_mouse(int x, int y, bool is_down, bool is_click
|
||||
if (current_view == VIEW_FONTS) {
|
||||
for (int i=0; i<font_count; i++) {
|
||||
if (widget_button_handle_mouse(&btn_fonts[i], x, y, is_down, is_click, NULL)) {
|
||||
if (is_click) { selected_font = i; sys_system(40 /*SET_FONT*/, (uint64_t)fonts[i].path, 0, 0, 0); btn_fonts[i].pressed=false;} return;
|
||||
if (is_click) { selected_font = i; sys_system(SYSTEM_CMD_SET_FONT, (uint64_t)fonts[i].path, 0, 0, 0); btn_fonts[i].pressed=false;} return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,7 +397,7 @@ int main(void) {
|
||||
ui_mark_dirty(win_taskman, 0, 0, 400, 480);
|
||||
|
||||
// Proper blocking sleep (200ms)
|
||||
sys_system(46, 200, 0, 0, 0); // SYSTEM_CMD_SLEEP
|
||||
sys_system(SYSTEM_CMD_SLEEP, 200, 0, 0, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -269,7 +269,7 @@ void viewer_open_file(const char *path) {
|
||||
viewer_img_h = fit_h;
|
||||
viewer_has_image = (viewer_frame_count > 0);
|
||||
if (viewer_has_image) {
|
||||
viewer_next_frame_tick = sys_system(16, 0, 0, 0, 0) + (viewer_delays[0] * 60 / 1000);
|
||||
viewer_next_frame_tick = sys_system(SYSTEM_CMD_GET_TICKS, 0, 0, 0, 0) + (viewer_delays[0] * 60 / 1000);
|
||||
}
|
||||
}
|
||||
free(delays);
|
||||
@@ -337,7 +337,7 @@ int main(int argc, char **argv) {
|
||||
win_w = ev.arg1;
|
||||
win_h = ev.arg2;
|
||||
resize_pending = true;
|
||||
last_resize_tick = sys_system(16, 0, 0, 0, 0);
|
||||
last_resize_tick = sys_system(SYSTEM_CMD_GET_TICKS, 0, 0, 0, 0);
|
||||
// Fast background clear during active resize
|
||||
ui_draw_rect(win, 0, 0, win_w, win_h, 0xFF000000);
|
||||
ui_mark_dirty(win, 0, 0, win_w, win_h - 20);
|
||||
@@ -348,7 +348,7 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
} else {
|
||||
if (resize_pending) {
|
||||
uint64_t now = sys_system(16, 0, 0, 0, 0);
|
||||
uint64_t now = sys_system(SYSTEM_CMD_GET_TICKS, 0, 0, 0, 0);
|
||||
if (now > last_resize_tick + 10) {
|
||||
viewer_paint(win);
|
||||
ui_mark_dirty(win, 0, 0, win_w, win_h - 20);
|
||||
@@ -357,7 +357,7 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
|
||||
if (viewer_has_image && viewer_frame_count > 1) {
|
||||
uint64_t now = sys_system(16, 0, 0, 0, 0);
|
||||
uint64_t now = sys_system(SYSTEM_CMD_GET_TICKS, 0, 0, 0, 0);
|
||||
if (now >= viewer_next_frame_tick) {
|
||||
viewer_current_frame = (viewer_current_frame + 1) % viewer_frame_count;
|
||||
viewer_next_frame_tick = now + (viewer_delays[viewer_current_frame] * 60 / 1000);
|
||||
|
||||
21
src/userland/libc/ctype.c
Normal file
21
src/userland/libc/ctype.c
Normal file
@@ -0,0 +1,21 @@
|
||||
#include "ctype.h"
|
||||
|
||||
__attribute__((weak)) int isdigit(int c) { return (c >= '0' && c <= '9'); }
|
||||
__attribute__((weak)) int isalpha(int c) { return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')); }
|
||||
__attribute__((weak)) int isalnum(int c) { return isalpha(c) || isdigit(c); }
|
||||
__attribute__((weak)) int isspace(int c) {
|
||||
return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v';
|
||||
}
|
||||
__attribute__((weak)) int isupper(int c) { return (c >= 'A' && c <= 'Z'); }
|
||||
__attribute__((weak)) int islower(int c) { return (c >= 'a' && c <= 'z'); }
|
||||
__attribute__((weak)) int isxdigit(int c) {
|
||||
return isdigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
|
||||
}
|
||||
__attribute__((weak)) int iscntrl(int c) { return ((c >= 0 && c < 32) || c == 127); }
|
||||
__attribute__((weak)) int isprint(int c) { return (c >= 32 && c < 127); }
|
||||
__attribute__((weak)) int isgraph(int c) { return (c > 32 && c < 127); }
|
||||
__attribute__((weak)) int ispunct(int c) {
|
||||
return isprint(c) && !isalnum(c) && !isspace(c);
|
||||
}
|
||||
__attribute__((weak)) int tolower(int c) { return isupper(c) ? (c - 'A' + 'a') : c; }
|
||||
__attribute__((weak)) int toupper(int c) { return islower(c) ? (c - 'a' + 'A') : c; }
|
||||
18
src/userland/libc/ctype.h
Normal file
18
src/userland/libc/ctype.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef BOREDOS_LIBC_CTYPE_H
|
||||
#define BOREDOS_LIBC_CTYPE_H
|
||||
|
||||
int isdigit(int c);
|
||||
int isalpha(int c);
|
||||
int isalnum(int c);
|
||||
int isspace(int c);
|
||||
int isupper(int c);
|
||||
int islower(int c);
|
||||
int isxdigit(int c);
|
||||
int iscntrl(int c);
|
||||
int ispunct(int c);
|
||||
int isprint(int c);
|
||||
int isgraph(int c);
|
||||
int tolower(int c);
|
||||
int toupper(int c);
|
||||
|
||||
#endif
|
||||
3
src/userland/libc/errno.c
Normal file
3
src/userland/libc/errno.c
Normal file
@@ -0,0 +1,3 @@
|
||||
#include "errno.h"
|
||||
|
||||
__attribute__((weak)) int errno = 0;
|
||||
27
src/userland/libc/errno.h
Normal file
27
src/userland/libc/errno.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef BOREDOS_LIBC_ERRNO_H
|
||||
#define BOREDOS_LIBC_ERRNO_H
|
||||
|
||||
extern int errno;
|
||||
|
||||
#define EDOM 33
|
||||
#define E2BIG 7
|
||||
#define ERANGE 34
|
||||
#define EINVAL 22
|
||||
#define EISDIR 21
|
||||
#define ENOENT 2
|
||||
#define ENOMEM 12
|
||||
#define EACCES 13
|
||||
#define EBADF 9
|
||||
#define EIO 5
|
||||
#define EEXIST 17
|
||||
#define EAGAIN 11
|
||||
#define EINTR 4
|
||||
#define ECHILD 10
|
||||
#define ENOTSUP 95
|
||||
#define EPIPE 32
|
||||
#define ENOTDIR 20
|
||||
#define EBUSY 16
|
||||
#define ESPIPE 29
|
||||
#define ENOSYS 38
|
||||
|
||||
#endif
|
||||
27
src/userland/libc/fcntl.h
Normal file
27
src/userland/libc/fcntl.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef BOREDOS_LIBC_FCNTL_H
|
||||
#define BOREDOS_LIBC_FCNTL_H
|
||||
|
||||
#include "sys/types.h"
|
||||
|
||||
#define O_RDONLY 0x0000
|
||||
#define O_WRONLY 0x0001
|
||||
#define O_RDWR 0x0002
|
||||
#define O_ACCMODE 0x0003
|
||||
#define O_CREAT 0x0040
|
||||
#define O_EXCL 0x0080
|
||||
#define O_TRUNC 0x0200
|
||||
#define O_APPEND 0x0400
|
||||
#define O_NONBLOCK 0x0800
|
||||
|
||||
#define F_GETFL 3
|
||||
#define F_SETFL 4
|
||||
|
||||
#define FD_CLOEXEC 1
|
||||
|
||||
int open(const char *pathname, int flags, ...);
|
||||
int fcntl(int fd, int cmd, ...);
|
||||
int dup(int oldfd);
|
||||
int dup2(int oldfd, int newfd);
|
||||
int pipe(int pipefd[2]);
|
||||
|
||||
#endif
|
||||
@@ -10,7 +10,6 @@ extern uint64_t syscall6(uint64_t sys_num, uint64_t arg1, uint64_t arg2, uint64_
|
||||
|
||||
// sys_gui uses syscall #3
|
||||
#define SYS_GUI 3
|
||||
#define GUI_CMD_GET_SCREEN_SIZE 17
|
||||
|
||||
ui_window_t ui_window_create(const char *title, int x, int y, int w, int h) {
|
||||
uint64_t params[4] = { (uint64_t)x, (uint64_t)y, (uint64_t)w, (uint64_t)h };
|
||||
|
||||
@@ -22,6 +22,10 @@
|
||||
#define GUI_CMD_WINDOW_SET_TITLE 15
|
||||
#define GUI_CMD_SET_FONT 16
|
||||
#define GUI_CMD_DRAW_STRING_SCALED_SLOPED 18
|
||||
#define GUI_CMD_GET_SCREEN_SIZE 50
|
||||
#define GUI_CMD_GET_SCREENBUFFER 51
|
||||
#define GUI_CMD_SHOW_NOTIFICATION 52
|
||||
#define GUI_CMD_GET_DATETIME 53
|
||||
|
||||
// Event Types
|
||||
#define GUI_EVENT_NONE 0
|
||||
|
||||
22
src/userland/libc/limits.h
Normal file
22
src/userland/libc/limits.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef BOREDOS_LIBC_LIMITS_H
|
||||
#define BOREDOS_LIBC_LIMITS_H
|
||||
|
||||
#define CHAR_BIT 8
|
||||
#define SCHAR_MIN (-128)
|
||||
#define SCHAR_MAX 127
|
||||
#define UCHAR_MAX 255
|
||||
#define SHRT_MIN (-32768)
|
||||
#define SHRT_MAX 32767
|
||||
#define USHRT_MAX 65535
|
||||
#define INT_MIN (-2147483647 - 1)
|
||||
#define INT_MAX 2147483647
|
||||
#define UINT_MAX 4294967295U
|
||||
#define LONG_MIN (-9223372036854775807L - 1)
|
||||
#define LONG_MAX 9223372036854775807L
|
||||
#define ULONG_MAX 18446744073709551615UL
|
||||
#define LLONG_MIN (-9223372036854775807LL - 1)
|
||||
#define LLONG_MAX 9223372036854775807LL
|
||||
#define ULLONG_MAX 18446744073709551615ULL
|
||||
#define DBL_MAX 1.7976931348623157e+308
|
||||
|
||||
#endif
|
||||
19
src/userland/libc/locale.c
Normal file
19
src/userland/libc/locale.c
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "locale.h"
|
||||
#include "string.h"
|
||||
|
||||
static struct lconv _b_lconv = {
|
||||
".", "", "", "", "", ".", "", "", "", "",
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
__attribute__((weak)) char *setlocale(int category, const char *locale) {
|
||||
(void)category;
|
||||
if (locale == NULL || strcmp(locale, "C") == 0 || strcmp(locale, "") == 0) {
|
||||
return "C";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
__attribute__((weak)) struct lconv *localeconv(void) {
|
||||
return &_b_lconv;
|
||||
}
|
||||
30
src/userland/libc/locale.h
Normal file
30
src/userland/libc/locale.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef BOREDOS_LIBC_LOCALE_H
|
||||
#define BOREDOS_LIBC_LOCALE_H
|
||||
|
||||
struct lconv {
|
||||
char *decimal_point;
|
||||
char *thousands_sep;
|
||||
char *grouping;
|
||||
char *int_curr_symbol;
|
||||
char *currency_symbol;
|
||||
char *mon_decimal_point;
|
||||
char *mon_thousands_sep;
|
||||
char *mon_grouping;
|
||||
char *positive_sign;
|
||||
char *negative_sign;
|
||||
char int_frac_digits;
|
||||
char frac_digits;
|
||||
char p_cs_precedes;
|
||||
char p_sep_by_space;
|
||||
char n_cs_precedes;
|
||||
char n_sep_by_space;
|
||||
char p_sign_posn;
|
||||
char n_sign_posn;
|
||||
};
|
||||
|
||||
#define LC_ALL 0
|
||||
|
||||
char *setlocale(int category, const char *locale);
|
||||
struct lconv *localeconv(void);
|
||||
|
||||
#endif
|
||||
@@ -28,7 +28,12 @@ double log(double x);
|
||||
double log2(double x);
|
||||
double log10(double x);
|
||||
double exp(double x);
|
||||
double ldexp(double x, int expn);
|
||||
double frexp(double x, int *expn);
|
||||
double pow(double base, double exponent);
|
||||
double atan2(double y, double x);
|
||||
double asin(double x);
|
||||
double acos(double x);
|
||||
double sinh(double x);
|
||||
double cosh(double x);
|
||||
double tanh(double x);
|
||||
|
||||
91
src/userland/libc/math_ext.c
Normal file
91
src/userland/libc/math_ext.c
Normal file
@@ -0,0 +1,91 @@
|
||||
#include "math.h"
|
||||
#include "errno.h"
|
||||
|
||||
__attribute__((weak)) double ldexp(double x, int expn) {
|
||||
double v = x;
|
||||
int i;
|
||||
if (expn >= 0) {
|
||||
for (i = 0; i < expn; i++) {
|
||||
v *= 2.0;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < -expn; i++) {
|
||||
v *= 0.5;
|
||||
}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
__attribute__((weak)) double frexp(double x, int *expn) {
|
||||
int e = 0;
|
||||
double v = x;
|
||||
if (x == 0.0) {
|
||||
*expn = 0;
|
||||
return 0.0;
|
||||
}
|
||||
while (fabs(v) >= 1.0) {
|
||||
v *= 0.5;
|
||||
e++;
|
||||
}
|
||||
while (fabs(v) > 0.0 && fabs(v) < 0.5) {
|
||||
v *= 2.0;
|
||||
e--;
|
||||
}
|
||||
*expn = e;
|
||||
return v;
|
||||
}
|
||||
|
||||
static double _b_atan_series(double x) {
|
||||
double x2 = x * x;
|
||||
double term = x;
|
||||
double sum = x;
|
||||
int n;
|
||||
for (n = 3; n <= 23; n += 2) {
|
||||
term *= -x2;
|
||||
sum += term / (double)n;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
static double _b_atan_precise(double x) {
|
||||
if (x < 0.0) {
|
||||
return -_b_atan_precise(-x);
|
||||
}
|
||||
if (x > 1.0) {
|
||||
return (M_PI / 2.0) - _b_atan_precise(1.0 / x);
|
||||
}
|
||||
if (x > 0.5) {
|
||||
double y = (x - 1.0) / (x + 1.0);
|
||||
return (M_PI / 4.0) + _b_atan_series(y);
|
||||
}
|
||||
return _b_atan_series(x);
|
||||
}
|
||||
|
||||
__attribute__((weak)) double atan2(double y, double x) {
|
||||
if (x > 0.0) {
|
||||
return _b_atan_precise(y / x);
|
||||
}
|
||||
if (x < 0.0) {
|
||||
if (y >= 0.0) return _b_atan_precise(y / x) + M_PI;
|
||||
return _b_atan_precise(y / x) - M_PI;
|
||||
}
|
||||
if (y > 0.0) return M_PI / 2.0;
|
||||
if (y < 0.0) return -M_PI / 2.0;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
__attribute__((weak)) double asin(double x) {
|
||||
if (x > 1.0 || x < -1.0) {
|
||||
errno = EDOM;
|
||||
return 0.0;
|
||||
}
|
||||
return atan2(x, sqrt(1.0 - x * x));
|
||||
}
|
||||
|
||||
__attribute__((weak)) double acos(double x) {
|
||||
if (x > 1.0 || x < -1.0) {
|
||||
errno = EDOM;
|
||||
return 0.0;
|
||||
}
|
||||
return M_PI / 2.0 - asin(x);
|
||||
}
|
||||
87
src/userland/libc/posix_fs.c
Normal file
87
src/userland/libc/posix_fs.c
Normal file
@@ -0,0 +1,87 @@
|
||||
#include "errno.h"
|
||||
#include "syscall.h"
|
||||
#include "sys/stat.h"
|
||||
|
||||
static void _b_stat_init(struct stat *st) {
|
||||
st->st_dev = 0;
|
||||
st->st_ino = 0;
|
||||
st->st_mode = 0;
|
||||
st->st_nlink = 1;
|
||||
st->st_uid = 0;
|
||||
st->st_gid = 0;
|
||||
st->st_rdev = 0;
|
||||
st->st_size = 0;
|
||||
st->st_blksize = 512;
|
||||
st->st_blocks = 0;
|
||||
st->st_atime = 0;
|
||||
st->st_mtime = 0;
|
||||
st->st_ctime = 0;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int mkdir(const char *pathname, int mode) {
|
||||
(void)mode;
|
||||
if (!pathname || pathname[0] == '\0') {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (sys_exists(pathname)) {
|
||||
errno = EEXIST;
|
||||
return -1;
|
||||
}
|
||||
if (sys_mkdir(pathname) == 0) {
|
||||
return 0;
|
||||
}
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int access(const char *pathname, int mode) {
|
||||
(void)mode;
|
||||
if (!pathname || pathname[0] == '\0') {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (sys_exists(pathname)) {
|
||||
return 0;
|
||||
}
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int stat(const char *pathname, struct stat *statbuf) {
|
||||
FAT32_FileInfo info;
|
||||
if (!pathname || pathname[0] == '\0') {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (!sys_exists(pathname)) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (statbuf) {
|
||||
_b_stat_init(statbuf);
|
||||
if (sys_get_file_info(pathname, &info) == 0) {
|
||||
statbuf->st_size = (int)info.size;
|
||||
if (info.is_directory) {
|
||||
statbuf->st_mode = S_IFDIR | 0755;
|
||||
} else {
|
||||
statbuf->st_mode = S_IFREG | 0644;
|
||||
}
|
||||
statbuf->st_blocks = (statbuf->st_size + 511) / 512;
|
||||
} else {
|
||||
int fd = sys_open(pathname, "rb");
|
||||
if (fd >= 0) {
|
||||
statbuf->st_size = (int)sys_size(fd);
|
||||
statbuf->st_mode = S_IFREG | 0644;
|
||||
statbuf->st_blocks = (statbuf->st_size + 511) / 512;
|
||||
sys_close(fd);
|
||||
} else {
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
650
src/userland/libc/posix_io.c
Normal file
650
src/userland/libc/posix_io.c
Normal file
@@ -0,0 +1,650 @@
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "errno.h"
|
||||
#include "fcntl.h"
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#include "sys/stat.h"
|
||||
#include "syscall.h"
|
||||
#include "unistd.h"
|
||||
|
||||
#define POSIX_MAX_FDS 256
|
||||
#define PIPE_BUF_SIZE 4096
|
||||
|
||||
typedef enum {
|
||||
HANDLE_UNUSED = 0,
|
||||
HANDLE_KERNEL_FD,
|
||||
HANDLE_PIPE_READ,
|
||||
HANDLE_PIPE_WRITE
|
||||
} handle_type_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned char data[PIPE_BUF_SIZE];
|
||||
size_t read_pos;
|
||||
size_t write_pos;
|
||||
size_t count;
|
||||
int readers;
|
||||
int writers;
|
||||
} pipe_state_t;
|
||||
|
||||
typedef struct {
|
||||
handle_type_t type;
|
||||
int refcount;
|
||||
int flags;
|
||||
int kernel_fd;
|
||||
pipe_state_t *pipe;
|
||||
} fd_handle_t;
|
||||
|
||||
static fd_handle_t *g_fd_table[POSIX_MAX_FDS];
|
||||
static fd_handle_t g_stdio_handles[3];
|
||||
static int g_fd_initialized = 0;
|
||||
|
||||
static void _b_fd_init(void) {
|
||||
int i;
|
||||
if (g_fd_initialized) {
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < POSIX_MAX_FDS; i++) {
|
||||
g_fd_table[i] = NULL;
|
||||
}
|
||||
for (i = 0; i < 3; i++) {
|
||||
g_stdio_handles[i].type = HANDLE_KERNEL_FD;
|
||||
g_stdio_handles[i].refcount = 1;
|
||||
g_stdio_handles[i].flags = O_RDWR;
|
||||
g_stdio_handles[i].kernel_fd = i;
|
||||
g_stdio_handles[i].pipe = NULL;
|
||||
g_fd_table[i] = &g_stdio_handles[i];
|
||||
}
|
||||
g_fd_initialized = 1;
|
||||
}
|
||||
|
||||
static int _b_alloc_fd_from(int start) {
|
||||
int fd;
|
||||
for (fd = start; fd < POSIX_MAX_FDS; fd++) {
|
||||
if (g_fd_table[fd] == NULL) {
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static fd_handle_t *_b_get_handle(int fd) {
|
||||
if (fd < 0 || fd >= POSIX_MAX_FDS) {
|
||||
return NULL;
|
||||
}
|
||||
return g_fd_table[fd];
|
||||
}
|
||||
|
||||
static void _b_reset_stat_common(struct stat *st) {
|
||||
memset(st, 0, sizeof(*st));
|
||||
st->st_blksize = 512;
|
||||
}
|
||||
|
||||
static int _b_fill_kernel_fstat(int kfd, struct stat *statbuf) {
|
||||
_b_reset_stat_common(statbuf);
|
||||
statbuf->st_mode = (kfd <= 2) ? (S_IFCHR | 0666) : (S_IFREG | 0644);
|
||||
statbuf->st_size = (kfd <= 2) ? 0 : (int)sys_size(kfd);
|
||||
statbuf->st_blocks = (statbuf->st_size + 511) / 512;
|
||||
statbuf->st_nlink = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *_b_mode_from_flags(int flags) {
|
||||
int accmode = flags & O_ACCMODE;
|
||||
|
||||
if (accmode == O_RDONLY) {
|
||||
return "rb";
|
||||
}
|
||||
|
||||
if (accmode == O_RDWR) {
|
||||
if (flags & O_TRUNC) {
|
||||
return "w+";
|
||||
}
|
||||
if (flags & O_APPEND) {
|
||||
return "a+";
|
||||
}
|
||||
return "r+";
|
||||
}
|
||||
|
||||
if (flags & O_APPEND) {
|
||||
return "ab";
|
||||
}
|
||||
if (flags & O_TRUNC) {
|
||||
return "wb";
|
||||
}
|
||||
return "wb";
|
||||
}
|
||||
|
||||
static int _b_pipe_read(fd_handle_t *h, void *buf, size_t count) {
|
||||
size_t n = 0;
|
||||
pipe_state_t *p = h->pipe;
|
||||
unsigned char *out = (unsigned char *)buf;
|
||||
|
||||
if (!p || !buf) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (n < count) {
|
||||
if (p->count == 0) {
|
||||
if (p->writers == 0) {
|
||||
break;
|
||||
}
|
||||
if (h->flags & O_NONBLOCK) {
|
||||
if (n == 0) {
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
sys_yield();
|
||||
continue;
|
||||
}
|
||||
|
||||
out[n++] = p->data[p->read_pos];
|
||||
p->read_pos = (p->read_pos + 1) % PIPE_BUF_SIZE;
|
||||
p->count--;
|
||||
}
|
||||
|
||||
return (int)n;
|
||||
}
|
||||
|
||||
static int _b_pipe_write(fd_handle_t *h, const void *buf, size_t count) {
|
||||
size_t n = 0;
|
||||
pipe_state_t *p = h->pipe;
|
||||
const unsigned char *in = (const unsigned char *)buf;
|
||||
|
||||
if (!p || !buf) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (p->readers == 0) {
|
||||
errno = EPIPE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (n < count) {
|
||||
if (p->count == PIPE_BUF_SIZE) {
|
||||
if (h->flags & O_NONBLOCK) {
|
||||
if (n == 0) {
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
sys_yield();
|
||||
continue;
|
||||
}
|
||||
|
||||
p->data[p->write_pos] = in[n++];
|
||||
p->write_pos = (p->write_pos + 1) % PIPE_BUF_SIZE;
|
||||
p->count++;
|
||||
}
|
||||
|
||||
return (int)n;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int open(const char *pathname, int flags, ...) {
|
||||
int fd;
|
||||
int kfd;
|
||||
int exists;
|
||||
mode_t mode = 0;
|
||||
fd_handle_t *h;
|
||||
|
||||
_b_fd_init();
|
||||
|
||||
if (!pathname || pathname[0] == '\0') {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((flags & O_ACCMODE) > O_RDWR) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((flags & O_TRUNC) && ((flags & O_ACCMODE) == O_RDONLY)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
exists = sys_exists(pathname);
|
||||
|
||||
if ((flags & O_CREAT) && (flags & O_EXCL) && exists) {
|
||||
errno = EEXIST;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(flags & O_CREAT) && !exists) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flags & O_CREAT) {
|
||||
va_list ap;
|
||||
va_start(ap, flags);
|
||||
mode = (mode_t)va_arg(ap, int);
|
||||
va_end(ap);
|
||||
(void)mode;
|
||||
}
|
||||
|
||||
kfd = sys_open(pathname, _b_mode_from_flags(flags));
|
||||
if (kfd < 0) {
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
h = (fd_handle_t *)malloc(sizeof(fd_handle_t));
|
||||
if (!h) {
|
||||
sys_close(kfd);
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd = _b_alloc_fd_from(3);
|
||||
if (fd < 0) {
|
||||
free(h);
|
||||
sys_close(kfd);
|
||||
errno = EBUSY;
|
||||
return -1;
|
||||
}
|
||||
|
||||
h->type = HANDLE_KERNEL_FD;
|
||||
h->refcount = 1;
|
||||
h->flags = flags;
|
||||
h->kernel_fd = kfd;
|
||||
h->pipe = NULL;
|
||||
g_fd_table[fd] = h;
|
||||
|
||||
if (flags & O_APPEND) {
|
||||
(void)sys_seek(kfd, 0, SEEK_END);
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int close(int fd) {
|
||||
fd_handle_t *h;
|
||||
|
||||
_b_fd_init();
|
||||
h = _b_get_handle(fd);
|
||||
if (!h) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
g_fd_table[fd] = NULL;
|
||||
if (--h->refcount > 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (h->type == HANDLE_KERNEL_FD) {
|
||||
if (h->kernel_fd >= 3) {
|
||||
sys_close(h->kernel_fd);
|
||||
}
|
||||
} else if (h->type == HANDLE_PIPE_READ || h->type == HANDLE_PIPE_WRITE) {
|
||||
pipe_state_t *p = h->pipe;
|
||||
if (p) {
|
||||
if (h->type == HANDLE_PIPE_READ) {
|
||||
p->readers--;
|
||||
} else {
|
||||
p->writers--;
|
||||
}
|
||||
if (p->readers <= 0 && p->writers <= 0) {
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (h < &g_stdio_handles[0] || h > &g_stdio_handles[2]) {
|
||||
free(h);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((weak)) ssize_t read(int fd, void *buf, size_t count) {
|
||||
fd_handle_t *h;
|
||||
int n;
|
||||
|
||||
_b_fd_init();
|
||||
|
||||
if (!buf && count != 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
h = _b_get_handle(fd);
|
||||
if (!h) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (h->type == HANDLE_PIPE_WRITE) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (h->type == HANDLE_PIPE_READ) {
|
||||
n = _b_pipe_read(h, buf, count);
|
||||
return (ssize_t)n;
|
||||
}
|
||||
|
||||
n = sys_read(h->kernel_fd, buf, (uint32_t)count);
|
||||
if (n < 0) {
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
return (ssize_t)n;
|
||||
}
|
||||
|
||||
__attribute__((weak)) ssize_t write(int fd, const void *buf, size_t count) {
|
||||
fd_handle_t *h;
|
||||
int n;
|
||||
|
||||
_b_fd_init();
|
||||
if (!buf && count != 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
h = _b_get_handle(fd);
|
||||
if (!h) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (h->type == HANDLE_PIPE_READ) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (h->type == HANDLE_PIPE_WRITE) {
|
||||
n = _b_pipe_write(h, buf, count);
|
||||
return (ssize_t)n;
|
||||
}
|
||||
|
||||
if (h->kernel_fd <= 2) {
|
||||
n = sys_write(h->kernel_fd, (const char *)buf, (int)count);
|
||||
} else {
|
||||
n = sys_write_fs(h->kernel_fd, buf, (uint32_t)count);
|
||||
}
|
||||
|
||||
if (n < 0) {
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
return (ssize_t)n;
|
||||
}
|
||||
|
||||
__attribute__((weak)) off_t lseek(int fd, off_t offset, int whence) {
|
||||
fd_handle_t *h;
|
||||
|
||||
_b_fd_init();
|
||||
h = _b_get_handle(fd);
|
||||
if (!h) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
if (h->type != HANDLE_KERNEL_FD) {
|
||||
errno = ESPIPE;
|
||||
return -1;
|
||||
}
|
||||
if (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sys_seek(h->kernel_fd, (int)offset, whence) < 0) {
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
return (off_t)sys_tell(h->kernel_fd);
|
||||
}
|
||||
|
||||
__attribute__((weak)) int unlink(const char *pathname) {
|
||||
if (!pathname || pathname[0] == '\0') {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (sys_delete(pathname) != 0) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int isatty(int fd) {
|
||||
fd_handle_t *h;
|
||||
_b_fd_init();
|
||||
h = _b_get_handle(fd);
|
||||
if (!h) {
|
||||
errno = EBADF;
|
||||
return 0;
|
||||
}
|
||||
return (h->type == HANDLE_KERNEL_FD && h->kernel_fd <= 2) ? 1 : 0;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int fstat(int fd, struct stat *statbuf) {
|
||||
fd_handle_t *h;
|
||||
_b_fd_init();
|
||||
if (!statbuf) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
h = _b_get_handle(fd);
|
||||
if (!h) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (h->type == HANDLE_PIPE_READ || h->type == HANDLE_PIPE_WRITE) {
|
||||
_b_reset_stat_common(statbuf);
|
||||
statbuf->st_mode = S_IFIFO | 0666;
|
||||
statbuf->st_size = (int)(h->pipe ? h->pipe->count : 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _b_fill_kernel_fstat(h->kernel_fd, statbuf);
|
||||
}
|
||||
|
||||
__attribute__((weak)) int dup(int oldfd) {
|
||||
fd_handle_t *h;
|
||||
int newfd;
|
||||
int newkfd;
|
||||
_b_fd_init();
|
||||
|
||||
h = _b_get_handle(oldfd);
|
||||
if (!h) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (h->type != HANDLE_KERNEL_FD) {
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
newkfd = sys_dup(h->kernel_fd);
|
||||
if (newkfd < 0) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
newfd = _b_alloc_fd_from(0);
|
||||
if (newfd < 0) {
|
||||
sys_close(newkfd);
|
||||
errno = EBUSY;
|
||||
return -1;
|
||||
}
|
||||
|
||||
h = (fd_handle_t *)malloc(sizeof(fd_handle_t));
|
||||
if (!h) {
|
||||
sys_close(newkfd);
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
h->type = HANDLE_KERNEL_FD;
|
||||
h->refcount = 1;
|
||||
h->flags = O_RDWR;
|
||||
h->kernel_fd = newkfd;
|
||||
h->pipe = NULL;
|
||||
g_fd_table[newfd] = h;
|
||||
return newfd;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int dup2(int oldfd, int newfd) {
|
||||
fd_handle_t *h;
|
||||
fd_handle_t *nh;
|
||||
int newkfd;
|
||||
_b_fd_init();
|
||||
|
||||
h = _b_get_handle(oldfd);
|
||||
if (!h || newfd < 0 || newfd >= POSIX_MAX_FDS) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (oldfd == newfd) {
|
||||
return newfd;
|
||||
}
|
||||
|
||||
if (h->type != HANDLE_KERNEL_FD) {
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (g_fd_table[newfd]) {
|
||||
if (close(newfd) != 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
newkfd = sys_dup(h->kernel_fd);
|
||||
if (newkfd < 0) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
nh = (fd_handle_t *)malloc(sizeof(fd_handle_t));
|
||||
if (!nh) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
nh->type = HANDLE_KERNEL_FD;
|
||||
nh->refcount = 1;
|
||||
nh->flags = h->flags;
|
||||
nh->kernel_fd = newkfd;
|
||||
nh->pipe = NULL;
|
||||
|
||||
g_fd_table[newfd] = nh;
|
||||
return newfd;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int pipe(int pipefd[2]) {
|
||||
fd_handle_t *rh;
|
||||
fd_handle_t *wh;
|
||||
int rfd;
|
||||
int wfd;
|
||||
int kpipe[2];
|
||||
|
||||
_b_fd_init();
|
||||
if (!pipefd) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sys_pipe(kpipe) < 0) {
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
rfd = _b_alloc_fd_from(3);
|
||||
if (rfd < 0) {
|
||||
sys_close(kpipe[0]);
|
||||
sys_close(kpipe[1]);
|
||||
errno = EBUSY;
|
||||
return -1;
|
||||
}
|
||||
wfd = _b_alloc_fd_from(rfd + 1);
|
||||
if (wfd < 0) {
|
||||
sys_close(kpipe[0]);
|
||||
sys_close(kpipe[1]);
|
||||
errno = EBUSY;
|
||||
return -1;
|
||||
}
|
||||
|
||||
rh = (fd_handle_t *)malloc(sizeof(fd_handle_t));
|
||||
wh = (fd_handle_t *)malloc(sizeof(fd_handle_t));
|
||||
if (!rh || !wh) {
|
||||
free(rh);
|
||||
free(wh);
|
||||
sys_close(kpipe[0]);
|
||||
sys_close(kpipe[1]);
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
rh->type = HANDLE_KERNEL_FD;
|
||||
rh->refcount = 1;
|
||||
rh->flags = O_RDONLY;
|
||||
rh->kernel_fd = kpipe[0];
|
||||
rh->pipe = NULL;
|
||||
|
||||
wh->type = HANDLE_KERNEL_FD;
|
||||
wh->refcount = 1;
|
||||
wh->flags = O_WRONLY;
|
||||
wh->kernel_fd = kpipe[1];
|
||||
wh->pipe = NULL;
|
||||
|
||||
g_fd_table[rfd] = rh;
|
||||
g_fd_table[wfd] = wh;
|
||||
pipefd[0] = rfd;
|
||||
pipefd[1] = wfd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int fcntl(int fd, int cmd, ...) {
|
||||
fd_handle_t *h;
|
||||
va_list ap;
|
||||
int val;
|
||||
|
||||
_b_fd_init();
|
||||
h = _b_get_handle(fd);
|
||||
if (!h) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case F_GETFL:
|
||||
if (h->type == HANDLE_KERNEL_FD) {
|
||||
int k = sys_fcntl(h->kernel_fd, cmd, 0);
|
||||
if (k < 0) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
h->flags = k;
|
||||
}
|
||||
return h->flags;
|
||||
case F_SETFL:
|
||||
va_start(ap, cmd);
|
||||
val = va_arg(ap, int);
|
||||
va_end(ap);
|
||||
if (h->type == HANDLE_KERNEL_FD) {
|
||||
if (sys_fcntl(h->kernel_fd, cmd, val) < 0) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
h->flags = (h->flags & ~(O_APPEND | O_NONBLOCK)) | (val & (O_APPEND | O_NONBLOCK));
|
||||
return 0;
|
||||
default:
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
224
src/userland/libc/posix_process.c
Normal file
224
src/userland/libc/posix_process.c
Normal file
@@ -0,0 +1,224 @@
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "errno.h"
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
#include "sys/types.h"
|
||||
#include "sys/wait.h"
|
||||
#include "syscall.h"
|
||||
#include "unistd.h"
|
||||
|
||||
static int _b_is_space(char c) {
|
||||
return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v';
|
||||
}
|
||||
|
||||
static int _b_path_exists(const char *path) {
|
||||
return path && path[0] && sys_exists(path);
|
||||
}
|
||||
|
||||
static const char *_b_resolve_exec_path(const char *file, char *out, size_t cap) {
|
||||
if (!file || !file[0]) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (file[0] == '/') {
|
||||
return _b_path_exists(file) ? file : NULL;
|
||||
}
|
||||
|
||||
snprintf(out, cap, "/bin/%s", file);
|
||||
if (_b_path_exists(out)) {
|
||||
return out;
|
||||
}
|
||||
|
||||
snprintf(out, cap, "/bin/%s.elf", file);
|
||||
if (_b_path_exists(out)) {
|
||||
return out;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int _b_join_argv(char *buf, size_t cap, char *const argv[]) {
|
||||
size_t used = 0;
|
||||
|
||||
if (!argv || !argv[0]) {
|
||||
if (cap) {
|
||||
buf[0] = '\0';
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = 1; argv[i]; i++) {
|
||||
const char *a = argv[i];
|
||||
size_t len = strlen(a);
|
||||
int need_quote = 0;
|
||||
|
||||
for (size_t j = 0; j < len; j++) {
|
||||
if (_b_is_space(a[j]) || a[j] == '"') {
|
||||
need_quote = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (used && used + 1 < cap) {
|
||||
buf[used++] = ' ';
|
||||
}
|
||||
|
||||
if (need_quote && used + 1 < cap) {
|
||||
buf[used++] = '"';
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < len; j++) {
|
||||
if (a[j] == '"' && used + 2 < cap) {
|
||||
buf[used++] = '\\';
|
||||
}
|
||||
if (used + 1 < cap) {
|
||||
buf[used++] = a[j];
|
||||
}
|
||||
}
|
||||
|
||||
if (need_quote && used + 1 < cap) {
|
||||
buf[used++] = '"';
|
||||
}
|
||||
|
||||
if (used >= cap) {
|
||||
errno = E2BIG;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (cap) {
|
||||
buf[used < cap ? used : cap - 1] = '\0';
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _b_exec_common(const char *path, char *const argv[]) {
|
||||
char resolved[260];
|
||||
char args[512];
|
||||
const char *exec_path = _b_resolve_exec_path(path, resolved, sizeof(resolved));
|
||||
|
||||
if (!exec_path) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_b_join_argv(args, sizeof(args), argv) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sys_exec(exec_path, args[0] ? args : NULL) < 0) {
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int execv(const char *path, char *const argv[]) {
|
||||
return _b_exec_common(path, argv);
|
||||
}
|
||||
|
||||
__attribute__((weak)) int execve(const char *path, char *const argv[], char *const envp[]) {
|
||||
(void)envp;
|
||||
return _b_exec_common(path, argv);
|
||||
}
|
||||
|
||||
__attribute__((weak)) int execvp(const char *file, char *const argv[]) {
|
||||
return _b_exec_common(file, argv);
|
||||
}
|
||||
|
||||
__attribute__((weak)) int execl(const char *path, const char *arg, ...) {
|
||||
va_list ap;
|
||||
char *argv[64];
|
||||
int i = 0;
|
||||
|
||||
argv[i++] = (char *)arg;
|
||||
va_start(ap, arg);
|
||||
while (i < 63) {
|
||||
char *v = va_arg(ap, char *);
|
||||
argv[i++] = v;
|
||||
if (!v) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
if (argv[i - 1] != NULL) {
|
||||
argv[63] = NULL;
|
||||
}
|
||||
|
||||
return execv(path, argv);
|
||||
}
|
||||
|
||||
__attribute__((weak)) int execlp(const char *file, const char *arg, ...) {
|
||||
va_list ap;
|
||||
char *argv[64];
|
||||
int i = 0;
|
||||
|
||||
argv[i++] = (char *)arg;
|
||||
va_start(ap, arg);
|
||||
while (i < 63) {
|
||||
char *v = va_arg(ap, char *);
|
||||
argv[i++] = v;
|
||||
if (!v) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
if (argv[i - 1] != NULL) {
|
||||
argv[63] = NULL;
|
||||
}
|
||||
|
||||
return execvp(file, argv);
|
||||
}
|
||||
|
||||
__attribute__((weak)) int execle(const char *path, const char *arg, ...) {
|
||||
va_list ap;
|
||||
char *argv[64];
|
||||
int i = 0;
|
||||
char *envp;
|
||||
|
||||
argv[i++] = (char *)arg;
|
||||
va_start(ap, arg);
|
||||
while (i < 63) {
|
||||
char *v = va_arg(ap, char *);
|
||||
argv[i++] = v;
|
||||
if (!v) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
envp = va_arg(ap, char *);
|
||||
va_end(ap);
|
||||
(void)envp;
|
||||
|
||||
if (argv[i - 1] != NULL) {
|
||||
argv[63] = NULL;
|
||||
}
|
||||
|
||||
return execv(path, argv);
|
||||
}
|
||||
|
||||
__attribute__((weak)) pid_t waitpid(pid_t pid, int *status, int options) {
|
||||
int st = 0;
|
||||
|
||||
for (;;) {
|
||||
int rc = sys_waitpid((int)pid, &st, options);
|
||||
if (rc > 0) {
|
||||
if (status) {
|
||||
*status = st;
|
||||
}
|
||||
return (pid_t)rc;
|
||||
}
|
||||
if (rc == 0 && (options & WNOHANG)) {
|
||||
return 0;
|
||||
}
|
||||
if (rc < 0) {
|
||||
errno = ECHILD;
|
||||
return -1;
|
||||
}
|
||||
sys_yield();
|
||||
}
|
||||
}
|
||||
178
src/userland/libc/runtime.c
Normal file
178
src/userland/libc/runtime.c
Normal file
@@ -0,0 +1,178 @@
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#include "errno.h"
|
||||
#include "syscall.h"
|
||||
#include "stdio.h"
|
||||
#include "math.h"
|
||||
|
||||
static int _b_is_space_char(int c) {
|
||||
return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v';
|
||||
}
|
||||
|
||||
static int _b_try_spawn_command(const char *command) {
|
||||
char cmd[128];
|
||||
char args[256];
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int pid;
|
||||
|
||||
while (command[i] && _b_is_space_char((unsigned char)command[i])) i++;
|
||||
while (command[i] && !_b_is_space_char((unsigned char)command[i]) && j < (int)sizeof(cmd) - 1) {
|
||||
cmd[j++] = command[i++];
|
||||
}
|
||||
cmd[j] = '\0';
|
||||
|
||||
if (cmd[0] == '\0') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (command[i] && _b_is_space_char((unsigned char)command[i])) i++;
|
||||
{
|
||||
int k = 0;
|
||||
while (command[i] && k < (int)sizeof(args) - 1) {
|
||||
args[k++] = command[i++];
|
||||
}
|
||||
args[k] = '\0';
|
||||
}
|
||||
|
||||
pid = sys_spawn(cmd, args[0] ? args : NULL, SPAWN_FLAG_TERMINAL | SPAWN_FLAG_INHERIT_TTY, 0);
|
||||
if (pid >= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cmd[0] != '/') {
|
||||
char path[160];
|
||||
snprintf(path, sizeof(path), "/bin/%s", cmd);
|
||||
pid = sys_spawn(path, args[0] ? args : NULL, SPAWN_FLAG_TERMINAL | SPAWN_FLAG_INHERIT_TTY, 0);
|
||||
if (pid >= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
snprintf(path, sizeof(path), "/bin/%s.elf", cmd);
|
||||
pid = sys_spawn(path, args[0] ? args : NULL, SPAWN_FLAG_TERMINAL | SPAWN_FLAG_INHERIT_TTY, 0);
|
||||
if (pid >= 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _b_streq(const char *a, const char *b) {
|
||||
while (*a && *b) {
|
||||
if (*a != *b) {
|
||||
return 0;
|
||||
}
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
return *a == '\0' && *b == '\0';
|
||||
}
|
||||
|
||||
__attribute__((weak)) int abs(int x) {
|
||||
return (x < 0) ? -x : x;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int system(const char *command) {
|
||||
if (command == NULL) {
|
||||
return 1;
|
||||
}
|
||||
return _b_try_spawn_command(command);
|
||||
}
|
||||
|
||||
__attribute__((weak)) char *getenv(const char *name) {
|
||||
const char *cfg;
|
||||
static char cwd_buf[256];
|
||||
if (!name || name[0] == '\0') {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (_b_streq(name, "PWD")) {
|
||||
if (sys_getcwd(cwd_buf, (int)sizeof(cwd_buf)) >= 0) {
|
||||
return cwd_buf;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (_b_streq(name, "PATH")) return "/bin:/";
|
||||
if (_b_streq(name, "HOME")) return "/";
|
||||
if (_b_streq(name, "SHELL")) return "/bin/bsh";
|
||||
if (_b_streq(name, "TERM")) return "boredos";
|
||||
|
||||
cfg = (const char *)(uintptr_t)sys_get_shell_config(name);
|
||||
if ((uintptr_t)cfg > 0x10000ULL) {
|
||||
return (char *)cfg;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
__attribute__((weak)) void abort(void) {
|
||||
sys_exit(1);
|
||||
while (1) {}
|
||||
}
|
||||
|
||||
__attribute__((weak)) void _exit(int status) {
|
||||
sys_exit(status);
|
||||
while (1) {}
|
||||
}
|
||||
|
||||
__attribute__((weak)) double strtod(const char *nptr, char **endptr) {
|
||||
const char *p = nptr;
|
||||
int sign = 1;
|
||||
double value = 0.0;
|
||||
double frac = 0.0;
|
||||
double scale = 1.0;
|
||||
int exp_sign = 1;
|
||||
int exp_val = 0;
|
||||
|
||||
while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r' || *p == '\f' || *p == '\v') p++;
|
||||
|
||||
if (*p == '-') {
|
||||
sign = -1;
|
||||
p++;
|
||||
} else if (*p == '+') {
|
||||
p++;
|
||||
}
|
||||
|
||||
while (*p >= '0' && *p <= '9') {
|
||||
value = value * 10.0 + (double)(*p - '0');
|
||||
p++;
|
||||
}
|
||||
|
||||
if (*p == '.') {
|
||||
p++;
|
||||
while (*p >= '0' && *p <= '9') {
|
||||
frac = frac * 10.0 + (double)(*p - '0');
|
||||
scale *= 10.0;
|
||||
p++;
|
||||
}
|
||||
value += frac / scale;
|
||||
}
|
||||
|
||||
if (*p == 'e' || *p == 'E') {
|
||||
const char *ep = p + 1;
|
||||
if (*ep == '-') {
|
||||
exp_sign = -1;
|
||||
ep++;
|
||||
} else if (*ep == '+') {
|
||||
ep++;
|
||||
}
|
||||
if (*ep >= '0' && *ep <= '9') {
|
||||
p = ep;
|
||||
while (*p >= '0' && *p <= '9') {
|
||||
exp_val = exp_val * 10 + (*p - '0');
|
||||
p++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (endptr) {
|
||||
*endptr = (char *)p;
|
||||
}
|
||||
|
||||
if (exp_val != 0) {
|
||||
value = ldexp(value, exp_sign * exp_val);
|
||||
}
|
||||
return sign * value;
|
||||
}
|
||||
38
src/userland/libc/setjmp.c
Normal file
38
src/userland/libc/setjmp.c
Normal file
@@ -0,0 +1,38 @@
|
||||
#include "setjmp.h"
|
||||
|
||||
__attribute__((weak)) int setjmp(jmp_buf env) {
|
||||
__asm__ volatile(
|
||||
"movq %%rbx, 0(%0)\n\t"
|
||||
"movq %%rbp, 8(%0)\n\t"
|
||||
"movq %%r12, 16(%0)\n\t"
|
||||
"movq %%r13, 24(%0)\n\t"
|
||||
"movq %%r14, 32(%0)\n\t"
|
||||
"movq %%r15, 40(%0)\n\t"
|
||||
"leaq 8(%%rsp), %%rax\n\t"
|
||||
"movq %%rax, 48(%0)\n\t"
|
||||
"movq (%%rsp), %%rax\n\t"
|
||||
"movq %%rax, 56(%0)\n\t"
|
||||
:
|
||||
: "r"(env)
|
||||
: "rax", "memory");
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((weak)) void longjmp(jmp_buf env, int val) {
|
||||
int r = (val == 0) ? 1 : val;
|
||||
__asm__ volatile(
|
||||
"movq 0(%0), %%rbx\n\t"
|
||||
"movq 8(%0), %%rbp\n\t"
|
||||
"movq 16(%0), %%r12\n\t"
|
||||
"movq 24(%0), %%r13\n\t"
|
||||
"movq 32(%0), %%r14\n\t"
|
||||
"movq 40(%0), %%r15\n\t"
|
||||
"movq 48(%0), %%rsp\n\t"
|
||||
"movl %1, %%eax\n\t"
|
||||
"movq 56(%0), %%rdx\n\t"
|
||||
"jmp *%%rdx\n\t"
|
||||
:
|
||||
: "r"(env), "r"(r)
|
||||
: "rax", "rdx", "memory");
|
||||
__builtin_unreachable();
|
||||
}
|
||||
20
src/userland/libc/setjmp.h
Normal file
20
src/userland/libc/setjmp.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef BOREDOS_LIBC_SETJMP_H
|
||||
#define BOREDOS_LIBC_SETJMP_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct boredos_jmp_buf_s {
|
||||
uint64_t rbx;
|
||||
uint64_t rbp;
|
||||
uint64_t r12;
|
||||
uint64_t r13;
|
||||
uint64_t r14;
|
||||
uint64_t r15;
|
||||
uint64_t rsp;
|
||||
uint64_t rip;
|
||||
} jmp_buf[1];
|
||||
|
||||
int setjmp(jmp_buf env) __attribute__((returns_twice, noinline));
|
||||
void longjmp(jmp_buf env, int val) __attribute__((noreturn, noinline));
|
||||
|
||||
#endif
|
||||
108
src/userland/libc/signal.c
Normal file
108
src/userland/libc/signal.c
Normal file
@@ -0,0 +1,108 @@
|
||||
#include "signal.h"
|
||||
#include "errno.h"
|
||||
#include "stdlib.h"
|
||||
#include "syscall.h"
|
||||
|
||||
typedef struct {
|
||||
unsigned long sa_handler;
|
||||
unsigned long sa_mask;
|
||||
int sa_flags;
|
||||
} k_sigaction_t;
|
||||
|
||||
__attribute__((weak)) sighandler_t signal(int sig, sighandler_t handler) {
|
||||
struct sigaction act;
|
||||
struct sigaction old;
|
||||
|
||||
if (sig <= 0 || sig >= 32) {
|
||||
errno = EINVAL;
|
||||
return SIG_ERR;
|
||||
}
|
||||
|
||||
act.sa_handler = handler;
|
||||
act.sa_mask = 0;
|
||||
act.sa_flags = 0;
|
||||
if (sigaction(sig, &act, &old) != 0) {
|
||||
return SIG_ERR;
|
||||
}
|
||||
return old.sa_handler;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int sigaction(int sig, const struct sigaction *act, struct sigaction *oldact) {
|
||||
k_sigaction_t kact;
|
||||
k_sigaction_t kold;
|
||||
int rc;
|
||||
|
||||
if (sig <= 0 || sig >= 32) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (act) {
|
||||
kact.sa_handler = (unsigned long)act->sa_handler;
|
||||
kact.sa_mask = (unsigned long)act->sa_mask;
|
||||
kact.sa_flags = act->sa_flags;
|
||||
}
|
||||
|
||||
rc = sys_sigaction(sig, act ? &kact : NULL, oldact ? &kold : NULL);
|
||||
if (rc < 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (oldact) {
|
||||
oldact->sa_handler = (sighandler_t)kold.sa_handler;
|
||||
oldact->sa_mask = (sigset_t)kold.sa_mask;
|
||||
oldact->sa_flags = kold.sa_flags;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int sigprocmask(int how, const sigset_t *set, sigset_t *oldset) {
|
||||
if (sys_sigprocmask(how,
|
||||
(const unsigned long *)set,
|
||||
(unsigned long *)oldset) < 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int sigpending(sigset_t *set) {
|
||||
if (!set) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (sys_sigpending((unsigned long *)set) < 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int raise(int sig) {
|
||||
if (sig <= 0 || sig >= 32) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sys_kill_signal(-1, sig) < 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int kill(pid_t pid, int sig) {
|
||||
if (pid <= 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sys_kill_signal((int)pid, sig) < 0) {
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
37
src/userland/libc/signal.h
Normal file
37
src/userland/libc/signal.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef BOREDOS_LIBC_SIGNAL_H
|
||||
#define BOREDOS_LIBC_SIGNAL_H
|
||||
|
||||
#include "sys/types.h"
|
||||
|
||||
typedef void (*sighandler_t)(int);
|
||||
typedef unsigned long sigset_t;
|
||||
|
||||
struct sigaction {
|
||||
sighandler_t sa_handler;
|
||||
sigset_t sa_mask;
|
||||
int sa_flags;
|
||||
};
|
||||
|
||||
#define SIG_DFL ((sighandler_t)0)
|
||||
#define SIG_IGN ((sighandler_t)1)
|
||||
#define SIG_ERR ((sighandler_t)-1)
|
||||
#define SIGKILL 9
|
||||
#define SIGTERM 15
|
||||
#define SIGINT 2
|
||||
|
||||
#define SIG_BLOCK 0
|
||||
#define SIG_UNBLOCK 1
|
||||
#define SIG_SETMASK 2
|
||||
|
||||
#define SA_RESTART 0x10000000
|
||||
#define SA_NODEFER 0x40000000
|
||||
#define SA_RESETHAND 0x80000000
|
||||
|
||||
sighandler_t signal(int sig, sighandler_t handler);
|
||||
int sigaction(int sig, const struct sigaction *act, struct sigaction *oldact);
|
||||
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
|
||||
int sigpending(sigset_t *set);
|
||||
int raise(int sig);
|
||||
int kill(pid_t pid, int sig);
|
||||
|
||||
#endif
|
||||
1046
src/userland/libc/stdio.c
Normal file
1046
src/userland/libc/stdio.c
Normal file
File diff suppressed because it is too large
Load Diff
56
src/userland/libc/stdio.h
Normal file
56
src/userland/libc/stdio.h
Normal file
@@ -0,0 +1,56 @@
|
||||
#ifndef BOREDOS_LIBC_STDIO_H
|
||||
#define BOREDOS_LIBC_STDIO_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
|
||||
typedef struct BOREDOS_FILE {
|
||||
int fd;
|
||||
int eof;
|
||||
int err;
|
||||
int has_ungetc;
|
||||
int ungetc_char;
|
||||
} FILE;
|
||||
|
||||
extern FILE *stdin;
|
||||
extern FILE *stdout;
|
||||
extern FILE *stderr;
|
||||
|
||||
#define EOF (-1)
|
||||
#define SEEK_SET 0
|
||||
#define SEEK_CUR 1
|
||||
#define SEEK_END 2
|
||||
#define BUFSIZ 1024
|
||||
#define FILENAME_MAX 260
|
||||
#define TMP_MAX 32
|
||||
|
||||
FILE *fopen(const char *path, const char *mode);
|
||||
FILE *freopen(const char *path, const char *mode, FILE *stream);
|
||||
int fclose(FILE *stream);
|
||||
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
|
||||
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
|
||||
int fseek(FILE *stream, long offset, int whence);
|
||||
long ftell(FILE *stream);
|
||||
int getc(FILE *stream);
|
||||
int ungetc(int c, FILE *stream);
|
||||
char *fgets(char *s, int n, FILE *stream);
|
||||
int fputs(const char *s, FILE *stream);
|
||||
int feof(FILE *stream);
|
||||
int ferror(FILE *stream);
|
||||
void clearerr(FILE *stream);
|
||||
int fflush(FILE *stream);
|
||||
int fputc(int c, FILE *stream);
|
||||
int putchar(int c);
|
||||
int fprintf(FILE *stream, const char *fmt, ...);
|
||||
int vfprintf(FILE *stream, const char *fmt, va_list ap);
|
||||
long filelength(FILE *f);
|
||||
int vsnprintf(char *str, size_t size, const char *fmt, va_list ap);
|
||||
int snprintf(char *str, size_t size, const char *fmt, ...);
|
||||
int sprintf(char *str, const char *fmt, ...);
|
||||
int sscanf(const char *str, const char *fmt, ...);
|
||||
int remove(const char *path);
|
||||
int rename(const char *oldpath, const char *newpath);
|
||||
FILE *tmpfile(void);
|
||||
char *tmpnam(char *s);
|
||||
|
||||
#endif
|
||||
@@ -334,7 +334,7 @@ char* getcwd(char *buf, int size) {
|
||||
}
|
||||
|
||||
void sleep(int ms) {
|
||||
sys_system(46, ms, 0, 0, 0);
|
||||
sys_system(SYSTEM_CMD_SLEEP, ms, 0, 0, 0);
|
||||
}
|
||||
|
||||
void exit(int status) {
|
||||
|
||||
@@ -16,15 +16,24 @@ void *memcpy(void *dest, const void *src, size_t n);
|
||||
// Math/Utility functions
|
||||
int atoi(const char *nptr);
|
||||
void itoa(int n, char *buf);
|
||||
int abs(int x);
|
||||
double strtod(const char *nptr, char **endptr);
|
||||
|
||||
// IO functions
|
||||
void puts(const char *s);
|
||||
void printf(const char *fmt, ...);
|
||||
|
||||
// Runtime stubs
|
||||
int system(const char *command);
|
||||
char *getenv(const char *name);
|
||||
void abort(void);
|
||||
|
||||
// System/Process functions
|
||||
int chdir(const char *path);
|
||||
char* getcwd(char *buf, int size);
|
||||
int access(const char *pathname, int mode);
|
||||
void sleep(int ms);
|
||||
void exit(int status);
|
||||
void _exit(int status);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -7,11 +7,22 @@ void *memmove(void *dest, const void *src, size_t n);
|
||||
int memcmp(const void *s1, const void *s2, size_t n);
|
||||
void *memcpy(void *dest, const void *src, size_t n);
|
||||
void *memset(void *s, int c, size_t n);
|
||||
void *memchr(const void *s, int c, size_t n);
|
||||
char *strchr(const char *s, int c);
|
||||
char *strrchr(const char *s, int c);
|
||||
char *strpbrk(const char *s, const char *accept);
|
||||
char *strstr(const char *haystack, const char *needle);
|
||||
size_t strspn(const char *s, const char *accept);
|
||||
size_t strcspn(const char *s, const char *reject);
|
||||
size_t strlen(const char *s);
|
||||
int strcmp(const char *s1, const char *s2);
|
||||
int strncmp(const char *s1, const char *s2, size_t n);
|
||||
int strncasecmp(const char *s1, const char *s2, size_t n);
|
||||
int strcasecmp(const char *s1, const char *s2);
|
||||
int strcoll(const char *s1, const char *s2);
|
||||
char* strcpy(char *dest, const char *src);
|
||||
char* strcat(char *dest, const char *src);
|
||||
char *strdup(const char *s);
|
||||
char *strerror(int errnum);
|
||||
|
||||
#endif
|
||||
|
||||
158
src/userland/libc/string_ext.c
Normal file
158
src/userland/libc/string_ext.c
Normal file
@@ -0,0 +1,158 @@
|
||||
#include "string.h"
|
||||
#include "errno.h"
|
||||
#include "ctype.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
__attribute__((weak)) int strncmp(const char *s1, const char *s2, size_t n) {
|
||||
size_t i;
|
||||
for (i = 0; i < n; i++) {
|
||||
unsigned char c1 = (unsigned char)s1[i];
|
||||
unsigned char c2 = (unsigned char)s2[i];
|
||||
if (c1 != c2) {
|
||||
return (int)c1 - (int)c2;
|
||||
}
|
||||
if (c1 == '\0') {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((weak)) char *strncpy(char *dest, const char *src, size_t n) {
|
||||
size_t i;
|
||||
for (i = 0; i < n && src[i] != '\0'; i++) {
|
||||
dest[i] = src[i];
|
||||
}
|
||||
for (; i < n; i++) {
|
||||
dest[i] = '\0';
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
__attribute__((weak)) char *strncat(char *dest, const char *src, size_t n) {
|
||||
size_t dlen = strlen(dest);
|
||||
size_t i;
|
||||
for (i = 0; i < n && src[i] != '\0'; i++) {
|
||||
dest[dlen + i] = src[i];
|
||||
}
|
||||
dest[dlen + i] = '\0';
|
||||
return dest;
|
||||
}
|
||||
|
||||
__attribute__((weak)) char *strrchr(const char *s, int c) {
|
||||
const char *last = NULL;
|
||||
for (;; s++) {
|
||||
if (*s == (char)c) {
|
||||
last = s;
|
||||
}
|
||||
if (*s == '\0') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (char *)last;
|
||||
}
|
||||
|
||||
__attribute__((weak)) char *strpbrk(const char *s, const char *accept) {
|
||||
for (; *s; s++) {
|
||||
const char *a;
|
||||
for (a = accept; *a; a++) {
|
||||
if (*s == *a) {
|
||||
return (char *)s;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
__attribute__((weak)) size_t strspn(const char *s, const char *accept) {
|
||||
size_t n = 0;
|
||||
while (*s) {
|
||||
if (!strchr(accept, *s)) {
|
||||
break;
|
||||
}
|
||||
n++;
|
||||
s++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
__attribute__((weak)) size_t strcspn(const char *s, const char *reject) {
|
||||
size_t n = 0;
|
||||
while (*s) {
|
||||
if (strchr(reject, *s)) {
|
||||
break;
|
||||
}
|
||||
n++;
|
||||
s++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
__attribute__((weak)) void *memchr(const void *s, int c, size_t n) {
|
||||
const unsigned char *p = (const unsigned char *)s;
|
||||
size_t i;
|
||||
for (i = 0; i < n; i++) {
|
||||
if (p[i] == (unsigned char)c) {
|
||||
return (void *)(p + i);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int strcoll(const char *s1, const char *s2) {
|
||||
return strcmp(s1, s2);
|
||||
}
|
||||
|
||||
__attribute__((weak)) char *strerror(int errnum) {
|
||||
switch (errnum) {
|
||||
case 0: return "no error";
|
||||
case EDOM: return "domain error";
|
||||
case ERANGE: return "range error";
|
||||
case EINVAL: return "invalid argument";
|
||||
case ENOENT: return "no such file or directory";
|
||||
case ENOMEM: return "not enough memory";
|
||||
case EEXIST: return "file exists";
|
||||
case EIO: return "i/o error";
|
||||
case ENOSYS: return "function not implemented";
|
||||
default: return "unknown error";
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((weak)) int strncasecmp(const char *s1, const char *s2, size_t n) {
|
||||
while (n--) {
|
||||
char c1 = (char)tolower((unsigned char)*s1++);
|
||||
char c2 = (char)tolower((unsigned char)*s2++);
|
||||
if (c1 != c2) {
|
||||
return c1 - c2;
|
||||
}
|
||||
if (!c1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int strcasecmp(const char *s1, const char *s2) {
|
||||
while (1) {
|
||||
char c1 = (char)tolower((unsigned char)*s1++);
|
||||
char c2 = (char)tolower((unsigned char)*s2++);
|
||||
if (c1 != c2) {
|
||||
return c1 - c2;
|
||||
}
|
||||
if (!c1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((weak)) char *strdup(const char *s) {
|
||||
size_t len = strlen(s) + 1;
|
||||
char *dup = (char *)malloc(len);
|
||||
if (!dup) {
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
memcpy(dup, s, len);
|
||||
return dup;
|
||||
}
|
||||
47
src/userland/libc/sys/stat.h
Normal file
47
src/userland/libc/sys/stat.h
Normal file
@@ -0,0 +1,47 @@
|
||||
#ifndef BOREDOS_LIBC_SYS_STAT_H
|
||||
#define BOREDOS_LIBC_SYS_STAT_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
typedef long time_t;
|
||||
|
||||
struct stat {
|
||||
unsigned long st_dev;
|
||||
unsigned long st_ino;
|
||||
mode_t st_mode;
|
||||
unsigned long st_nlink;
|
||||
uid_t st_uid;
|
||||
gid_t st_gid;
|
||||
unsigned long st_rdev;
|
||||
int st_size;
|
||||
long st_blksize;
|
||||
long st_blocks;
|
||||
time_t st_atime;
|
||||
time_t st_mtime;
|
||||
time_t st_ctime;
|
||||
};
|
||||
|
||||
#define S_IFMT 0170000
|
||||
#define S_IFIFO 0010000
|
||||
#define S_IFCHR 0020000
|
||||
#define S_IFDIR 0040000
|
||||
#define S_IFREG 0100000
|
||||
|
||||
#define S_IRUSR 0400
|
||||
#define S_IWUSR 0200
|
||||
#define S_IXUSR 0100
|
||||
#define S_IRGRP 0040
|
||||
#define S_IWGRP 0020
|
||||
#define S_IXGRP 0010
|
||||
#define S_IROTH 0004
|
||||
#define S_IWOTH 0002
|
||||
#define S_IXOTH 0001
|
||||
|
||||
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
|
||||
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
|
||||
|
||||
int stat(const char *pathname, struct stat *statbuf);
|
||||
int fstat(int fd, struct stat *statbuf);
|
||||
int mkdir(const char *pathname, int mode);
|
||||
|
||||
#endif
|
||||
11
src/userland/libc/sys/types.h
Normal file
11
src/userland/libc/sys/types.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef BOREDOS_LIBC_SYS_TYPES_H
|
||||
#define BOREDOS_LIBC_SYS_TYPES_H
|
||||
|
||||
typedef long ssize_t;
|
||||
typedef long off_t;
|
||||
typedef unsigned int mode_t;
|
||||
typedef int pid_t;
|
||||
typedef unsigned int uid_t;
|
||||
typedef unsigned int gid_t;
|
||||
|
||||
#endif
|
||||
15
src/userland/libc/sys/wait.h
Normal file
15
src/userland/libc/sys/wait.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef BOREDOS_LIBC_SYS_WAIT_H
|
||||
#define BOREDOS_LIBC_SYS_WAIT_H
|
||||
|
||||
#include "../sys/types.h"
|
||||
|
||||
#define WNOHANG 1
|
||||
|
||||
#define WEXITSTATUS(status) (((status) >> 8) & 0xff)
|
||||
#define WIFEXITED(status) ((((status) & 0x7f) == 0) ? 1 : 0)
|
||||
#define WTERMSIG(status) ((status) & 0x7f)
|
||||
#define WIFSIGNALED(status) (((status) & 0x7f) != 0)
|
||||
|
||||
pid_t waitpid(pid_t pid, int *status, int options);
|
||||
|
||||
#endif
|
||||
@@ -145,6 +145,22 @@ int sys_chdir(const char *path) {
|
||||
return (int)syscall2(SYS_FS, FS_CMD_CHDIR, (uint64_t)path);
|
||||
}
|
||||
|
||||
int sys_dup(int oldfd) {
|
||||
return (int)syscall2(SYS_FS, FS_CMD_DUP, (uint64_t)oldfd);
|
||||
}
|
||||
|
||||
int sys_dup2(int oldfd, int newfd) {
|
||||
return (int)syscall3(SYS_FS, FS_CMD_DUP2, (uint64_t)oldfd, (uint64_t)newfd);
|
||||
}
|
||||
|
||||
int sys_pipe(int pipefd[2]) {
|
||||
return (int)syscall2(SYS_FS, FS_CMD_PIPE, (uint64_t)pipefd);
|
||||
}
|
||||
|
||||
int sys_fcntl(int fd, int cmd, int val) {
|
||||
return (int)syscall4(SYS_FS, FS_CMD_FCNTL, (uint64_t)fd, (uint64_t)cmd, (uint64_t)val);
|
||||
}
|
||||
|
||||
int sys_tty_create(void) {
|
||||
return (int)syscall2(SYS_SYSTEM, SYSTEM_CMD_TTY_CREATE, 0);
|
||||
}
|
||||
@@ -165,6 +181,30 @@ int sys_spawn(const char *path, const char *args, uint64_t flags, uint64_t tty_i
|
||||
return (int)syscall5(SYS_SYSTEM, SYSTEM_CMD_SPAWN, (uint64_t)path, (uint64_t)args, flags, (uint64_t)tty_id);
|
||||
}
|
||||
|
||||
int sys_exec(const char *path, const char *args) {
|
||||
return (int)syscall4(SYS_SYSTEM, SYSTEM_CMD_EXEC, (uint64_t)path, (uint64_t)args, 0);
|
||||
}
|
||||
|
||||
int sys_waitpid(int pid, int *status, int options) {
|
||||
return (int)syscall4(SYS_SYSTEM, SYSTEM_CMD_WAITPID, (uint64_t)pid, (uint64_t)status, (uint64_t)options);
|
||||
}
|
||||
|
||||
int sys_kill_signal(int pid, int sig) {
|
||||
return (int)syscall4(SYS_SYSTEM, SYSTEM_CMD_KILL_SIGNAL, (uint64_t)pid, (uint64_t)sig, 0);
|
||||
}
|
||||
|
||||
int sys_sigaction(int sig, const void *act, void *oldact) {
|
||||
return (int)syscall4(SYS_SYSTEM, SYSTEM_CMD_SIGACTION, (uint64_t)sig, (uint64_t)act, (uint64_t)oldact);
|
||||
}
|
||||
|
||||
int sys_sigprocmask(int how, const unsigned long *set, unsigned long *oldset) {
|
||||
return (int)syscall4(SYS_SYSTEM, SYSTEM_CMD_SIGPROCMASK, (uint64_t)how, (uint64_t)set, (uint64_t)oldset);
|
||||
}
|
||||
|
||||
int sys_sigpending(unsigned long *set) {
|
||||
return (int)syscall3(SYS_SYSTEM, SYSTEM_CMD_SIGPENDING, (uint64_t)set, 0);
|
||||
}
|
||||
|
||||
int sys_tty_set_fg(int tty_id, int pid) {
|
||||
return (int)syscall4(SYS_SYSTEM, SYSTEM_CMD_TTY_SET_FG, (uint64_t)tty_id, (uint64_t)pid, 0);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,10 @@
|
||||
#define FS_CMD_GETCWD 12
|
||||
#define FS_CMD_CHDIR 13
|
||||
#define FS_CMD_GET_INFO 14
|
||||
#define FS_CMD_DUP 15
|
||||
#define FS_CMD_DUP2 16
|
||||
#define FS_CMD_PIPE 17
|
||||
#define FS_CMD_FCNTL 18
|
||||
|
||||
// System Commands (via SYS_SYSTEM)
|
||||
#define SYSTEM_CMD_SET_BG_COLOR 1
|
||||
@@ -44,6 +48,8 @@
|
||||
#define SYSTEM_CMD_REBOOT 12
|
||||
#define SYSTEM_CMD_SHUTDOWN 13
|
||||
#define SYSTEM_CMD_BEEP 14
|
||||
#define SYSTEM_CMD_GET_MEM_INFO 15
|
||||
#define SYSTEM_CMD_GET_TICKS 16
|
||||
#define SYSTEM_CMD_PCI_LIST 17
|
||||
#define SYSTEM_CMD_NETWORK_DHCP 18
|
||||
#define SYSTEM_CMD_NETWORK_GET_MAC 19
|
||||
@@ -60,6 +66,7 @@
|
||||
#define SYSTEM_CMD_NETWORK_GET_NIC_NAME 48
|
||||
#define SYSTEM_CMD_SET_TEXT_COLOR 29
|
||||
#define SYSTEM_CMD_SET_WALLPAPER_PATH 31
|
||||
#define SYSTEM_CMD_RTC_SET 32
|
||||
#define SYSTEM_CMD_TCP_CONNECT 33
|
||||
#define SYSTEM_CMD_TCP_SEND 34
|
||||
#define SYSTEM_CMD_TCP_RECV 35
|
||||
@@ -67,10 +74,12 @@
|
||||
#define SYSTEM_CMD_DNS_LOOKUP 37
|
||||
#define SYSTEM_CMD_SET_DNS 38
|
||||
#define SYSTEM_CMD_NET_UNLOCK 39
|
||||
#define SYSTEM_CMD_SET_FONT 40
|
||||
#define SYSTEM_CMD_SLEEP 46
|
||||
#define SYSTEM_CMD_SET_RAW_MODE 41
|
||||
#define SYSTEM_CMD_TCP_RECV_NB 42
|
||||
#define SYSTEM_CMD_YIELD 43
|
||||
#define SYSTEM_CMD_SET_RESOLUTION 47
|
||||
#define SYSTEM_CMD_PARALLEL_RUN 50
|
||||
#define SYSTEM_CMD_TTY_CREATE 60
|
||||
#define SYSTEM_CMD_TTY_READ_OUT 61
|
||||
@@ -82,10 +91,17 @@
|
||||
#define SYSTEM_CMD_TTY_KILL_FG 67
|
||||
#define SYSTEM_CMD_TTY_KILL_ALL 68
|
||||
#define SYSTEM_CMD_TTY_DESTROY 69
|
||||
#define SYSTEM_CMD_EXEC 70
|
||||
#define SYSTEM_CMD_WAITPID 71
|
||||
#define SYSTEM_CMD_KILL_SIGNAL 72
|
||||
#define SYSTEM_CMD_SIGACTION 73
|
||||
#define SYSTEM_CMD_SIGPROCMASK 74
|
||||
#define SYSTEM_CMD_SIGPENDING 75
|
||||
|
||||
#define SPAWN_FLAG_TERMINAL 0x1
|
||||
#define SPAWN_FLAG_INHERIT_TTY 0x2
|
||||
#define SPAWN_FLAG_TTY_ID 0x4
|
||||
#define SPAWN_FLAG_BACKGROUND 0x8
|
||||
|
||||
// Internal assembly entry into Ring 0
|
||||
extern uint64_t syscall0(uint64_t sys_num);
|
||||
@@ -128,12 +144,22 @@ int sys_mkdir(const char *path);
|
||||
int sys_exists(const char *path);
|
||||
int sys_getcwd(char *buf, int size);
|
||||
int sys_chdir(const char *path);
|
||||
int sys_dup(int oldfd);
|
||||
int sys_dup2(int oldfd, int newfd);
|
||||
int sys_pipe(int pipefd[2]);
|
||||
int sys_fcntl(int fd, int cmd, int val);
|
||||
|
||||
int sys_tty_create(void);
|
||||
int sys_tty_read_out(int tty_id, char *buf, int len);
|
||||
int sys_tty_write_in(int tty_id, const char *buf, int len);
|
||||
int sys_tty_read_in(char *buf, int len);
|
||||
int sys_spawn(const char *path, const char *args, uint64_t flags, uint64_t tty_id);
|
||||
int sys_exec(const char *path, const char *args);
|
||||
int sys_waitpid(int pid, int *status, int options);
|
||||
int sys_kill_signal(int pid, int sig);
|
||||
int sys_sigaction(int sig, const void *act, void *oldact);
|
||||
int sys_sigprocmask(int how, const unsigned long *set, unsigned long *oldset);
|
||||
int sys_sigpending(unsigned long *set);
|
||||
int sys_tty_set_fg(int tty_id, int pid);
|
||||
int sys_tty_get_fg(int tty_id);
|
||||
int sys_tty_kill_fg(int tty_id);
|
||||
|
||||
166
src/userland/libc/time.c
Normal file
166
src/userland/libc/time.c
Normal file
@@ -0,0 +1,166 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "time.h"
|
||||
#include "stdio.h"
|
||||
#include "syscall.h"
|
||||
|
||||
static int _b_is_leap(int year) {
|
||||
return ((year % 4) == 0 && (year % 100) != 0) || ((year % 400) == 0);
|
||||
}
|
||||
|
||||
static int _b_days_in_month(int year, int month) {
|
||||
static const int mdays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||
if (month == 1 && _b_is_leap(year)) {
|
||||
return 29;
|
||||
}
|
||||
return mdays[month];
|
||||
}
|
||||
|
||||
static long long _b_days_before_year(int year) {
|
||||
long long y = (long long)year - 1;
|
||||
return y * 365 + y / 4 - y / 100 + y / 400;
|
||||
}
|
||||
|
||||
static long long _b_days_since_epoch(int year, int month, int day) {
|
||||
long long days = _b_days_before_year(year) - _b_days_before_year(1970);
|
||||
int m;
|
||||
for (m = 0; m < month - 1; m++) {
|
||||
days += _b_days_in_month(year, m);
|
||||
}
|
||||
days += (day - 1);
|
||||
return days;
|
||||
}
|
||||
|
||||
static void _b_civil_from_days(long long z, int *year, int *month, int *day) {
|
||||
z += 719468;
|
||||
long long era = (z >= 0 ? z : z - 146096) / 146097;
|
||||
unsigned doe = (unsigned)(z - era * 146097);
|
||||
unsigned yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;
|
||||
int y = (int)yoe + (int)era * 400;
|
||||
unsigned doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
|
||||
unsigned mp = (5 * doy + 2) / 153;
|
||||
unsigned d = doy - (153 * mp + 2) / 5 + 1;
|
||||
unsigned m = mp + (mp < 10 ? 3 : (unsigned)-9);
|
||||
y += (m <= 2);
|
||||
*year = y;
|
||||
*month = (int)m;
|
||||
*day = (int)d;
|
||||
}
|
||||
|
||||
static time_t _b_seconds_from_ymdhms(int year, int month, int day, int hour, int minute, int second) {
|
||||
long long days = _b_days_since_epoch(year, month, day);
|
||||
return (time_t)(days * 86400LL + hour * 3600LL + minute * 60LL + second);
|
||||
}
|
||||
|
||||
static void _b_fill_tm_from_epoch(time_t t, struct tm *out) {
|
||||
long long sec = (long long)t;
|
||||
long long days;
|
||||
int sod;
|
||||
int year;
|
||||
int month;
|
||||
int day;
|
||||
|
||||
if (sec < 0) {
|
||||
long long d = ((-sec) + 86399LL) / 86400LL;
|
||||
sec += d * 86400LL;
|
||||
}
|
||||
|
||||
days = sec / 86400LL;
|
||||
sod = (int)(sec % 86400LL);
|
||||
if (sod < 0) {
|
||||
sod += 86400;
|
||||
days--;
|
||||
}
|
||||
|
||||
_b_civil_from_days(days, &year, &month, &day);
|
||||
|
||||
out->tm_year = year - 1900;
|
||||
out->tm_mon = month - 1;
|
||||
out->tm_mday = day;
|
||||
out->tm_hour = sod / 3600;
|
||||
out->tm_min = (sod % 3600) / 60;
|
||||
out->tm_sec = sod % 60;
|
||||
out->tm_wday = (int)((days + 4) % 7);
|
||||
if (out->tm_wday < 0) out->tm_wday += 7;
|
||||
|
||||
{
|
||||
long long jan1 = _b_days_since_epoch(year, 1, 1);
|
||||
out->tm_yday = (int)(days - jan1);
|
||||
}
|
||||
out->tm_isdst = 0;
|
||||
}
|
||||
|
||||
__attribute__((weak)) time_t time(time_t *out) {
|
||||
int dt[6] = {1970, 1, 1, 0, 0, 0};
|
||||
time_t t;
|
||||
if (sys_system(SYSTEM_CMD_RTC_GET, 0, (uint64_t)dt, 0, 0) != 0) {
|
||||
t = 0;
|
||||
} else {
|
||||
t = _b_seconds_from_ymdhms(dt[0], dt[1], dt[2], dt[3], dt[4], dt[5]);
|
||||
}
|
||||
if (out) {
|
||||
*out = t;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
__attribute__((weak)) clock_t clock(void) {
|
||||
static uint64_t start_tsc = 0;
|
||||
unsigned int lo;
|
||||
unsigned int hi;
|
||||
uint64_t now_tsc;
|
||||
|
||||
__asm__ volatile("rdtsc" : "=a"(lo), "=d"(hi));
|
||||
now_tsc = ((uint64_t)hi << 32) | (uint64_t)lo;
|
||||
|
||||
if (start_tsc == 0) {
|
||||
start_tsc = now_tsc;
|
||||
__asm__ volatile("rdtsc" : "=a"(lo), "=d"(hi));
|
||||
now_tsc = ((uint64_t)hi << 32) | (uint64_t)lo;
|
||||
}
|
||||
|
||||
return (clock_t)(now_tsc - start_tsc);
|
||||
}
|
||||
|
||||
__attribute__((weak)) struct tm *gmtime(const time_t *timer) {
|
||||
static struct tm tmv;
|
||||
if (!timer) {
|
||||
return NULL;
|
||||
}
|
||||
_b_fill_tm_from_epoch(*timer, &tmv);
|
||||
return &tmv;
|
||||
}
|
||||
|
||||
__attribute__((weak)) struct tm *localtime(const time_t *timer) {
|
||||
return gmtime(timer);
|
||||
}
|
||||
|
||||
__attribute__((weak)) size_t strftime(char *s, size_t max, const char *fmt, const struct tm *tm) {
|
||||
(void)fmt;
|
||||
if (!s || max == 0 || !tm) {
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
int n = snprintf(s, max, "%04d-%02d-%02d %02d:%02d:%02d",
|
||||
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
|
||||
tm->tm_hour, tm->tm_min, tm->tm_sec);
|
||||
if (n < 0 || (size_t)n >= max) {
|
||||
if (max > 0) s[0] = '\0';
|
||||
return 0;
|
||||
}
|
||||
return (size_t)n;
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((weak)) time_t mktime(struct tm *tm) {
|
||||
if (!tm) {
|
||||
return (time_t)-1;
|
||||
}
|
||||
return _b_seconds_from_ymdhms(
|
||||
tm->tm_year + 1900,
|
||||
tm->tm_mon + 1,
|
||||
tm->tm_mday,
|
||||
tm->tm_hour,
|
||||
tm->tm_min,
|
||||
tm->tm_sec);
|
||||
}
|
||||
30
src/userland/libc/time.h
Normal file
30
src/userland/libc/time.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef BOREDOS_LIBC_TIME_H
|
||||
#define BOREDOS_LIBC_TIME_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
typedef long long time_t;
|
||||
typedef unsigned long long clock_t;
|
||||
|
||||
#define CLOCKS_PER_SEC 3000000000ULL
|
||||
|
||||
struct tm {
|
||||
int tm_sec;
|
||||
int tm_min;
|
||||
int tm_hour;
|
||||
int tm_mday;
|
||||
int tm_mon;
|
||||
int tm_year;
|
||||
int tm_wday;
|
||||
int tm_yday;
|
||||
int tm_isdst;
|
||||
};
|
||||
|
||||
time_t time(time_t *out);
|
||||
clock_t clock(void);
|
||||
struct tm *localtime(const time_t *timer);
|
||||
struct tm *gmtime(const time_t *timer);
|
||||
size_t strftime(char *s, size_t max, const char *fmt, const struct tm *tm);
|
||||
time_t mktime(struct tm *tm);
|
||||
|
||||
#endif
|
||||
30
src/userland/libc/unistd.h
Normal file
30
src/userland/libc/unistd.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef BOREDOS_LIBC_UNISTD_H
|
||||
#define BOREDOS_LIBC_UNISTD_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include "sys/types.h"
|
||||
|
||||
#define SEEK_SET 0
|
||||
#define SEEK_CUR 1
|
||||
#define SEEK_END 2
|
||||
|
||||
#define F_OK 0
|
||||
#define X_OK 1
|
||||
#define W_OK 2
|
||||
#define R_OK 4
|
||||
|
||||
int close(int fd);
|
||||
ssize_t read(int fd, void *buf, size_t count);
|
||||
ssize_t write(int fd, const void *buf, size_t count);
|
||||
off_t lseek(int fd, off_t offset, int whence);
|
||||
int unlink(const char *pathname);
|
||||
int isatty(int fd);
|
||||
int execv(const char *path, char *const argv[]);
|
||||
int execve(const char *path, char *const argv[], char *const envp[]);
|
||||
int execvp(const char *file, char *const argv[]);
|
||||
int execl(const char *path, const char *arg, ...);
|
||||
int execlp(const char *file, const char *arg, ...);
|
||||
int execle(const char *path, const char *arg, ...);
|
||||
pid_t waitpid(pid_t pid, int *status, int options);
|
||||
|
||||
#endif
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
(void)argc; (void)argv;
|
||||
sys_system(14, 392, 400, 0, 0);
|
||||
sys_system(SYSTEM_CMD_BEEP, 392, 400, 0, 0);
|
||||
printf("BEEP!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,10 @@ static long long sw_start_ticks = 0;
|
||||
static long long sw_elapsed_ticks = 0;
|
||||
static bool sw_running = false;
|
||||
|
||||
static long long sys_ticks_now(void) {
|
||||
return sys_system(SYSTEM_CMD_GET_TICKS, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
static void format_time(char *buf, int h, int m, int s) {
|
||||
buf[0] = '0' + (h / 10);
|
||||
buf[1] = '0' + (h % 10);
|
||||
@@ -55,7 +59,7 @@ static void format_time(char *buf, int h, int m, int s) {
|
||||
static void update_rtc_state(void) {
|
||||
int dt[6];
|
||||
int old_s = cur_s;
|
||||
sys_system(11, (uint64_t)dt, 0, 0, 0);
|
||||
sys_system(SYSTEM_CMD_RTC_GET, (uint64_t)dt, 0, 0, 0);
|
||||
cur_y = dt[0]; cur_mon = dt[1]; cur_d = dt[2];
|
||||
cur_h = dt[3]; cur_m = dt[4]; cur_s = dt[5];
|
||||
|
||||
@@ -123,7 +127,7 @@ static void clock_paint(void) {
|
||||
draw_btn((WIN_W - 120) / 2, 195, 120, 28, "Apply changes", false);
|
||||
|
||||
} else if (current_tab == TAB_TIMER) {
|
||||
long long now = sys_system(16, 0, 0, 0, 0);
|
||||
long long now = sys_ticks_now();
|
||||
int display_h = timer_h, display_m = timer_m, display_s = timer_s;
|
||||
|
||||
if (timer_running) {
|
||||
@@ -131,7 +135,7 @@ static void clock_paint(void) {
|
||||
if (rem <= 0) {
|
||||
timer_running = false;
|
||||
display_h = display_m = display_s = 0;
|
||||
for(int i=0; i<3; i++) sys_system(14, 440, 200, 0, 0);
|
||||
for (int i = 0; i < 3; i++) sys_system(SYSTEM_CMD_BEEP, 440, 200, 0, 0);
|
||||
} else {
|
||||
int s = rem / 60;
|
||||
display_h = s / 3600;
|
||||
@@ -157,7 +161,7 @@ static void clock_paint(void) {
|
||||
|
||||
} else if (current_tab == TAB_STOPWATCH) {
|
||||
long long elapsed = sw_elapsed_ticks;
|
||||
if (sw_running) elapsed += (sys_system(16, 0, 0, 0, 0) - sw_start_ticks);
|
||||
if (sw_running) elapsed += (sys_ticks_now() - sw_start_ticks);
|
||||
|
||||
int ms_val = (elapsed % 60) * 1000 / 60;
|
||||
int s_val = (elapsed / 60) % 60;
|
||||
@@ -207,7 +211,7 @@ static void clock_click(int x, int y) {
|
||||
else if (x >= ax_clock + 73 && x <= ax_clock + 110) adj_s = (adj_s + 59) % 60;
|
||||
} else if (x >= (WIN_W - 120) / 2 && x <= (WIN_W + 120) / 2 && y >= 195 && y <= 223) {
|
||||
int dt[6] = {cur_y, cur_mon, cur_d, adj_h, adj_m, adj_s};
|
||||
sys_system(32, (uint64_t)dt, 0, 0, 0);
|
||||
sys_system(SYSTEM_CMD_RTC_SET, (uint64_t)dt, 0, 0, 0);
|
||||
}
|
||||
} else if (current_tab == TAB_TIMER) {
|
||||
if (!timer_running) {
|
||||
@@ -225,16 +229,16 @@ static void clock_click(int x, int y) {
|
||||
if (!timer_running) {
|
||||
if (timer_h > 0 || timer_m > 0 || timer_s > 0) {
|
||||
timer_running = true;
|
||||
timer_end_ticks = sys_system(16, 0, 0, 0, 0) + (long long)(timer_h * 3600 + timer_m * 60 + timer_s) * 60;
|
||||
timer_end_ticks = sys_ticks_now() + (long long)(timer_h * 3600 + timer_m * 60 + timer_s) * 60;
|
||||
}
|
||||
} else timer_running = false;
|
||||
}
|
||||
} else if (current_tab == TAB_STOPWATCH) {
|
||||
if (x >= 20 && x <= 110 && y >= 150 && y <= 180) {
|
||||
if (sw_running) { sw_elapsed_ticks += (sys_system(16, 0, 0, 0, 0) - sw_start_ticks); sw_running = false; }
|
||||
else { sw_start_ticks = sys_system(16, 0, 0, 0, 0); sw_running = true; }
|
||||
if (sw_running) { sw_elapsed_ticks += (sys_ticks_now() - sw_start_ticks); sw_running = false; }
|
||||
else { sw_start_ticks = sys_ticks_now(); sw_running = true; }
|
||||
} else if (x >= 140 && x <= 230 && y >= 150 && y <= 180) {
|
||||
sw_elapsed_ticks = 0; sw_start_ticks = sys_system(16, 0, 0, 0, 0);
|
||||
sw_elapsed_ticks = 0; sw_start_ticks = sys_ticks_now();
|
||||
}
|
||||
}
|
||||
clock_paint();
|
||||
@@ -254,7 +258,7 @@ int main(void) {
|
||||
else if (ev.type == GUI_EVENT_CLICK) clock_click(ev.arg1, ev.arg2);
|
||||
else if (ev.type == GUI_EVENT_CLOSE) sys_exit(0);
|
||||
} else {
|
||||
long long now = sys_system(16, 0, 0, 0, 0);
|
||||
long long now = sys_ticks_now();
|
||||
if (now - last_rep >= 6) { clock_paint(); ui_mark_dirty(win_clock, 0, 0, WIN_W, WIN_H); last_rep = now; }
|
||||
sleep(10);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
int main(int argc, char **argv) {
|
||||
(void)argc; (void)argv;
|
||||
uint64_t mem[2];
|
||||
if (sys_system(15, (uint64_t)mem, 0, 0, 0) == 0) {
|
||||
if (sys_system(SYSTEM_CMD_GET_MEM_INFO, (uint64_t)mem, 0, 0, 0) == 0) {
|
||||
printf("Memory Info:\n");
|
||||
printf("Total: %d MB\n", (int)(mem[0] / 1024 / 1024));
|
||||
printf("Used: %d MB\n", (int)(mem[1] / 1024 / 1024));
|
||||
|
||||
@@ -13,7 +13,7 @@ typedef struct {
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
(void)argc; (void)argv;
|
||||
int count = sys_system(17, 0, 0, 0, 0);
|
||||
int count = sys_system(SYSTEM_CMD_PCI_LIST, 0, 0, 0, 0);
|
||||
if (count < 0) {
|
||||
printf("Error: Could not retrieve PCI device count.\n");
|
||||
return 1;
|
||||
@@ -23,7 +23,7 @@ int main(int argc, char **argv) {
|
||||
printf("---------------------------\n");
|
||||
for (int i = 0; i < count; i++) {
|
||||
pci_info_t info;
|
||||
if (sys_system(17, (uint64_t)&info, i, 0, 0) == 0) {
|
||||
if (sys_system(SYSTEM_CMD_PCI_LIST, (uint64_t)&info, i, 0, 0) == 0) {
|
||||
printf("[%d] Vendor:%04x Device:%04x Class:%02x Sub:%02x\n",
|
||||
i, info.vendor, info.device, info.class_code, info.subclass);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,6 @@
|
||||
int main(int argc, char **argv) {
|
||||
(void)argc; (void)argv;
|
||||
printf("Rebooting...\n");
|
||||
sys_system(12, 0, 0, 0, 0); // SYSTEM_CMD_REBOOT
|
||||
sys_system(SYSTEM_CMD_REBOOT, 0, 0, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,6 @@
|
||||
int main(int argc, char **argv) {
|
||||
(void)argc; (void)argv;
|
||||
printf("Shutting down...\n");
|
||||
sys_system(13, 0, 0, 0, 0); // SYSTEM_CMD_SHUTDOWN
|
||||
sys_system(SYSTEM_CMD_SHUTDOWN, 0, 0, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user