Make the app supervisor interface versioned
[ladish.git] / daemon / app_supervisor.c
blob0b78448165a3373ed8d884aab489ec4e64978667
1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2009, 2010, 2011 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 "config.h" /* Get _GNU_SOURCE defenition first to have some GNU extension available */
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <signal.h>
32 #include <unistd.h>
34 #include "app_supervisor.h"
35 #include "../dbus/error.h"
36 #include "../dbus_constants.h"
37 #include "loader.h"
38 #include "studio_internal.h"
39 #include "../proxies/notify_proxy.h"
40 #include "../proxies/lash_client_proxy.h"
41 #include "../common/catdup.h"
42 #include "../common/dirhelpers.h"
44 struct ladish_app
46 struct list_head siblings;
47 uint64_t id;
48 uuid_t uuid;
49 char * name;
50 char * commandline;
51 bool terminal;
52 char level[MAX_LEVEL_CHARCOUNT];
53 pid_t pid;
54 pid_t pgrp;
55 pid_t firstborn_pid;
56 pid_t firstborn_pgrp;
57 int firstborn_refcount;
58 bool zombie; /* if true, remove when stopped */
59 bool autorun;
60 unsigned int state;
61 char * dbus_name;
62 struct ladish_app_supervisor * supervisor;
65 struct ladish_app_supervisor
67 char * name;
68 char * opath;
69 char * dir;
70 char * project_name;
71 uint64_t version;
72 uint64_t next_id;
73 struct list_head applist;
74 void * on_app_renamed_context;
75 ladish_app_supervisor_on_app_renamed_callback on_app_renamed;
78 bool ladish_check_app_level_validity(const char * level, size_t * len_ptr)
80 size_t len;
81 len = strlen(level);
82 if (len >= MAX_LEVEL_CHARCOUNT)
84 return false;
87 if (strcmp(level, LADISH_APP_LEVEL_0) != 0 &&
88 strcmp(level, LADISH_APP_LEVEL_1) != 0&&
89 strcmp(level, LADISH_APP_LEVEL_LASH) != 0)
91 return false;
94 if (len_ptr != NULL)
96 *len_ptr = len;
99 return true;
102 static int ladish_level_string_to_integer(const char * level)
104 if (strcmp(level, LADISH_APP_LEVEL_0) == 0)
106 return 0;
108 else if (strcmp(level, LADISH_APP_LEVEL_1) == 0)
110 return 1;
112 else if (strcmp(level, LADISH_APP_LEVEL_LASH) == 0 ||
113 strcmp(level, LADISH_APP_LEVEL_JACKSESSION) == 0)
115 return 2;
118 ASSERT_NO_PASS;
119 return 255;
122 bool
123 ladish_app_supervisor_create(
124 ladish_app_supervisor_handle * supervisor_handle_ptr,
125 const char * opath,
126 const char * name,
127 void * context,
128 ladish_app_supervisor_on_app_renamed_callback on_app_renamed)
130 struct ladish_app_supervisor * supervisor_ptr;
132 supervisor_ptr = malloc(sizeof(struct ladish_app_supervisor));
133 if (supervisor_ptr == NULL)
135 log_error("malloc() failed to allocate struct ladish_app_supervisor");
136 return false;
139 supervisor_ptr->opath = strdup(opath);
140 if (supervisor_ptr->opath == NULL)
142 log_error("strdup() failed for app supervisor opath");
143 free(supervisor_ptr);
144 return false;
147 supervisor_ptr->name = strdup(name);
148 if (supervisor_ptr->name == NULL)
150 log_error("strdup() failed for app supervisor name");
151 free(supervisor_ptr->opath);
152 free(supervisor_ptr);
153 return false;
156 supervisor_ptr->dir = NULL;
157 supervisor_ptr->project_name = NULL;
159 supervisor_ptr->version = 0;
160 supervisor_ptr->next_id = 1;
162 INIT_LIST_HEAD(&supervisor_ptr->applist);
164 supervisor_ptr->on_app_renamed_context = context;
165 supervisor_ptr->on_app_renamed = on_app_renamed;
167 *supervisor_handle_ptr = (ladish_app_supervisor_handle)supervisor_ptr;
169 return true;
172 struct ladish_app * ladish_app_supervisor_find_app_by_id_internal(struct ladish_app_supervisor * supervisor_ptr, uint64_t id)
174 struct list_head * node_ptr;
175 struct ladish_app * app_ptr;
177 list_for_each(node_ptr, &supervisor_ptr->applist)
179 app_ptr = list_entry(node_ptr, struct ladish_app, siblings);
180 if (app_ptr->id == id)
182 return app_ptr;
186 return NULL;
189 void remove_app_internal(struct ladish_app_supervisor * supervisor_ptr, struct ladish_app * app_ptr)
191 ASSERT(app_ptr->pid == 0); /* Removing not-stoped app? Zombies will make a rebellion! */
193 list_del(&app_ptr->siblings);
195 supervisor_ptr->version++;
197 dbus_signal_emit(
198 cdbus_g_dbus_connection,
199 supervisor_ptr->opath,
200 IFACE_APP_SUPERVISOR,
201 "AppRemoved",
202 "tt",
203 &supervisor_ptr->version,
204 &app_ptr->id);
206 free(app_ptr->dbus_name);
207 free(app_ptr->name);
208 free(app_ptr->commandline);
209 free(app_ptr);
212 void emit_app_state_changed(struct ladish_app_supervisor * supervisor_ptr, struct ladish_app * app_ptr)
214 dbus_bool_t running;
215 dbus_bool_t terminal;
216 const char * level_str;
217 uint8_t level_byte;
219 running = app_ptr->pid != 0;
220 terminal = app_ptr->terminal;
221 level_str = app_ptr->level;
222 level_byte = ladish_level_string_to_integer(app_ptr->level);
224 supervisor_ptr->version++;
226 dbus_signal_emit(
227 cdbus_g_dbus_connection,
228 supervisor_ptr->opath,
229 IFACE_APP_SUPERVISOR,
230 "AppStateChanged",
231 "ttsbby",
232 &supervisor_ptr->version,
233 &app_ptr->id,
234 &app_ptr->name,
235 &running,
236 &terminal,
237 &level_byte);
239 dbus_signal_emit(
240 cdbus_g_dbus_connection,
241 supervisor_ptr->opath,
242 IFACE_APP_SUPERVISOR,
243 "AppStateChanged2",
244 "ttsbbs",
245 &supervisor_ptr->version,
246 &app_ptr->id,
247 &app_ptr->name,
248 &running,
249 &terminal,
250 &level_str);
253 #define supervisor_ptr ((struct ladish_app_supervisor *)supervisor_handle)
255 const char * ladish_app_supervisor_get_opath(ladish_app_supervisor_handle supervisor_handle)
257 return supervisor_ptr->opath;
260 ladish_app_handle ladish_app_supervisor_find_app_by_name(ladish_app_supervisor_handle supervisor_handle, const char * name)
262 struct list_head * node_ptr;
263 struct ladish_app * app_ptr;
265 list_for_each(node_ptr, &supervisor_ptr->applist)
267 app_ptr = list_entry(node_ptr, struct ladish_app, siblings);
268 if (strcmp(app_ptr->name, name) == 0)
270 return (ladish_app_handle)app_ptr;
274 return NULL;
277 ladish_app_handle ladish_app_supervisor_find_app_by_id(ladish_app_supervisor_handle supervisor_handle, uint64_t id)
279 return (ladish_app_handle)ladish_app_supervisor_find_app_by_id_internal(supervisor_ptr, id);
282 ladish_app_handle ladish_app_supervisor_find_app_by_pid(ladish_app_supervisor_handle supervisor_handle, pid_t pid)
284 struct list_head * node_ptr;
285 struct ladish_app * app_ptr;
287 list_for_each(node_ptr, &supervisor_ptr->applist)
289 app_ptr = list_entry(node_ptr, struct ladish_app, siblings);
290 if (app_ptr->pid == pid)
292 //log_info("app \"%s\" found by pid %llu", app_ptr->name, (unsigned long long)pid);
293 return (ladish_app_handle)app_ptr;
297 return NULL;
300 ladish_app_handle ladish_app_supervisor_find_app_by_uuid(ladish_app_supervisor_handle supervisor_handle, const uuid_t uuid)
302 struct list_head * node_ptr;
303 struct ladish_app * app_ptr;
305 list_for_each(node_ptr, &supervisor_ptr->applist)
307 app_ptr = list_entry(node_ptr, struct ladish_app, siblings);
308 if (uuid_compare(app_ptr->uuid, uuid) == 0)
310 return (ladish_app_handle)app_ptr;
314 return NULL;
317 ladish_app_handle
318 ladish_app_supervisor_add(
319 ladish_app_supervisor_handle supervisor_handle,
320 const char * name,
321 uuid_t uuid,
322 bool autorun,
323 const char * command,
324 bool terminal,
325 const char * level)
327 struct ladish_app * app_ptr;
328 dbus_bool_t running;
329 dbus_bool_t dbus_terminal;
330 size_t len;
331 uint8_t level_byte;
333 if (!ladish_check_app_level_validity(level, &len))
335 log_error("invalid level '%s'", level);
336 return NULL;
339 app_ptr = malloc(sizeof(struct ladish_app));
340 if (app_ptr == NULL)
342 log_error("malloc of struct ladish_app failed");
343 return NULL;
346 app_ptr->name = strdup(name);
347 if (app_ptr->name == NULL)
349 log_error("strdup() failed for app name");
350 free(app_ptr);
351 return NULL;
354 app_ptr->commandline = strdup(command);
355 if (app_ptr->commandline == NULL)
357 log_error("strdup() failed for app commandline");
358 free(app_ptr->name);
359 free(app_ptr);
360 return NULL;
363 app_ptr->dbus_name = NULL;
365 app_ptr->terminal = terminal;
366 memcpy(app_ptr->level, level, len + 1);
367 app_ptr->pid = 0;
368 app_ptr->pgrp = 0;
369 app_ptr->firstborn_pid = 0;
370 app_ptr->firstborn_pgrp = 0;
371 app_ptr->firstborn_refcount = 0;
373 app_ptr->id = supervisor_ptr->next_id++;
374 if (uuid == NULL || uuid_is_null(uuid))
376 uuid_generate(app_ptr->uuid);
378 else
380 uuid_copy(app_ptr->uuid, uuid);
383 app_ptr->zombie = false;
384 app_ptr->state = LADISH_APP_STATE_STOPPED;
385 app_ptr->autorun = autorun;
386 app_ptr->supervisor = supervisor_ptr;
387 list_add_tail(&app_ptr->siblings, &supervisor_ptr->applist);
389 supervisor_ptr->version++;
391 running = false;
392 dbus_terminal = terminal;
393 level = app_ptr->level;
394 level_byte = ladish_level_string_to_integer(app_ptr->level);
395 dbus_signal_emit(
396 cdbus_g_dbus_connection,
397 supervisor_ptr->opath,
398 IFACE_APP_SUPERVISOR,
399 "AppAdded",
400 "ttsbby",
401 &supervisor_ptr->version,
402 &app_ptr->id,
403 &app_ptr->name,
404 &running,
405 &dbus_terminal,
406 &level_byte);
407 dbus_signal_emit(
408 cdbus_g_dbus_connection,
409 supervisor_ptr->opath,
410 IFACE_APP_SUPERVISOR,
411 "AppAdded2",
412 "ttsbbs",
413 &supervisor_ptr->version,
414 &app_ptr->id,
415 &app_ptr->name,
416 &running,
417 &dbus_terminal,
418 &level);
420 return (ladish_app_handle)app_ptr;
423 static void ladish_app_send_signal(struct ladish_app * app_ptr, int sig, bool prefer_firstborn)
425 pid_t pid;
426 const char * signal_name;
428 ASSERT(app_ptr->state = LADISH_APP_STATE_STARTED);
430 switch (sig)
432 case SIGTERM:
433 signal_name = "SIGTERM";
434 break;
435 case SIGKILL:
436 signal_name = "SIGKILL";
437 break;
438 case SIGUSR1:
439 signal_name = "SIGUSR1";
440 break;
441 default:
442 signal_name = strsignal(sig);
443 if (signal_name == NULL)
445 signal_name = "unknown";
449 if (app_ptr->pid == 0)
451 log_error("not sending signal %d (%s) to app '%s' because its pid is %d", sig, signal_name, app_ptr->name, (int)app_ptr->pid);
452 ASSERT_NO_PASS;
453 return;
456 switch (sig)
458 case SIGKILL:
459 case SIGTERM:
460 if (app_ptr->pgrp == 0)
462 app_ptr->pgrp = getpgid(app_ptr->pid);
463 if (app_ptr->pgrp == -1)
465 app_ptr->pgrp = 0;
466 if (errno != ESRCH)
468 log_error("getpgid(%u) failed. %s (%d)", (unsigned int)app_ptr->pid, strerror(errno), errno);
473 if (app_ptr->firstborn_pid != 0)
475 app_ptr->firstborn_pgrp = getpgid(app_ptr->firstborn_pid);
476 if (app_ptr->firstborn_pgrp == -1)
478 app_ptr->firstborn_pgrp = 0;
479 if (errno != ESRCH)
481 log_error("getpgid(%u) failed (firstborn). %s (%d)", (unsigned int)app_ptr->firstborn_pid, strerror(errno), errno);
486 if (app_ptr->pgrp != 0)
488 log_info("sending signal %d (%s) to pgrp %u ('%s')", sig, signal_name, (unsigned int)app_ptr->pgrp, app_ptr->name);
490 if (app_ptr->pgrp <= 1)
492 ASSERT_NO_PASS;
493 return;
496 killpg(app_ptr->pgrp, sig);
498 if (app_ptr->firstborn_pid != 0)
500 if (app_ptr->firstborn_pgrp != 0)
502 if (app_ptr->firstborn_pgrp <= 1)
504 ASSERT_NO_PASS;
505 return;
508 if (app_ptr->firstborn_pgrp != app_ptr->pgrp)
510 log_info("sending signal %d (%s) to firstborn pgrp %u ('%s')", sig, signal_name, (unsigned int)app_ptr->firstborn_pgrp, app_ptr->name);
512 killpg(app_ptr->firstborn_pgrp, sig);
514 return;
516 /* fall through to sending signal to pid */
518 else
520 return;
523 /* fall through to sending signal to pid */
524 default:
525 if (app_ptr->pid <= 1)
527 ASSERT_NO_PASS;
528 return;
531 if (prefer_firstborn && app_ptr->firstborn_pid != 0)
533 pid = app_ptr->firstborn_pid;
535 else
537 pid = app_ptr->pid;
540 if (pid <= 1)
542 ASSERT_NO_PASS;
543 return;
546 log_info("sending signal %d (%s) to '%s' with pid %u", sig, signal_name, app_ptr->name, (unsigned int)pid);
547 kill(pid, sig);
551 static inline void ladish_app_initiate_lash_save(struct ladish_app * app_ptr, const char * base_dir)
553 char * app_dir;
554 char uuid_str[37];
556 if (base_dir == NULL)
558 log_error("Cannot initiate LASH save because base dir is unknown");
559 ASSERT_NO_PASS;
560 goto exit;
563 uuid_unparse(app_ptr->uuid, uuid_str);
564 app_dir = catdup3(base_dir, "/lash_apps/", uuid_str);
565 if (app_dir == NULL)
567 log_error("Cannot initiate LASH save because of memory allocation failure.");
568 goto exit;
571 if (!ensure_dir_exist(app_dir, S_IRWXU | S_IRWXG | S_IRWXO))
573 goto free;
576 if (lash_client_proxy_save(app_ptr->dbus_name, app_dir))
578 log_info("LASH Save into '%s' initiated for '%s' with D-Bus name '%s'", app_dir, app_ptr->name, app_ptr->dbus_name);
581 free:
582 free(app_dir);
583 exit:
584 return;
587 static inline void ladish_app_initiate_lash_restore(struct ladish_app * app_ptr, const char * base_dir)
589 char * app_dir;
590 char uuid_str[37];
591 struct st;
593 if (base_dir == NULL)
595 log_error("Cannot initiate LASH restore because base dir is unknown");
596 ASSERT_NO_PASS;
597 goto exit;
600 uuid_unparse(app_ptr->uuid, uuid_str);
601 app_dir = catdup3(base_dir, "/lash_apps/", uuid_str);
602 if (app_dir == NULL)
604 log_error("Cannot initiate LASH restore because of memory allocation failure.");
605 goto exit;
608 if (!check_dir_exists(app_dir))
610 log_info("Not initiating LASH restore because of app directory '%s' does not exist.", app_dir);
611 goto free;
614 if (lash_client_proxy_restore(app_ptr->dbus_name, app_dir))
616 log_info("LASH Save from '%s' initiated for '%s' with D-Bus name '%s'", app_dir, app_ptr->name, app_ptr->dbus_name);
619 free:
620 free(app_dir);
621 exit:
622 return;
625 static inline void ladish_app_initiate_save(struct ladish_app * app_ptr)
627 if (strcmp(app_ptr->level, LADISH_APP_LEVEL_LASH) == 0 &&
628 app_ptr->dbus_name != NULL)
630 ladish_app_initiate_lash_save(app_ptr, app_ptr->supervisor->dir != NULL ? app_ptr->supervisor->dir : g_base_dir);
632 else if (strcmp(app_ptr->level, LADISH_APP_LEVEL_1) == 0)
634 ladish_app_send_signal(app_ptr, SIGUSR1, true);
638 static inline void ladish_app_initiate_stop(struct ladish_app * app_ptr)
640 if (strcmp(app_ptr->level, LADISH_APP_LEVEL_LASH) == 0 &&
641 app_ptr->dbus_name != NULL &&
642 lash_client_proxy_quit(app_ptr->dbus_name))
644 log_info("LASH Quit initiated for '%s' with D-Bus name '%s'", app_ptr->name, app_ptr->dbus_name);
646 else
648 ladish_app_send_signal(app_ptr, SIGTERM, false);
651 app_ptr->state = LADISH_APP_STATE_STOPPING;
654 bool ladish_app_supervisor_clear(ladish_app_supervisor_handle supervisor_handle)
656 struct list_head * node_ptr;
657 struct list_head * safe_node_ptr;
658 struct ladish_app * app_ptr;
659 bool lifeless;
661 free(supervisor_ptr->dir);
662 supervisor_ptr->dir = NULL;
664 free(supervisor_ptr->project_name);
665 supervisor_ptr->project_name = NULL;
667 lifeless = true;
669 list_for_each_safe(node_ptr, safe_node_ptr, &supervisor_ptr->applist)
671 app_ptr = list_entry(node_ptr, struct ladish_app, siblings);
672 if (app_ptr->pid != 0)
674 log_info("terminating '%s'...", app_ptr->name);
675 ladish_app_initiate_stop(app_ptr);
676 app_ptr->zombie = true;
677 lifeless = false;
679 else
681 log_info("removing '%s'", app_ptr->name);
682 remove_app_internal(supervisor_ptr, app_ptr);
686 return lifeless;
689 void ladish_app_supervisor_destroy(ladish_app_supervisor_handle supervisor_handle)
691 ladish_app_supervisor_clear(supervisor_handle);
692 free(supervisor_ptr->name);
693 free(supervisor_ptr->opath);
694 free(supervisor_ptr);
697 bool
698 ladish_app_supervisor_set_directory(
699 ladish_app_supervisor_handle supervisor_handle,
700 const char * dir)
702 char * dup;
704 dup = strdup(dir);
705 if (dup == NULL)
707 log_error("strdup(\"%s\") failed", dir);
708 return false;
711 if (supervisor_ptr->dir != NULL)
713 free(supervisor_ptr->dir);
716 supervisor_ptr->dir = dup;
718 return true;
721 bool
722 ladish_app_supervisor_set_project_name(
723 ladish_app_supervisor_handle supervisor_handle,
724 const char * project_name)
726 char * dup;
728 if (project_name != NULL)
730 dup = strdup(project_name);
731 if (dup == NULL)
733 log_error("strdup(\"%s\") failed", project_name);
734 return false;
737 else
739 dup = NULL;
742 free(supervisor_ptr->project_name);
743 supervisor_ptr->project_name = dup;
745 return true;
748 bool ladish_app_supervisor_child_exit(ladish_app_supervisor_handle supervisor_handle, pid_t pid)
750 struct list_head * node_ptr;
751 struct ladish_app * app_ptr;
753 list_for_each(node_ptr, &supervisor_ptr->applist)
755 app_ptr = list_entry(node_ptr, struct ladish_app, siblings);
756 if (app_ptr->pid == pid)
758 log_info("exit of child '%s' detected.", app_ptr->name);
760 app_ptr->pid = 0;
761 app_ptr->pgrp = 0;
762 /* firstborn pid and pgrp is not reset here because it is refcounted
763 and managed independently through the add/del_pid() methods */
765 if (app_ptr->zombie)
767 remove_app_internal(supervisor_ptr, app_ptr);
769 else
771 if (app_ptr->state == LADISH_APP_STATE_STARTED)
773 ladish_notify_simple(LADISH_NOTIFY_URGENCY_HIGH, "App terminated unexpectedly", app_ptr->name);
776 app_ptr->state = LADISH_APP_STATE_STOPPED;
778 emit_app_state_changed(supervisor_ptr, app_ptr);
781 return true;
785 return false;
788 bool
789 ladish_app_supervisor_enum(
790 ladish_app_supervisor_handle supervisor_handle,
791 void * context,
792 ladish_app_supervisor_enum_callback callback)
794 struct list_head * node_ptr;
795 struct ladish_app * app_ptr;
797 list_for_each(node_ptr, &supervisor_ptr->applist)
799 app_ptr = list_entry(node_ptr, struct ladish_app, siblings);
801 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))
803 return false;
807 return true;
810 #define app_ptr ((struct ladish_app *)app_handle)
812 bool ladish_app_supervisor_start_app(ladish_app_supervisor_handle supervisor_handle, ladish_app_handle app_handle)
814 app_ptr->zombie = false;
816 ASSERT(app_ptr->pid == 0);
818 if (!loader_execute(
819 supervisor_ptr->name,
820 supervisor_ptr->project_name,
821 app_ptr->name,
822 supervisor_ptr->dir != NULL ? supervisor_ptr->dir : "/",
823 app_ptr->terminal,
824 app_ptr->commandline,
825 &app_ptr->pid))
827 return false;
830 ASSERT(app_ptr->pid != 0);
831 app_ptr->state = LADISH_APP_STATE_STARTED;
833 emit_app_state_changed(supervisor_ptr, app_ptr);
834 return true;
837 void ladish_app_supervisor_remove_app(ladish_app_supervisor_handle supervisor_handle, ladish_app_handle app_handle)
839 remove_app_internal(supervisor_ptr, app_ptr);
842 unsigned int ladish_app_get_state(ladish_app_handle app_handle)
844 return app_ptr->state;
847 bool ladish_app_is_running(ladish_app_handle app_handle)
849 return app_ptr->pid != 0;
852 const char * ladish_app_get_name(ladish_app_handle app_handle)
854 return app_ptr->name;
857 void ladish_app_get_uuid(ladish_app_handle app_handle, uuid_t uuid)
859 uuid_copy(uuid, app_ptr->uuid);
862 void ladish_app_stop(ladish_app_handle app_handle)
864 ladish_app_initiate_stop(app_ptr);
867 void ladish_app_kill(ladish_app_handle app_handle)
869 ladish_app_send_signal(app_ptr, SIGKILL, false);
870 app_ptr->state = LADISH_APP_STATE_KILL;
873 void ladish_app_save(ladish_app_handle app_handle)
875 ladish_app_initiate_save(app_ptr);
878 void ladish_app_restore(ladish_app_handle app_handle)
880 if (strcmp(app_ptr->level, LADISH_APP_LEVEL_LASH) == 0 &&
881 app_ptr->dbus_name != NULL)
883 ladish_app_initiate_lash_restore(app_ptr, app_ptr->supervisor->dir != NULL ? app_ptr->supervisor->dir : g_base_dir);
887 void ladish_app_add_pid(ladish_app_handle app_handle, pid_t pid)
889 if (app_ptr->pid == 0)
891 log_error("Associating pid with stopped app does not make sense");
892 ASSERT_NO_PASS;
893 return;
896 if (pid <= 1) /* catch -1, 0 and 1 */
898 log_error("Refusing domination by ignoring pid %d", (int)pid);
899 ASSERT_NO_PASS;
900 return;
903 if (app_ptr->pid == pid)
904 { /* The top level process that is already known */
905 return;
908 if (app_ptr->firstborn_pid != 0)
909 { /* Ignore non-first children */
910 if (app_ptr->firstborn_pid == pid)
912 app_ptr->firstborn_refcount++;
914 return;
917 log_info("First grandchild with pid %u", (unsigned int)pid);
918 app_ptr->firstborn_pid = pid;
919 ASSERT(app_ptr->firstborn_refcount == 0);
920 app_ptr->firstborn_refcount = 1;
923 void ladish_app_del_pid(ladish_app_handle app_handle, pid_t pid)
925 if (app_ptr->firstborn_pid != 0 && app_ptr->firstborn_pid == pid)
927 ASSERT(app_ptr->firstborn_refcount > 0);
928 app_ptr->firstborn_refcount--;
929 if (app_ptr->firstborn_refcount > 0)
931 return;
933 log_info("First grandchild with pid %u has gone", (unsigned int)pid);
934 app_ptr->firstborn_pid = 0;
935 app_ptr->firstborn_pgrp = 0;
936 app_ptr->firstborn_refcount = 0;
940 bool ladish_app_set_dbus_name(ladish_app_handle app_handle, const char * name)
942 char * dup;
944 dup = strdup(name);
945 if (dup == NULL)
947 log_error("strdup() failed for app dbus name");
948 return false;
951 free(app_ptr->dbus_name);
952 app_ptr->dbus_name = dup;
953 return true;
956 #undef app_ptr
958 void ladish_app_supervisor_autorun(ladish_app_supervisor_handle supervisor_handle)
960 struct list_head * node_ptr;
961 struct ladish_app * app_ptr;
963 list_for_each(node_ptr, &supervisor_ptr->applist)
965 app_ptr = list_entry(node_ptr, struct ladish_app, siblings);
967 if (!app_ptr->autorun)
969 continue;
972 app_ptr->autorun = false;
974 log_info("autorun('%s', %s, '%s') called", app_ptr->name, app_ptr->terminal ? "terminal" : "shell", app_ptr->commandline);
976 if (!ladish_app_supervisor_start_app((ladish_app_supervisor_handle)supervisor_ptr, (ladish_app_handle)app_ptr))
978 log_error("Execution of '%s' failed", app_ptr->commandline);
979 return;
984 void ladish_app_supervisor_stop(ladish_app_supervisor_handle supervisor_handle)
986 struct list_head * node_ptr;
987 struct ladish_app * app_ptr;
989 list_for_each(node_ptr, &supervisor_ptr->applist)
991 app_ptr = list_entry(node_ptr, struct ladish_app, siblings);
992 if (app_ptr->pid != 0)
994 log_info("terminating '%s'...", app_ptr->name);
995 app_ptr->autorun = true;
996 ladish_app_initiate_stop(app_ptr);
1001 void ladish_app_supervisor_save(ladish_app_supervisor_handle supervisor_handle)
1003 struct list_head * node_ptr;
1004 struct ladish_app * app_ptr;
1006 list_for_each(node_ptr, &supervisor_ptr->applist)
1008 app_ptr = list_entry(node_ptr, struct ladish_app, siblings);
1009 if (app_ptr->state != LADISH_APP_STATE_STARTED)
1011 continue;
1014 if (app_ptr->pid == 0)
1016 ASSERT_NO_PASS;
1017 continue;
1020 ladish_app_initiate_save(app_ptr);
1024 const char * ladish_app_supervisor_get_name(ladish_app_supervisor_handle supervisor_handle)
1026 return supervisor_ptr->name;
1029 unsigned int ladish_app_supervisor_get_running_app_count(ladish_app_supervisor_handle supervisor_handle)
1031 struct list_head * node_ptr;
1032 struct ladish_app * app_ptr;
1033 unsigned int counter;
1035 counter = 0;
1036 list_for_each(node_ptr, &supervisor_ptr->applist)
1038 app_ptr = list_entry(node_ptr, struct ladish_app, siblings);
1039 if (app_ptr->pid != 0)
1041 counter++;
1045 return counter;
1048 bool ladish_app_supervisor_has_apps(ladish_app_supervisor_handle supervisor_handle)
1050 return !list_empty(&supervisor_ptr->applist);
1053 void ladish_app_supervisor_dump(ladish_app_supervisor_handle supervisor_handle)
1055 struct list_head * node_ptr;
1056 struct ladish_app * app_ptr;
1057 char uuid_str[37];
1059 list_for_each(node_ptr, &supervisor_ptr->applist)
1061 app_ptr = list_entry(node_ptr, struct ladish_app, siblings);
1062 uuid_unparse(app_ptr->uuid, uuid_str);
1063 log_info("app '%s' with commandline '%s'", app_ptr->name, app_ptr->commandline);
1064 log_info(" %s", uuid_str);
1065 log_info(" %s, %s, level '%s'", app_ptr->terminal ? "terminal" : "shell", app_ptr->autorun ? "autorun" : "stopped", app_ptr->level, app_ptr->commandline);
1069 #undef supervisor_ptr
1071 /**********************************************************************************/
1072 /* D-Bus methods */
1073 /**********************************************************************************/
1075 #define supervisor_ptr ((struct ladish_app_supervisor *)call_ptr->iface_context)
1077 static void get_version(struct dbus_method_call * call_ptr)
1079 uint32_t version;
1081 version = 1;
1083 method_return_new_single(call_ptr, DBUS_TYPE_UINT32, &version);
1086 static void get_all_multiversion(struct dbus_method_call * call_ptr, int version)
1088 DBusMessageIter iter, array_iter, struct_iter;
1089 struct list_head * node_ptr;
1090 struct ladish_app * app_ptr;
1091 dbus_bool_t running;
1092 dbus_bool_t terminal;
1093 const char * level_str;
1094 uint8_t level_byte;
1096 //log_info("get_all called");
1098 call_ptr->reply = dbus_message_new_method_return(call_ptr->message);
1099 if (call_ptr->reply == NULL)
1101 goto fail;
1104 dbus_message_iter_init_append(call_ptr->reply, &iter);
1106 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT64, &supervisor_ptr->version))
1108 goto fail_unref;
1111 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, version == 1 ? "(tsbby)" : "(tsbbs)", &array_iter))
1113 goto fail_unref;
1116 list_for_each(node_ptr, &supervisor_ptr->applist)
1118 app_ptr = list_entry(node_ptr, struct ladish_app, siblings);
1120 log_info("app '%s' (%llu)", app_ptr->name, (unsigned long long)app_ptr->id);
1122 if (!dbus_message_iter_open_container (&array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter))
1124 goto fail_unref;
1127 if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_UINT64, &app_ptr->id))
1129 goto fail_unref;
1132 if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &app_ptr->name))
1134 goto fail_unref;
1137 running = app_ptr->pid != 0;
1138 if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_BOOLEAN, &running))
1140 goto fail_unref;
1143 terminal = app_ptr->terminal;
1144 if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_BOOLEAN, &terminal))
1146 goto fail_unref;
1149 if (version == 1)
1151 level_byte = ladish_level_string_to_integer(app_ptr->level);
1152 if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_BYTE, &level_byte))
1154 goto fail_unref;
1157 else
1159 ASSERT(version == 2);
1161 level_str = app_ptr->level;
1162 if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &level_str))
1164 goto fail_unref;
1168 if (!dbus_message_iter_close_container(&array_iter, &struct_iter))
1170 goto fail_unref;
1174 if (!dbus_message_iter_close_container(&iter, &array_iter))
1176 goto fail_unref;
1179 return;
1181 fail_unref:
1182 dbus_message_unref(call_ptr->reply);
1183 call_ptr->reply = NULL;
1185 fail:
1186 log_error("Ran out of memory trying to construct method return");
1189 static void get_all1(struct dbus_method_call * call_ptr)
1191 get_all_multiversion(call_ptr, 1);
1194 static void get_all2(struct dbus_method_call * call_ptr)
1196 get_all_multiversion(call_ptr, 2);
1199 static void run_custom1(struct dbus_method_call * call_ptr)
1201 dbus_bool_t terminal;
1202 const char * commandline;
1203 const char * name;
1204 uint8_t level;
1206 if (!dbus_message_get_args(
1207 call_ptr->message,
1208 &cdbus_g_dbus_error,
1209 DBUS_TYPE_BOOLEAN, &terminal,
1210 DBUS_TYPE_STRING, &commandline,
1211 DBUS_TYPE_STRING, &name,
1212 DBUS_TYPE_BYTE, &level,
1213 DBUS_TYPE_INVALID))
1215 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, cdbus_g_dbus_error.message);
1216 dbus_error_free(&cdbus_g_dbus_error);
1217 return;
1220 log_info("%s('%s', %s, '%s', %"PRIu8") called", call_ptr->method_name, name, terminal ? "terminal" : "shell", commandline, level);
1222 if (level > 1)
1224 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "invalid integer level %"PRIu8, level);
1225 return;
1228 if (ladish_command_new_app(
1229 call_ptr,
1230 ladish_studio_get_cmd_queue(),
1231 supervisor_ptr->opath,
1232 terminal,
1233 commandline,
1234 name,
1235 level == 0 ? LADISH_APP_LEVEL_0 : LADISH_APP_LEVEL_1))
1237 method_return_new_void(call_ptr);
1241 static void run_custom2(struct dbus_method_call * call_ptr)
1243 dbus_bool_t terminal;
1244 const char * commandline;
1245 const char * name;
1246 const char * level;
1248 if (!dbus_message_get_args(
1249 call_ptr->message,
1250 &cdbus_g_dbus_error,
1251 DBUS_TYPE_BOOLEAN, &terminal,
1252 DBUS_TYPE_STRING, &commandline,
1253 DBUS_TYPE_STRING, &name,
1254 DBUS_TYPE_STRING, &level,
1255 DBUS_TYPE_INVALID))
1257 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, cdbus_g_dbus_error.message);
1258 dbus_error_free(&cdbus_g_dbus_error);
1259 return;
1262 log_info("%s('%s', %s, '%s', '%s') called", call_ptr->method_name, name, terminal ? "terminal" : "shell", commandline, level);
1264 if (!ladish_check_app_level_validity(level, NULL))
1266 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "invalid level '%s'", level);
1267 return;
1270 if (ladish_command_new_app(
1271 call_ptr,
1272 ladish_studio_get_cmd_queue(),
1273 supervisor_ptr->opath,
1274 terminal,
1275 commandline,
1276 name,
1277 level))
1279 method_return_new_void(call_ptr);
1283 static void start_app(struct dbus_method_call * call_ptr)
1285 uint64_t id;
1287 if (!dbus_message_get_args(
1288 call_ptr->message,
1289 &cdbus_g_dbus_error,
1290 DBUS_TYPE_UINT64, &id,
1291 DBUS_TYPE_INVALID))
1293 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, cdbus_g_dbus_error.message);
1294 dbus_error_free(&cdbus_g_dbus_error);
1295 return;
1298 if (ladish_command_change_app_state(call_ptr, ladish_studio_get_cmd_queue(), supervisor_ptr->opath, id, LADISH_APP_STATE_STARTED))
1300 method_return_new_void(call_ptr);
1304 static void stop_app(struct dbus_method_call * call_ptr)
1306 uint64_t id;
1308 if (!dbus_message_get_args(
1309 call_ptr->message,
1310 &cdbus_g_dbus_error,
1311 DBUS_TYPE_UINT64, &id,
1312 DBUS_TYPE_INVALID))
1314 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, cdbus_g_dbus_error.message);
1315 dbus_error_free(&cdbus_g_dbus_error);
1316 return;
1319 if (ladish_command_change_app_state(call_ptr, ladish_studio_get_cmd_queue(), supervisor_ptr->opath, id, LADISH_APP_STATE_STOPPED))
1321 method_return_new_void(call_ptr);
1325 static void kill_app(struct dbus_method_call * call_ptr)
1327 uint64_t id;
1329 if (!dbus_message_get_args(
1330 call_ptr->message,
1331 &cdbus_g_dbus_error,
1332 DBUS_TYPE_UINT64, &id,
1333 DBUS_TYPE_INVALID))
1335 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, cdbus_g_dbus_error.message);
1336 dbus_error_free(&cdbus_g_dbus_error);
1337 return;
1340 if (ladish_command_change_app_state(call_ptr, ladish_studio_get_cmd_queue(), supervisor_ptr->opath, id, LADISH_APP_STATE_KILL))
1342 method_return_new_void(call_ptr);
1346 static void get_app_properties_multiversion(struct dbus_method_call * call_ptr, int version)
1348 uint64_t id;
1349 struct ladish_app * app_ptr;
1350 dbus_bool_t running;
1351 dbus_bool_t terminal;
1352 const char * level_str;
1353 uint8_t level_byte;
1354 int level_type;
1355 void * level_ptr;
1357 if (!dbus_message_get_args(
1358 call_ptr->message,
1359 &cdbus_g_dbus_error,
1360 DBUS_TYPE_UINT64, &id,
1361 DBUS_TYPE_INVALID))
1363 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, cdbus_g_dbus_error.message);
1364 dbus_error_free(&cdbus_g_dbus_error);
1365 return;
1368 app_ptr = ladish_app_supervisor_find_app_by_id_internal(supervisor_ptr, id);
1369 if (app_ptr == NULL)
1371 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "App with ID %"PRIu64" not found", id);
1372 return;
1375 running = app_ptr->pid != 0;
1376 terminal = app_ptr->terminal;
1377 if (version == 1)
1379 level_byte = ladish_level_string_to_integer(app_ptr->level);
1380 level_type = DBUS_TYPE_BYTE;
1381 level_ptr = &level_byte;
1383 else
1385 ASSERT(version == 2);
1386 level_str = app_ptr->level;
1387 level_type = DBUS_TYPE_STRING;
1388 level_ptr = &level_str;
1391 call_ptr->reply = dbus_message_new_method_return(call_ptr->message);
1392 if (call_ptr->reply == NULL)
1394 goto fail;
1397 if (!dbus_message_append_args(
1398 call_ptr->reply,
1399 DBUS_TYPE_STRING, &app_ptr->name,
1400 DBUS_TYPE_STRING, &app_ptr->commandline,
1401 DBUS_TYPE_BOOLEAN, &running,
1402 DBUS_TYPE_BOOLEAN, &terminal,
1403 level_type, level_ptr,
1404 DBUS_TYPE_INVALID))
1406 goto fail_unref;
1409 return;
1411 fail_unref:
1412 dbus_message_unref(call_ptr->reply);
1413 call_ptr->reply = NULL;
1415 fail:
1416 log_error("Ran out of memory trying to construct method return");
1419 static void get_app_properties1(struct dbus_method_call * call_ptr)
1421 get_app_properties_multiversion(call_ptr, 1);
1424 static void get_app_properties2(struct dbus_method_call * call_ptr)
1426 get_app_properties_multiversion(call_ptr, 2);
1429 static void set_app_properties_multiversion(struct dbus_method_call * call_ptr, int version)
1431 uint64_t id;
1432 dbus_bool_t terminal;
1433 const char * name;
1434 const char * commandline;
1435 const char * level_str;
1436 uint8_t level_byte;
1437 int level_type;
1438 void * level_ptr;
1439 struct ladish_app * app_ptr;
1440 char * name_buffer;
1441 char * commandline_buffer;
1442 size_t len;
1444 if (version == 1)
1446 level_type = DBUS_TYPE_BYTE;
1447 level_ptr = &level_byte;
1449 else
1451 ASSERT(version == 2);
1452 level_type = DBUS_TYPE_STRING;
1453 level_ptr = &level_str;
1456 if (!dbus_message_get_args(
1457 call_ptr->message,
1458 &cdbus_g_dbus_error,
1459 DBUS_TYPE_UINT64, &id,
1460 DBUS_TYPE_STRING, &name,
1461 DBUS_TYPE_STRING, &commandline,
1462 DBUS_TYPE_BOOLEAN, &terminal,
1463 level_type, level_ptr,
1464 DBUS_TYPE_INVALID))
1466 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, cdbus_g_dbus_error.message);
1467 dbus_error_free(&cdbus_g_dbus_error);
1468 return;
1471 if (version == 1)
1473 if (level_byte > 1)
1475 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "invalid integer level %"PRIu8, level_byte);
1476 return;
1479 level_str = level_byte == 0 ? LADISH_APP_LEVEL_0 : LADISH_APP_LEVEL_1;
1480 len = strlen(level_str);
1482 else
1484 ASSERT(version == 2);
1485 if (!ladish_check_app_level_validity(level_str, &len))
1487 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "invalid level '%s'", level_str);
1488 return;
1492 app_ptr = ladish_app_supervisor_find_app_by_id_internal(supervisor_ptr, id);
1493 if (app_ptr == NULL)
1495 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "App with ID %"PRIu64" not found", id);
1496 return;
1499 if (app_ptr->pid != 0 && strcmp(commandline, app_ptr->commandline) != 0)
1501 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "Cannot change commandline when app is running. '%s' -> '%s'", app_ptr->commandline, commandline);
1502 return;
1505 if (app_ptr->pid != 0 && ((app_ptr->terminal && !terminal) || (!app_ptr->terminal && terminal)))
1507 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "Cannot change whether to run in terminal when app is running");
1508 return;
1511 if (app_ptr->pid != 0 && strcmp(app_ptr->level, level_str) != 0)
1513 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "Cannot change app level when app is running");
1514 return;
1517 if (strcmp(commandline, app_ptr->commandline) != 0)
1519 commandline_buffer = strdup(commandline);
1520 if (commandline_buffer == NULL)
1522 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "strdup() failed for app commandline");
1523 return;
1526 else
1528 commandline_buffer = NULL;
1531 if (strcmp(name, app_ptr->name) != 0)
1533 name_buffer = strdup(name);
1534 if (name_buffer == NULL)
1536 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "strdup() failed for app nam");
1537 if (commandline_buffer != NULL)
1539 free(commandline_buffer);
1541 return;
1544 else
1546 name_buffer = NULL;
1549 if (name_buffer != NULL)
1551 supervisor_ptr->on_app_renamed(supervisor_ptr->on_app_renamed_context, app_ptr->uuid, app_ptr->name, name_buffer);
1552 free(app_ptr->name);
1553 app_ptr->name = name_buffer;
1556 if (commandline_buffer != NULL)
1558 free(app_ptr->commandline);
1559 app_ptr->commandline = commandline_buffer;
1562 memcpy(app_ptr->level, level_str, len + 1);
1563 app_ptr->terminal = terminal;
1565 emit_app_state_changed(supervisor_ptr, app_ptr);
1567 method_return_new_void(call_ptr);
1570 static void set_app_properties1(struct dbus_method_call * call_ptr)
1572 set_app_properties_multiversion(call_ptr, 1);
1575 static void set_app_properties2(struct dbus_method_call * call_ptr)
1577 set_app_properties_multiversion(call_ptr, 2);
1581 static void remove_app(struct dbus_method_call * call_ptr)
1583 uint64_t id;
1585 if (!dbus_message_get_args(
1586 call_ptr->message,
1587 &cdbus_g_dbus_error,
1588 DBUS_TYPE_UINT64, &id,
1589 DBUS_TYPE_INVALID))
1591 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, cdbus_g_dbus_error.message);
1592 dbus_error_free(&cdbus_g_dbus_error);
1593 return;
1596 if (ladish_command_remove_app(call_ptr, ladish_studio_get_cmd_queue(), supervisor_ptr->opath, id))
1598 method_return_new_void(call_ptr);
1602 static void is_app_running(struct dbus_method_call * call_ptr)
1604 uint64_t id;
1605 struct ladish_app * app_ptr;
1606 dbus_bool_t running;
1608 if (!dbus_message_get_args(
1609 call_ptr->message,
1610 &cdbus_g_dbus_error,
1611 DBUS_TYPE_UINT64, &id,
1612 DBUS_TYPE_INVALID))
1614 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, cdbus_g_dbus_error.message);
1615 dbus_error_free(&cdbus_g_dbus_error);
1616 return;
1619 app_ptr = ladish_app_supervisor_find_app_by_id_internal(supervisor_ptr, id);
1620 if (app_ptr == NULL)
1622 lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "App with ID %"PRIu64" not found", id);
1623 return;
1626 running = app_ptr->pid != 0;
1628 method_return_new_single(call_ptr, DBUS_TYPE_BOOLEAN, &running);
1631 #undef supervisor_ptr
1633 METHOD_ARGS_BEGIN(GetInterfaceVersion, "Get version of this D-Bus interface")
1634 METHOD_ARG_DESCRIBE_OUT("running", DBUS_TYPE_UINT32_AS_STRING, "Interface version")
1635 METHOD_ARGS_END
1637 METHOD_ARGS_BEGIN(GetAll, "Get list of apps")
1638 METHOD_ARG_DESCRIBE_OUT("list_version", DBUS_TYPE_UINT64_AS_STRING, "Version of the list")
1639 METHOD_ARG_DESCRIBE_OUT("apps_list", "a(tsbby)", "List of apps")
1640 METHOD_ARGS_END
1642 METHOD_ARGS_BEGIN(GetAll2, "Get list of apps")
1643 METHOD_ARG_DESCRIBE_OUT("list_version", DBUS_TYPE_UINT64_AS_STRING, "Version of the list")
1644 METHOD_ARG_DESCRIBE_OUT("apps_list", "a(tsbbs)", "List of apps")
1645 METHOD_ARGS_END
1647 METHOD_ARGS_BEGIN(RunCustom, "Start application by supplying commandline")
1648 METHOD_ARG_DESCRIBE_IN("terminal", DBUS_TYPE_BOOLEAN_AS_STRING, "Whether to run in terminal")
1649 METHOD_ARG_DESCRIBE_IN("commandline", DBUS_TYPE_STRING_AS_STRING, "Commandline")
1650 METHOD_ARG_DESCRIBE_IN("name", DBUS_TYPE_STRING_AS_STRING, "Name")
1651 METHOD_ARG_DESCRIBE_IN("level", DBUS_TYPE_BYTE_AS_STRING, "Level")
1652 METHOD_ARGS_END
1654 METHOD_ARGS_BEGIN(RunCustom2, "Start application by supplying commandline")
1655 METHOD_ARG_DESCRIBE_IN("terminal", DBUS_TYPE_BOOLEAN_AS_STRING, "Whether to run in terminal")
1656 METHOD_ARG_DESCRIBE_IN("commandline", DBUS_TYPE_STRING_AS_STRING, "Commandline")
1657 METHOD_ARG_DESCRIBE_IN("name", DBUS_TYPE_STRING_AS_STRING, "Name")
1658 METHOD_ARG_DESCRIBE_IN("level", DBUS_TYPE_STRING_AS_STRING, "Level")
1659 METHOD_ARGS_END
1661 METHOD_ARGS_BEGIN(StartApp, "Start application")
1662 METHOD_ARG_DESCRIBE_IN("id", DBUS_TYPE_UINT64_AS_STRING, "id of app")
1663 METHOD_ARGS_END
1665 METHOD_ARGS_BEGIN(StopApp, "Stop application")
1666 METHOD_ARG_DESCRIBE_IN("id", DBUS_TYPE_UINT64_AS_STRING, "id of app")
1667 METHOD_ARGS_END
1669 METHOD_ARGS_BEGIN(KillApp, "Kill application")
1670 METHOD_ARG_DESCRIBE_IN("id", DBUS_TYPE_UINT64_AS_STRING, "id of app")
1671 METHOD_ARGS_END
1673 METHOD_ARGS_BEGIN(RemoveApp, "Remove application")
1674 METHOD_ARG_DESCRIBE_IN("id", DBUS_TYPE_UINT64_AS_STRING, "id of app")
1675 METHOD_ARGS_END
1677 METHOD_ARGS_BEGIN(GetAppProperties, "Get properties of an application")
1678 METHOD_ARG_DESCRIBE_IN("id", DBUS_TYPE_UINT64_AS_STRING, "id of app")
1679 METHOD_ARG_DESCRIBE_OUT("name", DBUS_TYPE_STRING_AS_STRING, "")
1680 METHOD_ARG_DESCRIBE_OUT("commandline", DBUS_TYPE_STRING_AS_STRING, "Commandline")
1681 METHOD_ARG_DESCRIBE_OUT("running", DBUS_TYPE_BOOLEAN_AS_STRING, "")
1682 METHOD_ARG_DESCRIBE_OUT("terminal", DBUS_TYPE_BOOLEAN_AS_STRING, "Whether to run in terminal")
1683 METHOD_ARG_DESCRIBE_OUT("level", DBUS_TYPE_BYTE_AS_STRING, "Level")
1684 METHOD_ARGS_END
1686 METHOD_ARGS_BEGIN(GetAppProperties2, "Get properties of an application")
1687 METHOD_ARG_DESCRIBE_IN("id", DBUS_TYPE_UINT64_AS_STRING, "id of app")
1688 METHOD_ARG_DESCRIBE_OUT("name", DBUS_TYPE_STRING_AS_STRING, "")
1689 METHOD_ARG_DESCRIBE_OUT("commandline", DBUS_TYPE_STRING_AS_STRING, "Commandline")
1690 METHOD_ARG_DESCRIBE_OUT("running", DBUS_TYPE_BOOLEAN_AS_STRING, "")
1691 METHOD_ARG_DESCRIBE_OUT("terminal", DBUS_TYPE_BOOLEAN_AS_STRING, "Whether to run in terminal")
1692 METHOD_ARG_DESCRIBE_OUT("level", DBUS_TYPE_STRING_AS_STRING, "Level")
1693 METHOD_ARGS_END
1695 METHOD_ARGS_BEGIN(SetAppProperties, "Set properties of an application")
1696 METHOD_ARG_DESCRIBE_IN("id", DBUS_TYPE_UINT64_AS_STRING, "id of app")
1697 METHOD_ARG_DESCRIBE_IN("name", DBUS_TYPE_STRING_AS_STRING, "")
1698 METHOD_ARG_DESCRIBE_IN("commandline", DBUS_TYPE_STRING_AS_STRING, "Commandline")
1699 METHOD_ARG_DESCRIBE_IN("terminal", DBUS_TYPE_BOOLEAN_AS_STRING, "Whether to run in terminal")
1700 METHOD_ARG_DESCRIBE_IN("level", DBUS_TYPE_BYTE_AS_STRING, "Level")
1701 METHOD_ARGS_END
1703 METHOD_ARGS_BEGIN(SetAppProperties2, "Set properties of an application")
1704 METHOD_ARG_DESCRIBE_IN("id", DBUS_TYPE_UINT64_AS_STRING, "id of app")
1705 METHOD_ARG_DESCRIBE_IN("name", DBUS_TYPE_STRING_AS_STRING, "")
1706 METHOD_ARG_DESCRIBE_IN("commandline", DBUS_TYPE_STRING_AS_STRING, "Commandline")
1707 METHOD_ARG_DESCRIBE_IN("terminal", DBUS_TYPE_BOOLEAN_AS_STRING, "Whether to run in terminal")
1708 METHOD_ARG_DESCRIBE_IN("level", DBUS_TYPE_STRING_AS_STRING, "Level")
1709 METHOD_ARGS_END
1711 METHOD_ARGS_BEGIN(IsAppRunning, "Check whether application is running")
1712 METHOD_ARG_DESCRIBE_IN("id", DBUS_TYPE_UINT64_AS_STRING, "id of app")
1713 METHOD_ARG_DESCRIBE_OUT("running", DBUS_TYPE_BOOLEAN_AS_STRING, "Whether app is running")
1714 METHOD_ARGS_END
1717 METHODS_BEGIN
1718 METHOD_DESCRIBE(GetInterfaceVersion, get_version) /* sync */
1719 METHOD_DESCRIBE(GetAll, get_all1) /* sync */
1720 METHOD_DESCRIBE(GetAll2, get_all2) /* sync */
1721 METHOD_DESCRIBE(RunCustom, run_custom1) /* async */
1722 METHOD_DESCRIBE(RunCustom2, run_custom2) /* async */
1723 METHOD_DESCRIBE(StartApp, start_app) /* async */
1724 METHOD_DESCRIBE(StopApp, stop_app) /* async */
1725 METHOD_DESCRIBE(KillApp, kill_app) /* async */
1726 METHOD_DESCRIBE(GetAppProperties, get_app_properties1) /* sync */
1727 METHOD_DESCRIBE(GetAppProperties2, get_app_properties2) /* sync */
1728 METHOD_DESCRIBE(SetAppProperties, set_app_properties1) /* sync */
1729 METHOD_DESCRIBE(SetAppProperties2, set_app_properties2) /* sync */
1730 METHOD_DESCRIBE(RemoveApp, remove_app) /* sync */
1731 METHOD_DESCRIBE(IsAppRunning, is_app_running) /* sync */
1732 METHODS_END
1734 SIGNAL_ARGS_BEGIN(AppAdded, "")
1735 SIGNAL_ARG_DESCRIBE("new_list_version", DBUS_TYPE_UINT64_AS_STRING, "")
1736 SIGNAL_ARG_DESCRIBE("id", DBUS_TYPE_UINT64_AS_STRING, "")
1737 SIGNAL_ARG_DESCRIBE("name", DBUS_TYPE_STRING_AS_STRING, "")
1738 SIGNAL_ARG_DESCRIBE("running", DBUS_TYPE_BOOLEAN_AS_STRING, "")
1739 SIGNAL_ARG_DESCRIBE("terminal", DBUS_TYPE_BOOLEAN_AS_STRING, "Whether to run in terminal")
1740 SIGNAL_ARG_DESCRIBE("level", DBUS_TYPE_BYTE_AS_STRING, "Level")
1741 SIGNAL_ARGS_END
1743 SIGNAL_ARGS_BEGIN(AppAdded2, "")
1744 SIGNAL_ARG_DESCRIBE("new_list_version", DBUS_TYPE_UINT64_AS_STRING, "")
1745 SIGNAL_ARG_DESCRIBE("id", DBUS_TYPE_UINT64_AS_STRING, "")
1746 SIGNAL_ARG_DESCRIBE("name", DBUS_TYPE_STRING_AS_STRING, "")
1747 SIGNAL_ARG_DESCRIBE("running", DBUS_TYPE_BOOLEAN_AS_STRING, "")
1748 SIGNAL_ARG_DESCRIBE("terminal", DBUS_TYPE_BOOLEAN_AS_STRING, "Whether to run in terminal")
1749 SIGNAL_ARG_DESCRIBE("level", DBUS_TYPE_STRING_AS_STRING, "Level")
1750 SIGNAL_ARGS_END
1752 SIGNAL_ARGS_BEGIN(AppRemoved, "")
1753 SIGNAL_ARG_DESCRIBE("new_list_version", DBUS_TYPE_UINT64_AS_STRING, "")
1754 SIGNAL_ARG_DESCRIBE("id", DBUS_TYPE_UINT64_AS_STRING, "")
1755 SIGNAL_ARGS_END
1757 SIGNAL_ARGS_BEGIN(AppStateChanged, "")
1758 SIGNAL_ARG_DESCRIBE("new_list_version", DBUS_TYPE_UINT64_AS_STRING, "")
1759 SIGNAL_ARG_DESCRIBE("id", DBUS_TYPE_UINT64_AS_STRING, "")
1760 SIGNAL_ARG_DESCRIBE("name", DBUS_TYPE_STRING_AS_STRING, "")
1761 SIGNAL_ARG_DESCRIBE("running", DBUS_TYPE_BOOLEAN_AS_STRING, "")
1762 SIGNAL_ARG_DESCRIBE("terminal", DBUS_TYPE_BOOLEAN_AS_STRING, "Whether to run in terminal")
1763 SIGNAL_ARG_DESCRIBE("level", DBUS_TYPE_BYTE_AS_STRING, "Level")
1764 SIGNAL_ARGS_END
1766 SIGNAL_ARGS_BEGIN(AppStateChanged2, "")
1767 SIGNAL_ARG_DESCRIBE("new_list_version", DBUS_TYPE_UINT64_AS_STRING, "")
1768 SIGNAL_ARG_DESCRIBE("id", DBUS_TYPE_UINT64_AS_STRING, "")
1769 SIGNAL_ARG_DESCRIBE("name", DBUS_TYPE_STRING_AS_STRING, "")
1770 SIGNAL_ARG_DESCRIBE("running", DBUS_TYPE_BOOLEAN_AS_STRING, "")
1771 SIGNAL_ARG_DESCRIBE("terminal", DBUS_TYPE_BOOLEAN_AS_STRING, "Whether to run in terminal")
1772 SIGNAL_ARG_DESCRIBE("level", DBUS_TYPE_STRING_AS_STRING, "Level")
1773 SIGNAL_ARGS_END
1775 SIGNALS_BEGIN
1776 SIGNAL_DESCRIBE(AppAdded)
1777 SIGNAL_DESCRIBE(AppAdded2)
1778 SIGNAL_DESCRIBE(AppRemoved)
1779 SIGNAL_DESCRIBE(AppStateChanged)
1780 SIGNAL_DESCRIBE(AppStateChanged2)
1781 SIGNALS_END
1783 INTERFACE_BEGIN(g_iface_app_supervisor, IFACE_APP_SUPERVISOR)
1784 INTERFACE_DEFAULT_HANDLER
1785 INTERFACE_EXPOSE_METHODS
1786 INTERFACE_EXPOSE_SIGNALS
1787 INTERFACE_END