gnunet-arm.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  1. /*
  2. This file is part of GNUnet.
  3. (C) 2009, 2012, 2013 Christian Grothoff (and other contributing authors)
  4. GNUnet is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published
  6. by the Free Software Foundation; either version 3, or (at your
  7. option) any later version.
  8. GNUnet 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 GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNUnet; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  15. Boston, MA 02111-1307, USA.
  16. */
  17. /**
  18. * @file arm/gnunet-arm.c
  19. * @brief arm for writing a tool
  20. * @author Christian Grothoff
  21. */
  22. #include "platform.h"
  23. #include "gnunet_arm_service.h"
  24. #include "gnunet_constants.h"
  25. #include "gnunet_util_lib.h"
  26. /**
  27. * Timeout for stopping services. Long to give some services a real chance.
  28. */
  29. #define STOP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 1)
  30. /**
  31. * Timeout for stopping ARM. Extra-long since ARM needs to stop everyone else.
  32. */
  33. #define STOP_TIMEOUT_ARM GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2)
  34. /**
  35. * Timeout for starting services, very short because of the strange way start works
  36. * (by checking if running before starting, so really this time is always waited on
  37. * startup (annoying)).
  38. */
  39. #define START_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
  40. /**
  41. * Timeout for listing all running services.
  42. */
  43. #define LIST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2)
  44. /**
  45. * Set if we are to shutdown all services (including ARM).
  46. */
  47. static int end;
  48. /**
  49. * Set if we are to start default services (including ARM).
  50. */
  51. static int start;
  52. /**
  53. * Set if we are to stop/start default services (including ARM).
  54. */
  55. static int restart;
  56. /**
  57. * Set if we should delete configuration and temp directory on exit.
  58. */
  59. static int delete;
  60. /**
  61. * Set if we should not print status messages.
  62. */
  63. static int quiet;
  64. /**
  65. * Monitor ARM activity.
  66. */
  67. static int monitor;
  68. /**
  69. * Set if we should print a list of currently running services.
  70. */
  71. static int list;
  72. /**
  73. * Set to the name of a service to start.
  74. */
  75. static char *init;
  76. /**
  77. * Set to the name of a service to kill.
  78. */
  79. static char *term;
  80. /**
  81. * Set to the name of the config file used.
  82. */
  83. static const char *config_file;
  84. /**
  85. * Set to the directory where runtime files are stored.
  86. */
  87. static char *dir;
  88. /**
  89. * Final status code.
  90. */
  91. static int ret;
  92. /**
  93. * Connection with ARM.
  94. */
  95. static struct GNUNET_ARM_Handle *h;
  96. /**
  97. * Monitor connection with ARM.
  98. */
  99. static struct GNUNET_ARM_MonitorHandle *m;
  100. /**
  101. * Our configuration.
  102. */
  103. static struct GNUNET_CONFIGURATION_Handle *cfg;
  104. /**
  105. * Processing stage that we are in. Simple counter.
  106. */
  107. static unsigned int phase;
  108. /**
  109. * User defined timestamp for completing operations.
  110. */
  111. static struct GNUNET_TIME_Relative timeout;
  112. /**
  113. * Do we want to give our stdout to gnunet-service-arm?
  114. */
  115. static unsigned int no_stdout;
  116. /**
  117. * Do we want to give our stderr to gnunet-service-arm?
  118. */
  119. static unsigned int no_stderr;
  120. /**
  121. * Attempts to delete configuration file and GNUNET_HOME
  122. * on ARM shutdown provided the end and delete options
  123. * were specified when gnunet-arm was run.
  124. */
  125. static void
  126. delete_files ()
  127. {
  128. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  129. "Will attempt to remove configuration file %s and service directory %s\n",
  130. config_file, dir);
  131. if (0 != UNLINK (config_file))
  132. {
  133. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  134. _("Failed to remove configuration file %s\n"),
  135. config_file);
  136. }
  137. if (GNUNET_OK != GNUNET_DISK_directory_remove (dir))
  138. {
  139. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  140. _("Failed to remove servicehome directory %s\n"),
  141. dir);
  142. }
  143. }
  144. /**
  145. * Main continuation-passing-style loop. Runs the various
  146. * jobs that we've been asked to do in order.
  147. *
  148. * @param cls closure, unused
  149. * @param tc context, unused
  150. */
  151. static void
  152. shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  153. {
  154. if (NULL != h)
  155. {
  156. GNUNET_ARM_disconnect_and_free (h);
  157. h = NULL;
  158. }
  159. if (NULL != m)
  160. {
  161. GNUNET_ARM_monitor_disconnect_and_free (m);
  162. m = NULL;
  163. }
  164. if ((GNUNET_YES == end) && (GNUNET_YES == delete))
  165. delete_files ();
  166. GNUNET_CONFIGURATION_destroy (cfg);
  167. cfg = NULL;
  168. }
  169. /**
  170. * Returns a string interpretation of 'rs'
  171. *
  172. * @param rs the request status from ARM
  173. * @return a string interpretation of the request status
  174. */
  175. static const char *
  176. req_string (enum GNUNET_ARM_RequestStatus rs)
  177. {
  178. switch (rs)
  179. {
  180. case GNUNET_ARM_REQUEST_SENT_OK:
  181. return _("Message was sent successfully");
  182. case GNUNET_ARM_REQUEST_CONFIGURATION_ERROR:
  183. return _("Misconfiguration (can not connect to the ARM service)");
  184. case GNUNET_ARM_REQUEST_DISCONNECTED:
  185. return _("We disconnected from ARM before we could send a request");
  186. case GNUNET_ARM_REQUEST_BUSY:
  187. return _("ARM API is busy");
  188. case GNUNET_ARM_REQUEST_TOO_LONG:
  189. return _("Request does not fit into a message");
  190. case GNUNET_ARM_REQUEST_TIMEOUT:
  191. return _("Request timed out");
  192. }
  193. return _("Unknown request status");
  194. }
  195. /**
  196. * Returns a string interpretation of the 'result'
  197. *
  198. * @param result the arm result
  199. * @return a string interpretation
  200. */
  201. static const char *
  202. ret_string (enum GNUNET_ARM_Result result)
  203. {
  204. switch (result)
  205. {
  206. case GNUNET_ARM_RESULT_STOPPED:
  207. return _("%s is stopped");
  208. case GNUNET_ARM_RESULT_STARTING:
  209. return _("%s is starting");
  210. case GNUNET_ARM_RESULT_STOPPING:
  211. return _("%s is stopping");
  212. case GNUNET_ARM_RESULT_IS_STARTING_ALREADY:
  213. return _("%s is starting already");
  214. case GNUNET_ARM_RESULT_IS_STOPPING_ALREADY:
  215. return _("%s is stopping already");
  216. case GNUNET_ARM_RESULT_IS_STARTED_ALREADY:
  217. return _("%s is started already");
  218. case GNUNET_ARM_RESULT_IS_STOPPED_ALREADY:
  219. return _("%s is stopped already");
  220. case GNUNET_ARM_RESULT_IS_NOT_KNOWN:
  221. return _("%s service is not known to ARM");
  222. case GNUNET_ARM_RESULT_START_FAILED:
  223. return _("%s service failed to start");
  224. case GNUNET_ARM_RESULT_IN_SHUTDOWN:
  225. return _("%s service cannot be started because ARM is shutting down");
  226. }
  227. return _("%.s Unknown result code.");
  228. }
  229. /**
  230. * Main task that runs our various operations in order.
  231. *
  232. * @param cls closure
  233. * @param tc scheudler context
  234. */
  235. static void
  236. action_loop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
  237. /**
  238. * Function called whenever we connect to or disconnect from ARM.
  239. * Termiantes the process if we fail to connect to the service on
  240. * our first attempt.
  241. *
  242. * @param cls closure
  243. * @param connected GNUNET_YES if connected, GNUNET_NO if disconnected,
  244. * GNUNET_SYSERR on error.
  245. */
  246. static void
  247. conn_status (void *cls,
  248. int connected)
  249. {
  250. static int once;
  251. if ( (GNUNET_SYSERR == connected) &&
  252. (0 == once) )
  253. {
  254. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  255. _("Fatal error initializing ARM API.\n"));
  256. GNUNET_SCHEDULER_shutdown ();
  257. return;
  258. }
  259. once = 1;
  260. }
  261. /**
  262. * We have requested ARM to be started, this function
  263. * is called with the result of the operation. Informs the
  264. * use of the result; on success, we continue with the event
  265. * loop, on failure we terminate the process.
  266. *
  267. * @param cls closure unused
  268. * @param rs what happened to our request
  269. * @param service name of the service we tried to start ("arm")
  270. * @param result if the request was processed, this is the result
  271. * according to ARM
  272. */
  273. static void
  274. start_callback (void *cls,
  275. enum GNUNET_ARM_RequestStatus rs, const char *service,
  276. enum GNUNET_ARM_Result result)
  277. {
  278. char *msg;
  279. if (GNUNET_ARM_REQUEST_SENT_OK != rs)
  280. {
  281. GNUNET_asprintf (&msg, "%s", _("Failed to start the ARM service: %s\n"));
  282. FPRINTF (stdout, msg, req_string (rs));
  283. GNUNET_free (msg);
  284. GNUNET_SCHEDULER_shutdown ();
  285. return;
  286. }
  287. if ( (GNUNET_ARM_RESULT_STARTING != result) &&
  288. (GNUNET_ARM_RESULT_IS_STARTED_ALREADY != result) )
  289. {
  290. GNUNET_asprintf (&msg, "%s", _("Failed to start the ARM service: %s\n"));
  291. FPRINTF (stdout, msg, ret_string (result));
  292. GNUNET_free (msg);
  293. GNUNET_SCHEDULER_shutdown ();
  294. return;
  295. }
  296. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ARM service [re]start successful\n");
  297. start = 0;
  298. GNUNET_SCHEDULER_add_now (action_loop, NULL);
  299. }
  300. /**
  301. * We have requested ARM to be stopped, this function
  302. * is called with the result of the operation. Informs the
  303. * use of the result; on success, we continue with the event
  304. * loop, on failure we terminate the process.
  305. *
  306. * @param cls closure unused
  307. * @param rs what happened to our request
  308. * @param service name of the service we tried to start ("arm")
  309. * @param result if the request was processed, this is the result
  310. * according to ARM
  311. */
  312. static void
  313. stop_callback (void *cls,
  314. enum GNUNET_ARM_RequestStatus rs, const char *service,
  315. enum GNUNET_ARM_Result result)
  316. {
  317. char *msg;
  318. if (GNUNET_ARM_REQUEST_SENT_OK != rs)
  319. {
  320. GNUNET_asprintf (&msg, "%s",
  321. _("Failed to send a stop request to the ARM service: %s\n"));
  322. FPRINTF (stdout, msg, req_string (rs));
  323. GNUNET_free (msg);
  324. GNUNET_SCHEDULER_shutdown ();
  325. return;
  326. }
  327. if ((GNUNET_ARM_RESULT_STOPPING != result) &&
  328. (GNUNET_ARM_RESULT_STOPPED != result) &&
  329. (GNUNET_ARM_RESULT_IS_STOPPED_ALREADY != result))
  330. {
  331. GNUNET_asprintf (&msg, "%s", _("Failed to stop the ARM service: %s\n"));
  332. FPRINTF (stdout, msg, ret_string (result));
  333. GNUNET_free (msg);
  334. GNUNET_SCHEDULER_shutdown ();
  335. return;
  336. }
  337. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  338. "ARM service shutdown successful\n");
  339. end = 0;
  340. if (restart)
  341. {
  342. restart = 0;
  343. start = 1;
  344. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  345. "Initiating an ARM restart\n");
  346. }
  347. GNUNET_SCHEDULER_add_now (&action_loop, NULL);
  348. }
  349. /**
  350. * We have requested a service to be started, this function
  351. * is called with the result of the operation. Informs the
  352. * use of the result; on success, we continue with the event
  353. * loop, on failure we terminate the process.
  354. *
  355. * @param cls closure unused
  356. * @param rs what happened to our request
  357. * @param service name of the service we tried to start
  358. * @param result if the request was processed, this is the result
  359. * according to ARM
  360. */
  361. static void
  362. init_callback (void *cls,
  363. enum GNUNET_ARM_RequestStatus rs, const char *service,
  364. enum GNUNET_ARM_Result result)
  365. {
  366. char *msg;
  367. if (GNUNET_ARM_REQUEST_SENT_OK != rs)
  368. {
  369. GNUNET_asprintf (&msg,
  370. _("Failed to send a request to start the `%s' service: %%s\n"),
  371. init);
  372. FPRINTF (stdout, msg, req_string (rs));
  373. GNUNET_free (msg);
  374. GNUNET_SCHEDULER_shutdown ();
  375. return;
  376. }
  377. if ((GNUNET_ARM_RESULT_STARTING != result) &&
  378. (GNUNET_ARM_RESULT_IS_STARTED_ALREADY != result))
  379. {
  380. GNUNET_asprintf (&msg, _("Failed to start the `%s' service: %s\n"),
  381. init, ret_string (result));
  382. FPRINTF (stdout, msg, service);
  383. GNUNET_free (msg);
  384. GNUNET_SCHEDULER_shutdown ();
  385. return;
  386. }
  387. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  388. "Service %s [re]started successfully\n",
  389. init);
  390. GNUNET_free (init);
  391. init = NULL;
  392. GNUNET_SCHEDULER_add_now (&action_loop, NULL);
  393. }
  394. /**
  395. * We have requested a service to be stopped, this function
  396. * is called with the result of the operation. Informs the
  397. * use of the result; on success, we continue with the event
  398. * loop, on failure we terminate the process.
  399. *
  400. * @param cls closure unused
  401. * @param rs what happened to our request
  402. * @param service name of the service we tried to start
  403. * @param result if the request was processed, this is the result
  404. * according to ARM
  405. */
  406. static void
  407. term_callback (void *cls,
  408. enum GNUNET_ARM_RequestStatus rs, const char *service,
  409. enum GNUNET_ARM_Result result)
  410. {
  411. char *msg;
  412. if (GNUNET_ARM_REQUEST_SENT_OK != rs)
  413. {
  414. GNUNET_asprintf (&msg,
  415. _("Failed to send a request to kill the `%s' service: %%s\n"),
  416. term);
  417. FPRINTF (stdout, msg, req_string (rs));
  418. GNUNET_free (msg);
  419. GNUNET_SCHEDULER_shutdown ();
  420. return;
  421. }
  422. if ((GNUNET_ARM_RESULT_STOPPED != result) &&
  423. (GNUNET_ARM_RESULT_IS_STOPPED_ALREADY != result))
  424. {
  425. GNUNET_asprintf (&msg,
  426. _("Failed to kill the `%s' service: %s\n"),
  427. term, ret_string (result));
  428. FPRINTF (stdout, msg, service);
  429. GNUNET_free (msg);
  430. GNUNET_SCHEDULER_shutdown ();
  431. return;
  432. }
  433. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  434. "Service %s stopped successfully\n",
  435. term);
  436. GNUNET_free (term);
  437. term = NULL;
  438. GNUNET_SCHEDULER_add_now (&action_loop, NULL);
  439. }
  440. /**
  441. * Function called with the list of running services. Prints
  442. * the list to stdout, then starts the event loop again.
  443. * Prints an error message and terminates the process on errors.
  444. *
  445. * @param cls closure (unused)
  446. * @param rs request status (success, failure, etc.)
  447. * @param count number of services in the list
  448. * @param list list of services that are running
  449. */
  450. static void
  451. list_callback (void *cls,
  452. enum GNUNET_ARM_RequestStatus rs, unsigned int count,
  453. const char *const*list)
  454. {
  455. unsigned int i;
  456. if (GNUNET_ARM_REQUEST_SENT_OK != rs)
  457. {
  458. char *msg;
  459. GNUNET_asprintf (&msg, "%s", _("Failed to request a list of services: %s\n"));
  460. FPRINTF (stdout, msg, req_string (rs));
  461. GNUNET_free (msg);
  462. ret = 3;
  463. GNUNET_SCHEDULER_shutdown ();
  464. }
  465. if (NULL == list)
  466. {
  467. FPRINTF (stderr, "%s", _("Error communicating with ARM. ARM not running?\n"));
  468. GNUNET_SCHEDULER_shutdown ();
  469. ret = 3;
  470. return;
  471. }
  472. FPRINTF (stdout, "%s", _("Running services:\n"));
  473. for (i = 0; i < count; i++)
  474. FPRINTF (stdout, "%s\n", list[i]);
  475. GNUNET_SCHEDULER_add_now (&action_loop, NULL);
  476. }
  477. /**
  478. * Main action loop. Runs the various jobs that we've been asked to
  479. * do, in order.
  480. *
  481. * @param cls closure, unused
  482. * @param tc context, unused
  483. */
  484. static void
  485. action_loop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  486. {
  487. if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
  488. return;
  489. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Running requested actions\n");
  490. while (1)
  491. {
  492. switch (phase++)
  493. {
  494. case 0:
  495. if (NULL != term)
  496. {
  497. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Termination action\n");
  498. GNUNET_ARM_request_service_stop (h, term,
  499. (0 == timeout.rel_value_us) ? STOP_TIMEOUT : timeout,
  500. &term_callback, NULL);
  501. return;
  502. }
  503. break;
  504. case 1:
  505. if (end || restart)
  506. {
  507. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "End action\n");
  508. GNUNET_ARM_request_service_stop (h, "arm",
  509. (0 == timeout.rel_value_us) ? STOP_TIMEOUT_ARM : timeout,
  510. &stop_callback, NULL);
  511. return;
  512. }
  513. break;
  514. case 2:
  515. if (start)
  516. {
  517. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start action\n");
  518. GNUNET_ARM_request_service_start (h, "arm",
  519. (no_stdout ? 0 : GNUNET_OS_INHERIT_STD_OUT) |
  520. (no_stderr ? 0 : GNUNET_OS_INHERIT_STD_ERR),
  521. (0 == timeout.rel_value_us) ? START_TIMEOUT: timeout,
  522. start_callback, NULL);
  523. return;
  524. }
  525. break;
  526. case 3:
  527. if (NULL != init)
  528. {
  529. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Initialization action\n");
  530. GNUNET_ARM_request_service_start (h, init, GNUNET_OS_INHERIT_STD_NONE,
  531. (0 == timeout.rel_value_us) ? STOP_TIMEOUT : timeout,
  532. &init_callback, NULL);
  533. return;
  534. }
  535. break;
  536. case 4:
  537. if (list)
  538. {
  539. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  540. "Going to list all running services controlled by ARM.\n");
  541. GNUNET_ARM_request_service_list (h,
  542. (0 == timeout.rel_value_us) ? LIST_TIMEOUT : timeout,
  543. &list_callback, &list);
  544. return;
  545. }
  546. break;
  547. case 5:
  548. if (monitor)
  549. {
  550. if (! quiet)
  551. fprintf (stderr,
  552. _("Now only monitoring, press CTRL-C to stop.\n"));
  553. quiet = 0; /* does not make sense to stay quiet in monitor mode at this time */
  554. return; /* done with tasks, just monitor */
  555. }
  556. break;
  557. default: /* last phase */
  558. GNUNET_SCHEDULER_shutdown ();
  559. return;
  560. }
  561. }
  562. }
  563. /**
  564. * Function called when a service starts or stops.
  565. *
  566. * @param cls closure
  567. * @param service service name
  568. * @param status status of the service
  569. */
  570. static void
  571. srv_status (void *cls,
  572. const char *service, enum GNUNET_ARM_ServiceStatus status)
  573. {
  574. const char *msg;
  575. switch (status)
  576. {
  577. case GNUNET_ARM_SERVICE_MONITORING_STARTED:
  578. return; /* this should be done silently */
  579. case GNUNET_ARM_SERVICE_STOPPED:
  580. msg = _("Stopped %s.\n");
  581. break;
  582. case GNUNET_ARM_SERVICE_STARTING:
  583. msg = _("Starting %s...\n");
  584. break;
  585. case GNUNET_ARM_SERVICE_STOPPING:
  586. msg = _("Stopping %s...\n");
  587. break;
  588. default:
  589. msg = NULL;
  590. break;
  591. }
  592. if (! quiet)
  593. {
  594. if (NULL != msg)
  595. FPRINTF (stderr, msg, service);
  596. else
  597. FPRINTF (stderr, _("Unknown status %u for service %s.\n"), status, service);
  598. }
  599. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got service %s status %d\n", service, (int) status);
  600. }
  601. /**
  602. * Main function that will be run by the scheduler.
  603. *
  604. * @param cls closure
  605. * @param args remaining command-line arguments
  606. * @param cfgfile name of the configuration file used (for saving, can be NULL!)
  607. * @param c configuration
  608. */
  609. static void
  610. run (void *cls,
  611. char *const *args,
  612. const char *cfgfile,
  613. const struct GNUNET_CONFIGURATION_Handle *c)
  614. {
  615. char *armconfig;
  616. cfg = GNUNET_CONFIGURATION_dup (c);
  617. config_file = cfgfile;
  618. if (GNUNET_OK !=
  619. GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS", "GNUNET_HOME", &dir))
  620. {
  621. GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
  622. "PATHS", "GNUNET_HOME");
  623. return;
  624. }
  625. if (NULL != cfgfile)
  626. {
  627. if (GNUNET_OK !=
  628. GNUNET_CONFIGURATION_get_value_filename (cfg, "arm", "CONFIG",
  629. &armconfig))
  630. {
  631. GNUNET_CONFIGURATION_set_value_string (cfg, "arm", "CONFIG",
  632. cfgfile);
  633. }
  634. else
  635. GNUNET_free (armconfig);
  636. }
  637. if (NULL == (h = GNUNET_ARM_connect (cfg, &conn_status, NULL)))
  638. return;
  639. if (monitor)
  640. m = GNUNET_ARM_monitor (cfg, &srv_status, NULL);
  641. GNUNET_SCHEDULER_add_now (&action_loop, NULL);
  642. GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
  643. &shutdown_task, NULL);
  644. }
  645. /**
  646. * The main function to obtain arm from gnunetd.
  647. *
  648. * @param argc number of arguments from the command line
  649. * @param argv command line arguments
  650. * @return 0 ok, 1 on error
  651. */
  652. int
  653. main (int argc, char *const *argv)
  654. {
  655. static const struct GNUNET_GETOPT_CommandLineOption options[] = {
  656. {'e', "end", NULL, gettext_noop ("stop all GNUnet services"),
  657. GNUNET_NO, &GNUNET_GETOPT_set_one, &end},
  658. {'i', "init", "SERVICE", gettext_noop ("start a particular service"),
  659. GNUNET_YES, &GNUNET_GETOPT_set_string, &init},
  660. {'k', "kill", "SERVICE", gettext_noop ("stop a particular service"),
  661. GNUNET_YES, &GNUNET_GETOPT_set_string, &term},
  662. {'s', "start", NULL, gettext_noop ("start all GNUnet default services"),
  663. GNUNET_NO, &GNUNET_GETOPT_set_one, &start},
  664. {'r', "restart", NULL,
  665. gettext_noop ("stop and start all GNUnet default services"),
  666. GNUNET_NO, &GNUNET_GETOPT_set_one, &restart},
  667. {'d', "delete", NULL,
  668. gettext_noop ("delete config file and directory on exit"),
  669. GNUNET_NO, &GNUNET_GETOPT_set_one, &delete},
  670. {'m', "monitor", NULL,
  671. gettext_noop ("monitor ARM activities"),
  672. GNUNET_NO, &GNUNET_GETOPT_set_one, &monitor},
  673. {'q', "quiet", NULL, gettext_noop ("don't print status messages"),
  674. GNUNET_NO, &GNUNET_GETOPT_set_one, &quiet},
  675. {'T', "timeout", "MSECS",
  676. gettext_noop ("timeout in MSECS milliseconds for completing current operation"),
  677. GNUNET_YES, &GNUNET_GETOPT_set_relative_time, &timeout},
  678. {'I', "info", NULL, gettext_noop ("list currently running services"),
  679. GNUNET_NO, &GNUNET_GETOPT_set_one, &list},
  680. {'O', "no-stdout", NULL, gettext_noop ("don't let gnunet-service-arm inherit standard output"),
  681. GNUNET_NO, &GNUNET_GETOPT_set_one, &no_stdout},
  682. {'E', "no-stderr", NULL, gettext_noop ("don't let gnunet-service-arm inherit standard error"),
  683. GNUNET_NO, &GNUNET_GETOPT_set_one, &no_stderr},
  684. GNUNET_GETOPT_OPTION_END
  685. };
  686. if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
  687. return 2;
  688. if (GNUNET_OK ==
  689. GNUNET_PROGRAM_run (argc, argv, "gnunet-arm",
  690. gettext_noop
  691. ("Control services and the Automated Restart Manager (ARM)"),
  692. options, &run, NULL))
  693. {
  694. GNUNET_free ((void *) argv);
  695. return ret;
  696. }
  697. GNUNET_free ((void*) argv);
  698. return 1;
  699. }
  700. /* end of gnunet-arm.c */