1 /** 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> 21 #include <mapper.h> 22 23 static void quit(int r, void *loop) 24 { 25 sd_event_exit((sd_event *)loop, r); 26 } 27 28 static 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"); 35 if (r < 0) { 36 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}"); 43 if (r < 0) { 44 fprintf(stderr, "Error entering container: %s\n", 45 strerror(-r)); 46 quit(r, loop); 47 return r; 48 } 49 50 while((r = sd_bus_message_enter_container( 51 m, 52 SD_BUS_TYPE_DICT_ENTRY, 53 "sv")) > 0) { 54 r = sd_bus_message_read(m, "s", &property); 55 if (r < 0) { 56 fprintf(stderr, "Error reading message: %s\n", 57 strerror(-r)); 58 quit(r, loop); 59 return r; 60 } 61 62 if(strcmp(property, "pgood")) 63 continue; 64 65 quit(0, loop); 66 break; 67 } 68 69 return 0; 70 } 71 72 int main(int argc, char *argv[]) 73 { 74 static const char *matchfmt = 75 "type='signal'," 76 "interface='org.freedesktop.DBus.Properties'," 77 "member='PropertiesChanged'," 78 "arg0='org.openbmc.control.Power'," 79 "path='%s'," 80 "sender='%s'"; 81 static const char *usage = 82 "Usage: %s OBJECTPATH on|off\n"; 83 static const size_t LEN = 256; 84 85 sd_bus *conn = NULL; 86 sd_event *loop = NULL; 87 sd_bus_slot *slot = NULL; 88 sd_bus_error error = SD_BUS_ERROR_NULL; 89 char *service = NULL; 90 int r, dest = -1, state; 91 char match[LEN]; 92 93 if(argc < 3) { 94 fprintf(stderr, usage, argv[0]); 95 exit(EXIT_FAILURE); 96 } 97 98 if(!strcmp(argv[2], "on")) 99 dest = 1; 100 if(!strcmp(argv[2], "off")) 101 dest = 0; 102 103 if(dest != 0 && dest != 1) { 104 fprintf(stderr, usage, argv[0]); 105 exit(EXIT_FAILURE); 106 } 107 108 r = sd_bus_default_system(&conn); 109 if(r < 0) { 110 fprintf(stderr, "Error connecting to system bus: %s\n", 111 strerror(-r)); 112 goto finish; 113 } 114 115 r = mapper_get_service(conn, argv[1], &service); 116 if (r < 0) { 117 fprintf(stderr, "Error obtaining host service: %s\n", 118 strerror(-r)); 119 goto finish; 120 } 121 122 r = sd_event_default(&loop); 123 if (r < 0) { 124 fprintf(stderr, "Error obtaining event loop: %s\n", 125 strerror(-r)); 126 goto finish; 127 } 128 129 r = sd_bus_attach_event(conn, loop, SD_EVENT_PRIORITY_NORMAL); 130 if (r < 0) { 131 fprintf(stderr, "Failed to attach system " 132 "bus to event loop: %s\n", 133 strerror(-r)); 134 goto finish; 135 } 136 137 if(strlen(matchfmt) + strnlen(argv[1], LEN) > LEN) { 138 r = -E2BIG; 139 fprintf(stderr, "Error adding match rule: %s\n", 140 strerror(-r)); 141 goto finish; 142 } 143 144 sprintf(match, matchfmt, argv[1], service); 145 146 r = sd_bus_add_match(conn, 147 &slot, 148 match, 149 callback, 150 loop); 151 if(r < 0) { 152 fprintf(stderr, "Error adding match rule: %s\n", 153 strerror(-r)); 154 goto finish; 155 } 156 157 r = sd_bus_get_property_trivial(conn, 158 service, 159 argv[1], 160 "org.openbmc.control.Power", 161 "pgood", 162 &error, 163 'i', 164 &state); 165 if(r < 0) { 166 fprintf(stderr, "Error getting property: %s\n", 167 strerror(-r)); 168 goto finish; 169 } 170 171 if(dest == state) 172 goto finish; 173 174 r = sd_event_loop(loop); 175 if(r < 0) { 176 fprintf(stderr, "Error starting event loop: %s\n", 177 strerror(-r)); 178 goto finish; 179 } 180 181 finish: 182 exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS); 183 } 184