blob: 45173bb37103063089b58002c27f112788ababcb [file] [log] [blame]
Brad Bishop2afe7182016-08-13 14:08:17 -04001/**
Andrew Geissler981f2662017-03-03 15:58:23 -06002 * Copyright 2016 IBM Corporation
Brad Bishop2afe7182016-08-13 14:08:17 -04003 *
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 */
Matthew Barthc6329c92016-11-15 11:13:37 -060016#include "config.h"
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050017
Matt Spinler59cbf342018-09-24 09:46:00 -050018#include <errno.h>
Brad Bishop2afe7182016-08-13 14:08:17 -040019#include <stdio.h>
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050020#include <stdlib.h>
Brad Bishop2afe7182016-08-13 14:08:17 -040021#include <systemd/sd-bus.h>
22#include <systemd/sd-event.h>
Matt Spinler55922022020-04-27 13:45:14 -050023#include <unistd.h>
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050024
Brad Bishop2afe7182016-08-13 14:08:17 -040025#include "mapper.h"
26
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050027static void quit(int r, void* loop)
Brad Bishop2afe7182016-08-13 14:08:17 -040028{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050029 sd_event_exit((sd_event*)loop, r);
Brad Bishop2afe7182016-08-13 14:08:17 -040030}
31
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050032static int wait_main(int argc, char* argv[])
Brad Bishop2afe7182016-08-13 14:08:17 -040033{
Ed Tanous167e2372018-05-07 11:59:10 -070034 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -050035 sd_bus* conn = NULL;
36 sd_event* loop = NULL;
37 mapper_async_wait* wait = NULL;
Matt Spinler55922022020-04-27 13:45:14 -050038 size_t attempts = 0;
39 const size_t max_attempts = 4;
Brad Bishop2afe7182016-08-13 14:08:17 -040040
Ed Tanous167e2372018-05-07 11:59:10 -070041 if (argc < 3)
42 {
43 fprintf(stderr, "Usage: %s wait OBJECTPATH...\n", argv[0]);
44 exit(EXIT_FAILURE);
45 }
Brad Bishop2afe7182016-08-13 14:08:17 -040046
Matt Spinler55922022020-04-27 13:45:14 -050047 /* Mapper waits are typically run early in the boot process, and in some
48 * cases the CPU and/or object manager daemon are so busy that the
49 * GetObject call may fail with a timeout and cause the event loop to exit.
50 * If this happens, retry a few times. Don't retry on other failures.
51 */
52 while (1)
Ed Tanous167e2372018-05-07 11:59:10 -070053 {
Matt Spinler55922022020-04-27 13:45:14 -050054 attempts++;
Brad Bishop2afe7182016-08-13 14:08:17 -040055
Matt Spinler55922022020-04-27 13:45:14 -050056 r = sd_bus_default_system(&conn);
57 if (r < 0)
58 {
59 fprintf(stderr, "Error connecting to system bus: %s\n",
60 strerror(-r));
61 goto finish;
62 }
Brad Bishop2afe7182016-08-13 14:08:17 -040063
Matt Spinler55922022020-04-27 13:45:14 -050064 r = sd_event_default(&loop);
65 if (r < 0)
66 {
67 fprintf(stderr, "Error obtaining event loop: %s\n", strerror(-r));
Brad Bishop2afe7182016-08-13 14:08:17 -040068
Matt Spinler55922022020-04-27 13:45:14 -050069 goto finish;
70 }
Brad Bishop2afe7182016-08-13 14:08:17 -040071
Matt Spinler55922022020-04-27 13:45:14 -050072 r = sd_bus_attach_event(conn, loop, SD_EVENT_PRIORITY_NORMAL);
73 if (r < 0)
74 {
75 fprintf(stderr,
76 "Failed to attach system "
77 "bus to event loop: %s\n",
78 strerror(-r));
79 goto finish;
80 }
Brad Bishop2afe7182016-08-13 14:08:17 -040081
Matt Spinler55922022020-04-27 13:45:14 -050082 r = mapper_wait_async(conn, loop, argv + 2, quit, loop, &wait);
83 if (r < 0)
84 {
85 fprintf(stderr, "Error configuring waitlist: %s\n", strerror(-r));
86 goto finish;
87 }
88
89 r = sd_event_loop(loop);
90 if (r < 0)
91 {
92 fprintf(stderr, "Event loop exited: %s\n", strerror(-r));
93
William A. Kennington III551fafb2020-05-08 02:43:01 -070094 if (-r == ETIMEDOUT || -r == EHOSTUNREACH)
Matt Spinler55922022020-04-27 13:45:14 -050095 {
96 if (attempts <= max_attempts)
97 {
98 fprintf(stderr, "Retrying in 5s\n");
99 sleep(5);
100 sd_event_unref(loop);
101 sd_bus_unref(conn);
102 continue;
103 }
104 else
105 {
106 fprintf(stderr, "Giving up\n");
107 }
108 }
109 else
110 {
111 goto finish;
112 }
113 }
114
115 break;
Ed Tanous167e2372018-05-07 11:59:10 -0700116 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400117
118finish:
Ed Tanous167e2372018-05-07 11:59:10 -0700119 exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
Brad Bishop2afe7182016-08-13 14:08:17 -0400120}
121
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500122static int subtree_main(int argc, char* argv[])
Adriana Kobylak04d7c7d2017-05-04 14:06:18 -0500123{
Ed Tanous167e2372018-05-07 11:59:10 -0700124 int r = 0;
125 int op = 0;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500126 static const char* token = ":";
127 char* tmp = NULL;
128 char* namespace = NULL;
129 char* interface = NULL;
130 sd_bus* conn = NULL;
131 sd_event* loop = NULL;
132 mapper_async_subtree* subtree = NULL;
Adriana Kobylak04d7c7d2017-05-04 14:06:18 -0500133
Ed Tanous167e2372018-05-07 11:59:10 -0700134 if (argc != 3)
135 {
136 fprintf(stderr,
137 "Usage: %s subtree-remove "
138 "NAMESPACE%sINTERFACE\n",
139 argv[0], token);
140 exit(EXIT_FAILURE);
141 }
Adriana Kobylak6a8688f2017-05-05 11:32:17 -0500142
Ed Tanous167e2372018-05-07 11:59:10 -0700143 op = MAPPER_OP_REMOVE;
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500144
Ed Tanous167e2372018-05-07 11:59:10 -0700145 namespace = strtok_r(argv[2], token, &tmp);
146 interface = strtok_r(NULL, token, &tmp);
147 if ((namespace == NULL) || (interface == NULL))
148 {
149 fprintf(stderr, "Token '%s' was not found in '%s'\n", token, argv[2]);
150 exit(EXIT_FAILURE);
151 }
Adriana Kobylak04d7c7d2017-05-04 14:06:18 -0500152
Ed Tanous167e2372018-05-07 11:59:10 -0700153 r = sd_bus_default_system(&conn);
154 if (r < 0)
155 {
156 fprintf(stderr, "Error connecting to system bus: %s\n", strerror(-r));
157 goto finish;
158 }
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500159
Ed Tanous167e2372018-05-07 11:59:10 -0700160 r = sd_event_default(&loop);
161 if (r < 0)
162 {
163 fprintf(stderr, "Error obtaining event loop: %s\n", strerror(-r));
164 goto finish;
165 }
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500166
Ed Tanous167e2372018-05-07 11:59:10 -0700167 r = sd_bus_attach_event(conn, loop, SD_EVENT_PRIORITY_NORMAL);
168 if (r < 0)
169 {
170 fprintf(stderr, "Failed to attach system bus to event loop: %s\n",
171 strerror(-r));
172 goto finish;
173 }
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500174
Ed Tanous167e2372018-05-07 11:59:10 -0700175 r = mapper_subtree_async(conn, loop, namespace, interface, quit, loop,
176 &subtree, op);
177 if (r < 0)
178 {
179 fprintf(stderr, "Error configuring subtree list: %s\n", strerror(-r));
180 goto finish;
181 }
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500182
Ed Tanous167e2372018-05-07 11:59:10 -0700183 r = sd_event_loop(loop);
184 if (r < 0)
185 {
Matt Spinler59cbf342018-09-24 09:46:00 -0500186 /* If this function has been called after the interface in */
187 /* question has already been removed, then GetSubTree will */
188 /* fail and it will show up here. Treat as success instead. */
189 if (r == -ENXIO)
190 {
191 r = 0;
192 }
193 else
194 {
195 fprintf(stderr, "Error starting event loop: %d(%s)\n", r,
196 strerror(-r));
197 goto finish;
198 }
Ed Tanous167e2372018-05-07 11:59:10 -0700199 }
Adriana Kobylak2a8bfc92017-05-11 09:16:02 -0500200
201finish:
Ed Tanous167e2372018-05-07 11:59:10 -0700202 exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
Adriana Kobylak04d7c7d2017-05-04 14:06:18 -0500203}
204
Andrew Geissler981f2662017-03-03 15:58:23 -0600205/* print out the distinct dbus service name for the input dbus path */
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500206static int get_service_main(int argc, char* argv[])
Andrew Geissler981f2662017-03-03 15:58:23 -0600207{
Ed Tanous167e2372018-05-07 11:59:10 -0700208 int r;
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500209 sd_bus* conn = NULL;
210 char* service = NULL;
Andrew Geissler981f2662017-03-03 15:58:23 -0600211
Ed Tanous167e2372018-05-07 11:59:10 -0700212 if (argc != 3)
213 {
214 fprintf(stderr, "Usage: %s get-service OBJECTPATH\n", argv[0]);
215 exit(EXIT_FAILURE);
216 }
Andrew Geissler981f2662017-03-03 15:58:23 -0600217
Ed Tanous167e2372018-05-07 11:59:10 -0700218 r = sd_bus_default_system(&conn);
219 if (r < 0)
220 {
221 fprintf(stderr, "Error connecting to system bus: %s\n", strerror(-r));
222 goto finish;
223 }
Andrew Geissler981f2662017-03-03 15:58:23 -0600224
Ed Tanous167e2372018-05-07 11:59:10 -0700225 r = mapper_get_service(conn, argv[2], &service);
226 if (r < 0)
227 {
228 fprintf(stderr, "Error finding '%s' service: %s\n", argv[2],
229 strerror(-r));
230 goto finish;
231 }
Andrew Geissler981f2662017-03-03 15:58:23 -0600232
Ed Tanous167e2372018-05-07 11:59:10 -0700233 printf("%s\n", service);
Andrew Geissler981f2662017-03-03 15:58:23 -0600234
235finish:
Ed Tanous167e2372018-05-07 11:59:10 -0700236 exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
Andrew Geissler981f2662017-03-03 15:58:23 -0600237}
238
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500239int main(int argc, char* argv[])
Brad Bishop2afe7182016-08-13 14:08:17 -0400240{
Matt Spinlercc6ee9c2018-09-19 13:23:13 -0500241 static const char* usage =
Ed Tanous167e2372018-05-07 11:59:10 -0700242 "Usage: %s {COMMAND} ...\n"
243 "\nCOMMANDS:\n"
Ed Tanous167e2372018-05-07 11:59:10 -0700244 " wait wait for the specified objects to appear on the "
245 "DBus\n"
246 " subtree-remove\n"
247 " wait until the specified interface is not present\n"
248 " in any of the subtrees of the specified namespace\n"
249 " get-service return the service identifier for input path\n";
Brad Bishop2afe7182016-08-13 14:08:17 -0400250
Ed Tanous167e2372018-05-07 11:59:10 -0700251 if (argc < 2)
252 {
253 fprintf(stderr, usage, argv[0]);
254 exit(EXIT_FAILURE);
255 }
Brad Bishop2afe7182016-08-13 14:08:17 -0400256
Ed Tanous167e2372018-05-07 11:59:10 -0700257 if (!strcmp(argv[1], "wait"))
258 wait_main(argc, argv);
259 if (!strcmp(argv[1], "subtree-remove"))
260 subtree_main(argc, argv);
261 if (!strcmp(argv[1], "get-service"))
262 get_service_main(argc, argv);
Brad Bishop2afe7182016-08-13 14:08:17 -0400263
Ed Tanous167e2372018-05-07 11:59:10 -0700264 fprintf(stderr, usage, argv[0]);
265 exit(EXIT_FAILURE);
Brad Bishop2afe7182016-08-13 14:08:17 -0400266}