aboutsummaryrefslogtreecommitdiffstats
path: root/nihil.posix/progname.ccm
blob: 127b972108d2195b9bb25c03d8c4252e5a906d20 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// This source code is released into the public domain.
module;

// progname: wrappers for getprogname and setprogname.
//
// setprogname() doesn't copy the provided name, which makes it awkward to provide
// dynamic values (e.g., std::string).  We solve this by making setprogname a guard
// object which resets the previous progname when it's destroyed.  This also happens
// to be useful in cases like nihil.cli where we want to temporarily set the progname.

#include <stdlib.h> // NOLINT

export module nihil.posix:progname;

import nihil.std;

namespace nihil {

// Get the current program name.  We could return std::string_view here, but since
// the current program name can change unexpectedly, we don't.
export [[nodiscard]] auto getprogname() -> std::optional<std::string>
{
	if (auto const *progname = ::getprogname(); progname != nullptr)
		return {progname};
	return {};
}

// Set the progname name to a new value for the lifetime of this object.
// Reset it to the previous value when the object is destroyed.
export struct setprogname final
{
	// Set the program name.
	explicit setprogname(std::string_view const progname)
		: m_progname(progname)
		, m_old_progname(::getprogname())
	{
		::setprogname(m_progname.data());
	}

	// Restore the old name on destruction.
	~setprogname()
	{
		if (m_old_progname != nullptr)
			::setprogname(m_old_progname);
	}

	// Restore the old program name immediately.
	auto release() -> void
	{
		if (m_old_progname != nullptr) {
			::setprogname(m_old_progname);
			m_old_progname = nullptr;
		}
	}

	// Not copyable.
	setprogname(setprogname const &) = delete;
	auto operator=(setprogname const &) -> setprogname & = delete;

	// Not movable.
	setprogname(setprogname &&) = delete;
	auto operator=(setprogname &&) -> setprogname & = delete;

private:
	std::string m_progname;
	char const *m_old_progname;
};
} // namespace nihil