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