diff options
| author | Brad Bishop <bradleyb@fuzziesquirrel.com> | 2016-08-13 14:08:17 -0400 |
|---|---|---|
| committer | Brad Bishop <bradleyb@fuzziesquirrel.com> | 2016-08-16 17:25:10 -0400 |
| commit | 2afe718f96f1a6d947de4ea0e7d06853400a72a7 (patch) | |
| tree | 939b57a43623da47d1fdf4673b7235736df6540f /libmapper | |
| parent | 22ff24a6e668d00557ef6465f96d664fe33226f3 (diff) | |
| download | phosphor-objmgr-2afe718f96f1a6d947de4ea0e7d06853400a72a7.tar.gz phosphor-objmgr-2afe718f96f1a6d947de4ea0e7d06853400a72a7.zip | |
mapper-cli: rewrite with sdbus
There are too many instances of the wait/call applications
spawned during BMC startup. Re-write using sdbus.
Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
Change-Id: Ia6fb3b74cb70f93cfd5cc57c1a8b7a9aa2d944c4
Diffstat (limited to 'libmapper')
| -rw-r--r-- | libmapper/Makefile | 13 | ||||
| -rw-r--r-- | libmapper/app.c | 159 | ||||
| -rw-r--r-- | libmapper/mapper.c | 309 | ||||
| -rw-r--r-- | libmapper/mapper.h | 5 |
4 files changed, 483 insertions, 3 deletions
diff --git a/libmapper/Makefile b/libmapper/Makefile index 806390c..2f71515 100644 --- a/libmapper/Makefile +++ b/libmapper/Makefile @@ -1,16 +1,18 @@ libdir=/usr/lib +sbindir=/usr/sbin includedir=/usr/include PACKAGE_DEPS=libsystemd SONAME=libmapper.so VERSION=1 LIBMAPPER=$(SONAME).$(VERSION) +BIN=mapper INCLUDES=mapper.h LDLIBS+=$(shell pkg-config --libs $(PACKAGE_DEPS)) ALL_CFLAGS+=$(shell pkg-config --cflags $(PACKAGE_DEPS)) -fPIC -Werror $(CFLAGS) -all: $(SONAME) +all: $(SONAME) $(BIN) %.o: %.c $(CC) -c $(ALL_CFLAGS) -o $@ $< @@ -22,12 +24,17 @@ $(LIBMAPPER): lib%.so.$(VERSION): %.o $(CC) -shared $(CFLAGS) $(LDFLAGS) -Wl,-soname,$(SONAME) \ -o $@ $^ $(LDLIBS) -install: $(SONAME) $(LIBMAPPER) +$(BIN): app.o $(LIBMAPPER) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) + +install: $(SONAME) $(LIBMAPPER) $(BIN) @mkdir -p $(DESTDIR)$(includedir) install $(INCLUDES) $(DESTDIR)$(includedir) @mkdir -p $(DESTDIR)$(libdir) install $(LIBMAPPER) $(DESTDIR)$(libdir) ln -sf $(LIBMAPPER) $(DESTDIR)$(libdir)/$(SONAME) + @mkdir -p $(DESTDIR)$(sbindir) + install $(BIN) $(DESTDIR)$(sbindir) clean: - rm -f *.o $(LIBMAPPER) $(SONAME) + rm -f *.o $(LIBMAPPER) $(SONAME) $(BIN) diff --git a/libmapper/app.c b/libmapper/app.c new file mode 100644 index 0000000..e2b94eb --- /dev/null +++ b/libmapper/app.c @@ -0,0 +1,159 @@ +/** + * 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 <systemd/sd-bus.h> +#include <systemd/sd-event.h> +#include "mapper.h" + +static int call_main(int argc, char *argv[]) +{ + int r; + sd_bus *conn = NULL; + char *service = NULL; + sd_bus_message *m = NULL, *reply = NULL; + sd_bus_error error = SD_BUS_ERROR_NULL; + + if(argc < 5) { + fprintf(stderr, "Usage: %s call OBJECTPATH INTERFACE " + "METHOD [SIGNATURE [ARGUMENT...]\n", argv[0]); + r = -1; + goto finish; + } + + 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[2], &service); + if(r < 0) { + fprintf(stderr, "Error finding service: %s\n", + strerror(-r)); + goto finish; + } + + r = sd_bus_message_new_method_call( + conn, &m, service, argv[2], argv[3], argv[4]); + if(r < 0) { + fprintf(stderr, "Error populating message: %s\n", + strerror(-r)); + goto finish; + } + + if(argc > 5) { + char **p; + p = argv + 6; + r = sd_bus_message_append_cmdline(m, argv[5], &p); + if(r < 0) { + fprintf(stderr, "Error appending method arguments: %s\n", + strerror(-r)); + goto finish; + } + } + + r = sd_bus_call(conn, m, 0, &error, &reply); + if(r < 0) { + fprintf(stderr, "Error invoking method: %s\n", + strerror(-r)); + goto finish; + } + +finish: + exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS); +} + +static void quit(int r, void *loop) +{ + sd_event_exit((sd_event *)loop, r); +} + +static int wait_main(int argc, char *argv[]) +{ + int r; + sd_bus *conn = NULL; + sd_event *loop = NULL; + mapper_async_wait *wait = NULL; + + if(argc < 3) { + fprintf(stderr, "Usage: %s wait OBJECTPATH...\n", 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 = 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; + } + + r = mapper_wait_async(conn, argv+2, quit, loop, &wait); + if(r < 0) { + fprintf(stderr, "Error configuring waitlist: %s\n", + strerror(-r)); + 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); +} + +int main(int argc, char *argv[]) +{ + static const char *usage = + "Usage: %s {COMMAND} ...\n" + "\nCOMMANDS:\n" + " call invoke the specified method\n" + " wait wait for the specified objects to appear on the DBus\n"; + + if(argc < 2) { + fprintf(stderr, usage, argv[0]); + exit(EXIT_FAILURE); + } + + if(!strcmp(argv[1], "call")) + call_main(argc, argv); + if(!strcmp(argv[1], "wait")) + wait_main(argc, argv); + + fprintf(stderr, usage, argv[0]); + exit(EXIT_FAILURE); +} diff --git a/libmapper/mapper.c b/libmapper/mapper.c index 62dd2e6..3646cc1 100644 --- a/libmapper/mapper.c +++ b/libmapper/mapper.c @@ -13,10 +13,319 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include <stdlib.h> #include <string.h> +#include <stdio.h> +#include <errno.h> #include <systemd/sd-bus.h> #include "mapper.h" +static const char *async_wait_name_owner_match = + "type='signal'," + "sender='org.freedesktop.DBus'," + "interface='org.freedesktop.DBus'," + "member='NameOwnerChanged'," + "path='/org/freedesktop/DBus'"; + +static const char *async_wait_interfaces_added_match = + "type='signal'," + "interface='org.freedesktop.DBus.ObjectManager'," + "member='InterfacesAdded'"; + +struct mapper_async_wait +{ + char **objs; + void (*callback)(int, void *); + void *userdata; + sd_bus *conn; + sd_bus_slot *name_owner_slot; + sd_bus_slot *intf_slot; + int *status; + int count; + int finished; + int r; +}; + +struct async_wait_callback_data +{ + mapper_async_wait *wait; + const char *path; +}; + +static int async_wait_match_name_owner_changed(sd_bus_message *, void *, + sd_bus_error *); +static int async_wait_match_interfaces_added(sd_bus_message *, void *, + sd_bus_error *); +static int async_wait_check_done(mapper_async_wait *); +static void async_wait_done(int r, mapper_async_wait *); +static int async_wait_get_objects(mapper_async_wait *); + +static int sarraylen(char *array[]) +{ + int count = 0; + char **p = array; + + while(*p != NULL) { + ++count; + ++p; + } + + return count; +} + +static void sarrayfree(char *array[]) +{ + char **p = array; + while(*p != NULL) { + free(*p); + ++p; + } + free(array); +} + +static char **sarraydup(char *array[]) +{ + int count = sarraylen(array); + int i; + char **ret = NULL; + + ret = malloc(sizeof(*ret) * count); + if(!ret) + return NULL; + + for(i=0; i<count; ++i) { + ret[i] = strdup(array[i]); + if(!ret[i]) + goto error; + } + + return ret; + +error: + sarrayfree(ret); + return NULL; +} + +static int async_wait_getobject_callback(sd_bus_message *m, + void *userdata, + sd_bus_error *e) +{ + int i, r; + const char *msg; + struct async_wait_callback_data *data = userdata; + mapper_async_wait *wait = data->wait; + + if(wait->finished) + return 0; + if(sd_bus_message_get_errno(m)) + return 0; + + for(i=0; i<wait->count; ++i) { + if(!strcmp(data->path, wait->objs[i])) { + wait->status[i] = 1; + } + } + + free(data); + if(async_wait_check_done(wait)) + async_wait_done(0, wait); + + return 0; +} + +static int async_wait_get_objects(mapper_async_wait *wait) +{ + int i, r; + struct async_wait_callback_data *data = NULL; + + for(i=0; i<wait->count; ++i) { + if(wait->status[i]) + continue; + data = malloc(sizeof(*data)); + data->wait = wait; + data->path = wait->objs[i]; + r = sd_bus_call_method_async( + wait->conn, + NULL, + "org.openbmc.ObjectMapper", + "/org/openbmc/ObjectMapper", + "org.openbmc.ObjectMapper", + "GetObject", + async_wait_getobject_callback, + data, + "s", + wait->objs[i]); + if(r < 0) { + free(data); + fprintf(stderr, "Error invoking method: %s\n", + strerror(-r)); + return r; + } + } + + return 0; +} + +static int async_wait_match_name_owner_changed(sd_bus_message *m, void *w, + sd_bus_error *e) +{ + int i, r; + + mapper_async_wait *wait = w; + if(wait->finished) + return 0; + + r = async_wait_get_objects(wait); + if(r < 0) + async_wait_done(r, wait); + + return 0; +} + +static int async_wait_match_interfaces_added(sd_bus_message *m, void *w, + sd_bus_error *e) +{ + int i, r; + mapper_async_wait *wait = w; + const char *path; + + if(wait->finished) + return 0; + + r = sd_bus_message_read(m, "o", &path); + if (r < 0) { + fprintf(stderr, "Error reading message: %s\n", + strerror(-r)); + goto finished; + } + + for(i=0; i<wait->count; ++i) { + if(!strcmp(path, wait->objs[i])) + wait->status[i] = 1; + } + +finished: + if(r < 0 || async_wait_check_done(wait)) + async_wait_done(r < 0 ? r : 0, wait); + + return 0; +} + +static void async_wait_done(int r, mapper_async_wait *w) +{ + if(w->finished) + return; + + w->finished = 1; + sd_bus_slot_unref(w->name_owner_slot); + sd_bus_slot_unref(w->intf_slot); + + if(w->callback) + w->callback(r, w->userdata); +} + +static int async_wait_check_done(mapper_async_wait *w) +{ + int i; + + if(w->finished) + return 1; + + for(i=0; i<w->count; ++i) + if(!w->status[i]) + return 0; + + return 1; +} + +void mapper_wait_async_free(mapper_async_wait *w) +{ + free(w->status); + sarrayfree(w->objs); + free(w); +} + +int mapper_wait_async(sd_bus *conn, + char *objs[], + void (*callback)(int, void *), + void *userdata, + mapper_async_wait **w) +{ + int r; + mapper_async_wait *wait = NULL; + + wait = malloc(sizeof(*wait)); + if(!wait) + return -ENOMEM; + + memset(wait, 0, sizeof(*wait)); + wait->conn = conn; + wait->callback = callback; + wait->userdata = userdata; + wait->count = sarraylen(objs); + if(!wait->count) + return 0; + + wait->objs = sarraydup(objs); + if(!wait->objs) { + r = -ENOMEM; + goto free_wait; + } + + wait->status = malloc(sizeof(*wait->status) * wait->count); + if(!wait->status) { + r = -ENOMEM; + goto free_objs; + } + memset(wait->status, 0, sizeof(*wait->status) * wait->count); + + r = sd_bus_add_match(conn, + &wait->name_owner_slot, + async_wait_name_owner_match, + async_wait_match_name_owner_changed, + wait); + if(r < 0) { + fprintf(stderr, "Error adding match rule: %s\n", + strerror(-r)); + goto free_status; + } + + r = sd_bus_add_match(conn, + &wait->intf_slot, + async_wait_interfaces_added_match, + async_wait_match_interfaces_added, + wait); + if(r < 0) { + fprintf(stderr, "Error adding match rule: %s\n", + strerror(-r)); + goto unref_name_slot; + } + + r = async_wait_get_objects(wait); + if(r < 0) { + fprintf(stderr, "Error calling method: %s\n", + strerror(-r)); + goto unref_intf_slot; + } + + *w = wait; + + return 0; + +unref_intf_slot: + sd_bus_slot_unref(wait->intf_slot); +unref_name_slot: + sd_bus_slot_unref(wait->name_owner_slot); +free_status: + free(wait->status); +free_objs: + sarrayfree(wait->objs); +free_wait: + free(wait); + + return r; +} + int mapper_get_service(sd_bus *conn, const char *obj, char **service) { sd_bus_error error = SD_BUS_ERROR_NULL; diff --git a/libmapper/mapper.h b/libmapper/mapper.h index 58f1844..b49b302 100644 --- a/libmapper/mapper.h +++ b/libmapper/mapper.h @@ -3,6 +3,11 @@ #ifdef __cplusplus extern "C" { #endif +typedef struct mapper_async_wait mapper_async_wait; +void mapper_wait_async_free(mapper_async_wait *); + +int mapper_wait_async(sd_bus *, char *[], + void (*)(int, void *), void *, mapper_async_wait **); int mapper_get_service(sd_bus *conn, const char *obj, char **service); #ifdef __cplusplus } |

