gnunet-arm.c 21 KB

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