diff options
Diffstat (limited to 'third_party/nix/src/nix/main.cc')
-rw-r--r-- | third_party/nix/src/nix/main.cc | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/third_party/nix/src/nix/main.cc b/third_party/nix/src/nix/main.cc new file mode 100644 index 000000000000..08390fd24b9f --- /dev/null +++ b/third_party/nix/src/nix/main.cc @@ -0,0 +1,185 @@ +#include <algorithm> + +#include <glog/logging.h> +#include <ifaddrs.h> +#include <netdb.h> +#include <netinet/in.h> +#include <sys/socket.h> +#include <sys/types.h> + +#include "libexpr/eval.hh" +#include "libmain/common-args.hh" +#include "libmain/shared.hh" +#include "libstore/download.hh" +#include "libstore/globals.hh" +#include "libstore/store-api.hh" +#include "libutil/finally.hh" +#include "nix/command.hh" +#include "nix/legacy.hh" + +extern std::string chrootHelperName; + +void chrootHelper(int argc, char** argv); + +namespace nix { + +/* Check if we have a non-loopback/link-local network interface. */ +static bool haveInternet() { + struct ifaddrs* addrs; + + if (getifaddrs(&addrs) != 0) { + return true; + } + + Finally free([&]() { freeifaddrs(addrs); }); + + for (auto i = addrs; i != nullptr; i = i->ifa_next) { + if (i->ifa_addr == nullptr) { + continue; + } + if (i->ifa_addr->sa_family == AF_INET) { + if (ntohl( + (reinterpret_cast<sockaddr_in*>(i->ifa_addr))->sin_addr.s_addr) != + INADDR_LOOPBACK) { + return true; + } + } else if (i->ifa_addr->sa_family == AF_INET6) { + if (!IN6_IS_ADDR_LOOPBACK(&((sockaddr_in6*)i->ifa_addr)->sin6_addr) && + !IN6_IS_ADDR_LINKLOCAL(&((sockaddr_in6*)i->ifa_addr)->sin6_addr)) { + return true; + } + } + } + + return false; +} + +std::string programPath; + +struct NixArgs : virtual MultiCommand, virtual MixCommonArgs { + bool printBuildLogs = false; + bool useNet = true; + + NixArgs() : MultiCommand(*RegisterCommand::commands), MixCommonArgs("nix") { + mkFlag() + .longName("help") + .description("show usage information") + .handler([&]() { showHelpAndExit(); }); + + mkFlag() + .longName("help-config") + .description("show configuration options") + .handler([&]() { + std::cout << "The following configuration options are available:\n\n"; + Table2 tbl; + std::map<std::string, Config::SettingInfo> settings; + globalConfig.getSettings(settings); + for (const auto& s : settings) { + tbl.emplace_back(s.first, s.second.description); + } + printTable(std::cout, tbl); + throw Exit(); + }); + + mkFlag() + .longName("print-build-logs") + .shortName('L') + .description("print full build logs on stderr") + .set(&printBuildLogs, true); + + mkFlag() + .longName("version") + .description("show version information") + .handler([&]() { printVersion(programName); }); + + mkFlag() + .longName("no-net") + .description( + "disable substituters and consider all previously downloaded files " + "up-to-date") + .handler([&]() { useNet = false; }); + } + + void printFlags(std::ostream& out) override { + Args::printFlags(out); + std::cout << "\n" + "In addition, most configuration settings can be overriden " + "using '--<name> <value>'.\n" + "Boolean settings can be overriden using '--<name>' or " + "'--no-<name>'. See 'nix\n" + "--help-config' for a list of configuration settings.\n"; + } + + void showHelpAndExit() { + printHelp(programName, std::cout); + std::cout + << "\nNote: this program is EXPERIMENTAL and subject to change.\n"; + throw Exit(); + } +}; + +void mainWrapped(int argc, char** argv) { + /* The chroot helper needs to be run before any threads have been + started. */ + if (argc > 0 && argv[0] == chrootHelperName) { + chrootHelper(argc, argv); + return; + } + + initNix(); + + programPath = argv[0]; + std::string programName = baseNameOf(programPath); + + { + auto legacy = (*RegisterLegacyCommand::commands)[programName]; + if (legacy) { + return legacy(argc, argv); + } + } + + settings.verboseBuild = false; + + NixArgs args; + + args.parseCmdline(argvToStrings(argc, argv)); + + if (!args.command) { + args.showHelpAndExit(); + } + + if (args.useNet && !haveInternet()) { + LOG(WARNING) << "you don't have Internet access; " + << "disabling some network-dependent features"; + args.useNet = false; + } + + if (!args.useNet) { + // FIXME: should check for command line overrides only. + if (!settings.useSubstitutes.overriden) { + settings.useSubstitutes = false; + } + if (!settings.tarballTtl.overriden) { + settings.tarballTtl = std::numeric_limits<unsigned int>::max(); + } + if (!downloadSettings.tries.overriden) { + downloadSettings.tries = 0; + } + if (!downloadSettings.connectTimeout.overriden) { + downloadSettings.connectTimeout = 1; + } + } + + args.command->prepare(); + args.command->run(); +} + +} // namespace nix + +int main(int argc, char* argv[]) { + FLAGS_logtostderr = true; + google::InitGoogleLogging(argv[0]); + + return nix::handleExceptions(argv[0], + [&]() { nix::mainWrapped(argc, argv); }); +} |