Files
frostbyte/user/pipecat.c
T

57 lines
2.0 KiB
C

#include "ulib.h"
/*
* Middle stage of shell.c's new N-stage pipeline live demo
* (`pipesrc | pipecat | pipesink`) -- the first process in this kernel with
* BOTH ends of two DIFFERENT real inter-process pipes baked into its fds at
* once (fd 0 from jobctlSpawnPiped's stdinHandle, fd 1 from its
* stdoutHandle). user/hcat.c already proved a piped stdout alongside a
* piped stdin, but that stdin was always a shell-fed here-string
* (jobctlSpawnPipedHereString), never a second real process-to-process
* pipe the way this one's is -- this program is the actual proof that
* shell.c's runPipelineStages can wire a genuine middle pipeline stage
* where NEITHER end is the console. From this program's own point of view
* there is nothing special about either fd: it is simply "cat" -- read
* stdin to real EOF, then write exactly those bytes to stdout -- with no
* idea either end is a pipe rather than a real file or console, the same
* shape as hcat.c's/pipesink.c's own read loops.
*
* Diagnostics go to fd 2 (never fd 1), same reason as every other filter in
* this pipeline family: fd 1 here is the real payload pipesink.c compares
* byte-for-byte, and print()/printDec() (ulib.h) are both hardcoded to fd 1.
*/
static void printErr(const char* text)
{
userWrite(2, text, stringLength(text));
}
int main(void)
{
printErr("pipecat: reading piped stdin\n");
char buffer[64];
unsigned long total = 0;
for (;;) {
long got = userRead(0, buffer + total, sizeof(buffer) - 1 - total);
if (got < 0) {
printErr("pipecat: FAIL read\n");
return 1;
}
if (got == 0)
break;
total += (unsigned long)got;
if (total >= sizeof(buffer) - 1)
break;
}
long written = userWrite(1, buffer, total);
if (written != (long)total) {
printErr("pipecat: FAIL short/failed write\n");
return 1;
}
printErr("pipecat: forwarded payload\n");
return 0;
}