| /** |
| * Copyright © 2016 IBM Corporation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <errno.h> |
| #include <systemd/sd-bus.h> |
| #include <systemd/sd-event.h> |
| #include <mapper.h> |
| |
| static void quit(int r, void *loop) |
| { |
| sd_event_exit((sd_event *)loop, r); |
| } |
| |
| static int callback(sd_bus_message *m, void *user, sd_bus_error *error) |
| { |
| sd_event *loop = user; |
| int r; |
| char *property = NULL; |
| |
| r = sd_bus_message_skip(m, "s"); |
| if (r < 0) { |
| fprintf(stderr, "Error skipping message fields: %s\n", |
| strerror(-r)); |
| quit(r, loop); |
| return r; |
| } |
| |
| r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}"); |
| if (r < 0) { |
| fprintf(stderr, "Error entering container: %s\n", |
| strerror(-r)); |
| quit(r, loop); |
| return r; |
| } |
| |
| while((r = sd_bus_message_enter_container( |
| m, |
| SD_BUS_TYPE_DICT_ENTRY, |
| "sv")) > 0) { |
| r = sd_bus_message_read(m, "s", &property); |
| if (r < 0) { |
| fprintf(stderr, "Error reading message: %s\n", |
| strerror(-r)); |
| quit(r, loop); |
| return r; |
| } |
| |
| if(strcmp(property, "pgood")) |
| continue; |
| |
| quit(0, loop); |
| break; |
| } |
| |
| return 0; |
| } |
| |
| int main(int argc, char *argv[]) |
| { |
| static const char *matchfmt = |
| "type='signal'," |
| "interface='org.freedesktop.DBus.Properties'," |
| "member='PropertiesChanged'," |
| "arg0='org.openbmc.control.Power'," |
| "path='%s'," |
| "sender='%s'"; |
| static const char *usage = |
| "Usage: %s OBJECTPATH on|off\n"; |
| static const size_t LEN = 256; |
| |
| sd_bus *conn = NULL; |
| sd_event *loop = NULL; |
| sd_bus_slot *slot = NULL; |
| sd_bus_error error = SD_BUS_ERROR_NULL; |
| char *service = NULL; |
| int r, dest = -1, state; |
| char match[LEN]; |
| |
| if(argc < 3) { |
| fprintf(stderr, usage, argv[0]); |
| exit(EXIT_FAILURE); |
| } |
| |
| if(!strcmp(argv[2], "on")) |
| dest = 1; |
| if(!strcmp(argv[2], "off")) |
| dest = 0; |
| |
| if(dest != 0 && dest != 1) { |
| fprintf(stderr, usage, argv[0]); |
| exit(EXIT_FAILURE); |
| } |
| |
| r = sd_bus_default_system(&conn); |
| if(r < 0) { |
| fprintf(stderr, "Error connecting to system bus: %s\n", |
| strerror(-r)); |
| goto finish; |
| } |
| |
| r = mapper_get_service(conn, argv[1], &service); |
| if (r < 0) { |
| fprintf(stderr, "Error obtaining host service: %s\n", |
| strerror(-r)); |
| goto finish; |
| } |
| |
| r = sd_event_default(&loop); |
| if (r < 0) { |
| fprintf(stderr, "Error obtaining event loop: %s\n", |
| strerror(-r)); |
| goto finish; |
| } |
| |
| r = sd_bus_attach_event(conn, loop, SD_EVENT_PRIORITY_NORMAL); |
| if (r < 0) { |
| fprintf(stderr, "Failed to attach system " |
| "bus to event loop: %s\n", |
| strerror(-r)); |
| goto finish; |
| } |
| |
| if(strlen(matchfmt) + strnlen(argv[1], LEN) > LEN) { |
| r = -E2BIG; |
| fprintf(stderr, "Error adding match rule: %s\n", |
| strerror(-r)); |
| goto finish; |
| } |
| |
| sprintf(match, matchfmt, argv[1], service); |
| |
| r = sd_bus_add_match(conn, |
| &slot, |
| match, |
| callback, |
| loop); |
| if(r < 0) { |
| fprintf(stderr, "Error adding match rule: %s\n", |
| strerror(-r)); |
| goto finish; |
| } |
| |
| r = sd_bus_get_property_trivial(conn, |
| service, |
| argv[1], |
| "org.openbmc.control.Power", |
| "pgood", |
| &error, |
| 'i', |
| &state); |
| if(r < 0) { |
| fprintf(stderr, "Error getting property: %s\n", |
| strerror(-r)); |
| goto finish; |
| } |
| |
| if(dest == state) |
| goto finish; |
| |
| r = sd_event_loop(loop); |
| if(r < 0) { |
| fprintf(stderr, "Error starting event loop: %s\n", |
| strerror(-r)); |
| goto finish; |
| } |
| |
| finish: |
| exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS); |
| } |