feat: add streq and printErr
This commit is contained in:
1 parent
6184cf43be
commit
b4acf5d4d2
4 files changed
+203
No files matched your search
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
Reference in new issue
Block a user