xref: /openbmc/phosphor-objmgr/libmapper/app.c (revision ea6516c4)
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 "config.h"
17 
18 #include <errno.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <systemd/sd-bus.h>
22 #include <systemd/sd-event.h>
23 
24 #include "mapper.h"
25 
26 static void quit(int r, void* loop)
27 {
28     sd_event_exit((sd_event*)loop, r);
29 }
30 
31 static int wait_main(int argc, char* argv[])
32 {
33     int r;
34     sd_bus* conn = NULL;
35     sd_event* loop = NULL;
36     mapper_async_wait* wait = NULL;
37 
38     if (argc < 3)
39     {
40         fprintf(stderr, "Usage: %s wait OBJECTPATH...\n", argv[0]);
41         exit(EXIT_FAILURE);
42     }
43 
44     r = sd_bus_default_system(&conn);
45     if (r < 0)
46     {
47         fprintf(stderr, "Error connecting to system bus: %s\n", strerror(-r));
48         goto finish;
49     }
50 
51     r = sd_event_default(&loop);
52     if (r < 0)
53     {
54         fprintf(stderr, "Error obtaining event loop: %s\n", strerror(-r));
55 
56         goto finish;
57     }
58 
59     r = sd_bus_attach_event(conn, loop, SD_EVENT_PRIORITY_NORMAL);
60     if (r < 0)
61     {
62         fprintf(stderr,
63                 "Failed to attach system "
64                 "bus to event loop: %s\n",
65                 strerror(-r));
66         goto finish;
67     }
68 
69     r = mapper_wait_async(conn, loop, argv + 2, quit, loop, &wait);
70     if (r < 0)
71     {
72         fprintf(stderr, "Error configuring waitlist: %s\n", strerror(-r));
73         goto finish;
74     }
75 
76     r = sd_event_loop(loop);
77     if (r < 0)
78     {
79         fprintf(stderr, "Error starting event loop: %s\n", strerror(-r));
80         goto finish;
81     }
82 
83 finish:
84     exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
85 }
86 
87 static int subtree_main(int argc, char* argv[])
88 {
89     int r = 0;
90     int op = 0;
91     static const char* token = ":";
92     char* tmp = NULL;
93     char* namespace = NULL;
94     char* interface = NULL;
95     sd_bus* conn = NULL;
96     sd_event* loop = NULL;
97     mapper_async_subtree* subtree = NULL;
98 
99     if (argc != 3)
100     {
101         fprintf(stderr,
102                 "Usage: %s subtree-remove "
103                 "NAMESPACE%sINTERFACE\n",
104                 argv[0], token);
105         exit(EXIT_FAILURE);
106     }
107 
108     op = MAPPER_OP_REMOVE;
109 
110     namespace = strtok_r(argv[2], token, &tmp);
111     interface = strtok_r(NULL, token, &tmp);
112     if ((namespace == NULL) || (interface == NULL))
113     {
114         fprintf(stderr, "Token '%s' was not found in '%s'\n", token, argv[2]);
115         exit(EXIT_FAILURE);
116     }
117 
118     r = sd_bus_default_system(&conn);
119     if (r < 0)
120     {
121         fprintf(stderr, "Error connecting to system bus: %s\n", strerror(-r));
122         goto finish;
123     }
124 
125     r = sd_event_default(&loop);
126     if (r < 0)
127     {
128         fprintf(stderr, "Error obtaining event loop: %s\n", strerror(-r));
129         goto finish;
130     }
131 
132     r = sd_bus_attach_event(conn, loop, SD_EVENT_PRIORITY_NORMAL);
133     if (r < 0)
134     {
135         fprintf(stderr, "Failed to attach system bus to event loop: %s\n",
136                 strerror(-r));
137         goto finish;
138     }
139 
140     r = mapper_subtree_async(conn, loop, namespace, interface, quit, loop,
141                              &subtree, op);
142     if (r < 0)
143     {
144         fprintf(stderr, "Error configuring subtree list: %s\n", strerror(-r));
145         goto finish;
146     }
147 
148     r = sd_event_loop(loop);
149     if (r < 0)
150     {
151         /* If this function has been called after the interface in   */
152         /* question has already been removed, then GetSubTree will   */
153         /* fail and it will show up here.  Treat as success instead. */
154         if (r == -ENXIO)
155         {
156             r = 0;
157         }
158         else
159         {
160             fprintf(stderr, "Error starting event loop: %d(%s)\n", r,
161                     strerror(-r));
162             goto finish;
163         }
164     }
165 
166 finish:
167     exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
168 }
169 
170 /* print out the distinct dbus service name for the input dbus path */
171 static int get_service_main(int argc, char* argv[])
172 {
173     int r;
174     sd_bus* conn = NULL;
175     char* service = NULL;
176 
177     if (argc != 3)
178     {
179         fprintf(stderr, "Usage: %s get-service OBJECTPATH\n", argv[0]);
180         exit(EXIT_FAILURE);
181     }
182 
183     r = sd_bus_default_system(&conn);
184     if (r < 0)
185     {
186         fprintf(stderr, "Error connecting to system bus: %s\n", strerror(-r));
187         goto finish;
188     }
189 
190     r = mapper_get_service(conn, argv[2], &service);
191     if (r < 0)
192     {
193         fprintf(stderr, "Error finding '%s' service: %s\n", argv[2],
194                 strerror(-r));
195         goto finish;
196     }
197 
198     printf("%s\n", service);
199 
200 finish:
201     exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
202 }
203 
204 int main(int argc, char* argv[])
205 {
206     static const char* usage =
207         "Usage: %s {COMMAND} ...\n"
208         "\nCOMMANDS:\n"
209         "  wait           wait for the specified objects to appear on the "
210         "DBus\n"
211         "  subtree-remove\n"
212         "                 wait until the specified interface is not present\n"
213         "                 in any of the subtrees of the specified namespace\n"
214         "  get-service    return the service identifier for input path\n";
215 
216     if (argc < 2)
217     {
218         fprintf(stderr, usage, argv[0]);
219         exit(EXIT_FAILURE);
220     }
221 
222     if (!strcmp(argv[1], "wait"))
223         wait_main(argc, argv);
224     if (!strcmp(argv[1], "subtree-remove"))
225         subtree_main(argc, argv);
226     if (!strcmp(argv[1], "get-service"))
227         get_service_main(argc, argv);
228 
229     fprintf(stderr, usage, argv[0]);
230     exit(EXIT_FAILURE);
231 }
232