It seams as if you imply that DOS is kind of an unixoide OS, which it isn't. While Microsoft's goal with MS-DOS 2.0 was to move it toward Unix like operations, for compatibility with Xenix, it never went all the way. Not in internal workings nor API or shell. MS-DOS is a single user, single program OS - with a few 'handmade' exceptions like TSR.
For instance the pipe() command from unistd.h isn't present in BorlandC, which I'm using.
UNISTD is a POSIX definition. DOS isn't a POSIX system. POSIX definitions where made years after DOS got unix alike features.
DOS only implements STDIN/OUT/ERR. They are made as simple file handles (0,1,2) to be read from/writen to and inherited from the parent program.
Can anyone tell me how to to this? Preferably in C or Batch.
Just use redirection one the command line in the usual way via </|/>
Also, how to pipe stdin/out from the current shell (command.com or 4dos.com) in order to "Skin" the console?
You might get a hard time, as DOS can only run a single program at a time. Without two concurrent processes it's just not possible to transfer data between them without having the first terminated before the second is started.
DOS's redirection is more like chaining.
Workings of Redirection in DOS
DOS implements pipeing (redirection to a program) as an application of redirection to files.
When pipeing is used, all output of the first program to STDOUT gets written into a temporary file until the program terminates. Then the next program gets started (after the first is unloaded) and the file written is assigned to STDIN. Then the program terminates, the (input) File gets deleted.
In other words a command line like
TREE C:\ /F | FIND /I ".COM" | SORT
to display all .COM files with their path on drive C works in sequential steps like this:
TREE C:\ /F >tempfile1
FIND /I ".COM" <tempfile1 >tempfile2
From a user perspective the result is the same, but inner workings are complete different (*1).
So unless you spread your programs across multiple DOS machines, you can't come close to Unix behaviour (*2).
I'm working on a retro project and was trying to create a pipe of stdin/out/err in DOS, but I can't find any functions to to this?
See, that's the true lesson of retrocomputing: these old machines and OSes were not the same as today, just in small, slow and with blocky graphics, they where different. And not just between today and back then, but as well between different manufactures and even machines. Backporting ideas isn't about finding the same function, but to work from a complete different angle.
Discovering unknown space with different laws of physic :))
Now, having said all of this and taking the assumption of adding bells and whistles to STDOUT), a clean way to do this would be writing a character driver and assign them as STDIN/OUT when starting command.com. If the driver is (for example) named skinner.dev and the resulting device would be SKINNER, then config.sys needs to contain these two lines (*3):
And from there on, all output to STDOUT is delivered thru your driver - unless redirected that is. Now you may add any kind of framing skins or whatsoever. Keep in mind that the application might not be aware of and for example still assume a 24x80 screen, even if you took some characters off for a beautiful frame. Similar any output bypassing STDOUT, like when using BIOS calls or direkt screen manipulation, may show up at the wrong place (*4). Last but not least, every program opening CON on its own will as well bypass your driver.
A few points to think about may be:
Don't forget to make the driver as well handling read requests, as Command.Com requires both ways to go thru the same device.
You may as well try to replace the build-in CON driver(*5), this means setting the CON bit in the device attributes word as well as replacing/capturing INT 29h, as DOS does handle CON a bit different. (*6)
Adding I/O-Control support would support a clean interface to set the workings during runtime (changing colours or whatsoever it does) with a configuration command supplied by you.
Do your users a favour and use Assembly - at least for the driver.
Device drivers can be a lot of fun and are usually way less complicated to write then people tend to assume.
Caveat: Some mechanics only work with DOS 3.1 and higher even though already defined before. This goes especially for monitoring open/close calls.
*1 - Now, when devices are used as targets of a redirection, access is immediate and concurrent. Just they can only be source or destination.
*2 - And even then you may need some file server allowing read while write and plunge in a zillion FLUSH calls to make each output seen.
*3 - For test purpose it may be more appropriate to only load the driver and use redirected STDIN/OUT only via a sub-shell.
*4 - Some of this may be captured by the driver due manipulation of BIOS data and alike - but that will as well lead to a slow creep into machine and OS dependence while at the same time bloating code ever more.
*5 - This would remove some of the possible ways to screw up things for child processes in complex scenarios involving sub-shells as well as redirections with the explicit use of CON. On the down side, you'd have to rewrite all of it's functionality - hopefully compatible with ANSI.SYS which already is one.
*6 - Which BTW would be the better way (when going this route) - get the source for some ANSI.SYS compatible driver like NANSI.SYS and tweek it to support your additional functionality - more work than writing your own, but for sure a great drop in by naming it ANSI.SYS and copying it onto any machine available - not other change needed.