xref: /openbmc/phosphor-objmgr/libmapper/app.c (revision 6a8688f4)
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