blob: e7ddb8cf536334f84ec2ec705ccc7a0674978005 [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 */
16#include <stdlib.h>
17#include <stdio.h>
18#include <errno.h>
19#include <systemd/sd-bus.h>
20#include <systemd/sd-event.h>
Brad Bishop059cffb2016-08-23 10:47:19 -040021
22static void quit(int r, void *loop)
23{
24 sd_event_exit((sd_event *)loop, r);
25}
26
27static int callback(sd_bus_message *m, void *user, sd_bus_error *error)
28{
29 sd_event *loop = user;
30 int r;
31 char *property = NULL;
32
33 r = sd_bus_message_skip(m, "s");
George Liu6f207742024-02-04 10:21:43 +080034 if (r < 0)
35 {
Brad Bishop059cffb2016-08-23 10:47:19 -040036 fprintf(stderr, "Error skipping message fields: %s\n",
37 strerror(-r));
38 quit(r, loop);
39 return r;
40 }
41
42 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
George Liu6f207742024-02-04 10:21:43 +080043 if (r < 0)
44 {
Brad Bishop059cffb2016-08-23 10:47:19 -040045 fprintf(stderr, "Error entering container: %s\n",
46 strerror(-r));
47 quit(r, loop);
48 return r;
49 }
50
George Liu6f207742024-02-04 10:21:43 +080051 while ((r = sd_bus_message_enter_container(
52 m,
53 SD_BUS_TYPE_DICT_ENTRY,
54 "sv")) > 0)
55 {
Brad Bishop059cffb2016-08-23 10:47:19 -040056 r = sd_bus_message_read(m, "s", &property);
George Liu6f207742024-02-04 10:21:43 +080057 if (r < 0)
58 {
Brad Bishop059cffb2016-08-23 10:47:19 -040059 fprintf(stderr, "Error reading message: %s\n",
60 strerror(-r));
61 quit(r, loop);
62 return r;
63 }
64
George Liu6f207742024-02-04 10:21:43 +080065 if (strcmp(property, "pgood"))
Brad Bishop059cffb2016-08-23 10:47:19 -040066 continue;
67
68 quit(0, loop);
69 break;
70 }
71
72 return 0;
73}
74
George Liu6f207742024-02-04 10:21:43 +080075static int get_object(sd_bus *conn, const char *obj,
76 sd_bus_message **reply)
77{
78 sd_bus_message *request = NULL;
79 int r, retry = 0;
80
81 r = sd_bus_message_new_method_call(
82 conn, &request, "xyz.openbmc_project.ObjectMapper",
83 "/xyz/openbmc_project/object_mapper",
84 "xyz.openbmc_project.ObjectMapper", "GetObject");
85 if (r < 0)
86 goto exit;
87
88 r = sd_bus_message_append(request, "s", obj);
89 if (r < 0)
90 goto exit;
91 r = sd_bus_message_append(request, "as", 0, NULL);
92 if (r < 0)
93 goto exit;
94
95 while (true)
96 {
97 r = sd_bus_call(conn, request, 0, NULL, reply);
98 if (r == -EBUSY || r == -ENOBUFS)
99 {
100 if (retry >= mapper_busy_retries)
101 break;
102
103 usleep(mapper_busy_delay_interval_usec * (1 << retry));
104 ++retry;
105 continue;
106 }
107 break;
108 }
109
110 if (r < 0)
111 goto exit;
112
113exit:
114 sd_bus_message_unref(request);
115
116 return r;
117}
118
119static int get_service(sd_bus *conn, const char *obj, char **service)
120{
121 sd_bus_message *reply = NULL;
122 const char *tmp;
123 int r;
124
125 r = get_object(conn, obj, &reply);
126 if (r < 0)
127 goto exit;
128
129 r = sd_bus_message_enter_container(reply, 0, NULL);
130 if (r < 0)
131 goto exit;
132
133 r = sd_bus_message_enter_container(reply, 0, NULL);
134 if (r < 0)
135 goto exit;
136
137 r = sd_bus_message_read(reply, "s", &tmp);
138 if (r < 0)
139 goto exit;
140
141 *service = strdup(tmp);
142
143exit:
144 sd_bus_message_unref(reply);
145
146 return r;
147}
148
Brad Bishop059cffb2016-08-23 10:47:19 -0400149int main(int argc, char *argv[])
150{
151 static const char *matchfmt =
152 "type='signal',"
153 "interface='org.freedesktop.DBus.Properties',"
154 "member='PropertiesChanged',"
155 "arg0='org.openbmc.control.Power',"
156 "path='%s',"
157 "sender='%s'";
158 static const char *usage =
159 "Usage: %s OBJECTPATH on|off\n";
160 static const size_t LEN = 256;
161
162 sd_bus *conn = NULL;
163 sd_event *loop = NULL;
164 sd_bus_slot *slot = NULL;
165 sd_bus_error error = SD_BUS_ERROR_NULL;
166 char *service = NULL;
167 int r, dest = -1, state;
168 char match[LEN];
169
George Liu6f207742024-02-04 10:21:43 +0800170 if (argc < 3)
171 {
Brad Bishop059cffb2016-08-23 10:47:19 -0400172 fprintf(stderr, usage, argv[0]);
173 exit(EXIT_FAILURE);
174 }
175
George Liu6f207742024-02-04 10:21:43 +0800176 if (!strcmp(argv[2], "on"))
Brad Bishop059cffb2016-08-23 10:47:19 -0400177 dest = 1;
George Liu6f207742024-02-04 10:21:43 +0800178 if (!strcmp(argv[2], "off"))
Brad Bishop059cffb2016-08-23 10:47:19 -0400179 dest = 0;
180
George Liu6f207742024-02-04 10:21:43 +0800181 if (dest != 0 && dest != 1)
182 {
Brad Bishop059cffb2016-08-23 10:47:19 -0400183 fprintf(stderr, usage, argv[0]);
184 exit(EXIT_FAILURE);
185 }
186
187 r = sd_bus_default_system(&conn);
George Liu6f207742024-02-04 10:21:43 +0800188 if (r < 0)
189 {
Brad Bishop059cffb2016-08-23 10:47:19 -0400190 fprintf(stderr, "Error connecting to system bus: %s\n",
191 strerror(-r));
192 goto finish;
193 }
194
George Liu6f207742024-02-04 10:21:43 +0800195 r = get_service(conn, argv[1], &service);
196 if (r < 0)
197 {
Brad Bishop059cffb2016-08-23 10:47:19 -0400198 fprintf(stderr, "Error obtaining host service: %s\n",
199 strerror(-r));
200 goto finish;
201 }
202
203 r = sd_event_default(&loop);
George Liu6f207742024-02-04 10:21:43 +0800204 if (r < 0)
205 {
Brad Bishop059cffb2016-08-23 10:47:19 -0400206 fprintf(stderr, "Error obtaining event loop: %s\n",
207 strerror(-r));
208 goto finish;
209 }
210
211 r = sd_bus_attach_event(conn, loop, SD_EVENT_PRIORITY_NORMAL);
George Liu6f207742024-02-04 10:21:43 +0800212 if (r < 0)
213 {
Brad Bishop059cffb2016-08-23 10:47:19 -0400214 fprintf(stderr, "Failed to attach system "
George Liu6f207742024-02-04 10:21:43 +0800215 "bus to event loop: %s\n",
Brad Bishop059cffb2016-08-23 10:47:19 -0400216 strerror(-r));
217 goto finish;
218 }
219
George Liu6f207742024-02-04 10:21:43 +0800220 if (strlen(matchfmt) + strnlen(argv[1], LEN) > LEN)
221 {
Brad Bishop059cffb2016-08-23 10:47:19 -0400222 r = -E2BIG;
223 fprintf(stderr, "Error adding match rule: %s\n",
224 strerror(-r));
225 goto finish;
226 }
227
228 sprintf(match, matchfmt, argv[1], service);
229
230 r = sd_bus_add_match(conn,
George Liu6f207742024-02-04 10:21:43 +0800231 &slot,
232 match,
233 callback,
234 loop);
235 if (r < 0)
236 {
Brad Bishop059cffb2016-08-23 10:47:19 -0400237 fprintf(stderr, "Error adding match rule: %s\n",
238 strerror(-r));
239 goto finish;
240 }
241
242 r = sd_bus_get_property_trivial(conn,
George Liu6f207742024-02-04 10:21:43 +0800243 service,
244 argv[1],
245 "org.openbmc.control.Power",
246 "pgood",
247 &error,
248 'i',
249 &state);
250 if (r < 0)
251 {
Brad Bishop059cffb2016-08-23 10:47:19 -0400252 fprintf(stderr, "Error getting property: %s\n",
253 strerror(-r));
254 goto finish;
255 }
256
George Liu6f207742024-02-04 10:21:43 +0800257 if (dest == state)
Brad Bishop059cffb2016-08-23 10:47:19 -0400258 goto finish;
259
260 r = sd_event_loop(loop);
George Liu6f207742024-02-04 10:21:43 +0800261 if (r < 0)
262 {
Brad Bishop059cffb2016-08-23 10:47:19 -0400263 fprintf(stderr, "Error starting event loop: %s\n",
264 strerror(-r));
265 goto finish;
266 }
267
268finish:
269 exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
270}