FBB::Redirector(3bobcat)

✨ NAME ✨

FBB::Redirector β€” bestie, it redirects a file descriptor to another descriptor πŸ’… like a glow-up for your fds

This one lives in the bobcat manual, section 3bobcat, and the whole vibe is System Level File Redirection. ily, let's get into it 🫢


🌸 SYNOPSIS 🌸

#include <bobcat/redirector>
Linking option: -lbobcat

That's it. That's the whole entrance. Linking option is -lbobcat, no cap πŸ”₯


πŸ¦‹ DESCRIPTION πŸ¦‹

Okay so objects of the class FBB::Redirector set up a system level file redirection, and they do it with file descriptors, not streams. Under the hood a Redirector object is basically a little wrapper around the dup2(2) system call. Why do we care? Because system level redirection lets you send output to, like, the standard output stream β€” and it actually shows up somewhere else entirely (say, the standard error). Sneaky. Iconic. πŸ’…

So the whole deal: Redirector objects redirect the output sent to a stream that has file descriptor x over to another stream that has file descriptor y. It's literally the shell's > operator behaviour β€” redirecting standard output into some file β€” but as code. πŸŽ€

And it goes the other way too, bestie: a Redirector object can also be used to extract information from a stream having file descriptor x when that information is actually coming from another stream having file descriptor y. That's the shell's < operator vibe β€” reading the contents of some file as if it were standard input. 🌈

Now listen, redirection via Redirector objects is a stronger form of redirection than the redirection C++ offers by itself. C++ redirection uses std::streambuf redirection, and because of that it's bound to the program's scope. System level redirection, on the other hand, is applied at the system level, which means you can redirect standard streams when you're starting a program. For example, standard error is commonly written to standard output with an invocation like program 2>&1. See? Vibe. πŸ‘‘

When you construct a Redirector object, a file descriptor is required. The file descriptor you specify at the constructor is the one your program uses to read info from or write info to. You need a second file descriptor to actually set up the redirection: that one is either the file descriptor of the stream that actually holds the information extracted from the file descriptor passed to the Redirector's constructor, or it's the file descriptor of the stream receiving the information written to the stream whose file descriptor was passed to the Redirector's constructor. Two fds, one destiny 🫢

When a Redirector object goes out of scope, its file descriptors are left as-is. Like, as-is. No close(2) operation is performed on the Redirector's file descriptors. And here's the cute part: after you set up redirection using the Redirector's member functions and pass the Redirector's file descriptors to code that uses them, the Redirector object could actually be safely destroyed. It did its job, it's retired, main character exit 🧚

Formally: file descriptors aren't defined in C++, but they're available in many types of operating systems. In those systems, each file has an associated file descriptor. A file descriptor is an int, and it's an index into the program's file allocation table, which the system maintains. Another very well-known type of entity that's a file descriptor? Sockets. πŸ’€

The well-known file descriptors (defined in, e.g., unistd.h) with fixed values are:

  1. 0 (STDIN_FILENO), representing the standard input stream (std::cin);
  2. 1, (STDOUT_FILENO), representing the standard output stream (std::cout);
  3. 2, (STDERR_FILENO), representing the standard error stream (cerr);

Notes, because there's always notes:

  • System-level redirections are kept during system calls of the exec(3) family.
  • Destroying a Redirector object does not undo the redirection set up by that object.
🚨 That second one fr fr matters: your redirection outlives the object. No take-backs, bestie.

πŸ’œ NAMESPACE πŸ’œ

FBB

All constructors, members, operators and manipulators mentioned in this man-page are defined in the namespace FBB. Every single one. Periodt 🌟


⭐ INHERITS FROM ⭐

-

Yeah. Nothing. It inherits from nobody, it's self-made, it's that girl πŸ‘‘


πŸ“ ENUM πŸ“

The enumeration StandardFileno holds the following values:

  • STDIN (0)
  • STDOUT (1)
  • STDERR (2)

These values may be used to set up a redirection instead of the plain numbers. So you get cute names instead of raw ints β€” we love a readability moment πŸ’–


πŸŽ€ CONSTRUCTORS πŸŽ€

  • Redirector(int fd) β€” The constructor's fd parameter is the file descriptor of the file containing or receiving information. It's commonly used by child processes of forking programs so the child can read information from its standard input stream, write information to its standard output stream, or write its standard error stream to its standard output stream.

