aboutsummaryrefslogtreecommitdiff
path: root/src/cli/arm/gnunet-arm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cli/arm/gnunet-arm.c')
-rw-r--r--src/cli/arm/gnunet-arm.c1065
1 files changed, 1065 insertions, 0 deletions
diff --git a/src/cli/arm/gnunet-arm.c b/src/cli/arm/gnunet-arm.c
new file mode 100644
index 000000000..ea3a012ab
--- /dev/null
+++ b/src/cli/arm/gnunet-arm.c
@@ -0,0 +1,1065 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 2012, 2013 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file arm/gnunet-arm.c
23 * @brief arm for writing a tool
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_arm_service.h"
28#include "gnunet_constants.h"
29#include "gnunet_util_lib.h"
30
31/**
32 * Set if we are to shutdown all services (including ARM).
33 */
34static int end;
35
36/**
37 * Set if we are to start default services (including ARM).
38 */
39static int start;
40
41/**
42 * Set if we are to stop/start default services (including ARM).
43 */
44static int restart;
45
46/**
47 * Set if we should delete configuration and temp directory on exit.
48 */
49static int delete;
50
51/**
52 * Set if we should not print status messages.
53 */
54static int quiet;
55
56/**
57 * Set if we should print all services, including stopped ones.
58 */
59static int show_all;
60
61/**
62 * Monitor ARM activity.
63 */
64static int monitor;
65
66/**
67 * Set if we should print a list of currently running services.
68 */
69static int list;
70
71/**
72 * Set to the name of a service to start.
73 */
74static char *init;
75
76/**
77 * Set to the name of a service to kill.
78 */
79static char *term;
80
81/**
82 * Set to the name of the config file used.
83 */
84static char *config_file;
85
86/**
87 * Set to the directory where runtime files are stored.
88 */
89static char *dir;
90
91/**
92 * Final status code.
93 */
94static int ret;
95
96/**
97 * Connection with ARM.
98 */
99static struct GNUNET_ARM_Handle *h;
100
101/**
102 * Monitor connection with ARM.
103 */
104static struct GNUNET_ARM_MonitorHandle *m;
105
106/**
107 * Our configuration.
108 */
109static struct GNUNET_CONFIGURATION_Handle *cfg;
110
111/**
112 * Processing stage that we are in. Simple counter.
113 */
114static unsigned int phase;
115
116/**
117 * User defined timestamp for completing operations.
118 */
119static struct GNUNET_TIME_Relative timeout;
120
121/**
122 * Task to be run on timeout.
123 */
124static struct GNUNET_SCHEDULER_Task *timeout_task;
125
126/**
127 * Do we want to give our stdout to gnunet-service-arm?
128 */
129static int no_stdout;
130
131/**
132 * Do we want to give our stderr to gnunet-service-arm?
133 */
134static int no_stderr;
135
136/**
137 * Handle for the task running the #action_loop().
138 */
139static struct GNUNET_SCHEDULER_Task *al_task;
140
141/**
142 * Current operation.
143 */
144static struct GNUNET_ARM_Operation *op;
145
146/**
147 * Attempts to delete configuration file and GNUNET_HOME
148 * on ARM shutdown provided the end and delete options
149 * were specified when gnunet-arm was run.
150 */
151static void
152delete_files ()
153{
154 GNUNET_log (
155 GNUNET_ERROR_TYPE_DEBUG,
156 "Will attempt to remove configuration file %s and service directory %s\n",
157 config_file,
158 dir);
159 if (0 != unlink (config_file))
160 {
161 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
162 _ ("Failed to remove configuration file %s\n"),
163 config_file);
164 }
165 if (GNUNET_OK != GNUNET_DISK_directory_remove (dir))
166 {
167 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
168 _ ("Failed to remove servicehome directory %s\n"),
169 dir);
170 }
171}
172
173
174/**
175 * Main continuation-passing-style loop. Runs the various
176 * jobs that we've been asked to do in order.
177 *
178 * @param cls closure, unused
179 */
180static void
181shutdown_task (void *cls)
182{
183 (void) cls;
184 if (NULL != al_task)
185 {
186 GNUNET_SCHEDULER_cancel (al_task);
187 al_task = NULL;
188 }
189 if (NULL != op)
190 {
191 GNUNET_ARM_operation_cancel (op);
192 op = NULL;
193 }
194 if (NULL != h)
195 {
196 GNUNET_ARM_disconnect (h);
197 h = NULL;
198 }
199 if (NULL != m)
200 {
201 GNUNET_ARM_monitor_stop (m);
202 m = NULL;
203 }
204 if (NULL != timeout_task)
205 {
206 GNUNET_SCHEDULER_cancel (timeout_task);
207 timeout_task = NULL;
208 }
209 if ( (GNUNET_YES == end) &&
210 (GNUNET_YES == delete) )
211 delete_files ();
212 GNUNET_CONFIGURATION_destroy (cfg);
213 cfg = NULL;
214}
215
216
217/**
218 * Returns a string interpretation of @a rs
219 *
220 * @param rs the request status from ARM
221 * @return a string interpretation of the request status
222 */
223static const char *
224req_string (enum GNUNET_ARM_RequestStatus rs)
225{
226 switch (rs)
227 {
228 case GNUNET_ARM_REQUEST_SENT_OK:
229 return _ ("Message was sent successfully");
230
231 case GNUNET_ARM_REQUEST_DISCONNECTED:
232 return _ ("We disconnected from ARM before we could send a request");
233 }
234 return _ ("Unknown request status");
235}
236
237
238/**
239 * Returns a string interpretation of the @a result
240 *
241 * @param result the arm result
242 * @return a string interpretation
243 */
244static const char *
245ret_string (enum GNUNET_ARM_Result result)
246{
247 switch (result)
248 {
249 case GNUNET_ARM_RESULT_STOPPED:
250 return _ ("is stopped");
251
252 case GNUNET_ARM_RESULT_STARTING:
253 return _ ("is starting");
254
255 case GNUNET_ARM_RESULT_STOPPING:
256 return _ ("is stopping");
257
258 case GNUNET_ARM_RESULT_IS_STARTING_ALREADY:
259 return _ ("is starting already");
260
261 case GNUNET_ARM_RESULT_IS_STOPPING_ALREADY:
262 return _ ("is stopping already");
263
264 case GNUNET_ARM_RESULT_IS_STARTED_ALREADY:
265 return _ ("is started already");
266
267 case GNUNET_ARM_RESULT_IS_STOPPED_ALREADY:
268 return _ ("is stopped already");
269
270 case GNUNET_ARM_RESULT_IS_NOT_KNOWN:
271 return _ ("service is not known to ARM");
272
273 case GNUNET_ARM_RESULT_START_FAILED:
274 return _ ("service failed to start");
275
276 case GNUNET_ARM_RESULT_IN_SHUTDOWN:
277 return _ ("service cannot be manipulated because ARM is shutting down");
278 }
279 return _ ("Unknown result code.");
280}
281
282
283/**
284 * Main task that runs our various operations in order.
285 *
286 * @param cls closure
287 */
288static void
289action_loop (void *cls);
290
291
292/**
293 * Function called whenever we connect to or disconnect from ARM.
294 * Termiantes the process if we fail to connect to the service on
295 * our first attempt.
296 *
297 * @param cls closure
298 * @param connected #GNUNET_YES if connected, #GNUNET_NO if disconnected,
299 * #GNUNET_SYSERR on error.
300 */
301static void
302conn_status (void *cls,
303 int connected)
304{
305 static int once;
306
307 (void) cls;
308 if ( (GNUNET_SYSERR == connected) &&
309 (0 == once) )
310 {
311 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
312 _ ("Fatal error initializing ARM API.\n"));
313 GNUNET_SCHEDULER_shutdown ();
314 return;
315 }
316 once = 1;
317}
318
319
320/**
321 * We have requested ARM to be started, this function
322 * is called with the result of the operation. Informs the
323 * use of the result; on success, we continue with the event
324 * loop, on failure we terminate the process.
325 *
326 * @param cls closure unused
327 * @param rs what happened to our request
328 * @param result if the request was processed, this is the result
329 * according to ARM
330 */
331static void
332start_callback (void *cls,
333 enum GNUNET_ARM_RequestStatus rs,
334 enum GNUNET_ARM_Result result)
335{
336 (void) cls;
337 op = NULL;
338 if (GNUNET_ARM_REQUEST_SENT_OK != rs)
339 {
340 fprintf (stdout,
341 _ ("Failed to start the ARM service: %s\n"),
342 req_string (rs));
343 GNUNET_SCHEDULER_shutdown ();
344 return;
345 }
346 if ((GNUNET_ARM_RESULT_STARTING != result) &&
347 (GNUNET_ARM_RESULT_IS_STARTED_ALREADY != result))
348 {
349 fprintf (stdout,
350 _ ("Failed to start the ARM service: %s\n"),
351 ret_string (result));
352 GNUNET_SCHEDULER_shutdown ();
353 return;
354 }
355 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
356 "ARM service [re]start successful\n");
357 start = 0;
358 al_task = GNUNET_SCHEDULER_add_now (&action_loop,
359 NULL);
360}
361
362
363/**
364 * We have requested ARM to be stopped, this function
365 * is called with the result of the operation. Informs the
366 * use of the result; on success, we continue with the event
367 * loop, on failure we terminate the process.
368 *
369 * @param cls closure unused
370 * @param rs what happened to our request
371 * @param result if the request was processed, this is the result
372 * according to ARM
373 */
374static void
375stop_callback (void *cls,
376 enum GNUNET_ARM_RequestStatus rs,
377 enum GNUNET_ARM_Result result)
378{
379 char *msg;
380
381 (void) cls;
382 op = NULL;
383 if (GNUNET_ARM_REQUEST_SENT_OK != rs)
384 {
385 GNUNET_asprintf (&msg,
386 "%s",
387 _ (
388 "Failed to send a stop request to the ARM service: %s\n"));
389 fprintf (stdout, msg, req_string (rs));
390 GNUNET_free (msg);
391 GNUNET_SCHEDULER_shutdown ();
392 return;
393 }
394 if ( (GNUNET_ARM_RESULT_STOPPING != result) &&
395 (GNUNET_ARM_RESULT_STOPPED != result) &&
396 (GNUNET_ARM_RESULT_IS_STOPPED_ALREADY != result) )
397 {
398 fprintf (stdout,
399 _ ("Failed to stop the ARM service: %s\n"),
400 ret_string (result));
401 GNUNET_SCHEDULER_shutdown ();
402 return;
403 }
404 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
405 "ARM service shutdown successful\n");
406 end = 0;
407 if (restart)
408 {
409 restart = 0;
410 start = 1;
411 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
412 "Initiating an ARM restart\n");
413 }
414 al_task = GNUNET_SCHEDULER_add_now (&action_loop,
415 NULL);
416}
417
418
419/**
420 * We have requested a service to be started, this function
421 * is called with the result of the operation. Informs the
422 * use of the result; on success, we continue with the event
423 * loop, on failure we terminate the process.
424 *
425 * @param cls closure unused
426 * @param rs what happened to our request
427 * @param result if the request was processed, this is the result
428 * according to ARM
429 */
430static void
431init_callback (void *cls,
432 enum GNUNET_ARM_RequestStatus rs,
433 enum GNUNET_ARM_Result result)
434{
435 (void) cls;
436 op = NULL;
437 if (GNUNET_ARM_REQUEST_SENT_OK != rs)
438 {
439 fprintf (stdout,
440 _ ("Failed to send a request to start the `%s' service: %s\n"),
441 init,
442 req_string (rs));
443 GNUNET_SCHEDULER_shutdown ();
444 return;
445 }
446 if ((GNUNET_ARM_RESULT_STARTING != result) &&
447 (GNUNET_ARM_RESULT_IS_STARTED_ALREADY != result))
448 {
449 fprintf (stdout,
450 _ ("Failed to start the `%s' service: %s\n"),
451 init,
452 ret_string (result));
453 GNUNET_SCHEDULER_shutdown ();
454 return;
455 }
456 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
457 "Service %s [re]started successfully\n",
458 init);
459 GNUNET_free (init);
460 init = NULL;
461 al_task = GNUNET_SCHEDULER_add_now (&action_loop,
462 NULL);
463}
464
465
466/**
467 * We have requested a service to be stopped, this function
468 * is called with the result of the operation. Informs the
469 * use of the result; on success, we continue with the event
470 * loop, on failure we terminate the process.
471 *
472 * @param cls closure unused
473 * @param rs what happened to our request
474 * @param result if the request was processed, this is the result
475 * according to ARM
476 */
477static void
478term_callback (void *cls,
479 enum GNUNET_ARM_RequestStatus rs,
480 enum GNUNET_ARM_Result result)
481{
482 char *msg;
483
484 (void) cls;
485 op = NULL;
486 if (GNUNET_ARM_REQUEST_SENT_OK != rs)
487 {
488 GNUNET_asprintf (&msg,
489 _ (
490 "Failed to send a request to kill the `%s' service: %%s\n"),
491 term);
492 fprintf (stdout,
493 msg,
494 req_string (rs));
495 GNUNET_free (msg);
496 GNUNET_SCHEDULER_shutdown ();
497 return;
498 }
499 if ( (GNUNET_ARM_RESULT_STOPPED != result) &&
500 (GNUNET_ARM_RESULT_IS_STOPPED_ALREADY != result) )
501 {
502 fprintf (stdout,
503 _ ("Failed to kill the `%s' service: %s\n"),
504 term,
505 ret_string (result));
506 GNUNET_SCHEDULER_shutdown ();
507 return;
508 }
509
510 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
511 "Service %s stopped successfully\n",
512 term);
513 GNUNET_free (term);
514 term = NULL;
515 al_task = GNUNET_SCHEDULER_add_now (&action_loop,
516 NULL);
517}
518
519
520/**
521 * Function called with the list of running services. Prints
522 * the list to stdout, then starts the event loop again.
523 * Prints an error message and terminates the process on errors.
524 *
525 * @param cls closure (unused)
526 * @param rs request status (success, failure, etc.)
527 * @param count number of services in the list
528 * @param list list of services managed by arm
529 */
530static void
531list_callback (void *cls,
532 enum GNUNET_ARM_RequestStatus rs,
533 unsigned int count,
534 const struct GNUNET_ARM_ServiceInfo *list)
535{
536 unsigned int num_stopped = 0;
537 unsigned int num_started = 0;
538 unsigned int num_stopping = 0;
539 unsigned int num_failed = 0;
540 unsigned int num_finished = 0;
541 (void) cls;
542 op = NULL;
543 if (GNUNET_ARM_REQUEST_SENT_OK != rs)
544 {
545 char *msg;
546
547 GNUNET_asprintf (&msg,
548 "%s",
549 _ ("Failed to request a list of services: %s\n"));
550 fprintf (stdout,
551 msg,
552 req_string (rs));
553 GNUNET_free (msg);
554 ret = 3;
555 GNUNET_SCHEDULER_shutdown ();
556 }
557 if (NULL == list)
558 {
559 fprintf (stderr,
560 "%s",
561 _ ("Error communicating with ARM. ARM not running?\n"));
562 GNUNET_SCHEDULER_shutdown ();
563 ret = 3;
564 return;
565 }
566 for (unsigned int i = 0; i < count; i++)
567 {
568 switch (list[i].status)
569 {
570 case GNUNET_ARM_SERVICE_STATUS_STOPPED:
571 num_stopped++;
572 break;
573 case GNUNET_ARM_SERVICE_STATUS_FAILED:
574 num_failed++;
575 break;
576 case GNUNET_ARM_SERVICE_STATUS_FINISHED:
577 num_finished++;
578 break;
579 case GNUNET_ARM_SERVICE_STATUS_STARTED:
580 num_started++;
581 break;
582 case GNUNET_ARM_SERVICE_STATUS_STOPPING:
583 num_stopping++;
584 fprintf (stdout,
585 "%s (binary='%s', status=stopping)\n",
586 list[i].name,
587 list[i].binary);
588 break;
589 default:
590 GNUNET_break_op (0);
591 fprintf (stdout,
592 "%s (binary='%s', status=unknown)\n",
593 list[i].name,
594 list[i].binary);
595 break;
596 }
597 }
598 if (! quiet)
599 {
600 if (show_all)
601 fprintf (stdout,
602 "%s",
603 _ ("All services:\n"));
604 else
605 fprintf (stdout,
606 "%s",
607 _ ("Services (excluding stopped services):\n"));
608 if (num_stopped || num_failed || num_finished || num_stopping ||
609 num_started)
610 {
611 int sep = 0;
612 fprintf (stdout, "(");
613 if (0 != num_started)
614 {
615 if (sep)
616 fprintf (stdout, " / ");
617 fprintf (stdout,
618 "started: %u",
619 num_started);
620 sep = 1;
621 }
622 if (0 != num_failed)
623 {
624 if (sep)
625 fprintf (stdout, " / ");
626 fprintf (stdout,
627 "failed: %u",
628 num_failed);
629 sep = 1;
630 }
631 if (0 != num_stopping)
632 {
633 if (sep)
634 fprintf (stdout, " / ");
635 fprintf (stdout,
636 "stopping: %u",
637 num_stopping);
638 sep = 1;
639 }
640 if (0 != num_stopped)
641 {
642 if (sep)
643 fprintf (stdout, " / ");
644 fprintf (stdout,
645 "stopped: %u",
646 num_stopped);
647 sep = 1;
648 }
649 if (0 != num_finished)
650 {
651 if (sep)
652 fprintf (stdout, " / ");
653 fprintf (stdout,
654 "finished: %u",
655 num_finished);
656 sep = 1;
657 }
658 fprintf (stdout, ")\n");
659 }
660 else
661 {
662 fprintf (stdout,
663 "%s",
664 _ ("(No services configured.)\n"));
665 }
666 }
667 for (unsigned int i = 0; i < count; i++)
668 {
669 struct GNUNET_TIME_Relative restart_in;
670 switch (list[i].status)
671 {
672 case GNUNET_ARM_SERVICE_STATUS_STOPPED:
673 if (show_all)
674 fprintf (stdout,
675 "%s (binary='%s', status=stopped)\n",
676 list[i].name,
677 list[i].binary);
678 break;
679 case GNUNET_ARM_SERVICE_STATUS_FAILED:
680 restart_in = GNUNET_TIME_absolute_get_remaining (list[i].restart_at);
681 fprintf (stdout,
682 "%s (binary='%s', status=failed, exit_status=%d, restart_delay='%s')\n",
683 list[i].name,
684 list[i].binary,
685 list[i].last_exit_status,
686 GNUNET_STRINGS_relative_time_to_string (restart_in,
687 GNUNET_YES));
688 break;
689 case GNUNET_ARM_SERVICE_STATUS_FINISHED:
690 fprintf (stdout,
691 "%s (binary='%s', status=finished)\n",
692 list[i].name,
693 list[i].binary);
694 break;
695 case GNUNET_ARM_SERVICE_STATUS_STARTED:
696 fprintf (stdout,
697 "%s (binary='%s', status=started)\n",
698 list[i].name,
699 list[i].binary);
700 break;
701 case GNUNET_ARM_SERVICE_STATUS_STOPPING:
702 fprintf (stdout,
703 "%s (binary='%s', status=stopping)\n",
704 list[i].name,
705 list[i].binary);
706 break;
707 default:
708 GNUNET_break_op (0);
709 fprintf (stdout,
710 "%s (binary='%s', status=unknown)\n",
711 list[i].name,
712 list[i].binary);
713 break;
714 }
715 }
716 al_task = GNUNET_SCHEDULER_add_now (&action_loop,
717 NULL);
718}
719
720
721/**
722 * Main action loop. Runs the various jobs that we've been asked to
723 * do, in order.
724 *
725 * @param cls closure, unused
726 */
727static void
728action_loop (void *cls)
729{
730 (void) cls;
731 al_task = NULL;
732 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
733 "Running requested actions\n");
734 while (1)
735 {
736 switch (phase++)
737 {
738 case 0:
739 if (NULL != term)
740 {
741 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
742 "Termination action\n");
743 op = GNUNET_ARM_request_service_stop (h,
744 term,
745 &term_callback,
746 NULL);
747 return;
748 }
749 break;
750
751 case 1:
752 if (end || restart)
753 {
754 if (GNUNET_YES !=
755 GNUNET_CLIENT_test (cfg,
756 "arm"))
757 {
758 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
759 "GNUnet not running, cannot stop the peer\n");
760 }
761 else
762 {
763 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
764 "End action\n");
765 op = GNUNET_ARM_request_service_stop (h,
766 "arm",
767 &stop_callback,
768 NULL);
769 return;
770 }
771 }
772 break;
773
774 case 2:
775 if (start)
776 {
777 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
778 "Start action\n");
779 op =
780 GNUNET_ARM_request_service_start (h,
781 "arm",
782 (no_stdout
783 ? 0
784 : GNUNET_OS_INHERIT_STD_OUT)
785 | (no_stderr
786 ? 0
787 : GNUNET_OS_INHERIT_STD_ERR),
788 &start_callback,
789 NULL);
790 return;
791 }
792 break;
793
794 case 3:
795 if (NULL != init)
796 {
797 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
798 "Initialization action\n");
799 op = GNUNET_ARM_request_service_start (h,
800 init,
801 GNUNET_OS_INHERIT_STD_NONE,
802 &init_callback,
803 NULL);
804 return;
805 }
806 break;
807
808 case 4:
809 if (list)
810 {
811 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
812 "Going to list all running services controlled by ARM.\n");
813 op = GNUNET_ARM_request_service_list (h,
814 &list_callback,
815 &list);
816 return;
817 }
818 break;
819
820 case 5:
821 if (monitor)
822 {
823 if (! quiet)
824 fprintf (stderr,
825 _ ("Now only monitoring, press CTRL-C to stop.\n"));
826 quiet =
827 0; /* does not make sense to stay quiet in monitor mode at this time */
828 return; /* done with tasks, just monitor */
829 }
830 break;
831
832 default: /* last phase */
833 GNUNET_SCHEDULER_shutdown ();
834 return;
835 }
836 }
837}
838
839
840/**
841 * Function called when a service starts or stops.
842 *
843 * @param cls closure
844 * @param service service name
845 * @param status status of the service
846 */
847static void
848srv_status (void *cls,
849 const char *service,
850 enum GNUNET_ARM_ServiceMonitorStatus status)
851{
852 const char *msg;
853
854 (void) cls;
855 switch (status)
856 {
857 case GNUNET_ARM_SERVICE_MONITORING_STARTED:
858 return; /* this should be done silently */
859
860 case GNUNET_ARM_SERVICE_STOPPED:
861 msg = _ ("Stopped %s.\n");
862 break;
863
864 case GNUNET_ARM_SERVICE_STARTING:
865 msg = _ ("Starting %s...\n");
866 break;
867
868 case GNUNET_ARM_SERVICE_STOPPING:
869 msg = _ ("Stopping %s...\n");
870 break;
871
872 default:
873 msg = NULL;
874 break;
875 }
876 if (! quiet)
877 {
878 if (NULL != msg)
879 fprintf (stderr,
880 msg,
881 service);
882 else
883 fprintf (stderr,
884 _ ("Unknown status %u for service %s.\n"),
885 status,
886 service);
887 }
888 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
889 "Got service %s status %d\n",
890 service,
891 (int) status);
892}
893
894
895/**
896 * Task run on timeout (if -T is given).
897 */
898static void
899timeout_task_cb (void *cls)
900{
901 (void) cls;
902 timeout_task = NULL;
903 ret = 2;
904 GNUNET_SCHEDULER_shutdown ();
905}
906
907
908/**
909 * Main function that will be run by the scheduler.
910 *
911 * @param cls closure
912 * @param args remaining command-line arguments
913 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
914 * @param c configuration
915 */
916static void
917run (void *cls,
918 char *const *args,
919 const char *cfgfile,
920 const struct GNUNET_CONFIGURATION_Handle *c)
921{
922 (void) cls;
923 (void) args;
924 (void) cfgfile;
925 cfg = GNUNET_CONFIGURATION_dup (c);
926 if (GNUNET_OK !=
927 GNUNET_CONFIGURATION_get_value_string (cfg,
928 "PATHS",
929 "GNUNET_HOME",
930 &dir))
931 {
932 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
933 "PATHS",
934 "GNUNET_HOME");
935 return;
936 }
937 (void) GNUNET_CONFIGURATION_get_value_filename (cfg,
938 "arm",
939 "CONFIG",
940 &config_file);
941 if (NULL == (h = GNUNET_ARM_connect (cfg,
942 &conn_status,
943 NULL)))
944 return;
945 if (monitor)
946 m = GNUNET_ARM_monitor_start (cfg,
947 &srv_status,
948 NULL);
949 al_task = GNUNET_SCHEDULER_add_now (&action_loop,
950 NULL);
951 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
952 NULL);
953 if (0 != timeout.rel_value_us)
954 timeout_task =
955 GNUNET_SCHEDULER_add_delayed (timeout,
956 &timeout_task_cb,
957 NULL);
958}
959
960
961/**
962 * The main function to obtain arm from gnunetd.
963 *
964 * @param argc number of arguments from the command line
965 * @param argv command line arguments
966 * @return 0 ok, 1 on error, 2 on timeout
967 */
968int
969main (int argc, char *const *argv)
970{
971 struct GNUNET_GETOPT_CommandLineOption options[] = {
972 GNUNET_GETOPT_option_flag ('e',
973 "end",
974 gettext_noop ("stop all GNUnet services"),
975 &end),
976 GNUNET_GETOPT_option_string ('i',
977 "init",
978 "SERVICE",
979 gettext_noop ("start a particular service"),
980 &init),
981 GNUNET_GETOPT_option_string ('k',
982 "kill",
983 "SERVICE",
984 gettext_noop ("stop a particular service"),
985 &term),
986 GNUNET_GETOPT_option_flag ('a',
987 "all",
988 gettext_noop (
989 "also show stopped services (used with -I)"),
990 &show_all),
991 GNUNET_GETOPT_option_flag ('s',
992 "start",
993 gettext_noop (
994 "start all GNUnet default services"),
995 &start),
996 GNUNET_GETOPT_option_flag ('r',
997 "restart",
998 gettext_noop (
999 "stop and start all GNUnet default services"),
1000 &restart),
1001 GNUNET_GETOPT_option_flag ('d',
1002 "delete",
1003 gettext_noop (
1004 "delete config file and directory on exit"),
1005 &delete),
1006 GNUNET_GETOPT_option_flag ('m',
1007 "monitor",
1008 gettext_noop ("monitor ARM activities"),
1009 &monitor),
1010 GNUNET_GETOPT_option_flag ('q',
1011 "quiet",
1012 gettext_noop ("don't print status messages"),
1013 &quiet),
1014 GNUNET_GETOPT_option_relative_time (
1015 'T',
1016 "timeout",
1017 "DELAY",
1018 gettext_noop (
1019 "exit with error status if operation does not finish after DELAY"),
1020 &timeout),
1021 GNUNET_GETOPT_option_flag ('I',
1022 "info",
1023 gettext_noop (
1024 "list currently running services"),
1025 &list),
1026 GNUNET_GETOPT_option_flag (
1027 'O',
1028 "no-stdout",
1029 gettext_noop ("don't let gnunet-service-arm inherit standard output"),
1030 &no_stdout),
1031 GNUNET_GETOPT_option_flag (
1032 'E',
1033 "no-stderr",
1034 gettext_noop ("don't let gnunet-service-arm inherit standard error"),
1035 &no_stderr),
1036 GNUNET_GETOPT_OPTION_END
1037 };
1038 int lret;
1039
1040 if (GNUNET_OK !=
1041 GNUNET_STRINGS_get_utf8_args (argc,
1042 argv,
1043 &argc,
1044 &argv))
1045 return 2;
1046 if (GNUNET_OK ==
1047 (lret = GNUNET_PROGRAM_run (
1048 argc,
1049 argv,
1050 "gnunet-arm",
1051 gettext_noop (
1052 "Control services and the Automated Restart Manager (ARM)"),
1053 options,
1054 &run,
1055 NULL)))
1056 {
1057 GNUNET_free_nz ((void *) argv);
1058 return ret;
1059 }
1060 GNUNET_free_nz ((void *) argv);
1061 return lret;
1062}
1063
1064
1065/* end of gnunet-arm.c */