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 char** split_args(char* arg) 88 { 89 int i = 0; 90 int count = 0; 91 char* p = arg; 92 93 while((p = strchr(p, ' ')) != NULL) { 94 count++; 95 p++; 96 } 97 if (count == 0) 98 return NULL; 99 100 /* Need to allocate space for count+1 number of arguments */ 101 count++; 102 char** args = (char**)malloc(sizeof(*args) * count); 103 if (args != NULL) { 104 i = 0; 105 p = strtok(arg, " "); 106 while((p != NULL) && (i < count)) { 107 args[i++] = p; 108 p = strtok(NULL, " "); 109 } 110 } 111 112 return args; 113 } 114 115 static int wait_main(int argc, char *argv[]) 116 { 117 int r; 118 bool free_args = false; 119 char** args = argv + 2; 120 sd_bus *conn = NULL; 121 sd_event *loop = NULL; 122 mapper_async_wait *wait = NULL; 123 124 if((!strcmp(argv[1], "wait")) && argc < 3) { 125 fprintf(stderr, "Usage: %s wait OBJECTPATH...\n", argv[0]); 126 exit(EXIT_FAILURE); 127 } else if((!strcmp(argv[1], "wait-until-removed")) && argc < 4) { 128 /* The arguments can be passed by a single string, ex: "intf obj1..." */ 129 /* Try to split the single into the multiple arguments */ 130 args = split_args(argv[2]); 131 if (args != NULL) 132 free_args = true; 133 else { 134 fprintf(stderr, "Usage: %s wait-until-removed \ 135 INTERFACE OBJECTPATH...\n", argv[0]); 136 exit(EXIT_FAILURE); 137 } 138 } 139 140 r = sd_bus_default_system(&conn); 141 if(r < 0) { 142 fprintf(stderr, "Error connecting to system bus: %s\n", 143 strerror(-r)); 144 goto finish; 145 } 146 147 r = sd_event_default(&loop); 148 if (r < 0) { 149 fprintf(stderr, "Error obtaining event loop: %s\n", 150 strerror(-r)); 151 152 goto finish; 153 } 154 155 r = sd_bus_attach_event(conn, loop, SD_EVENT_PRIORITY_NORMAL); 156 if (r < 0) { 157 fprintf(stderr, "Failed to attach system " 158 "bus to event loop: %s\n", 159 strerror(-r)); 160 goto finish; 161 } 162 163 if (!strcmp(argv[1], "wait")) 164 r = mapper_wait_async(conn, loop, NULL, args, quit, loop, &wait, 165 true); 166 else if (!strcmp(argv[1], "wait-until-removed")) 167 r = mapper_wait_async(conn, loop, args[0], args+1, quit, loop, &wait, 168 false); 169 if(r < 0) { 170 fprintf(stderr, "Error configuring waitlist: %s\n", 171 strerror(-r)); 172 goto finish; 173 } 174 175 r = sd_event_loop(loop); 176 if(r < 0) { 177 fprintf(stderr, "Error starting event loop: %s\n", 178 strerror(-r)); 179 goto finish; 180 } 181 182 finish: 183 if (free_args) 184 free(args); 185 exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS); 186 } 187 188 /* print out the distinct dbus service name for the input dbus path */ 189 static int get_service_main(int argc, char *argv[]) 190 { 191 int r; 192 sd_bus *conn = NULL; 193 char *service = NULL; 194 195 if(argc != 3) { 196 fprintf(stderr, "Usage: %s get-service OBJECTPATH\n", 197 argv[0]); 198 exit(EXIT_FAILURE); 199 } 200 201 r = sd_bus_default_system(&conn); 202 if(r < 0) { 203 fprintf(stderr, "Error connecting to system bus: %s\n", 204 strerror(-r)); 205 goto finish; 206 } 207 208 r = mapper_get_service(conn, argv[2], &service); 209 if(r < 0) { 210 fprintf(stderr, "Error finding '%s' service: %s\n", 211 argv[2], strerror(-r)); 212 goto finish; 213 } 214 215 printf("%s\n", service); 216 217 218 finish: 219 exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS); 220 } 221 222 int main(int argc, char *argv[]) 223 { 224 static const char *usage = 225 "Usage: %s {COMMAND} ...\n" 226 "\nCOMMANDS:\n" 227 " call invoke the specified method\n" 228 " wait wait for the specified objects to appear on the DBus\n" 229 " wait-until-removed" 230 " wait until the specified objects are not present in the DBus\n" 231 " get-service return the service identifier for input path\n"; 232 233 if(argc < 2) { 234 fprintf(stderr, usage, argv[0]); 235 exit(EXIT_FAILURE); 236 } 237 238 if(!strcmp(argv[1], "call")) 239 call_main(argc, argv); 240 if(!strcmp(argv[1], "wait") || 241 !strcmp(argv[1], "wait-until-removed")) 242 wait_main(argc, argv); 243 if(!strcmp(argv[1], "get-service")) 244 get_service_main(argc, argv); 245 246 fprintf(stderr, usage, argv[0]); 247 exit(EXIT_FAILURE); 248 } 249