~ubuntu-branches/ubuntu/utopic/upstart-app-launch/utopic-proposed

« back to all changes in this revision

Viewing changes to libupstart-app-launch/upstart-app-launch.c

  • Committer: Package Import Robot
  • Author(s): Ubuntu daily release, Ted Gould, Ubuntu daily release
  • Date: 2014-02-06 16:54:55 UTC
  • mfrom: (1.1.24)
  • Revision ID: package-import@ubuntu.com-20140206165455-ybv8tumonbcw4ag5
Tags: 0.3+14.04.20140206-0ubuntu1
[ Ted Gould ]
* Basic merge and review requirements.
* On error print the exec line
* Make the last environment variable set synchronous to make Upstart
  respond that it received it. (LP: #1275017)

[ Ubuntu daily release ]
* New rebuild forced

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 */
19
19
 
20
20
#include "upstart-app-launch.h"
 
21
#include <json-glib/json-glib.h>
21
22
#include <upstart.h>
22
23
#include <nih/alloc.h>
23
24
#include <nih/error.h>
695
696
 
696
697
        return primary == pid;
697
698
}
 
699
 
 
700
/* Try and get a manifest file and do a couple sanity checks on it */
 
701
static JsonParser *
 
702
get_manifest_file (const gchar * pkg)
 
703
{
 
704
        /* Get the directory from click */
 
705
        GError * error = NULL;
 
706
        const gchar * click_exec = NULL;
 
707
 
 
708
        if (g_getenv("UAL_CLICK_EXEC") != NULL) {
 
709
                click_exec = g_getenv("UAL_CLICK_EXEC");
 
710
        } else {
 
711
                click_exec = "click";
 
712
        }
 
713
 
 
714
        gchar * cmdline = g_strdup_printf("%s info \"%s\"",
 
715
                click_exec, pkg);
 
716
 
 
717
        gchar * output = NULL;
 
718
        g_spawn_command_line_sync(cmdline, &output, NULL, NULL, &error);
 
719
        g_free(cmdline);
 
720
 
 
721
        if (error != NULL) {
 
722
                g_warning("Unable to get manifest for '%s' package: %s", pkg, error->message);
 
723
                g_error_free(error);
 
724
                g_free(output);
 
725
                return NULL;
 
726
        }
 
727
 
 
728
        /* Let's look at that manifest file */
 
729
        JsonParser * parser = json_parser_new();
 
730
        json_parser_load_from_data(parser, output, -1, &error);
 
731
        g_free(output);
 
732
 
 
733
        if (error != NULL) {
 
734
                g_warning("Unable to load manifest for '%s': %s", pkg, error->message);
 
735
                g_error_free(error);
 
736
                g_object_unref(parser);
 
737
                return NULL;
 
738
        }
 
739
        JsonNode * root = json_parser_get_root(parser);
 
740
        if (json_node_get_node_type(root) != JSON_NODE_OBJECT) {
 
741
                g_warning("Manifest file for package '%s' does not have an object as its root node", pkg);
 
742
                g_object_unref(parser);
 
743
                return NULL;
 
744
        }
 
745
 
 
746
        JsonObject * rootobj = json_node_get_object(root);
 
747
        if (!json_object_has_member(rootobj, "version")) {
 
748
                g_warning("Manifest file for package '%s' does not have a version", pkg);
 
749
                g_object_unref(parser);
 
750
                return NULL;
 
751
        }
 
752
 
 
753
        return parser;
 
754
}
 
755
 
 
756
/* Types of search we can do for an app name */
 
757
typedef enum _app_name_t app_name_t;
 
758
enum _app_name_t {
 
759
        APP_NAME_ONLY,
 
760
        APP_NAME_FIRST,
 
761
        APP_NAME_LAST
 
762
};
 
763
 
 
764
/* Figure out the app name if it's one of the keywords */
 
765
static const gchar *
 
766
manifest_app_name (JsonParser ** manifest, const gchar * pkg, const gchar * original_app)
 
