summaryrefslogtreecommitdiff
path: root/indra/llcommon/lltempredirect.h
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon/lltempredirect.h')
-rw-r--r--indra/llcommon/lltempredirect.h91
1 files changed, 91 insertions, 0 deletions
diff --git a/indra/llcommon/lltempredirect.h b/indra/llcommon/lltempredirect.h
new file mode 100644
index 0000000000..33e05dc06b
--- /dev/null
+++ b/indra/llcommon/lltempredirect.h
@@ -0,0 +1,91 @@
+/**
+ * @file lltempredirect.h
+ * @author Nat Goodspeed
+ * @date 2019-10-31
+ * @brief RAII low-level file-descriptor redirection
+ *
+ * $LicenseInfo:firstyear=2019&license=viewerlgpl$
+ * Copyright (c) 2019, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLTEMPREDIRECT_H)
+#define LL_LLTEMPREDIRECT_H
+
+// Functions in this namespace are intended to insulate the caller from the
+// aggravating distinction between ::close() and Microsoft _close().
+namespace llfd
+{
+
+int close(int fd);
+int dup(int target);
+int dup2(int target, int reference);
+FILE* open(int fd, const char* mode);
+int fileno(FILE* stream);
+
+} // namespace llfd
+
+/**
+ * LLTempRedirect is an RAII class that performs file redirection on low-level
+ * file descriptors, expressed as ints. (Use llfd::fileno() to obtain the file
+ * descriptor from a classic-C FILE*. There is no portable way to obtain the
+ * file descriptor from a std::fstream.)
+ *
+ * Instantiate LLTempRedirect with a target file descriptor (e.g. for some
+ * open file) and a reference file descriptor (e.g. for stderr). From that
+ * point until the LLTempRedirect instance is destroyed, all OS-level writes
+ * to the reference file descriptor will be redirected to the target file.
+ *
+ * Because dup2() is used for redirection, the original passed target file
+ * descriptor remains open. If you want LLTempRedirect's destructor to close
+ * the target file, close() the target file descriptor after passing it to
+ * LLTempRedirect's constructor.
+ *
+ * LLTempRedirect's constructor saves the original target of the reference
+ * file descriptor. Its destructor restores the reference file descriptor to
+ * point once again to its original target.
+ */
+class LLTempRedirect
+{
+public:
+ LLTempRedirect();
+ /**
+ * For the lifespan of this LLTempRedirect instance, all writes to
+ * 'reference' will be redirected to 'target'. When this LLTempRedirect is
+ * destroyed, the original target for 'reference' will be restored.
+ *
+ * Pass 'target' as NULL if you simply want to save and restore
+ * 'reference' against possible redirection in the meantime.
+ */
+ LLTempRedirect(FILE* target, FILE* reference);
+ /**
+ * For the lifespan of this LLTempRedirect instance, all writes to
+ * 'reference' will be redirected to 'target'. When this LLTempRedirect is
+ * destroyed, the original target for 'reference' will be restored.
+ *
+ * Pass 'target' as -1 if you simply want to save and restore
+ * 'reference' against possible redirection in the meantime.
+ */
+ LLTempRedirect(int target, int reference);
+ LLTempRedirect(const LLTempRedirect&) = delete;
+ LLTempRedirect(LLTempRedirect&& other);
+
+ ~LLTempRedirect();
+
+ LLTempRedirect& operator=(const LLTempRedirect&) = delete;
+ LLTempRedirect& operator=(LLTempRedirect&& other);
+
+ /// returns (duplicate file descriptor for) the original target of the
+ /// 'reference' file descriptor passed to our constructor
+ int getOriginalTarget() const { return mOrigTarget; }
+ /// returns the original 'reference' file descriptor passed to our
+ /// constructor
+ int getReference() const { return mReference; }
+
+private:
+ void reset();
+
+ int mOrigTarget, mReference;
+};
+
+#endif /* ! defined(LL_LLTEMPREDIRECT_H) */