Home | History | Annotate | Download | only in shims
      1 //
      2 // Copyright (C) 2012 The Android Open Source Project
      3 //
      4 // Licensed under the Apache License, Version 2.0 (the "License");
      5 // you may not use this file except in compliance with the License.
      6 // You may obtain a copy of the License at
      7 //
      8 //      http://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unless required by applicable law or agreed to in writing, software
     11 // distributed under the License is distributed on an "AS IS" BASIS,
     12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 // See the License for the specific language governing permissions and
     14 // limitations under the License.
     15 //
     16 
     17 // Shim to set Cellular.APN property for a service. This exists because
     18 // dbus-send isn't capable of sending anything with nested containers, such as a
     19 // variant that is a dict.
     20 
     21 #ifdef HAVE_CONFIG_H
     22 #include <config.h>
     23 #endif
     24 
     25 #include <stdio.h>
     26 #include <stdlib.h>
     27 #include <string.h>
     28 
     29 #include <dbus/dbus.h>
     30 
     31 #define CONNMAN_SERVICE			"org.chromium.flimflam"
     32 
     33 #define CONNMAN_SERVICE_INTERFACE	CONNMAN_SERVICE ".Service"
     34 
     35 static void append(DBusMessageIter *dict,
     36 		   const char *key,
     37 		   const char *value)
     38 {
     39 	DBusMessageIter entry;
     40 
     41 	dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
     42 							NULL, &entry);
     43 
     44 	dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
     45 
     46 	dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &value);
     47 
     48 	dbus_message_iter_close_container(dict, &entry);
     49 }
     50 
     51 int main(int argc, char *argv[])
     52 {
     53 	DBusConnection *conn;
     54 	DBusError error;
     55 	DBusMessage *msg;
     56 	DBusMessageIter iter, value, dict;
     57 	const char *property;
     58 	char *args;
     59 	char *cp;
     60 	char *argname;
     61 	char *argvalue;
     62 	int done;
     63 
     64 
     65 	if (argc < 4) {
     66 		fprintf(stderr,
     67 	"Usage: %s <service-dbus-path> <property-name> <apn-args>\n",
     68 			argv[0]);
     69 		return 1;
     70 	}
     71 
     72 	dbus_error_init(&error);
     73 
     74 	conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
     75 	if (conn == NULL) {
     76 		if (dbus_error_is_set(&error) == TRUE) {
     77 			fprintf(stderr, "%s\n", error.message);
     78 			dbus_error_free(&error);
     79 		} else
     80 			fprintf(stderr, "Failed to get on system bus\n");
     81 		return 1;
     82 	}
     83 
     84 	msg = dbus_message_new_method_call(CONNMAN_SERVICE,
     85 					   argv[1],
     86 					   CONNMAN_SERVICE_INTERFACE,
     87 					   "SetProperty");
     88 	if (msg == NULL) {
     89 		dbus_connection_unref(conn);
     90 		fprintf(stderr, "Failed to allocate method call\n");
     91 		return 1;
     92 	}
     93 
     94 	dbus_message_set_no_reply(msg, TRUE);
     95 
     96 	dbus_message_iter_init_append(msg, &iter);
     97 
     98 	property = argv[2];
     99 	dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &property);
    100 
    101 	dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
    102 			DBUS_TYPE_ARRAY_AS_STRING
    103 			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
    104 			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_STRING_AS_STRING
    105 			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &value);
    106 
    107 	dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
    108 			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
    109 			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_STRING_AS_STRING
    110 			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
    111 
    112 	args = argv[3];
    113 	cp = args;
    114 	done = 0;
    115 
    116 	while (!done) {
    117 		argname = cp;
    118 		cp = strchr(cp, ',');
    119 		if (cp == NULL) {
    120 			fprintf(stderr, "Badly formed argument string\n");
    121 			dbus_message_unref(msg);
    122 			dbus_connection_unref(conn);
    123 			return 1;
    124 		}
    125 		*cp++ = '\0';
    126 		argvalue = cp;
    127 		cp = strchr(cp, ',');
    128 		if (cp == NULL)
    129 			done = 1;
    130 		else
    131 			*cp++ = '\0';
    132 		append(&dict, argname, argvalue);
    133 	}
    134 
    135 	dbus_message_iter_close_container(&iter, &dict);
    136 	dbus_message_iter_close_container(&dict, &value);
    137 
    138 	dbus_connection_send(conn, msg, NULL);
    139 
    140 	dbus_message_unref(msg);
    141 	dbus_connection_unref(conn);
    142 
    143 	return 0;
    144 }
    145