1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2009, 2010 Nedko Arnaudov <nedko@arnaudov.name>
7 **************************************************************************
8 * This file contains implementation of app supervisor object
9 **************************************************************************
11 * LADI Session Handler is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * LADI Session Handler is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with LADI Session Handler. If not, see <http://www.gnu.org/licenses/>
23 * or write to the Free Software Foundation, Inc.,
24 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include <sys/types.h>
30 #include "app_supervisor.h"
31 #include "../dbus/error.h"
32 #include "../dbus_constants.h"
34 #include "studio_internal.h"
35 #include "../proxies/notify_proxy.h"
39 struct list_head siblings
;
47 bool zombie
; /* if true, remove when stopped */
52 struct ladish_app_supervisor
59 struct list_head applist
;
60 void * on_app_renamed_context
;
61 ladish_app_supervisor_on_app_renamed_callback on_app_renamed
;
65 ladish_app_supervisor_create(
66 ladish_app_supervisor_handle
* supervisor_handle_ptr
,
70 ladish_app_supervisor_on_app_renamed_callback on_app_renamed
)
72 struct ladish_app_supervisor
* supervisor_ptr
;
74 supervisor_ptr
= malloc(sizeof(struct ladish_app_supervisor
));
75 if (supervisor_ptr
== NULL
)
77 log_error("malloc() failed to allocate struct ladish_app_supervisor");
81 supervisor_ptr
->opath
= strdup(opath
);
82 if (supervisor_ptr
->opath
== NULL
)
84 log_error("strdup() failed for app supervisor opath");
89 supervisor_ptr
->name
= strdup(name
);
90 if (supervisor_ptr
->name
== NULL
)
92 log_error("strdup() failed for app supervisor name");
93 free(supervisor_ptr
->opath
);
98 supervisor_ptr
->dir
= NULL
;
100 supervisor_ptr
->version
= 0;
101 supervisor_ptr
->next_id
= 1;
103 INIT_LIST_HEAD(&supervisor_ptr
->applist
);
105 supervisor_ptr
->on_app_renamed_context
= context
;
106 supervisor_ptr
->on_app_renamed
= on_app_renamed
;
108 *supervisor_handle_ptr
= (ladish_app_supervisor_handle
)supervisor_ptr
;
113 struct ladish_app
* ladish_app_supervisor_find_app_by_id_internal(struct ladish_app_supervisor
* supervisor_ptr
, uint64_t id
)
115 struct list_head
* node_ptr
;
116 struct ladish_app
* app_ptr
;
118 list_for_each(node_ptr
, &supervisor_ptr
->applist
)
120 app_ptr
= list_entry(node_ptr
, struct ladish_app
, siblings
);
121 if (app_ptr
->id
== id
)
130 void remove_app_internal(struct ladish_app_supervisor
* supervisor_ptr
, struct ladish_app
* app_ptr
)
132 ASSERT(app_ptr
->pid
== 0); /* Removing not-stoped app? Zombies will make a rebellion! */
134 list_del(&app_ptr
->siblings
);
136 supervisor_ptr
->version
++;
140 supervisor_ptr
->opath
,
141 IFACE_APP_SUPERVISOR
,
144 &supervisor_ptr
->version
,
148 free(app_ptr
->commandline
);
152 void emit_app_state_changed(struct ladish_app_supervisor
* supervisor_ptr
, struct ladish_app
* app_ptr
)
155 dbus_bool_t terminal
;
157 running
= app_ptr
->pid
!= 0;
158 terminal
= app_ptr
->terminal
;
160 supervisor_ptr
->version
++;
164 supervisor_ptr
->opath
,
165 IFACE_APP_SUPERVISOR
,
168 &supervisor_ptr
->version
,
176 #define supervisor_ptr ((struct ladish_app_supervisor *)supervisor_handle)
178 const char * ladish_app_supervisor_get_opath(ladish_app_supervisor_handle supervisor_handle
)
180 return supervisor_ptr
->opath
;
183 ladish_app_handle
ladish_app_supervisor_find_app_by_name(ladish_app_supervisor_handle supervisor_handle
, const char * name
)
185 struct list_head
* node_ptr
;
186 struct ladish_app
* app_ptr
;
188 list_for_each(node_ptr
, &supervisor_ptr
->applist
)
190 app_ptr
= list_entry(node_ptr
, struct ladish_app
, siblings
);
191 if (strcmp(app_ptr
->name
, name
) == 0)
193 return (ladish_app_handle
)app_ptr
;
200 ladish_app_handle
ladish_app_supervisor_find_app_by_id(ladish_app_supervisor_handle supervisor_handle
, uint64_t id
)
202 return (ladish_app_handle
)ladish_app_supervisor_find_app_by_id_internal(supervisor_ptr
, id
);
205 ladish_app_handle
ladish_app_supervisor_find_app_by_pid(ladish_app_supervisor_handle supervisor_handle
, pid_t pid
)
207 struct list_head
* node_ptr
;
208 struct ladish_app
* app_ptr
;
210 list_for_each(node_ptr
, &supervisor_ptr
->applist
)
212 app_ptr
= list_entry(node_ptr
, struct ladish_app
, siblings
);
213 if (app_ptr
->pid
== pid
)
215 //log_info("app \"%s\" found by pid %llu", app_ptr->name, (unsigned long long)pid);
216 return (ladish_app_handle
)app_ptr
;
224 ladish_app_supervisor_add(
225 ladish_app_supervisor_handle supervisor_handle
,
228 const char * command
,
232 struct ladish_app
* app_ptr
;
235 app_ptr
= malloc(sizeof(struct ladish_app
));
238 log_error("malloc of struct ladish_app failed");
242 app_ptr
->name
= strdup(name
);
243 if (app_ptr
->name
== NULL
)
245 log_error("strdup() failed for app name");
250 app_ptr
->commandline
= strdup(command
);
251 if (app_ptr
->commandline
== NULL
)
253 log_error("strdup() failed for app commandline");
259 app_ptr
->terminal
= terminal
;
260 app_ptr
->level
= level
;
263 app_ptr
->id
= supervisor_ptr
->next_id
++;
264 uuid_generate(app_ptr
->uuid
);
265 app_ptr
->zombie
= false;
266 app_ptr
->state
= LADISH_APP_STATE_STOPPED
;
267 app_ptr
->autorun
= autorun
;
268 list_add_tail(&app_ptr
->siblings
, &supervisor_ptr
->applist
);
270 supervisor_ptr
->version
++;
275 supervisor_ptr
->opath
,
276 IFACE_APP_SUPERVISOR
,
279 &supervisor_ptr
->version
,
286 return (ladish_app_handle
)app_ptr
;
289 static void ladish_app_send_signal(struct ladish_app
* app_ptr
, int sig
)
291 ASSERT(app_ptr
->state
= LADISH_APP_STATE_STARTED
);
292 if (app_ptr
->pid
<= 0)
297 kill(app_ptr
->pid
, sig
);
300 void ladish_app_supervisor_clear(ladish_app_supervisor_handle supervisor_handle
)
302 struct list_head
* node_ptr
;
303 struct list_head
* safe_node_ptr
;
304 struct ladish_app
* app_ptr
;
306 if (supervisor_ptr
->dir
!= NULL
)
308 free(supervisor_ptr
->dir
);
309 supervisor_ptr
->dir
= NULL
;
312 list_for_each_safe(node_ptr
, safe_node_ptr
, &supervisor_ptr
->applist
)
314 app_ptr
= list_entry(node_ptr
, struct ladish_app
, siblings
);
315 if (app_ptr
->pid
!= 0)
317 log_info("terminating '%s'...", app_ptr
->name
);
318 ladish_app_send_signal(app_ptr
, SIGTERM
);
319 app_ptr
->zombie
= true;
320 app_ptr
->state
= LADISH_APP_STATE_STOPPING
;
324 log_info("removing '%s'", app_ptr
->name
);
325 remove_app_internal(supervisor_ptr
, app_ptr
);
330 void ladish_app_supervisor_destroy(ladish_app_supervisor_handle supervisor_handle
)
332 ladish_app_supervisor_clear(supervisor_handle
);
333 free(supervisor_ptr
->name
);
334 free(supervisor_ptr
->opath
);
335 free(supervisor_ptr
);
339 ladish_app_supervisor_set_directory(
340 ladish_app_supervisor_handle supervisor_handle
,
348 log_error("strdup(\"%s\") failed", dir
);
352 if (supervisor_ptr
->dir
!= NULL
)
354 free(supervisor_ptr
->dir
);
357 supervisor_ptr
->dir
= dup
;
362 bool ladish_app_supervisor_child_exit(ladish_app_supervisor_handle supervisor_handle
, pid_t pid
)
364 struct list_head
* node_ptr
;
365 struct ladish_app
* app_ptr
;
367 list_for_each(node_ptr
, &supervisor_ptr
->applist
)
369 app_ptr
= list_entry(node_ptr
, struct ladish_app
, siblings
);
370 if (app_ptr
->pid
== pid
)
372 log_info("exit of child '%s' detected.", app_ptr
->name
);
377 remove_app_internal(supervisor_ptr
, app_ptr
);
381 if (app_ptr
->state
== LADISH_APP_STATE_STARTED
)
383 ladish_notify_simple(LADISH_NOTIFY_URGENCY_HIGH
, "App terminated unexpectedly", app_ptr
->name
);
386 app_ptr
->state
= LADISH_APP_STATE_STOPPED
;
388 emit_app_state_changed(supervisor_ptr
, app_ptr
);
399 ladish_app_supervisor_enum(
400 ladish_app_supervisor_handle supervisor_handle
,
402 ladish_app_supervisor_enum_callback callback
)
404 struct list_head
* node_ptr
;
405 struct ladish_app
* app_ptr
;
407 list_for_each(node_ptr
, &supervisor_ptr
->applist
)
409 app_ptr
= list_entry(node_ptr
, struct ladish_app
, siblings
);
411 if (!callback(context
, app_ptr
->name
, app_ptr
->pid
!= 0, app_ptr
->commandline
, app_ptr
->terminal
, app_ptr
->level
, app_ptr
->pid
, app_ptr
->uuid
))
420 #define app_ptr ((struct ladish_app *)app_handle)
422 bool ladish_app_supervisor_start_app(ladish_app_supervisor_handle supervisor_handle
, ladish_app_handle app_handle
)
424 app_ptr
->zombie
= false;
426 ASSERT(app_ptr
->pid
== 0);
429 supervisor_ptr
->name
,
431 supervisor_ptr
->dir
!= NULL
? supervisor_ptr
->dir
: "/",
433 app_ptr
->commandline
,
439 ASSERT(app_ptr
->pid
!= 0);
440 app_ptr
->state
= LADISH_APP_STATE_STARTED
;
442 emit_app_state_changed(supervisor_ptr
, app_ptr
);
446 void ladish_app_supervisor_remove_app(ladish_app_supervisor_handle supervisor_handle
, ladish_app_handle app_handle
)
448 remove_app_internal(supervisor_ptr
, app_ptr
);
451 unsigned int ladish_app_get_state(ladish_app_handle app_handle
)
453 return app_ptr
->state
;
456 bool ladish_app_is_running(ladish_app_handle app_handle
)
458 return app_ptr
->pid
!= 0;
461 const char * ladish_app_get_name(ladish_app_handle app_handle
)
463 return app_ptr
->name
;
466 void ladish_app_get_uuid(ladish_app_handle app_handle
, uuid_t uuid
)
468 uuid_copy(uuid
, app_ptr
->uuid
);
471 void ladish_app_stop(ladish_app_handle app_handle
)
473 ladish_app_send_signal(app_ptr
, SIGTERM
);
474 app_ptr
->state
= LADISH_APP_STATE_STOPPING
;
477 void ladish_app_kill(ladish_app_handle app_handle
)
479 ladish_app_send_signal(app_ptr
, SIGKILL
);
480 app_ptr
->state
= LADISH_APP_STATE_KILL
;
483 void ladish_app_save_L1(ladish_app_handle app_handle
)
485 if (app_ptr
->level
== 1)
487 log_info("sending SIGUSR1 to '%s' with pid %u", app_ptr
->name
, (unsigned int)app_ptr
->pid
);
488 ladish_app_send_signal(app_ptr
, SIGUSR1
);
494 void ladish_app_supervisor_autorun(ladish_app_supervisor_handle supervisor_handle
)
496 struct list_head
* node_ptr
;
497 struct ladish_app
* app_ptr
;
499 list_for_each(node_ptr
, &supervisor_ptr
->applist
)
501 app_ptr
= list_entry(node_ptr
, struct ladish_app
, siblings
);
503 if (!app_ptr
->autorun
)
508 app_ptr
->autorun
= false;
510 log_info("autorun('%s', %s, '%s') called", app_ptr
->name
, app_ptr
->terminal
? "terminal" : "shell", app_ptr
->commandline
);
512 if (!ladish_app_supervisor_start_app((ladish_app_supervisor_handle
)supervisor_ptr
, (ladish_app_handle
)app_ptr
))
514 log_error("Execution of '%s' failed", app_ptr
->commandline
);
520 void ladish_app_supervisor_stop(ladish_app_supervisor_handle supervisor_handle
)
522 struct list_head
* node_ptr
;
523 struct ladish_app
* app_ptr
;
525 list_for_each(node_ptr
, &supervisor_ptr
->applist
)
527 app_ptr
= list_entry(node_ptr
, struct ladish_app
, siblings
);
528 if (app_ptr
->pid
!= 0)
530 log_info("terminating '%s'...", app_ptr
->name
);
531 ladish_app_send_signal(app_ptr
, SIGTERM
);
532 app_ptr
->autorun
= true;
533 app_ptr
->state
= LADISH_APP_STATE_STOPPING
;
538 void ladish_app_supervisor_save_L1(ladish_app_supervisor_handle supervisor_handle
)
540 struct list_head
* node_ptr
;
541 struct ladish_app
* app_ptr
;
543 list_for_each(node_ptr
, &supervisor_ptr
->applist
)
545 app_ptr
= list_entry(node_ptr
, struct ladish_app
, siblings
);
546 if (app_ptr
->state
!= LADISH_APP_STATE_STARTED
)
551 if (app_ptr
->pid
== 0)
557 if (app_ptr
->level
== 1)
559 log_info("sending SIGUSR1 to '%s' with pid %u", app_ptr
->name
, (unsigned int)app_ptr
->pid
);
560 ladish_app_send_signal(app_ptr
, SIGUSR1
);
565 const char * ladish_app_supervisor_get_name(ladish_app_supervisor_handle supervisor_handle
)
567 return supervisor_ptr
->name
;
570 unsigned int ladish_app_supervisor_get_running_app_count(ladish_app_supervisor_handle supervisor_handle
)
572 struct list_head
* node_ptr
;
573 struct ladish_app
* app_ptr
;
574 unsigned int counter
;
577 list_for_each(node_ptr
, &supervisor_ptr
->applist
)
579 app_ptr
= list_entry(node_ptr
, struct ladish_app
, siblings
);
580 if (app_ptr
->pid
!= 0)
589 bool ladish_app_supervisor_has_apps(ladish_app_supervisor_handle supervisor_handle
)
591 return !list_empty(&supervisor_ptr
->applist
);
594 #undef supervisor_ptr
596 /**********************************************************************************/
598 /**********************************************************************************/
600 #define supervisor_ptr ((struct ladish_app_supervisor *)call_ptr->iface_context)
602 static void get_all(struct dbus_method_call
* call_ptr
)
604 DBusMessageIter iter
, array_iter
, struct_iter
;
605 struct list_head
* node_ptr
;
606 struct ladish_app
* app_ptr
;
608 dbus_bool_t terminal
;
610 //log_info("get_all called");
612 call_ptr
->reply
= dbus_message_new_method_return(call_ptr
->message
);
613 if (call_ptr
->reply
== NULL
)
618 dbus_message_iter_init_append(call_ptr
->reply
, &iter
);
620 if (!dbus_message_iter_append_basic(&iter
, DBUS_TYPE_UINT64
, &supervisor_ptr
->version
))
625 if (!dbus_message_iter_open_container(&iter
, DBUS_TYPE_ARRAY
, "(tsbby)", &array_iter
))
630 list_for_each(node_ptr
, &supervisor_ptr
->applist
)
632 app_ptr
= list_entry(node_ptr
, struct ladish_app
, siblings
);
634 log_info("app '%s' (%llu)", app_ptr
->name
, (unsigned long long)app_ptr
->id
);
636 if (!dbus_message_iter_open_container (&array_iter
, DBUS_TYPE_STRUCT
, NULL
, &struct_iter
))
641 if (!dbus_message_iter_append_basic(&struct_iter
, DBUS_TYPE_UINT64
, &app_ptr
->id
))
646 if (!dbus_message_iter_append_basic(&struct_iter
, DBUS_TYPE_STRING
, &app_ptr
->name
))
651 running
= app_ptr
->pid
!= 0;
652 if (!dbus_message_iter_append_basic(&struct_iter
, DBUS_TYPE_BOOLEAN
, &running
))
657 terminal
= app_ptr
->terminal
;
658 if (!dbus_message_iter_append_basic(&struct_iter
, DBUS_TYPE_BOOLEAN
, &terminal
))
663 if (!dbus_message_iter_append_basic(&struct_iter
, DBUS_TYPE_BYTE
, &app_ptr
->level
))
668 if (!dbus_message_iter_close_container(&array_iter
, &struct_iter
))
674 if (!dbus_message_iter_close_container(&iter
, &array_iter
))
682 dbus_message_unref(call_ptr
->reply
);
683 call_ptr
->reply
= NULL
;
686 log_error("Ran out of memory trying to construct method return");
689 static void run_custom(struct dbus_method_call
* call_ptr
)
691 dbus_bool_t terminal
;
692 const char * commandline
;
696 if (!dbus_message_get_args(
699 DBUS_TYPE_BOOLEAN
, &terminal
,
700 DBUS_TYPE_STRING
, &commandline
,
701 DBUS_TYPE_STRING
, &name
,
702 DBUS_TYPE_BYTE
, &level
,
705 lash_dbus_error(call_ptr
, LASH_DBUS_ERROR_INVALID_ARGS
, "Invalid arguments to method \"%s\": %s", call_ptr
->method_name
, g_dbus_error
.message
);
706 dbus_error_free(&g_dbus_error
);
710 log_info("run_custom('%s', %s, '%s', %"PRIu8
") called", name
, terminal
? "terminal" : "shell", commandline
, level
);
712 if (level
!= 0 && level
!= 1)
714 lash_dbus_error(call_ptr
, LASH_DBUS_ERROR_INVALID_ARGS
, "invalid level %"PRIu8
, level
);
718 if (ladish_command_new_app(
720 ladish_studio_get_cmd_queue(),
721 supervisor_ptr
->opath
,
727 method_return_new_void(call_ptr
);
731 static void start_app(struct dbus_method_call
* call_ptr
)
735 if (!dbus_message_get_args(
738 DBUS_TYPE_UINT64
, &id
,
741 lash_dbus_error(call_ptr
, LASH_DBUS_ERROR_INVALID_ARGS
, "Invalid arguments to method \"%s\": %s", call_ptr
->method_name
, g_dbus_error
.message
);
742 dbus_error_free(&g_dbus_error
);
746 if (ladish_command_change_app_state(call_ptr
, ladish_studio_get_cmd_queue(), supervisor_ptr
->opath
, id
, LADISH_APP_STATE_STARTED
))
748 method_return_new_void(call_ptr
);
752 static void stop_app(struct dbus_method_call
* call_ptr
)
756 if (!dbus_message_get_args(
759 DBUS_TYPE_UINT64
, &id
,
762 lash_dbus_error(call_ptr
, LASH_DBUS_ERROR_INVALID_ARGS
, "Invalid arguments to method \"%s\": %s", call_ptr
->method_name
, g_dbus_error
.message
);
763 dbus_error_free(&g_dbus_error
);
767 if (ladish_command_change_app_state(call_ptr
, ladish_studio_get_cmd_queue(), supervisor_ptr
->opath
, id
, LADISH_APP_STATE_STOPPED
))
769 method_return_new_void(call_ptr
);
773 static void kill_app(struct dbus_method_call
* call_ptr
)
777 if (!dbus_message_get_args(
780 DBUS_TYPE_UINT64
, &id
,
783 lash_dbus_error(call_ptr
, LASH_DBUS_ERROR_INVALID_ARGS
, "Invalid arguments to method \"%s\": %s", call_ptr
->method_name
, g_dbus_error
.message
);
784 dbus_error_free(&g_dbus_error
);
788 if (ladish_command_change_app_state(call_ptr
, ladish_studio_get_cmd_queue(), supervisor_ptr
->opath
, id
, LADISH_APP_STATE_KILL
))
790 method_return_new_void(call_ptr
);
794 static void get_app_properties(struct dbus_method_call
* call_ptr
)
797 struct ladish_app
* app_ptr
;
799 dbus_bool_t terminal
;
801 if (!dbus_message_get_args(
804 DBUS_TYPE_UINT64
, &id
,
807 lash_dbus_error(call_ptr
, LASH_DBUS_ERROR_INVALID_ARGS
, "Invalid arguments to method \"%s\": %s", call_ptr
->method_name
, g_dbus_error
.message
);
808 dbus_error_free(&g_dbus_error
);
812 app_ptr
= ladish_app_supervisor_find_app_by_id_internal(supervisor_ptr
, id
);
815 lash_dbus_error(call_ptr
, LASH_DBUS_ERROR_INVALID_ARGS
, "App with ID %"PRIu64
" not found", id
);
819 running
= app_ptr
->pid
!= 0;
820 terminal
= app_ptr
->terminal
;
822 call_ptr
->reply
= dbus_message_new_method_return(call_ptr
->message
);
823 if (call_ptr
->reply
== NULL
)
828 if (!dbus_message_append_args(
830 DBUS_TYPE_STRING
, &app_ptr
->name
,
831 DBUS_TYPE_STRING
, &app_ptr
->commandline
,
832 DBUS_TYPE_BOOLEAN
, &running
,
833 DBUS_TYPE_BOOLEAN
, &terminal
,
834 DBUS_TYPE_BYTE
, &app_ptr
->level
,
843 dbus_message_unref(call_ptr
->reply
);
844 call_ptr
->reply
= NULL
;
847 log_error("Ran out of memory trying to construct method return");
850 static void set_app_properties(struct dbus_method_call
* call_ptr
)
853 dbus_bool_t terminal
;
855 const char * commandline
;
857 struct ladish_app
* app_ptr
;
859 char * commandline_buffer
;
861 if (!dbus_message_get_args(
864 DBUS_TYPE_UINT64
, &id
,
865 DBUS_TYPE_STRING
, &name
,
866 DBUS_TYPE_STRING
, &commandline
,
867 DBUS_TYPE_BOOLEAN
, &terminal
,
868 DBUS_TYPE_BYTE
, &level
,
871 lash_dbus_error(call_ptr
, LASH_DBUS_ERROR_INVALID_ARGS
, "Invalid arguments to method \"%s\": %s", call_ptr
->method_name
, g_dbus_error
.message
);
872 dbus_error_free(&g_dbus_error
);
876 app_ptr
= ladish_app_supervisor_find_app_by_id_internal(supervisor_ptr
, id
);
879 lash_dbus_error(call_ptr
, LASH_DBUS_ERROR_INVALID_ARGS
, "App with ID %"PRIu64
" not found", id
);
883 if (app_ptr
->pid
!= 0 && strcmp(commandline
, app_ptr
->commandline
) != 0)
885 lash_dbus_error(call_ptr
, LASH_DBUS_ERROR_GENERIC
, "Cannot change commandline when app is running. '%s' -> '%s'", app_ptr
->commandline
, commandline
);
889 if (app_ptr
->pid
!= 0 && ((app_ptr
->terminal
&& !terminal
) || (!app_ptr
->terminal
&& terminal
)))
891 lash_dbus_error(call_ptr
, LASH_DBUS_ERROR_GENERIC
, "Cannot change whether to run in terminal when app is running");
895 if (app_ptr
->pid
!= 0 && app_ptr
->level
!= level
)
897 lash_dbus_error(call_ptr
, LASH_DBUS_ERROR_GENERIC
, "Cannot change app level when app is running");
901 if (strcmp(commandline
, app_ptr
->commandline
) != 0)
903 commandline_buffer
= strdup(commandline
);
904 if (commandline_buffer
== NULL
)
906 lash_dbus_error(call_ptr
, LASH_DBUS_ERROR_GENERIC
, "strdup() failed for app commandline");
912 commandline_buffer
= NULL
;
915 if (strcmp(name
, app_ptr
->name
) != 0)
917 name_buffer
= strdup(name
);
918 if (name_buffer
== NULL
)
920 lash_dbus_error(call_ptr
, LASH_DBUS_ERROR_GENERIC
, "strdup() failed for app nam");
921 if (commandline_buffer
!= NULL
)
923 free(commandline_buffer
);
933 if (name_buffer
!= NULL
)
935 supervisor_ptr
->on_app_renamed(supervisor_ptr
->on_app_renamed_context
, app_ptr
->uuid
, app_ptr
->name
, name_buffer
);
937 app_ptr
->name
= name_buffer
;
940 if (commandline_buffer
!= NULL
)
942 free(app_ptr
->commandline
);
943 app_ptr
->commandline
= commandline_buffer
;
946 app_ptr
->level
= level
;
947 app_ptr
->terminal
= terminal
;
949 emit_app_state_changed(supervisor_ptr
, app_ptr
);
951 method_return_new_void(call_ptr
);
954 static void remove_app(struct dbus_method_call
* call_ptr
)
958 if (!dbus_message_get_args(
961 DBUS_TYPE_UINT64
, &id
,
964 lash_dbus_error(call_ptr
, LASH_DBUS_ERROR_INVALID_ARGS
, "Invalid arguments to method \"%s\": %s", call_ptr
->method_name
, g_dbus_error
.message
);
965 dbus_error_free(&g_dbus_error
);
969 if (ladish_command_remove_app(call_ptr
, ladish_studio_get_cmd_queue(), supervisor_ptr
->opath
, id
))
971 method_return_new_void(call_ptr
);
975 static void is_app_running(struct dbus_method_call
* call_ptr
)
978 struct ladish_app
* app_ptr
;
981 if (!dbus_message_get_args(
984 DBUS_TYPE_UINT64
, &id
,
987 lash_dbus_error(call_ptr
, LASH_DBUS_ERROR_INVALID_ARGS
, "Invalid arguments to method \"%s\": %s", call_ptr
->method_name
, g_dbus_error
.message
);
988 dbus_error_free(&g_dbus_error
);
992 app_ptr
= ladish_app_supervisor_find_app_by_id_internal(supervisor_ptr
, id
);
995 lash_dbus_error(call_ptr
, LASH_DBUS_ERROR_INVALID_ARGS
, "App with ID %"PRIu64
" not found", id
);
999 running
= app_ptr
->pid
!= 0;
1001 method_return_new_single(call_ptr
, DBUS_TYPE_BOOLEAN
, &running
);
1004 #undef supervisor_ptr
1006 METHOD_ARGS_BEGIN(GetAll
, "Get list of apps")
1007 METHOD_ARG_DESCRIBE_OUT("list_version", DBUS_TYPE_UINT64_AS_STRING
, "Version of the list")
1008 METHOD_ARG_DESCRIBE_OUT("apps_list", "a(tsbby)", "List of apps")
1011 METHOD_ARGS_BEGIN(RunCustom
, "Start application by supplying commandline")
1012 METHOD_ARG_DESCRIBE_IN("terminal", DBUS_TYPE_BOOLEAN_AS_STRING
, "Whether to run in terminal")
1013 METHOD_ARG_DESCRIBE_IN("commandline", DBUS_TYPE_STRING_AS_STRING
, "Commandline")
1014 METHOD_ARG_DESCRIBE_IN("name", DBUS_TYPE_STRING_AS_STRING
, "Name")
1015 METHOD_ARG_DESCRIBE_IN("level", DBUS_TYPE_BYTE_AS_STRING
, "Level")
1018 METHOD_ARGS_BEGIN(StartApp
, "Start application")
1019 METHOD_ARG_DESCRIBE_IN("id", DBUS_TYPE_UINT64_AS_STRING
, "id of app")
1022 METHOD_ARGS_BEGIN(StopApp
, "Stop application")
1023 METHOD_ARG_DESCRIBE_IN("id", DBUS_TYPE_UINT64_AS_STRING
, "id of app")
1026 METHOD_ARGS_BEGIN(KillApp
, "Kill application")
1027 METHOD_ARG_DESCRIBE_IN("id", DBUS_TYPE_UINT64_AS_STRING
, "id of app")
1030 METHOD_ARGS_BEGIN(RemoveApp
, "Remove application")
1031 METHOD_ARG_DESCRIBE_IN("id", DBUS_TYPE_UINT64_AS_STRING
, "id of app")
1034 METHOD_ARGS_BEGIN(GetAppProperties
, "Get properties of an application")
1035 METHOD_ARG_DESCRIBE_IN("id", DBUS_TYPE_UINT64_AS_STRING
, "id of app")
1036 METHOD_ARG_DESCRIBE_OUT("name", DBUS_TYPE_STRING_AS_STRING
, "")
1037 METHOD_ARG_DESCRIBE_OUT("commandline", DBUS_TYPE_STRING_AS_STRING
, "Commandline")
1038 METHOD_ARG_DESCRIBE_OUT("running", DBUS_TYPE_BOOLEAN_AS_STRING
, "")
1039 METHOD_ARG_DESCRIBE_OUT("terminal", DBUS_TYPE_BOOLEAN_AS_STRING
, "Whether to run in terminal")
1040 METHOD_ARG_DESCRIBE_OUT("level", DBUS_TYPE_BYTE_AS_STRING
, "Level")
1043 METHOD_ARGS_BEGIN(SetAppProperties
, "Set properties of an application")
1044 METHOD_ARG_DESCRIBE_IN("id", DBUS_TYPE_UINT64_AS_STRING
, "id of app")
1045 METHOD_ARG_DESCRIBE_IN("name", DBUS_TYPE_STRING_AS_STRING
, "")
1046 METHOD_ARG_DESCRIBE_IN("commandline", DBUS_TYPE_STRING_AS_STRING
, "Commandline")
1047 METHOD_ARG_DESCRIBE_IN("terminal", DBUS_TYPE_BOOLEAN_AS_STRING
, "Whether to run in terminal")
1048 METHOD_ARG_DESCRIBE_IN("level", DBUS_TYPE_BYTE_AS_STRING
, "Level")
1051 METHOD_ARGS_BEGIN(IsAppRunning
, "Check whether application is running")
1052 METHOD_ARG_DESCRIBE_IN("id", DBUS_TYPE_UINT64_AS_STRING
, "id of app")
1053 METHOD_ARG_DESCRIBE_IN("terminal", DBUS_TYPE_BOOLEAN_AS_STRING
, "Whether app is running")
1058 METHOD_DESCRIBE(GetAll
, get_all
) /* sync */
1059 METHOD_DESCRIBE(RunCustom
, run_custom
) /* async */
1060 METHOD_DESCRIBE(StartApp
, start_app
) /* async */
1061 METHOD_DESCRIBE(StopApp
, stop_app
) /* async */
1062 METHOD_DESCRIBE(KillApp
, kill_app
) /* async */
1063 METHOD_DESCRIBE(GetAppProperties
, get_app_properties
) /* sync */
1064 METHOD_DESCRIBE(SetAppProperties
, set_app_properties
) /* sync */
1065 METHOD_DESCRIBE(RemoveApp
, remove_app
) /* sync */
1066 METHOD_DESCRIBE(IsAppRunning
, is_app_running
) /* sync */
1069 SIGNAL_ARGS_BEGIN(AppAdded
, "")
1070 SIGNAL_ARG_DESCRIBE("new_list_version", DBUS_TYPE_UINT64_AS_STRING
, "")
1071 SIGNAL_ARG_DESCRIBE("id", DBUS_TYPE_UINT64_AS_STRING
, "")
1072 SIGNAL_ARG_DESCRIBE("name", DBUS_TYPE_STRING_AS_STRING
, "")
1073 SIGNAL_ARG_DESCRIBE("running", DBUS_TYPE_BOOLEAN_AS_STRING
, "")
1074 SIGNAL_ARG_DESCRIBE("terminal", DBUS_TYPE_BOOLEAN_AS_STRING
, "Whether to run in terminal")
1075 SIGNAL_ARG_DESCRIBE("level", DBUS_TYPE_BYTE_AS_STRING
, "Level")
1078 SIGNAL_ARGS_BEGIN(AppRemoved
, "")
1079 SIGNAL_ARG_DESCRIBE("new_list_version", DBUS_TYPE_UINT64_AS_STRING
, "")
1080 SIGNAL_ARG_DESCRIBE("id", DBUS_TYPE_UINT64_AS_STRING
, "")
1083 SIGNAL_ARGS_BEGIN(AppStateChanged
, "")
1084 SIGNAL_ARG_DESCRIBE("new_list_version", DBUS_TYPE_UINT64_AS_STRING
, "")
1085 SIGNAL_ARG_DESCRIBE("id", DBUS_TYPE_UINT64_AS_STRING
, "")
1086 SIGNAL_ARG_DESCRIBE("name", DBUS_TYPE_STRING_AS_STRING
, "")
1087 SIGNAL_ARG_DESCRIBE("running", DBUS_TYPE_BOOLEAN_AS_STRING
, "")
1088 SIGNAL_ARG_DESCRIBE("terminal", DBUS_TYPE_BOOLEAN_AS_STRING
, "Whether to run in terminal")
1089 SIGNAL_ARG_DESCRIBE("level", DBUS_TYPE_BYTE_AS_STRING
, "Level")
1093 SIGNAL_DESCRIBE(AppAdded
)
1094 SIGNAL_DESCRIBE(AppRemoved
)
1095 SIGNAL_DESCRIBE(AppStateChanged
)
1098 INTERFACE_BEGIN(g_iface_app_supervisor
, IFACE_APP_SUPERVISOR
)
1099 INTERFACE_DEFAULT_HANDLER
1100 INTERFACE_EXPOSE_METHODS
1101 INTERFACE_EXPOSE_SIGNALS