/** * 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 #include #include #include #include #include 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); }