1 /** 2 * Copyright 2016 IBM Corporation 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 #include "config.h" 17 #include <stdlib.h> 18 #include <stdio.h> 19 #include <systemd/sd-bus.h> 20 #include <systemd/sd-event.h> 21 #include "mapper.h" 22 23 static int call_main(int argc, char *argv[]) 24 { 25 int r; 26 sd_bus *conn = NULL; 27 char *service = NULL; 28 sd_bus_message *m = NULL, *reply = NULL; 29 sd_bus_error error = SD_BUS_ERROR_NULL; 30 31 if(argc < 5) { 32 fprintf(stderr, "Usage: %s call OBJECTPATH INTERFACE " 33 "METHOD [SIGNATURE [ARGUMENT...]\n", argv[0]); 34 r = -1; 35 goto finish; 36 } 37 38 r = sd_bus_default_system(&conn); 39 if(r < 0) { 40 fprintf(stderr, "Error connecting to system bus: %s\n", 41 strerror(-r)); 42 goto finish; 43 } 44 45 r = mapper_get_service(conn, argv[2], &service); 46 if(r < 0) { 47 fprintf(stderr, "Error finding '%s' service: %s\n", 48 argv[2], strerror(-r)); 49 goto finish; 50 } 51 52 r = sd_bus_message_new_method_call( 53 conn, &m, service, argv[2], argv[3], argv[4]); 54 if(r < 0) { 55 fprintf(stderr, "Error populating message: %s\n", 56 strerror(-r)); 57 goto finish; 58 } 59 60 if(argc > 5) { 61 char **p; 62 p = argv + 6; 63 r = sd_bus_message_append_cmdline(m, argv[5], &p); 64 if(r < 0) { 65 fprintf(stderr, "Error appending method arguments: %s\n", 66 strerror(-r)); 67 goto finish; 68 } 69 } 70 71 r = sd_bus_call(conn, m, 0, &error, &reply); 72 if(r < 0) { 73 fprintf(stderr, "Error invoking method: %s\n", 74 strerror(-r)); 75 goto finish; 76 } 77 78 finish: 79 exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS); 80 } 81 82 static void quit(int r, void *loop) 83 { 84 sd_event_exit((sd_event *)loop, r); 85 } 86 87 static int wait_main(int argc, char *argv[]) 88 { 89 int r; 90 sd_bus *conn = NULL; 91 sd_event *loop = NULL; 92 mapper_async_wait *wait = NULL; 93 94 if(argc < 3) { 95 fprintf(stderr, "Usage: %s wait OBJECTPATH...\n", argv[0]); 96 exit(EXIT_FAILURE); 97 } 98 99 r = sd_bus_default_system(&conn); 100 if(r < 0) { 101 fprintf(stderr, "Error connecting to system bus: %s\n", 102 strerror(-r)); 103 goto finish; 104 } 105 106 r = sd_event_default(&loop); 107 if (r < 0) { 108 fprintf(stderr, "Error obtaining event loop: %s\n", 109 strerror(-r)); 110 111 goto finish; 112 } 113 114 r = sd_bus_attach_event(conn, loop, SD_EVENT_PRIORITY_NORMAL); 115 if (r < 0) { 116 fprintf(stderr, "Failed to attach system " 117 "bus to event loop: %s\n", 118 strerror(-r)); 119 goto finish; 120 } 121 122 r = mapper_wait_async(conn, loop, argv+2, quit, loop, &wait); 123 if(r < 0) { 124 fprintf(stderr, "Error configuring waitlist: %s\n", 125 strerror(-r)); 126 goto finish; 127 } 128 129 r = sd_event_loop(loop); 130 if(r < 0) { 131 fprintf(stderr, "Error starting event loop: %s\n", 132 strerror(-r)); 133 goto finish; 134 } 135 136 finish: 137 exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS); 138 } 139 140 static int subtree_main(int argc, char *argv[]) 141 { 142 int r = 0; 143 static const char* token = ":"; 144 char* tmp = NULL; 145 char* namespace = NULL; 146 char* interface = NULL; 147 148 if (argc != 3) { 149 fprintf(stderr, "Usage: %s subtree-remove " 150 "NAMESPACE%sINTERFACE\n", argv[0], token); 151 exit(EXIT_FAILURE); 152 } 153 154 namespace = strtok_r(argv[2], token, &tmp); 155 interface = strtok_r(NULL, token, &tmp); 156 if ((namespace == NULL) || (interface == NULL)) { 157 fprintf(stderr, "Token '%s' was not found in '%s'\n", token, argv[2]); 158 exit(EXIT_FAILURE); 159 } 160 161 exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS); 162 } 163 164 /* print out the distinct dbus service name for the input dbus path */ 165 static int get_service_main(int argc, char *argv[]) 166 { 167 int r; 168 sd_bus *conn = NULL; 169 char *service = NULL; 170 171 if(argc != 3) { 172 fprintf(stderr, "Usage: %s get-service OBJECTPATH\n", 173 argv[0]); 174 exit(EXIT_FAILURE); 175 } 176 177 r = sd_bus_default_system(&conn); 178 if(r < 0) { 179 fprintf(stderr, "Error connecting to system bus: %s\n", 180 strerror(-r)); 181 goto finish; 182 } 183 184 r = mapper_get_service(conn, argv[2], &service); 185 if(r < 0) { 186 fprintf(stderr, "Error finding '%s' service: %s\n", 187 argv[2], strerror(-r)); 188 goto finish; 189 } 190 191 printf("%s\n", service); 192 193 194 finish: 195 exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS); 196 } 197 198 int main(int argc, char *argv[]) 199 { 200 static const char *usage = 201 "Usage: %s {COMMAND} ...\n" 202 "\nCOMMANDS:\n" 203 " call invoke the specified method\n" 204 " wait wait for the specified objects to appear on the DBus\n" 205 " subtree-remove\n" 206 " wait until the specified interface is not present\n" 207 " in any of the subtrees of the specified namespace\n" 208 " get-service return the service identifier for input path\n"; 209 210 if(argc < 2) { 211 fprintf(stderr, usage, argv[0]); 212 exit(EXIT_FAILURE); 213 } 214 215 if(!strcmp(argv[1], "call")) 216 call_main(argc, argv); 217 if(!strcmp(argv[1], "wait")) 218 wait_main(argc, argv); 219 if(!strcmp(argv[1], "subtree-remove")) 220 subtree_main(argc, argv); 221 if(!strcmp(argv[1], "get-service")) 222 get_service_main(argc, argv); 223 224 fprintf(stderr, usage, argv[0]); 225 exit(EXIT_FAILURE); 226 } 227