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 35static 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 51int 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