767
{
 
768
        app_name_t app_type = APP_NAME_FIRST;
 
769
 
 
770
        if (original_app == NULL) {
 
771
                /* first */
 
772
        } else if (g_strcmp0(original_app, "first-listed-app") == 0) {
 
773
                /* first */
 
774
        } else if (g_strcmp0(original_app, "last-listed-app") == 0) {
 
775
                app_type = APP_NAME_LAST;
 
776
        } else if (g_strcmp0(original_app, "only-listed-app") == 0) {
 
777
                app_type = APP_NAME_ONLY;
 
778
        } else {
 
779
                return original_app;
 
780
        }
 
781
 
 
782
        if (*manifest == NULL) {
 
783
                *manifest = get_manifest_file(pkg);
 
784
        }
 
785
 
 
786
        JsonNode * root_node = json_parser_get_root(*manifest);
 
787
        JsonObject * root_obj = json_node_get_object(root_node);
 
788
        JsonObject * hooks = json_object_get_object_member(root_obj, "hooks");
 
789
 
 
790
        if (hooks == NULL) {
 
791
                return NULL;
 
792
        }
 
793
 
 
794
        GList * apps = json_object_get_members(hooks);
 
795
        if (apps == NULL) {
 
796
                return NULL;
 
797
        }
 
798
 
 
799
        const gchar * retapp = NULL;
 
800
 
 
801
        switch (app_type) {
 
802
        case APP_NAME_ONLY:
 
803
                if (g_list_length(apps) == 1) {
 
804
                        retapp = (const gchar *)apps->data;
 
805
                }
 
806
                break;
 
807
        case APP_NAME_FIRST:
 
808
                retapp = (const gchar *)apps->data;
 
809
                break;
 
810
        case APP_NAME_LAST:
 
811
                retapp = (const gchar *)(g_list_last(apps)->data);
 
812
                break;
 
813
        default:
 
814
                break;
 
815
        }
 
816
 
 
817
        g_list_free(apps);
 
818
 
 
819
        return retapp;
 
820
}
 
821
 
 
822
/* Figure out the app version using the manifest */
 
823
static const gchar *
 
824
manifest_version (JsonParser ** manifest, const gchar * pkg, const gchar * original_ver)
 
825
{
 
826
        if (original_ver != NULL && g_strcmp0(original_ver, "current-user-version") != 0) {
 
827
                return original_ver;
 
828
        } else  {
 
829
                if (*manifest == NULL) {
 
830
                        *manifest = get_manifest_file(pkg);
 
831
                }
 
832
                g_return_val_if_fail(*manifest != NULL, NULL);
 
833
 
 
834
                JsonNode * node = json_parser_get_root(*manifest);
 
835
                JsonObject * obj = json_node_get_object(node);
 
836
 
 
837
                return g_strdup(json_object_get_string_member(obj, "version"));
 
838
        }
 
839
 
 
840
        return NULL;
 
841
}
 
842
 
 
843
gchar *
 
844
upstart_app_launch_triplet_to_app_id (const gchar * pkg, const gchar * app, const gchar * ver)
 
845
{
 
846
        g_return_val_if_fail(pkg != NULL, NULL);
 
847
 
 
848
        const gchar * version = NULL;
 
849
        const gchar * application = NULL;
 
850
        JsonParser * manifest = NULL;
 
851
 
 
852
        version = manifest_version(&manifest, pkg, ver);
 
853
        g_return_val_if_fail(version != NULL, NULL);
 
854
 
 
855
        application = manifest_app_name(&manifest, pkg, app);
 
856
        g_return_val_if_fail(application != NULL, NULL);
 
857
 
 
858
        gchar * retval = g_strdup_printf("%s_%s_%s", pkg, application, version);
 
859
 
 
860
        /* The parser may hold allocation for some of our strings used above */
 
861
        g_clear_object(&manifest);
 
862
 
 
863
        return retval;
 
864
}