You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

270 lines
7.6 KiB

  1. /* GNU Guix --- Functional package management for GNU
  2. Copyright (C) 2012, 2013 Ludovic Courtès <ludo@gnu.org>
  3. This file is part of GNU Guix.
  4. GNU Guix is free software; you can redistribute it and/or modify it
  5. under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or (at
  7. your option) any later version.
  8. GNU Guix is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. */
  14. #include <config.h>
  15. #include <types.hh>
  16. #include "shared.hh"
  17. #include <globals.hh>
  18. #include <util.hh>
  19. #include <gcrypt.h>
  20. #include <stdlib.h>
  21. #include <argp.h>
  22. #include <unistd.h>
  23. #include <sys/types.h>
  24. #include <sys/stat.h>
  25. #include <exception>
  26. /* Variables used by `nix-daemon.cc'. */
  27. volatile ::sig_atomic_t blockInt;
  28. char **argvSaved;
  29. using namespace nix;
  30. /* Entry point in `nix-daemon.cc'. */
  31. extern void run (Strings args);
  32. /* Command-line options. */
  33. const char *argp_program_version =
  34. "guix-daemon (" PACKAGE_NAME ") " PACKAGE_VERSION;
  35. const char *argp_program_bug_address = PACKAGE_BUGREPORT;
  36. static char doc[] =
  37. "guix-daemon -- perform derivation builds and store accesses\
  38. \v\
  39. This program is a daemon meant to run in the background. It serves \
  40. requests sent over a Unix-domain socket. It accesses the store, and \
  41. builds derivations on behalf of its clients.";
  42. #define GUIX_OPT_SYSTEM 1
  43. #define GUIX_OPT_DISABLE_CHROOT 2
  44. #define GUIX_OPT_BUILD_USERS_GROUP 3
  45. #define GUIX_OPT_CACHE_FAILURES 4
  46. #define GUIX_OPT_LOSE_LOGS 5
  47. #define GUIX_OPT_DISABLE_LOG_COMPRESSION 6
  48. #define GUIX_OPT_DISABLE_STORE_OPTIMIZATION 7
  49. #define GUIX_OPT_IMPERSONATE_LINUX_26 8
  50. #define GUIX_OPT_DEBUG 9
  51. #define GUIX_OPT_CHROOT_DIR 10
  52. #define GUIX_OPT_LISTEN 11
  53. #define GUIX_OPT_NO_SUBSTITUTES 12
  54. static const struct argp_option options[] =
  55. {
  56. { "system", GUIX_OPT_SYSTEM, "SYSTEM", 0,
  57. "Assume SYSTEM as the current system type" },
  58. { "cores", 'c', "N", 0,
  59. "Use N CPU cores to build each derivation; 0 means as many as available" },
  60. { "max-jobs", 'M', "N", 0,
  61. "Allow at most N build jobs" },
  62. { "disable-chroot", GUIX_OPT_DISABLE_CHROOT, 0, 0,
  63. "Disable chroot builds"
  64. #ifndef HAVE_CHROOT
  65. " (chroots are not supported in this configuration, so "
  66. "this option has no effect)"
  67. #endif
  68. },
  69. { "chroot-directory", GUIX_OPT_CHROOT_DIR, "DIR", 0,
  70. "Add DIR to the build chroot"
  71. #ifndef HAVE_CHROOT
  72. " (chroots are not supported in this configuration, so "
  73. "this option has no effect)"
  74. #endif
  75. },
  76. { "build-users-group", GUIX_OPT_BUILD_USERS_GROUP, "GROUP", 0,
  77. "Perform builds as a user of GROUP" },
  78. { "no-substitutes", GUIX_OPT_NO_SUBSTITUTES, 0, 0,
  79. "Do not use substitutes" },
  80. { "cache-failures", GUIX_OPT_CACHE_FAILURES, 0, 0,
  81. "Cache build failures" },
  82. { "lose-logs", GUIX_OPT_LOSE_LOGS, 0, 0,
  83. "Do not keep build logs" },
  84. { "disable-log-compression", GUIX_OPT_DISABLE_LOG_COMPRESSION, 0, 0,
  85. "Disable compression of the build logs" },
  86. { "disable-store-optimization", GUIX_OPT_DISABLE_STORE_OPTIMIZATION, 0, 0,
  87. "Disable automatic file \"deduplication\" in the store" },
  88. { "impersonate-linux-2.6", GUIX_OPT_IMPERSONATE_LINUX_26, 0, 0,
  89. "Impersonate Linux 2.6"
  90. #ifndef HAVE_SYS_PERSONALITY_H
  91. " (this option has no effect in this configuration)"
  92. #endif
  93. },
  94. { "listen", GUIX_OPT_LISTEN, "SOCKET", 0,
  95. "Listen for connections on SOCKET" },
  96. { "debug", GUIX_OPT_DEBUG, 0, 0,
  97. "Produce debugging output" },
  98. { 0, 0, 0, 0, 0 }
  99. };
  100. /* Parse a single option. */
  101. static error_t
  102. parse_opt (int key, char *arg, struct argp_state *state)
  103. {
  104. switch (key)
  105. {
  106. case GUIX_OPT_DISABLE_CHROOT:
  107. settings.useChroot = false;
  108. break;
  109. case GUIX_OPT_CHROOT_DIR:
  110. settings.dirsInChroot.insert (arg);
  111. break;
  112. case GUIX_OPT_DISABLE_LOG_COMPRESSION:
  113. settings.compressLog = false;
  114. break;
  115. case GUIX_OPT_BUILD_USERS_GROUP:
  116. settings.buildUsersGroup = arg;
  117. break;
  118. case GUIX_OPT_DISABLE_STORE_OPTIMIZATION:
  119. settings.autoOptimiseStore = false;
  120. break;
  121. case GUIX_OPT_CACHE_FAILURES:
  122. settings.cacheFailure = true;
  123. break;
  124. case GUIX_OPT_IMPERSONATE_LINUX_26:
  125. settings.impersonateLinux26 = true;
  126. break;
  127. case GUIX_OPT_LOSE_LOGS:
  128. settings.keepLog = false;
  129. break;
  130. case GUIX_OPT_LISTEN:
  131. try
  132. {
  133. settings.nixDaemonSocketFile = canonPath (arg);
  134. }
  135. catch (std::exception &e)
  136. {
  137. fprintf (stderr, "error: %s\n", e.what ());
  138. exit (EXIT_FAILURE);
  139. }
  140. break;
  141. case GUIX_OPT_NO_SUBSTITUTES:
  142. settings.useSubstitutes = false;
  143. break;
  144. case GUIX_OPT_DEBUG:
  145. verbosity = lvlDebug;
  146. break;
  147. case 'c':
  148. settings.buildCores = atoi (arg);
  149. break;
  150. case 'M':
  151. settings.maxBuildJobs = atoi (arg);
  152. break;
  153. case GUIX_OPT_SYSTEM:
  154. settings.thisSystem = arg;
  155. break;
  156. default:
  157. return (error_t) ARGP_ERR_UNKNOWN;
  158. }
  159. return (error_t) 0;
  160. }
  161. /* Argument parsing. */
  162. static struct argp argp = { options, parse_opt, 0, doc };
  163. int
  164. main (int argc, char *argv[])
  165. {
  166. Strings nothing;
  167. /* Initialize libgcrypt. */
  168. if (!gcry_check_version (GCRYPT_VERSION))
  169. {
  170. fprintf (stderr, "error: libgcrypt version mismatch\n");
  171. exit (EXIT_FAILURE);
  172. }
  173. /* Tell Libgcrypt that initialization has completed, as per the Libgcrypt
  174. 1.6.0 manual (although this does not appear to be strictly needed.) */
  175. gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
  176. /* Set the umask so that the daemon does not end up creating group-writable
  177. files, which would lead to "suspicious ownership or permission" errors.
  178. See <http://lists.gnu.org/archive/html/bug-guix/2013-07/msg00033.html>. */
  179. umask (S_IWGRP | S_IWOTH);
  180. #ifdef HAVE_CHROOT
  181. settings.useChroot = true;
  182. #else
  183. settings.useChroot = false;
  184. #endif
  185. argvSaved = argv;
  186. try
  187. {
  188. settings.processEnvironment ();
  189. /* Hackily help 'local-store.cc' find our 'guix-authenticate' program, which
  190. is known as 'OPENSSL_PATH' here. */
  191. std::string search_path (getenv ("PATH"));
  192. search_path = settings.nixLibexecDir + ":" + search_path;
  193. setenv ("PATH", search_path.c_str (), 1);
  194. /* Use our substituter by default. */
  195. settings.substituters.clear ();
  196. settings.useSubstitutes = true;
  197. argp_parse (&argp, argc, argv, 0, 0, 0);
  198. if (settings.useSubstitutes)
  199. {
  200. string subs = getEnv ("NIX_SUBSTITUTERS", "default");
  201. if (subs == "default")
  202. settings.substituters.push_back (settings.nixLibexecDir
  203. + "/guix/substitute-binary");
  204. else
  205. settings.substituters = tokenizeString<Strings> (subs, ":");
  206. }
  207. if (geteuid () == 0 && settings.buildUsersGroup.empty ())
  208. fprintf (stderr, "warning: daemon is running as root, so "
  209. "using `--build-users-group' is highly recommended\n");
  210. #ifdef HAVE_CHROOT
  211. if (settings.useChroot)
  212. {
  213. foreach (PathSet::iterator, i, settings.dirsInChroot)
  214. {
  215. printMsg (lvlDebug,
  216. format ("directory `%1%' added to the chroot") % *i);
  217. }
  218. }
  219. #endif
  220. printMsg (lvlDebug,
  221. format ("listening on `%1%'") % settings.nixDaemonSocketFile);
  222. run (nothing);
  223. }
  224. catch (std::exception &e)
  225. {
  226. fprintf (stderr, "error: %s\n", e.what ());
  227. return EXIT_FAILURE;
  228. }
  229. return EXIT_SUCCESS; /* never reached */
  230. }