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