#include #include #include #include #include #include #include #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(((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 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 '-- '.\n" "Boolean settings can be overriden using '--' or " "'--no-'. 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(); initGC(); 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::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); }); }