blob: 069ee35f15c3836f02b295c079b120bf0d230207 [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 Williamsac3b9682024-10-03 21:46:15 -040016#include <stdbool.h>
Brad Bishop059cffb2016-08-23 10:47:19 -040017#include <stdio.h>
Patrick Williamsac3b9682024-10-03 21:46:15 -040018#include <stdlib.h>
Brad Bishop059cffb2016-08-23 10:47:19 -040019#include <errno.h>
20#include <systemd/sd-bus.h>
21#include <systemd/sd-event.h>
Brad Bishop059cffb2016-08-23 10:47:19 -040022
23static void quit(int r, void *loop)
24{
25 sd_event_exit((sd_event *)loop, r);
26}
27
28static int callback(sd_bus_message *m, void *user, sd_bus_error *error)
29{
30 sd_event *loop = user;
31 int r;
32 char *property = NULL;
33
34 r = sd_bus_message_skip(m, "s");
George Liu6f207742024-02-04 10:21:43 +080035 if (r < 0)
36 {
Brad Bishop059cffb2016-08-23 10:47:19 -040037 fprintf(stderr, "Error skipping message fields: %s\n",
38 strerror(-r));
39 quit(r, loop);
40 return r;
41 }
42
43 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
George Liu6f207742024-02-04 10:21:43 +080044 if (r < 0)
45 {
Brad Bishop059cffb2016-08-23 10:47:19 -040046 fprintf(stderr, "Error entering container: %s\n",
47 strerror(-r));
48 quit(r, loop);
49 return r;
50 }
51
George Liu6f207742024-02-04 10:21:43 +080052 while ((r = sd_bus_message_enter_container(
53 m,
54 SD_BUS_TYPE_DICT_ENTRY,
55 "sv")) > 0)
56 {
Brad Bishop059cffb2016-08-23 10:47:19 -040057 r = sd_bus_message_read(m, "s", &property);
George Liu6f207742024-02-04 10:21:43 +080058 if (r < 0)
59 {
Brad Bishop059cffb2016-08-23 10:47:19 -040060 fprintf(stderr, "Error reading message: %s\n",
61 strerror(-r));
62 quit(r, loop);
63 return r;
64 }
65
George Liu6f207742024-02-04 10:21:43 +080066 if (strcmp(property, "pgood"))
Brad Bishop059cffb2016-08-23 10:47:19 -040067 continue;
68
69 quit(0, loop);
70 break;
71 }
72
73 return 0;
74}
75
George Liu6f207742024-02-04 10:21:43 +080076static int get_object(sd_bus *conn, const char *obj,
77 sd_bus_message **reply)
78{
79 sd_bus_message *request = NULL;
80 int r, retry = 0;
81
82 r = sd_bus_message_new_method_call(
83 conn, &request, "xyz.openbmc_project.ObjectMapper",
84 "/xyz/openbmc_project/object_mapper",
85 "xyz.openbmc_project.ObjectMapper", "GetObject");
86 if (r < 0)
87 goto exit;
88
89 r = sd_bus_message_append(request, "s", obj);
90 if (r < 0)
91 goto exit;
92 r = sd_bus_message_append(request, "as", 0, NULL);
93 if (r < 0)
94 goto exit;
95
96 while (true)
97 {
98 r = sd_bus_call(conn, request, 0, NULL, reply);
99 if (r == -EBUSY || r == -ENOBUFS)
100 {
101 if (retry >= mapper_busy_retries)
102 break;
103
104 usleep(mapper_busy_delay_interval_usec * (1 << retry));
105 ++retry;
106 continue;
107 }
108 break;
109 }
110
111 if (r < 0)
112 goto exit;
113
114exit:
115 sd_bus_message_unref(request);
116
117 return r;
118}
119
120static int get_service(sd_bus *conn, const char *obj, char **service)
121{
122 sd_bus_message *reply = NULL;
123 const char *tmp;
124 int r;
125
126 r = get_object(conn, obj, &reply);
127 if (r < 0)
128 goto exit;
129
130 r = sd_bus_message_enter_container(reply, 0, NULL);
131 if (r < 0)
132 goto exit;
133
134 r = sd_bus_message_enter_container(reply, 0, NULL);
135 if (r < 0)
136 goto exit;
137
138 r = sd_bus_message_read(reply, "s", &tmp);
139 if (r < 0)
140 goto exit;
141
142 *service = strdup(tmp);
143
144exit:
145 sd_bus_message_unref(reply);
146
147 return r;
148}
149
Brad Bishop059cffb2016-08-23 10:47:19 -0400150int main(int argc, char *argv[])
151{
152 static const char *matchfmt =
153 "type='signal',"
154 "interface='org.freedesktop.DBus.Properties',"
155 "member='PropertiesChanged',"
156 "arg0='org.openbmc.control.Power',"
157 "path='%s',"
158 "sender='%s'";
159 static const char *usage =
160 "Usage: %s OBJECTPATH on|off\n";
161 static const size_t LEN = 256;
162
163 sd_bus *conn = NULL;
164 sd_event *loop = NULL;
165 sd_bus_slot *slot = NULL;
166 sd_bus_error error = SD_BUS_ERROR_NULL;
167 char *service = NULL;
168 int r, dest = -1, state;
169 char match[LEN];
170
George Liu6f207742024-02-04 10:21:43 +0800171 if (argc < 3)
172 {
Brad Bishop059cffb2016-08-23 10:47:19 -0400173 fprintf(stderr, usage, argv[0]);
174 exit(EXIT_FAILURE);
175 }
176
George Liu6f207742024-02-04 10:21:43 +0800177 if (!strcmp(argv[2], "on"))
Brad Bishop059cffb2016-08-23 10:47:19 -0400178 dest = 1;
George Liu6f207742024-02-04 10:21:43 +0800179 if (!strcmp(argv[2], "off"))
Brad Bishop059cffb2016-08-23 10:47:19 -0400180 dest = 0;
181
George Liu6f207742024-02-04 10:21:43 +0800182 if (dest != 0 && dest != 1)
183 {
Brad Bishop059cffb2016-08-23 10:47:19 -0400184 fprintf(stderr, usage, argv[0]);
185 exit(EXIT_FAILURE);
186 }
187
188 r = sd_bus_default_system(&conn);
George Liu6f207742024-02-04 10:21:43 +0800189 if (r < 0)
190 {
Brad Bishop059cffb2016-08-23 10:47:19 -0400191 fprintf(stderr, "Error connecting to system bus: %s\n",
192 strerror(-r));
193 goto finish;
194 }
195
George Liu6f207742024-02-04 10:21:43 +0800196 r = get_service(conn, argv[1], &service);
197 if (r < 0)
198 {
Brad Bishop059cffb2016-08-23 10:47:19 -0400199 fprintf(stderr, "Error obtaining host service: %s\n",
200 strerror(-r));
201 goto finish;
202 }
203
204 r = sd_event_default(&loop);
George Liu6f207742024-02-04 10:21:43 +0800205 if (r < 0)
206 {
Brad Bishop059cffb2016-08-23 10:47:19 -0400207 fprintf(stderr, "Error obtaining event loop: %s\n",
208 strerror(-r));
209 goto finish;
210 }
211
212 r = sd_bus_attach_event(conn, loop, SD_EVENT_PRIORITY_NORMAL);
George Liu6f207742024-02-04 10:21:43 +0800213 if (r < 0)
214 {
Brad Bishop059cffb2016-08-23 10:47:19 -0400215 fprintf(stderr, "Failed to attach system "
George Liu6f207742024-02-04 10:21:43 +0800216 "bus to event loop: %s\n",
Brad Bishop059cffb2016-08-23 10:47:19 -0400217 strerror(-r));
218 goto finish;
219 }
220
George Liu6f207742024-02-04 10:21:43 +0800221 if (strlen(matchfmt) + strnlen(argv[1], LEN) > LEN)
222 {
Brad Bishop059cffb2016-08-23 10:47:19 -0400223 r = -E2BIG;
224 fprintf(stderr, "Error adding match rule: %s\n",
225 strerror(-r));
226 goto finish;
227 }
228
229 sprintf(match, matchfmt, argv[1], service);
230
231 r = sd_bus_add_match(conn,
George Liu6f207742024-02-04 10:21:43 +0800232 &slot,
233 match,
234 callback,
235 loop);
236 if (r < 0)
237 {
Brad Bishop059cffb2016-08-23 10:47:19 -0400238 fprintf(stderr, "Error adding match rule: %s\n",
239 strerror(-r));
240 goto finish;
241 }
242
243 r = sd_bus_get_property_trivial(conn,
George Liu6f207742024-02-04 10:21:43 +0800244 service,
245 argv[1],
246 "org.openbmc.control.Power",
247 "pgood",
248 &error,
249 'i',
250 &state);
251 if (r < 0)
252 {
Brad Bishop059cffb2016-08-23 10:47:19 -0400253 fprintf(stderr, "Error getting property: %s\n",
254 strerror(-r));
255 goto finish;
256 }
257
George Liu6f207742024-02-04 10:21:43 +0800258 if (dest == state)
Brad Bishop059cffb2016-08-23 10:47:19 -0400259 goto finish;
260
261 r = sd_event_loop(loop);
George Liu6f207742024-02-04 10:21:43 +0800262 if (r < 0)
263 {
Brad Bishop059cffb2016-08-23 10:47:19 -0400264 fprintf(stderr, "Error starting event loop: %s\n",
265 strerror(-r));
266 goto finish;
267 }
268
269finish:
270 exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
271}