xref: /openbmc/phosphor-objmgr/libmapper/app.c (revision 2a8bfc96)
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 	int op = 0;
144 	static const char* token = ":";
145 	char* tmp = NULL;
146 	char* namespace = NULL;
147 	char* interface = NULL;
148 	sd_bus *conn = NULL;
149 	sd_event *loop = NULL;
150 	mapper_async_subtree *subtree = NULL;
151 
152 	if (argc != 3) {
153 		fprintf(stderr, "Usage: %s subtree-remove "
154 				"NAMESPACE%sINTERFACE\n", argv[0], token);
155 		exit(EXIT_FAILURE);
156 	}
157 
158 	op = MAPPER_OP_REMOVE;
159 
160 	namespace = strtok_r(argv[2], token, &tmp);
161 	interface = strtok_r(NULL, token, &tmp);
162 	if ((namespace == NULL) || (interface == NULL)) {
163 		fprintf(stderr, "Token '%s' was not found in '%s'\n", token, argv[2]);
164 		exit(EXIT_FAILURE);
165 	}
166 
167 	r = sd_bus_default_system(&conn);
168 	if(r < 0) {
169 		fprintf(stderr, "Error connecting to system bus: %s\n",
170 				strerror(-r));
171 		goto finish;
172 	}
173 
174 	r = sd_event_default(&loop);
175 	if (r < 0) {
176 		fprintf(stderr, "Error obtaining event loop: %s\n",
177 				strerror(-r));
178 		goto finish;
179 	}
180 
181 	r = sd_bus_attach_event(conn, loop, SD_EVENT_PRIORITY_NORMAL);
182 	if (r < 0) {
183 		fprintf(stderr, "Failed to attach system bus to event loop: %s\n",
184 				strerror(-r));
185 		goto finish;
186 	}
187 
188 	r = mapper_subtree_async(conn, loop, namespace, interface, quit, loop,
189 				&subtree, op);
190 	if(r < 0) {
191 		fprintf(stderr, "Error configuring subtree list: %s\n",
192 				strerror(-r));
193 		goto finish;
194 	}
195 
196 	r = sd_event_loop(loop);
197 	if(r < 0) {
198 		fprintf(stderr, "Error starting event loop: %s\n",
199 				strerror(-r));
200 		goto finish;
201 	}
202 
203 finish:
204 	exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
205 }
206 
207 /* print out the distinct dbus service name for the input dbus path */
208 static int get_service_main(int argc, char *argv[])
209 {
210 	int r;
211 	sd_bus *conn = NULL;
212 	char *service = NULL;
213 
214 	if(argc != 3) {
215 		fprintf(stderr, "Usage: %s get-service OBJECTPATH\n",
216 				argv[0]);
217 		exit(EXIT_FAILURE);
218 	}
219 
220 	r = sd_bus_default_system(&conn);
221 	if(r < 0) {
222 		fprintf(stderr, "Error connecting to system bus: %s\n",
223 				strerror(-r));
224 		goto finish;
225 	}
226 
227 	r = mapper_get_service(conn, argv[2], &service);
228 	if(r < 0) {
229 		fprintf(stderr, "Error finding '%s' service: %s\n",
230 				argv[2], strerror(-r));
231 		goto finish;
232 	}
233 
234 	printf("%s\n", service);
235 
236 
237 finish:
238 	exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
239 }
240 
241 int main(int argc, char *argv[])
242 {
243 	static const char *usage =
244 		"Usage: %s {COMMAND} ...\n"
245 		"\nCOMMANDS:\n"
246 		"  call           invoke the specified method\n"
247 		"  wait           wait for the specified objects to appear on the DBus\n"
248 		"  subtree-remove\n"
249 		"                 wait until the specified interface is not present\n"
250 		"                 in any of the subtrees of the specified namespace\n"
251 		"  get-service    return the service identifier for input path\n";
252 
253 	if(argc < 2) {
254 		fprintf(stderr, usage, argv[0]);
255 		exit(EXIT_FAILURE);
256 	}
257 
258 	if(!strcmp(argv[1], "call"))
259 		call_main(argc, argv);
260 	if(!strcmp(argv[1], "wait"))
261 		wait_main(argc, argv);
262 	if(!strcmp(argv[1], "subtree-remove"))
263 		subtree_main(argc, argv);
264 	if(!strcmp(argv[1], "get-service"))
265 		get_service_main(argc, argv);
266 
267 	fprintf(stderr, usage, argv[0]);
268 	exit(EXIT_FAILURE);
269 }
270