blob: f89a24f50f2ebbb574d8a990f90c4870de2d2de9 [file] [log] [blame]
Brad Bishop059cffb2016-08-23 10:47:19 -04001/**
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 */
Patrick Williamsc1d00e22024-10-04 09:26:09 -040016#include <errno.h>
Patrick Williamsac3b9682024-10-03 21:46:15 -040017#include <stdbool.h>
Brad Bishop059cffb2016-08-23 10:47:19 -040018#include <stdio.h>
Patrick Williamsac3b9682024-10-03 21:46:15 -040019#include <stdlib.h>
Patrick Williamsc1d00e22024-10-04 09:26:09 -040020#include <unistd.h>
Brad Bishop059cffb2016-08-23 10:47:19 -040021#include <systemd/sd-bus.h>
22#include <systemd/sd-event.h>
Brad Bishop059cffb2016-08-23 10:47:19 -040023
Patrick Williamsc1d00e22024-10-04 09:26:09 -040024/* Copied from phosphor-objmgr to make the code compile. */
25static const int mapper_busy_retries = 5;
26static const uint64_t mapper_busy_delay_interval_usec = 1000000;
27
Brad Bishop059cffb2016-08-23 10:47:19 -040028static void quit(int r, void *loop)
29{
30 sd_event_exit((sd_event *)loop, r);
31}
32
33static int callback(sd_bus_message *m, void *user, sd_bus_error *error)
34{
Patrick Williamsc1d00e22024-10-04 09:26:09 -040035 (void) error;
36
Brad Bishop059cffb2016-08-23 10:47:19 -040037 sd_event *loop = user;
38 int r;
39 char *property = NULL;
40
41 r = sd_bus_message_skip(m, "s");
George Liu6f207742024-02-04 10:21:43 +080042 if (r < 0)
43 {
Brad Bishop059cffb2016-08-23 10:47:19 -040044 fprintf(stderr, "Error skipping message fields: %s\n",
45 strerror(-r));
46 quit(r, loop);
47 return r;
48 }
49
50 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
George Liu6f207742024-02-04 10:21:43 +080051 if (r < 0)
52 {
Brad Bishop059cffb2016-08-23 10:47:19 -040053 fprintf(stderr, "Error entering container: %s\n",
54 strerror(-r));
55 quit(r, loop);
56 return r;
57 }
58
George Liu6f207742024-02-04 10:21:43 +080059 while ((r = sd_bus_message_enter_container(
60 m,
61 SD_BUS_TYPE_DICT_ENTRY,
62 "sv")) > 0)
63 {
Brad Bishop059cffb2016-08-23 10:47:19 -040064 r = sd_bus_message_read(m, "s", &property);
George Liu6f207742024-02-04 10:21:43 +080065 if (r < 0)
66 {
Brad Bishop059cffb2016-08-23 10:47:19 -040067 fprintf(stderr, "Error reading message: %s\n",
68 strerror(-r));
69 quit(r, loop);
70 return r;
71 }
72
George Liu6f207742024-02-04 10:21:43 +080073 if (strcmp(property, "pgood"))
Brad Bishop059cffb2016-08-23 10:47:19 -040074 continue;
75
76 quit(0, loop);
77 break;
78 }
79
80 return 0;
81}
82
George Liu6f207742024-02-04 10:21:43 +080083static int get_object(sd_bus *conn, const char *obj,
84 sd_bus_message **reply)
85{
86 sd_bus_message *request = NULL;
87 int r, retry = 0;
88
89 r = sd_bus_message_new_method_call(
90 conn, &request, "xyz.openbmc_project.ObjectMapper",
91 "/xyz/openbmc_project/object_mapper",
92 "xyz.openbmc_project.ObjectMapper", "GetObject");
93 if (r < 0)
94 goto exit;
95
96 r = sd_bus_message_append(request, "s", obj);
97 if (r < 0)
98 goto exit;
99 r = sd_bus_message_append(request, "as", 0, NULL);
100 if (r < 0)
101 goto exit;
102
103 while (true)
104 {
105 r = sd_bus_call(conn, request, 0, NULL, reply);
106 if (r == -EBUSY || r == -ENOBUFS)
107 {
108 if (retry >= mapper_busy_retries)
109 break;
110
111 usleep(mapper_busy_delay_interval_usec * (1 << retry));
112 ++retry;
113 continue;
114 }
115 break;
116 }
117
118 if (r < 0)
119 goto exit;
120
121exit:
122 sd_bus_message_unref(request);
123
124 return r;
125}
126
127static int get_service(sd_bus *conn, const char *obj, char **service)
128{
129 sd_bus_message *reply = NULL;
130 const char *tmp;
131 int r;
132
133 r = get_object(conn, obj, &reply);
134 if (r < 0)
135 goto exit;
136
137 r = sd_bus_message_enter_container(reply, 0, NULL);
138 if (r < 0)
139 goto exit;
140
141 r = sd_bus_message_enter_container(reply, 0, NULL);
142 if (r < 0)
143 goto exit;
144
145 r = sd_bus_message_read(reply, "s", &tmp);
146 if (r < 0)
147 goto exit;
148
149 *service = strdup(tmp);
150
151exit:
152 sd_bus_message_unref(reply);
153
154 return r;
155}
156
Brad Bishop059cffb2016-08-23 10:47:19 -0400157int main(int argc, char *argv[])
158{
159 static const char *matchfmt =
160 "type='signal',"
161 "interface='org.freedesktop.DBus.Properties',"
162 "member='PropertiesChanged',"
163 "arg0='org.openbmc.control.Power',"
164 "path='%s',"
165 "sender='%s'";
166 static const char *usage =
167 "Usage: %s OBJECTPATH on|off\n";
168 static const size_t LEN = 256;
169
170 sd_bus *conn = NULL;
171 sd_event *loop = NULL;
172 sd_bus_slot *slot = NULL;
173 sd_bus_error error = SD_BUS_ERROR_NULL;
174 char *service = NULL;
175 int r, dest = -1, state;
176 char match[LEN];
177
George Liu6f207742024-02-04 10:21:43 +0800178 if (argc < 3)
179 {
Brad Bishop059cffb2016-08-23 10:47:19 -0400180 fprintf(stderr, usage, argv[0]);
181 exit(EXIT_FAILURE);
182 }
183
George Liu6f207742024-02-04 10:21:43 +0800184 if (!strcmp(argv[2], "on"))
Brad Bishop059cffb2016-08-23 10:47:19 -0400185 dest = 1;
George Liu6f207742024-02-04 10:21:43 +0800186 if (!strcmp(argv[2], "off"))
Brad Bishop059cffb2016-08-23 10:47:19 -0400187 dest = 0;
188
George Liu6f207742024-02-04 10:21:43 +0800189 if (dest != 0 && dest != 1)
190 {
Brad Bishop059cffb2016-08-23 10:47:19 -0400191 fprintf(stderr, usage, argv[0]);
192 exit(EXIT_FAILURE);
193 }
194
195 r = sd_bus_default_system(&conn);
George Liu6f207742024-02-04 10:21:43 +0800196 if (r < 0)
197 {
Brad Bishop059cffb2016-08-23 10:47:19 -0400198 fprintf(stderr, "Error connecting to system bus: %s\n",
199 strerror(-r));
200 goto finish;
201 }
202
George Liu6f207742024-02-04 10:21:43 +0800203 r = get_service(conn, argv[1], &service);
204 if (r < 0)
205 {
Brad Bishop059cffb2016-08-23 10:47:19 -0400206 fprintf(stderr, "Error obtaining host service: %s\n",
207 strerror(-r));
208 goto finish;
209 }
210
211 r = sd_event_default(&loop);
George Liu6f207742024-02-04 10:21:43 +0800212 if (r < 0)
213 {
Brad Bishop059cffb2016-08-23 10:47:19 -0400214 fprintf(stderr, "Error obtaining event loop: %s\n",
215 strerror(-r));
216 goto finish;
217 }
218
219 r = sd_bus_attach_event(conn, loop, SD_EVENT_PRIORITY_NORMAL);
George Liu6f207742024-02-04 10:21:43 +0800220 if (r < 0)
221 {
Brad Bishop059cffb2016-08-23 10:47:19 -0400222 fprintf(stderr, "Failed to attach system "
George Liu6f207742024-02-04 10:21:43 +0800223 "bus to event loop: %s\n",
Brad Bishop059cffb2016-08-23 10:47:19 -0400224 strerror(-r));
225 goto finish;
226 }
227
George Liu6f207742024-02-04 10:21:43 +0800228 if (strlen(matchfmt) + strnlen(argv[1], LEN) > LEN)
229 {
Brad Bishop059cffb2016-08-23 10:47:19 -0400230 r = -E2BIG;
231 fprintf(stderr, "Error adding match rule: %s\n",
232 strerror(-r));
233 goto finish;
234 }
235
236 sprintf(match, matchfmt, argv[1], service);
237
238 r = sd_bus_add_match(conn,
George Liu6f207742024-02-04 10:21:43 +0800239 &slot,
240 match,
241 callback,
242 loop);
243 if (r < 0)
244 {
Brad Bishop059cffb2016-08-23 10:47:19 -0400245 fprintf(stderr, "Error adding match rule: %s\n",
246 strerror(-r));
247 goto finish;
248 }
249
250 r = sd_bus_get_property_trivial(conn,
George Liu6f207742024-02-04 10:21:43 +0800251 service,
252 argv[1],
253 "org.openbmc.control.Power",
254 "pgood",
255 &error,
256 'i',
257 &state);
258 if (r < 0)
259 {
Brad Bishop059cffb2016-08-23 10:47:19 -0400260 fprintf(stderr, "Error getting property: %s\n",
261 strerror(-r));
262 goto finish;
263 }
264
George Liu6f207742024-02-04 10:21:43 +0800265 if (dest == state)
Brad Bishop059cffb2016-08-23 10:47:19 -0400266 goto finish;
267
268 r = sd_event_loop(loop);
George Liu6f207742024-02-04 10:21:43 +0800269 if (r < 0)
270 {
Brad Bishop059cffb2016-08-23 10:47:19 -0400271 fprintf(stderr, "Error starting event loop: %s\n",
272 strerror(-r));
273 goto finish;
274 }
275
276finish:
277 exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
278}