SYSCALL_GETPEERNAME = 134,
SYSCALL_GETSOCKNAME = 135,
SYSCALL_UNAME = 136,
+ SYSCALL_GETRUSAGE = 137,
};
#endif
return revents;
}
+static int pipe_ioctl(fs_node_t* n, uint32_t cmd, void* user_arg) {
+ struct pipe_node* pn = (struct pipe_node*)n;
+ if (!pn || !pn->ps) return -EBADF;
+ if (cmd == 0x541B /* FIONREAD */) {
+ if (!user_arg || user_range_ok(user_arg, sizeof(int)) == 0) return -EFAULT;
+ int avail = (int)pn->ps->count;
+ if (copy_to_user(user_arg, &avail, sizeof(avail)) < 0) return -EFAULT;
+ return 0;
+ }
+ return -ENOTTY;
+}
+
static const struct file_operations pipe_read_fops = {
.read = pipe_read,
.close = pipe_close,
.poll = pipe_poll,
+ .ioctl = pipe_ioctl,
};
static const struct file_operations pipe_write_fops = {
.write = pipe_write,
.close = pipe_close,
.poll = pipe_poll,
+ .ioctl = pipe_ioctl,
};
static int pipe_node_create(struct pipe_state* ps, int is_read_end, fs_node_t** out_node) {
return;
}
+ if (syscall_no == SYSCALL_GETRUSAGE) {
+ int who = (int)sc_arg0(regs);
+ void* user_buf = (void*)sc_arg1(regs);
+ if (!user_buf || user_range_ok(user_buf, 64) == 0) {
+ sc_ret(regs) = (uint32_t)-EFAULT; return;
+ }
+ /* struct rusage: we fill ru_utime and ru_stime (2 x struct timeval = 16 bytes)
+ * then zero the rest (total 64 bytes to be safe) */
+ struct {
+ uint32_t ru_utime_sec; uint32_t ru_utime_usec;
+ uint32_t ru_stime_sec; uint32_t ru_stime_usec;
+ uint32_t padding[12]; /* remaining fields zero */
+ } ru;
+ memset(&ru, 0, sizeof(ru));
+ (void)who; /* RUSAGE_SELF=0, RUSAGE_CHILDREN=-1 — we only report self */
+ uint32_t hz = 100; /* tick rate */
+ ru.ru_utime_sec = current_process->utime / hz;
+ ru.ru_utime_usec = (current_process->utime % hz) * (1000000 / hz);
+ ru.ru_stime_sec = current_process->stime / hz;
+ ru.ru_stime_usec = (current_process->stime % hz) * (1000000 / hz);
+ if (copy_to_user(user_buf, &ru, sizeof(ru)) < 0) {
+ sc_ret(regs) = (uint32_t)-EFAULT; return;
+ }
+ sc_ret(regs) = 0;
+ return;
+ }
+
if (syscall_no == SYSCALL_UNAME) {
/* struct utsname: 5 fields of 65 bytes each = 325 bytes */
void* user_buf = (void*)sc_arg0(regs);
TTY_TIOCSPGRP = 0x5410,
TTY_TIOCGWINSZ = 0x5413,
TTY_TIOCSWINSZ = 0x5414,
+ TTY_FIONREAD = 0x541B,
};
int tty_ioctl(uint32_t cmd, void* user_arg) {
return 0;
}
+ if (cmd == TTY_FIONREAD) {
+ if (user_range_ok(user_arg, sizeof(int)) == 0) return -EFAULT;
+ uintptr_t flags = spin_lock_irqsave(&tty_lock);
+ int avail = (int)((canon_head - canon_tail) & (TTY_CANON_BUF - 1));
+ spin_unlock_irqrestore(&tty_lock, flags);
+ if (copy_to_user(user_arg, &avail, sizeof(avail)) < 0) return -EFAULT;
+ return 0;
+ }
+
return -EINVAL;
}
--- /dev/null
+#ifndef ULIBC_LIBGEN_H
+#define ULIBC_LIBGEN_H
+
+char* basename(char* path);
+char* dirname(char* path);
+
+#endif
#define ULIBC_SYS_RESOURCE_H
#include <stdint.h>
+#include <sys/time.h>
#define RLIMIT_CPU 0
#define RLIMIT_FSIZE 1
int getrlimit(int resource, struct rlimit *rlim);
int setrlimit(int resource, const struct rlimit *rlim);
+#define RUSAGE_SELF 0
+#define RUSAGE_CHILDREN (-1)
+
+struct rusage {
+ struct timeval ru_utime;
+ struct timeval ru_stime;
+ long ru_maxrss;
+ long ru_ixrss;
+ long ru_idrss;
+ long ru_isrss;
+ long ru_minflt;
+ long ru_majflt;
+ long ru_nswap;
+ long ru_inblock;
+ long ru_oublock;
+ long ru_msgsnd;
+ long ru_msgrcv;
+ long ru_nsignals;
+ long ru_nvcsw;
+ long ru_nivcsw;
+};
+
+int getrusage(int who, struct rusage *usage);
+
#endif
SYS_GETPEERNAME = 134,
SYS_GETSOCKNAME = 135,
SYS_UNAME = 136,
+ SYS_GETRUSAGE = 137,
};
/* Raw syscall wrappers — up to 5 args via INT 0x80 */
--- /dev/null
+#include "libgen.h"
+#include "string.h"
+
+char* basename(char* path) {
+ if (!path || !*path) return ".";
+ size_t len = strlen(path);
+ /* Remove trailing slashes */
+ while (len > 1 && path[len - 1] == '/') path[--len] = '\0';
+ char* p = strrchr(path, '/');
+ return p ? p + 1 : path;
+}
+
+char* dirname(char* path) {
+ static char dot[] = ".";
+ if (!path || !*path) return dot;
+ size_t len = strlen(path);
+ /* Remove trailing slashes */
+ while (len > 1 && path[len - 1] == '/') path[--len] = '\0';
+ char* p = strrchr(path, '/');
+ if (!p) return dot;
+ if (p == path) { path[1] = '\0'; return path; }
+ *p = '\0';
+ return path;
+}
--- /dev/null
+#include "unistd.h"
+#include "string.h"
+#include "syscall.h"
+#include "errno.h"
+
+int gethostname(char* name, size_t len) {
+ if (!name || len == 0) { errno = EINVAL; return -1; }
+ const char* hostname = "adros";
+ size_t hlen = strlen(hostname);
+ if (hlen + 1 > len) { errno = ENAMETOOLONG; return -1; }
+ memcpy(name, hostname, hlen + 1);
+ return 0;
+}
+
+static char ttyname_buf[32];
+
+char* ttyname(int fd) {
+ if (!isatty(fd)) return (char*)0;
+ strcpy(ttyname_buf, "/dev/tty");
+ return ttyname_buf;
+}
+
+int pipe2(int fds[2], int flags) {
+ int r = _syscall2(SYS_PIPE2, (int)fds, flags);
+ return __syscall_ret(r);
+}
int setrlimit(int resource, const struct rlimit *rlim) {
return __syscall_ret(_syscall2(SYS_SETRLIMIT, resource, (int)rlim));
}
+
+int getrusage(int who, struct rusage *usage) {
+ return __syscall_ret(_syscall2(SYS_GETRUSAGE, who, (int)usage));
+}