| /** |
| * 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 "config.h" |
| #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 '%s' service: %s\n", |
| argv[2], 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 char** split_args(char* arg) |
| { |
| int i = 0; |
| int count = 0; |
| char* p = arg; |
| |
| while((p = strchr(p, ' ')) != NULL) { |
| count++; |
| p++; |
| } |
| if (count == 0) |
| return NULL; |
| |
| /* Need to allocate space for count+1 number of arguments */ |
| count++; |
| char** args = (char**)malloc(sizeof(*args) * count); |
| if (args != NULL) { |
| i = 0; |
| p = strtok(arg, " "); |
| while((p != NULL) && (i < count)) { |
| args[i++] = p; |
| p = strtok(NULL, " "); |
| } |
| } |
| |
| return args; |
| } |
| |
| static int wait_main(int argc, char *argv[]) |
| { |
| int r; |
| bool free_args = false; |
| char** args = argv + 2; |
| sd_bus *conn = NULL; |
| sd_event *loop = NULL; |
| mapper_async_wait *wait = NULL; |
| |
| if((!strcmp(argv[1], "wait")) && argc < 3) { |
| fprintf(stderr, "Usage: %s wait OBJECTPATH...\n", argv[0]); |
| exit(EXIT_FAILURE); |
| } else if((!strcmp(argv[1], "wait-until-removed")) && argc < 4) { |
| /* The arguments can be passed by a single string, ex: "intf obj1..." */ |
| /* Try to split the single into the multiple arguments */ |
| args = split_args(argv[2]); |
| if (args != NULL) |
| free_args = true; |
| else { |
| fprintf(stderr, "Usage: %s wait-until-removed \ |
| INTERFACE 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; |
| } |
| |
| if (!strcmp(argv[1], "wait")) |
| r = mapper_wait_async(conn, loop, NULL, args, quit, loop, &wait, |
| true); |
| else if (!strcmp(argv[1], "wait-until-removed")) |
| r = mapper_wait_async(conn, loop, args[0], args+1, quit, loop, &wait, |
| false); |
| 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: |
| if (free_args) |
| free(args); |
| exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS); |
| } |
| |
| /* print out the distinct dbus service name for the input dbus path */ |
| static int get_service_main(int argc, char *argv[]) |
| { |
| int r; |
| sd_bus *conn = NULL; |
| char *service = NULL; |
| |
| if(argc != 3) { |
| fprintf(stderr, "Usage: %s get-service 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 = mapper_get_service(conn, argv[2], &service); |
| if(r < 0) { |
| fprintf(stderr, "Error finding '%s' service: %s\n", |
| argv[2], strerror(-r)); |
| goto finish; |
| } |
| |
| printf("%s\n", service); |
| |
| |
| 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" |
| " wait-until-removed" |
| " wait until the specified objects are not present in the DBus\n" |
| " get-service return the service identifier for input path\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") || |
| !strcmp(argv[1], "wait-until-removed")) |
| wait_main(argc, argv); |
| if(!strcmp(argv[1], "get-service")) |
| get_service_main(argc, argv); |
| |
| fprintf(stderr, usage, argv[0]); |
| exit(EXIT_FAILURE); |
| } |