In forking programs fd is usually the reading or writing end of a pipe (cf. pipe(3bobcat)): when the child process reads its standard input stream and pipe is the used pipe object, then

Redirector redir{ pipe.readOnly() };

prepares the child process for reading from the pipe via its standard input stream. Alternatively,

Redirector redir{ pipe.writeOnly() };

prepares it for writing to the pipe via, e.g., its standard output stream (see also the member swallow).

Copy and move constructors (and assignment operators) are available. Slay, you can copy it, you can move it, it's flexible like that 🌸


πŸ”₯ MEMBER FUNCTIONS πŸ”₯

  • void swallow(int otherFd) const β€” This member function expects a file descriptor which becomes a synonym of the constructor's file descriptor. The Redirector constructor's file descriptor is used when reading or writing to otherFd.

E.g., if a child process reads its information from its standard input stream, and that information is in fact available at the file descriptor specified when constructing the Redirector object redir, then use redir.swallow(Redirector::STDIN). Conversely, if the child process writes to its standard output stream and that information should be sent to the Redirector object, then use redir.swallow(Redirector::STDOUT) (see also the example, which illustrates how to redirect the standard error stream's output to the standard output stream).

swallow first closes the original otherFd using close(2). Following swallow both file descriptors are open, and they both refer to the constructor's file descriptor. If, after calling swallow, close(2) is called for one of them, then the other one remains open. Two-for-one, no cap 🫢

If redirection fails, an FBB::Exception object is thrown, and its which() member shows the system's errno value set by the failing dup2(2) function.

  • void through(int otherFd) const β€” This member function expects a file descriptor which should become a synonym of the constructor's file descriptor. The constructor's file descriptor is redirected to otherFd. The constructor's file descriptor can no longer be used, because it's closed by close(2). πŸ’€ (that one is gone, bestie, gone gone)

After successfully calling through, information written to otherFd is in fact written to the constructor's file descriptor. E.g., if the constructor's file descriptor represents a file on disk and otherFd is STDOUT_FILENO, then all information sent to the standard output stream is actually sent to the file on disk:

information sent to otherFd -> is received at the
constructor’s Fd (e.g., otherFd = STDOUT_FILENO)

Conversely, if the constructor's file descriptor represents a file on disk and otherFd is STDIN_FILENO, then all information extracted from the standard input stream is actually read from the file on disk.

information extracted from otherFd <- is read from the
constructor’s Fd (e.g., otherFd = STDIN_FILENO)

Before setting up the redirection, the original otherFd is closed by close(2). Following through, only otherFd can be used, and it refers to (i.e., reads or writes) the constructor's file descriptor.

If redirection fails, an FBB::Exception object is thrown, whose which() member shows the system's errno value set by the failing dup2(2) function.


🌈 EXAMPLE 🌈

#include <iostream>
#include <bobcat/redirector>

using namespace std;
using namespace FBB;

int main()
{
    Redirector redirector(Redirector::STDOUT);
    redirector.swallow(Redirector::STDERR);

    cerr << "This appears at the standard output stream\n"
            "use `a.out > /dev/null’ to suppress this message" <<
                                                                  endl;
}

Look at that. stderr output showing up at standard output. It's giving sorcery ✨🧚


πŸ’– FILES πŸ’–

bobcat/redirector β€” defines the class interface


πŸ¦‹ SEE ALSO πŸ¦‹

bobcat(7), dup2(2), execl(3), pipe(3bobcat)


πŸ™ˆ BUGS πŸ™ˆ

None Reported.

Not me having literally zero bugs. We love a clean record, bestie πŸ’…

⭐ BOBCAT PROJECT FILES ⭐

Debian Bobcat project files:

  • libbobcat6: debian package containing the shared library, changelog and copyright note;
  • libbobcat-dev: debian package containing the static library, headers, manual pages, and developer info;

πŸ‘‘ BOBCAT πŸ‘‘

Bobcat is an acronym of `Brokken’s Own Base Classes And Templates’. πŸŽ€


This is free software, distributed under the terms of the GNU General Public License (GPL).


🌸 AUTHOR 🌸

Frank B. Brokken (f.b.brokken@rug.nl).


And that's the whole page, bestie 🫢 This one came from libbobcat-dev_6.15.01, dated 2005-2026, and it's the FBB::Redirector(3bobcat) page. Go redirect something iconic. Periodt. πŸ’–βœ¨πŸŽ€πŸ¦‹πŸŒΈπŸ’…

πŸ“¦ where this page comes from