}
if (new_fd < 0) return -EMFILE;
current_process->files[new_fd] = f;
- f->refcount++;
+ __sync_fetch_and_add(&f->refcount, 1);
current_process->fd_flags[new_fd] = FD_CLOEXEC;
return new_fd;
}
uint32_t* uaddr = (uint32_t*)sc_arg0(regs);
int op = (int)sc_arg1(regs);
uint32_t val = sc_arg2(regs);
-
+
if (!uaddr) { sc_ret(regs) = (uint32_t)-EFAULT; return; }
-
+
if (op == FUTEX_WAIT) {
uint32_t cur = 0;
if (copy_from_user(&cur, uaddr, sizeof(cur)) < 0) {
futex_waiters[slot].addr = (uintptr_t)uaddr;
futex_waiters[slot].proc = current_process;
extern void schedule(void);
+
+ /* Compute timeout: arg3 is a userspace timespec* or NULL */
+ uint32_t timeout_ticks = 5000; /* default ~100s */
+ const struct k_timeval* user_ts = (const struct k_timeval*)(uintptr_t)sc_arg3(regs);
+ if (user_ts && user_range_ok(user_ts, sizeof(struct k_timeval))) {
+ struct k_timeval kts;
+ if (copy_from_user(&kts, user_ts, sizeof(kts)) == 0) {
+ if (kts.tv_sec == 0 && kts.tv_usec == 0) {
+ /* timeout==0 means no wait (poll) */
+ futex_waiters[slot].proc = NULL;
+ futex_waiters[slot].addr = 0;
+ sc_ret(regs) = (uint32_t)-ETIMEDOUT;
+ return;
+ }
+ timeout_ticks = timeval_to_ticks(&kts);
+ }
+ }
+
current_process->state = PROCESS_SLEEPING;
- current_process->wake_at_tick = get_tick_count() + 5000; /* 100s timeout */
+ current_process->wake_at_tick = get_tick_count() + timeout_ticks;
schedule();
futex_waiters[slot].proc = NULL;
futex_waiters[slot].addr = 0;
if (current_process) {
current_process->state = PROCESS_ZOMBIE;
current_process->exit_status = 128;
+ schedule();
}
- for (;;) { hal_cpu_disable_interrupts(); schedule(); hal_cpu_idle(); }
+ return NULL;
}
/* Split down to the required order */
if (current_process) {
current_process->state = PROCESS_ZOMBIE;
current_process->exit_status = 128;
+ schedule();
}
- for (;;) { hal_cpu_disable_interrupts(); schedule(); hal_cpu_idle(); }
+ return;
}
if (blk->is_free) {
if (current_process) {
current_process->state = PROCESS_ZOMBIE;
current_process->exit_status = 128;
+ schedule();
}
- for (;;) { hal_cpu_disable_interrupts(); schedule(); hal_cpu_idle(); }
+ return;
}
blk->is_free = 1;
#include <unistd.h>
#include <fcntl.h>
-static int parse_size(const char* s) {
- int v = atoi(s);
+static long parse_size(const char* s) {
+ long v = strtol(s, NULL, 10);
int len = (int)strlen(s);
if (len > 0) {
char suf = s[len - 1];
- if (suf == 'k' || suf == 'K') v *= 1024;
- else if (suf == 'm' || suf == 'M') v *= 1024 * 1024;
+ if (suf == 'k' || suf == 'K') v *= 1024L;
+ else if (suf == 'm' || suf == 'M') v *= 1024L * 1024L;
}
return v;
}
int main(int argc, char** argv) {
const char* inf = NULL;
const char* outf = NULL;
- int bs = 512;
+ long bs = 512;
int count = -1;
int skip = 0;
int seek_val = 0;
act.sa_mask = 0;
act.sa_flags = 0;
- struct sigaction oldact;
+ struct sigaction oldact = {{0}};
struct sigaction* oldp = old_out ? &oldact : 0;
int r = sys_sigaction2(sig, &act, oldp);
static int sys_futex(uint32_t* uaddr, int op, uint32_t val) {
int ret;
- __asm__ volatile("int $0x80" : "=a"(ret) : "a"(SYSCALL_FUTEX), "b"(uaddr), "c"(op), "d"(val) : "memory");
+ __asm__ volatile("int $0x80" : "=a"(ret) : "a"(SYSCALL_FUTEX), "b"(uaddr), "c"(op), "d"(val), "S"(0) : "memory");
return __syscall_fix(ret);
}
int main(int argc, char** argv) {
int i = 1;
+ const char* e_pattern = NULL;
while (i < argc && argv[i][0] == '-' && argv[i][1]) {
if (strcmp(argv[i], "--") == 0) { i++; break; }
for (int j = 1; argv[i][j]; j++) {
else if (argv[i][j] == 'r') recursive = 1;
else if (argv[i][j] == 'E') use_regex = 2;
else if (argv[i][j] == 'F') use_regex = 0;
- else if (argv[i][j] == 'e' && j == 1) {
- /* -e PATTERN */
- if (argv[i][j+1]) { /* pattern follows in same arg */ }
- /* handled below */
+ else if (argv[i][j] == 'e') {
+ if (argv[i][j+1]) {
+ e_pattern = &argv[i][j+1];
+ } else {
+ i++;
+ if (i >= argc) { fprintf(stderr, "grep: -e requires an argument\n"); return 2; }
+ e_pattern = argv[i];
+ }
+ break; /* rest of this arg is the pattern */
}
else {
fprintf(stderr, "grep: invalid option -- '%c'\n", argv[i][j]);
}
i++;
}
- if (i >= argc) { fprintf(stderr, "usage: grep [-vcnlqiErF] PATTERN [FILE...]\n"); return 2; }
- const char* pattern = argv[i++];
+ const char* pattern = e_pattern;
+ if (!pattern) {
+ if (i >= argc) { fprintf(stderr, "usage: grep [-vcnlqiErF] PATTERN [FILE...]\n"); return 2; }
+ pattern = argv[i++];
+ }
/* Compile regex or set fixed pattern */
if (use_regex == 0) {
buf[total] = '\0';
close(fd);
+ if (total >= (int)sizeof(buf) - 1) {
+ write(2, "init: warning: /etc/inittab truncated\n", 38);
+ }
+
char* p = buf;
while (*p && nentries < MAX_ENTRIES) {
/* Skip whitespace and comments */
/* Parse first address */
if (*p && *p != 's' && *p != 'd' && *p != 'p' && *p != 'q' &&
*p != 'a' && *p != 'i' && *p != 'c' && *p != 'y') {
- if (parse_addr(&p, &c->addr1) < 0) return -1;
+ if (parse_addr(&p, &c->addr1) < 0) {
+ if (c->addr1.has_re) regfree(&c->addr1.re);
+ return -1;
+ }
while (*p == ' ' || *p == '\t') p++;
if (*p == ',') {
p++;
while (*p == ' ' || *p == '\t') p++;
- if (parse_addr(&p, &c->addr2) < 0) return -1;
+ if (parse_addr(&p, &c->addr2) < 0) {
+ if (c->addr1.has_re) regfree(&c->addr1.re);
+ if (c->addr2.has_re) regfree(&c->addr2.re);
+ return -1;
+ }
c->has_addr2 = 1;
while (*p == ' ' || *p == '\t') p++;
}
int pi = 0;
while (*p && *p != delim && pi < 255) c->s_pat[pi++] = *p++;
c->s_pat[pi] = '\0';
- if (*p != delim) return -1;
+ if (*p != delim) { if (c->addr1.has_re) regfree(&c->addr1.re); if (c->addr2.has_re) regfree(&c->addr2.re); return -1; }
p++;
int ri = 0;
while (*p && *p != delim && ri < 255) c->s_rep[ri++] = *p++;
c->s_rep[ri] = '\0';
if (*p == delim) { p++; if (*p == 'g') c->s_global = 1; }
- if (regcomp(&c->s_re, c->s_pat, 0) != 0) return -1;
+ if (regcomp(&c->s_re, c->s_pat, 0) != 0) { if (c->addr1.has_re) regfree(&c->addr1.re); if (c->addr2.has_re) regfree(&c->addr2.re); return -1; }
c->s_has_re = 1;
break;
}
#define ULIBC_LINUX_FUTEX_H
#include <stdint.h>
+#include <sys/time.h>
#define FUTEX_WAIT 0
#define FUTEX_WAKE 1
-int futex(uint32_t* uaddr, int op, uint32_t val);
+int futex(uint32_t* uaddr, int op, uint32_t val, const struct timeval* timeout);
#endif
#include "linux/futex.h"
#include "syscall.h"
+#include <sys/time.h>
-int futex(uint32_t* uaddr, int op, uint32_t val) {
- return _syscall3(SYS_FUTEX, (int)uaddr, op, (int)val);
+int futex(uint32_t* uaddr, int op, uint32_t val, const struct timeval* timeout) {
+ return _syscall4(SYS_FUTEX, (int)uaddr, op, (int)val, (int)(uintptr_t)timeout);
}
#define FUTEX_WAKE 1
static int futex_wait(volatile int* addr, int val) {
- return _syscall3(SYS_FUTEX, (int)addr, FUTEX_WAIT, val);
+ return _syscall4(SYS_FUTEX, (int)addr, FUTEX_WAIT, val, 0);
}
static int futex_wake(volatile int* addr, int count) {
- return _syscall3(SYS_FUTEX, (int)addr, FUTEX_WAKE, count);
+ return _syscall4(SYS_FUTEX, (int)addr, FUTEX_WAKE, count, 0);
}
static int atomic_cas(volatile int* ptr, int old, int new_val) {
}
int vfprintf(FILE* fp, const char* fmt, va_list ap) {
- char buf[1024];
+ char buf[4096];
int n = vsnprintf(buf, sizeof(buf), fmt, ap);
if (n > 0) {
int w = n;
- if (w > (int)(sizeof(buf) - 1)) w = (int)(sizeof(buf) - 1);
- fwrite(buf, 1, (size_t)w, fp);
+ if (w > (int)(sizeof(buf) - 1)) {
+ /* Output was truncated — write the full buffer and report total */
+ fwrite(buf, 1, sizeof(buf) - 1, fp);
+ } else {
+ fwrite(buf, 1, (size_t)w, fp);
+ }
}
return n;
}
/* Coalesce with previous block if adjacent */
struct block_hdr* p_prev = free_list;
if (p_prev != b) {
- while (p_prev && (struct block_hdr*)(uintptr_t)p_prev->next_free != b)
+ int iters = 0;
+ while (p_prev && (struct block_hdr*)(uintptr_t)p_prev->next_free != b) {
p_prev = (struct block_hdr*)(uintptr_t)p_prev->next_free;
+ if (++iters > 1024 || (uintptr_t)p_prev < 0x1000U) { p_prev = NULL; break; }
+ }
if (p_prev && (char*)p_prev + blk_size(p_prev) == (char*)b) {
p_prev->size += blk_size(b);
p_prev->next_free = b->next_free;