Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarco Pesenti Gritti <marco@localhost.localdomain>2007-06-29 11:15:36 (GMT)
committer Marco Pesenti Gritti <marco@localhost.localdomain>2007-06-29 11:15:36 (GMT)
commit858e43dea92474f0e48975b0cae9d9d84809f4b3 (patch)
tree8108e8133af351836a2960aef749f984a5381057
parent17c4166707f93fe2b34c7aa57bcce67fd1bf10b3 (diff)
Add the native factory by bertf
-rw-r--r--.gitignore1
-rw-r--r--bin/.gitignore1
-rw-r--r--bin/Makefile.am6
-rw-r--r--bin/sugar-native-factory.c307
-rw-r--r--configure.ac2
5 files changed, 317 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index 22b0384..6217e61 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,7 @@ Makefile.in
*.deps
*.libs
*.la
+*.o
*.lo
*.loT
.*.sw?
diff --git a/bin/.gitignore b/bin/.gitignore
new file mode 100644
index 0000000..10c2d34
--- /dev/null
+++ b/bin/.gitignore
@@ -0,0 +1 @@
+sugar-native-factory
diff --git a/bin/Makefile.am b/bin/Makefile.am
index ffbc7bb..ecc0e0d 100644
--- a/bin/Makefile.am
+++ b/bin/Makefile.am
@@ -1,6 +1,12 @@
sugardir = $(pkgdatadir)/bin
sugar_SCRIPTS = sugar-activity-factory
+bin_PROGRAMS = sugar-native-factory
+
+sugar_native_factory_SOURCE = sugar-native-factory.c
+sugar_native_factory_CFLAGS = $(NATIVE_FACTORY_CFLAGS)
+sugar_native_factory_LDADD = $(NATIVE_FACTORY_LIBS)
+
bin_SCRIPTS = \
sugar \
sugar-activity \
diff --git a/bin/sugar-native-factory.c b/bin/sugar-native-factory.c
new file mode 100644
index 0000000..a04cd94
--- /dev/null
+++ b/bin/sugar-native-factory.c
@@ -0,0 +1,307 @@
+/*
+Copyright (c) 2007 Bert Freudenberg
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/wait.h>
+#include <dbus/dbus.h>
+
+char* prog;
+
+/* command and arguments for activity instance*/
+static char* inst_argv[100];
+static int inst_argc = 0;
+
+/* instance process ids */
+static pid_t pidv[100];
+static int pidc = 0;
+
+/* instance process id that exited before it was added */
+static pid_t exited = 0;
+
+
+
+/* add and remove instances, quit when last instance exits*/
+
+static void
+quit()
+{
+ fprintf(stderr, "%s: quitting\n", prog);
+ exit(0);
+}
+
+
+static void
+add_pid(pid_t pid)
+{
+ if (pid == exited)
+ {
+ fprintf(stderr, "%s: ign instance pid %i\n", prog, pid);
+ exited = 0;
+ if (pidc == 0)
+ quit();
+ return;
+ }
+ pidv[pidc++] = pid;
+ fprintf(stderr, "%s: add instance pid %i\n", prog, pid);
+}
+
+
+static void
+remove_pid(pid_t pid)
+{
+ int i;
+ for (i=0; i<pidc; i++)
+ if (pidv[i]=pid)
+ break;
+ if (i==pidc)
+ {
+ exited = pid;
+ return;
+ }
+ pidc--;
+ for ( ; i<pidc; i++)
+ pidv[i] = pidv[i+1];
+
+ fprintf(stderr, "%s: del instance pid %i\n", prog, pid);
+
+ if (pidc == 0)
+ quit();
+}
+
+
+static void
+sigchld_handler(int signum)
+{
+ int pid;
+ int status;
+ while (1)
+ {
+ pid = waitpid(WAIT_ANY, &status, WNOHANG);
+ if (pid <= 0)
+ break;
+ remove_pid(pid);
+ }
+}
+
+
+
+/* fork and exit a new activity instance */
+
+static void
+create_instance(int argc)
+{
+ pid_t pid = fork();
+
+ if (pid<0)
+ {
+ perror("fork failed");
+ exit(1);
+ }
+
+ inst_argv[argc] = NULL;
+ if (pid == 0)
+ {
+ execvp(inst_argv[0], inst_argv);
+ perror(inst_argv[0]);
+ exit(1);
+ }
+
+ add_pid(pid);
+}
+
+
+
+/* handle dbus create() call */
+
+static DBusHandlerResult
+handle_create(DBusConnection *connection, DBusMessage* message)
+{
+ DBusMessage *reply;
+ DBusMessageIter iter_arss, iter_rss, iter_ss;
+ char *key, *value;
+ char *activity_id = 0;
+ int argc = inst_argc;
+
+ dbus_message_iter_init(message, &iter_arss);
+ if (strcmp("a{ss}", dbus_message_iter_get_signature(&iter_arss)))
+ {
+ reply = dbus_message_new_error(message,
+ DBUS_ERROR_INVALID_ARGS,
+ "signature a{ss} expected");
+ dbus_connection_send(connection, reply, NULL);
+ dbus_message_unref(reply);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ dbus_message_iter_recurse(&iter_arss, &iter_rss);
+
+ do
+ {
+ dbus_message_iter_recurse(&iter_rss, &iter_ss);
+ dbus_message_iter_get_basic(&iter_ss, &key);
+ dbus_message_iter_next(&iter_ss);
+ dbus_message_iter_get_basic(&iter_ss, &value);
+
+ inst_argv[argc++] = key;
+ inst_argv[argc++] = value;
+
+ if (!strcmp("activity_id", key))
+ activity_id = value;
+
+ } while(dbus_message_iter_next(&iter_rss));
+
+ if (!activity_id)
+ {
+ reply = dbus_message_new_error(message,
+ DBUS_ERROR_INVALID_ARGS,
+ "'activity_id' expected");
+ dbus_connection_send(connection, reply, NULL);
+ dbus_message_unref(reply);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ create_instance(argc);
+
+ reply = dbus_message_new_method_return(message);
+ dbus_connection_send(connection, reply, NULL);
+ dbus_message_unref(reply);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+
+
+/* activity factory dbus service */
+
+static void
+factory_unregistered_func(DBusConnection *connection,
+ void *user_data)
+{
+}
+
+
+static DBusHandlerResult
+factory_message_func(DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ if (dbus_message_is_method_call(message,
+ "org.laptop.ActivityFactory",
+ "create"))
+ return handle_create(connection, message);
+ else
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+
+static DBusObjectPathVTable
+factory_vtable = {
+ factory_unregistered_func,
+ factory_message_func,
+ NULL,
+};
+
+
+
+/* register service and run main loop */
+
+static char*
+dots_to_slashes(char* dotted)
+{
+ char* slashed = (char*) malloc(strlen(dotted)+2);
+ char* p = slashed;
+ *p++ = '/';
+ strcpy(p, dotted);
+ while (*++p) if (*p == '.') *p = '/';
+ return slashed;
+}
+
+
+int main(int argc, char **argv)
+{
+ DBusConnection *connection;
+ DBusError error;
+ int result;
+ int i;
+ char* service;
+
+ if (argc < 3)
+ {
+ printf("Usage: %s org.laptop.MyActivity cmd args\n", argv[0]);
+ printf("\twhere cmd will be invoked as\n");
+ printf("\tcmd args \\\n");
+ printf("\t bundle_id org.laptop.MyActivity \\\n");
+ printf("\t activity_id 123ABC... \\\n");
+ printf("\t object_id 456DEF... \\\n");
+ printf("\t pservice_id 789ACE.. \\\n");
+ printf("\t uri file:///path/to/file\n");
+ printf("\tas given in the org.laptop.ActivityFactory.create() call\n");
+ exit(1);
+ }
+ prog = argv[0];
+ service = argv[1];
+
+ for (i = 2; i<argc; i++)
+ inst_argv[inst_argc++] = argv[i];
+ inst_argv[inst_argc++] = "bundle_id";
+ inst_argv[inst_argc++] = service;
+
+ signal(SIGCHLD, sigchld_handler);
+
+ dbus_error_init(&error);
+
+ connection = dbus_bus_get(DBUS_BUS_SESSION, &error);
+ if (dbus_error_is_set(&error))
+ {
+ fprintf(stderr, "%s: could not get bus connection: %s\n", prog, error.message);
+ exit(1);
+ }
+
+ result = dbus_bus_request_name(connection,
+ service,
+ DBUS_NAME_FLAG_DO_NOT_QUEUE,
+ &error);
+ if (dbus_error_is_set(&error))
+ {
+ fprintf(stderr, "%s: could not aquire name %s: %s\n", prog, service, error.message);
+ exit(1);
+ }
+ if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
+ {
+ fprintf(stderr, "%: could not become primary owner of %s\n", prog, service);
+ exit(1);
+ }
+
+ dbus_connection_register_object_path(connection,
+ dots_to_slashes(service),
+ &factory_vtable,
+ NULL);
+
+ while (dbus_connection_read_write_dispatch(connection, -1))
+ ;
+}
diff --git a/configure.ac b/configure.ac
index 4e10aff..77f78f0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -19,6 +19,8 @@ AC_PATH_PROG(PYGTK_CODEGEN, pygtk-codegen-2.0, no)
PKG_CHECK_MODULES(SHELL, pygtk-2.0 gtk+-2.0)
+PKG_CHECK_MODULES(NATIVE_FACTORY, dbus-1)
+
PKG_CHECK_MODULES(LIB, gtk+-2.0)
PKG_CHECK_MODULES(LIB_BINDINGS, pygtk-2.0)