feat: implement streq and printErr
This commit is contained in:
1 parent
f9973a7fe8
commit
1818463484
2 files changed
+100
No files matched your search
@@ -0,0 +1,57 @@
|
|||||||
|
#include "ulib.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Companion to redirwriter.c -- reads fd 0 (redirected by the shell to a
|
||||||
|
* REAL file via `<`, jobctlApplyRedirects) in a loop until a real EOF (a
|
||||||
|
* regular file's own vfsRead already returns 0 the instant the offset
|
||||||
|
* reaches its size -- no writer-count bookkeeping needed the way
|
||||||
|
* pipesink.c's pipe-backed EOF does, since a file's "end" is just its
|
||||||
|
* length, not "every writer has gone away"), then compares byte-for-byte
|
||||||
|
* against two back-to-back copies of redirwriter.c's own payload -- proof
|
||||||
|
* that `>` (create/truncate) followed by `>>` (append) on the SAME path
|
||||||
|
* produced exactly that file, not a truncated/duplicated/reordered one.
|
||||||
|
*
|
||||||
|
* Unlike pipesink.c, this process's own fd 1 (stdout) is NOT redirected --
|
||||||
|
* print()/printDec() (ulib.h) reach the real console exactly like any
|
||||||
|
* unredirected demo, so the needle below is exactly as observable to
|
||||||
|
* ci-test.sh as every other one.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int streq(const char* a, const char* b)
|
||||||
|
{
|
||||||
|
while (*a && *a == *b) {
|
||||||
|
a++;
|
||||||
|
b++;
|
||||||
|
}
|
||||||
|
return *a == *b;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
print("redirreader: reading redirected stdin\n");
|
||||||
|
|
||||||
|
char buffer[80];
|
||||||
|
unsigned long total = 0;
|
||||||
|
for (;;) {
|
||||||
|
long got = userRead(0, buffer + total, sizeof(buffer) - 1 - total);
|
||||||
|
if (got < 0) {
|
||||||
|
print("redirreader: FAIL read\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (got == 0)
|
||||||
|
break;
|
||||||
|
total += (unsigned long)got;
|
||||||
|
if (total >= sizeof(buffer) - 1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
buffer[total] = 0;
|
||||||
|
|
||||||
|
print("redirreader: got: ");
|
||||||
|
print(buffer);
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
int ok = streq(buffer, "redirect-payload-okredirect-payload-ok");
|
||||||
|
print(ok ? "redirreader: payload-ok\n" : "redirreader: payload-FAIL\n");
|
||||||
|
|
||||||
|
return ok ? 0 : 1;
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
#include "ulib.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Live ring-3 proof for shell.c's new `cmd > file` / `cmd >> file` file
|
||||||
|
* redirection (jobctlApplyRedirects/jobctlSpawnForegroundRedirected,
|
||||||
|
* jobctl.h): from this program's own point of view it just writes its
|
||||||
|
* stdout exactly like pipesrc.c already does for the pipe case -- it has
|
||||||
|
* no idea whether fd 1 is the real console, a pipe, or (here) a real file
|
||||||
|
* on tmpfs, the same "redirection is invisible to the child" property a
|
||||||
|
* real shell's dup2()-before-exec gives every Unix program. fd 2 is
|
||||||
|
* deliberately left alone (only fd 0/fd 1 are ever redirected, matching
|
||||||
|
* jobctlSpawnPiped's own pipeline convention), so the diagnostic line
|
||||||
|
* below reaches the real console even while fd 1's own payload goes to
|
||||||
|
* the file instead -- writing it through fd 1 would corrupt the exact
|
||||||
|
* bytes redirreader.c later compares.
|
||||||
|
*
|
||||||
|
* kmain.c's redirDriverThread runs this program TWICE against the same
|
||||||
|
* path -- once through `>` (truncate/create) and once through `>>`
|
||||||
|
* (append) -- so the resulting file holds two back-to-back copies of this
|
||||||
|
* same payload with no separator, proving `>>` genuinely continues from
|
||||||
|
* the end of what `>` already wrote rather than overwriting it.
|
||||||
|
*/
|
||||||
|
#define redirectPayload "redirect-payload-ok"
|
||||||
|
|
||||||
|
static void printErr(const char* text)
|
||||||
|
{
|
||||||
|
userWrite(2, text, stringLength(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
printErr("redirwriter: writing payload to stdout (redirected)\n");
|
||||||
|
|
||||||
|
unsigned long length = stringLength(redirectPayload);
|
||||||
|
long written = userWrite(1, redirectPayload, length);
|
||||||
|
if (written != (long)length) {
|
||||||
|
printErr("redirwriter: FAIL short/failed write\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printErr("redirwriter: wrote payload\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in new issue
Block a user