feat: add streq and printErr

This commit is contained in:
dualfroz committed 2026-09-08 23:22:55 +02:00
1 parent 6184cf43be
commit b4acf5d4d2
4 files changed
+203

No files matched your search

+56
View File
@@ -0,0 +1,56 @@
#include "ulib.h"
/*
* Drives the shared-pipe demo added this wave (pipeCreateDetached/
* pipeAddReader/pipeAddWriter, pipe.h; vfsPipeCreateHandle/vfsPipeAttach,
* vfs.h; sysRead/sysWrite's retry-the-syscall path, syscall.c): creates one
* detached pipe handle and hands it to two INDEPENDENTLY spawned processes
* as a decimal argv string (decToString/parseDec, ulib.c) rather than a
* shared fd -- frostbyte has no fork(), so a raw pipe.h handle number is
* the only thing two unrelated processes can rendezvous on. fifowriter.c
* deliberately sleeps before writing, so fiforeader.c's read() genuinely
* has to block across several timer ticks and be woken later, not just win
* a scheduling race against an already-full buffer -- see fifowriter.c/
* fiforeader.c for how each end proves that on its own side.
*/
int main(void)
{
print("fifomaster: start, pid=");
printDec(userGetpid());
print("\n");
long handle = userPipeCreate();
if (handle < 0) {
print("fifomaster: FAIL pipe create\n");
return 1;
}
char handleStr[24];
decToString(handle, handleStr);
char* readerArgv[] = { "/bin/fiforeader", handleStr, 0 };
long readerPid = userSpawn("/bin/fiforeader", readerArgv);
if (readerPid < 0) {
print("fifomaster: FAIL spawn fiforeader\n");
return 1;
}
char* writerArgv[] = { "/bin/fifowriter", handleStr, 0 };
long writerPid = userSpawn("/bin/fifowriter", writerArgv);
if (writerPid < 0) {
print("fifomaster: FAIL spawn fifowriter\n");
return 1;
}
long readerStatus = userWait(readerPid);
long writerStatus = userWait(writerPid);
if (readerStatus != 0 || writerStatus != 0) {
print("fifomaster: FAIL reader or writer reported failure\n");
return 1;
}
print("fifomaster: pipeshare ok\n");
return 0;
}
+53
View File
@@ -0,0 +1,53 @@
#include "ulib.h"
/*
* Only ever spawned by fifomaster.c, with the shared pipe's handle number
* as argv[1]. Attaches its end and immediately calls a blocking read() on
* a pipe fifowriter.c (spawned alongside it, sleeping before it writes)
* has not put anything into yet -- this call must genuinely park (the
* syscall-restart path in syscall.c's sysRead, parked on pipeChannel) and
* only return once fifowriter.c's write wakes it back up, not before.
*/
static int streq(const char* a, const char* b)
{
while (*a && *a == *b) {
a++;
b++;
}
return *a == *b;
}
int main(int argc, char** argv)
{
if (argc != 2) {
print("fiforeader: FAIL expected one argv (pipe handle)\n");
return 1;
}
long handle = parseDec(argv[1]);
long fd = userPipeAttach(handle, 0);
if (fd < 0) {
print("fiforeader: FAIL attach\n");
return 1;
}
print("fiforeader: attached, blocking on read\n");
char buffer[64];
long got = userRead((int)fd, buffer, sizeof(buffer) - 1);
if (got <= 0) {
print("fiforeader: FAIL read\n");
return 1;
}
buffer[got] = 0;
print("fiforeader: got: ");
print(buffer);
print("\n");
int ok = streq(buffer, "shared pipe payload");
print(ok ? "fiforeader: payload-ok\n" : "fiforeader: payload-FAIL\n");
userClose((int)fd);
return ok ? 0 : 1;
}
+43
View File
@@ -0,0 +1,43 @@
#include "ulib.h"
/*
* Only ever spawned by fifomaster.c, with the shared pipe's handle number
* as argv[1] (decToString'd -- see fifomaster.c). Sleeps well past when
* fiforeader.c (spawned moments earlier) will already be parked in a
* blocking read() on the still-empty pipe, so the write below has to
* actually wake it back up (schedWakeChannel, pipeWrite in pipe.c) instead
* of the reader simply finding data already waiting for it -- proof that
* the block was real, not a lucky race.
*/
#define fifoWriterDelayMs 200
static const char* payload = "shared pipe payload";
int main(int argc, char** argv)
{
if (argc != 2) {
print("fifowriter: FAIL expected one argv (pipe handle)\n");
return 1;
}
long handle = parseDec(argv[1]);
long fd = userPipeAttach(handle, 1);
if (fd < 0) {
print("fifowriter: FAIL attach\n");
return 1;
}
print("fifowriter: attached, sleeping before write\n");
userSleep(fifoWriterDelayMs);
long written = userWrite((int)fd, payload, stringLength(payload));
if (written != (long)stringLength(payload)) {
print("fifowriter: FAIL short/failed write\n");
return 1;
}
print("fifowriter: wrote payload\n");
userClose((int)fd);
return 0;
}
+51
View File
@@ -0,0 +1,51 @@
#include "ulib.h"
/*
* Live proof that shell.c's new wildcard glob expansion (shellExpandGlobs)
* really hands a spawned process REAL, distinct filenames resolved from a
* pattern typed at the shell (`globcat /tmp/gd/ *.txt`) -- not a literal,
* unexpanded "*.txt" string, and not every file in the directory (the
* sibling /tmp/gd/c.log the driver thread also creates must NOT appear).
* Prints how many files it actually received, then each one's own path and
* content, all on fd 1 (unlike pipecat.c/hcat.c, this program's own argv
* and stdout ARE the thing being demonstrated, not a pipe payload it must
* keep pristine).
*/
static void printErr(const char* text)
{
userWrite(2, text, stringLength(text));
}
int main(int argc, char** argv)
{
print("globcat: got ");
printDec(argc - 1);
print(" files\n");
for (int i = 1; i < argc; i++) {
long fd = userOpen(argv[i], oReadOnly);
if (fd < 0) {
printErr("globcat: FAIL cannot open ");
printErr(argv[i]);
printErr("\n");
return 1;
}
char buffer[64];
long got = userRead((int)fd, buffer, sizeof(buffer) - 1);
userClose((int)fd);
if (got < 0) {
printErr("globcat: FAIL read\n");
return 1;
}
buffer[got] = 0;
print("globcat: ");
print(argv[i]);
print("=");
print(buffer);
}
return 0;
}