about summary refs log blame commit diff
path: root/third_party/nix/src/nix/main.cc
blob: fac2c78a639ee08e38228bd9618cefa808488e54 (plain) (tree)
1
2
3
4
5
6
7
8
9




                       
                    

                         
                      
                  
                     
                     
                         
                    
                          

                       
 

                                    
                                         
 

               
                                                                   

                            
 


                                              
 










                                                                            
     
   
 
               

 

                        


























































                                                                                

  






                                                                   
 

            
 

                                               
 



                                                                  
 

                                
 
               
 
                                               
 
                
 
                                            
 
                                         
 
                                        
 





                                                                           
 








                                                                            
 

                          

 
                   
 



                                     

                                                                        
 
#include <ifaddrs.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <algorithm>
#include "command.hh"
#include "common-args.hh"
#include "download.hh"
#include "eval.hh"
#include "finally.hh"
#include "globals.hh"
#include "glog/logging.h"
#include "legacy.hh"
#include "progress-bar.hh"
#include "shared.hh"
#include "store-api.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)) return true;

  Finally free([&]() { freeifaddrs(addrs); });

  for (auto i = addrs; i; i = i->ifa_next) {
    if (!i->ifa_addr) 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<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();
  initGC();

  programPath = argv[0];
  string programName = baseNameOf(programPath);

  {
    auto legacy = (*RegisterLegacyCommand::commands)[programName];
    if (legacy) return legacy(argc, argv);
  }

  verbosity = lvlWarn;
  settings.verboseBuild = false;

  NixArgs args;

  args.parseCmdline(argvToStrings(argc, argv));

  initPlugins();

  if (!args.command) args.showHelpAndExit();

  Finally f([]() { stopProgressBar(); });

  startProgressBar(args.printBuildLogs);

  if (args.useNet && !haveInternet()) {
    warn(
        "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 = 1;
  google::InitGoogleLogging(argv[0]);

  return nix::handleExceptions(argv[0],
                               [&]() { nix::mainWrapped(argc, argv); });
}