client: Print out any errors on command execution
[platform/upstream/connman.git] / client / commands.c
index cbc440f..1aa2783 100644 (file)
@@ -66,163 +66,21 @@ static char *proxy_simple[] = {
 
 static int cmd_help(char *args[], int num, struct option *options);
 
-void show_help(void)
+static int parse_args(char *arg, struct option *options)
 {
-       printf("Usage: connmanctl <command> [args]\n"
-       "  enable                             Enables given technology\n"
-       "        <technology>\n"
-       "        offlinemode                  Enables OfflineMode\n"
-       "  disable                            Disables given technology\n"
-       "        <technology>\n"
-       "        offlinemode                  Disables OfflineMode\n"
-       "  state                              Shows if the system is online or offline\n"
-       "  services                           Display list of all services\n"
-       "        --properties <service name>  Show properties of service\n"
-       "  technologies                       Current technology on the system\n"
-       "  scan <technology>                  Scans for new services on the given technology\n"
-       "  connect <service>                  Connect to a given service\n"
-       "  disconnect <service>               Disconnect from service\n"
-       "  config <service> [arg]             Set certain config options\n"
-       "        --autoconnect=y/n            Set autoconnect to service\n"
-       "        --nameservers <names>        Set manual name servers\n"
-       "        --timeservers <names>        Set manual time servers\n"
-       "        --domains <domains>          Set manual domains\n"
-       "        --ipv4                       Set ipv4 configuration\n"
-       "          [METHOD|DHCP|AUTO|MANUAL] [IP] [NETMASK] [GATEWAY]\n"
-       "        --ipv6                       Set ipv6 configuration\n"
-       "          [METHOD|AUTO|MANUAL|OFF] [IP] [PREFIXLENGTH] [GATEWAY]\n"
-       "          [PRIVACY|DISABLED|ENABLED|PREFERED]\n"
-       "        --proxy                      Set proxy configuration\n"
-       "          [METHOD|URL|SERVERS|EXCLUDES]\n"
-       "          if METHOD = manual, enter 'servers' then the list of servers\n"
-       "                         then enter 'excludes' then the list of excludes\n"
-       "        --remove                     Remove the service from favorite\n"
-       "  monitor                            Monitor signals from all Connman interfaces\n"
-       "        --services                   Monitor signals from the Service interface\n"
-       "        --tech                       Monitor signals from the Technology interface\n"
-       "        --manager                    Monitor signals from the Manager interface\n"
-       "  help, --help, (no arguments)       Show this dialogue\n"
-       "  exit, quit, q                      Quit interactive mode\n"
-       "\nNote: arguments and output are considered EXPERIMENTAL for now.\n\n");
-}
-
-int service_switch(int argc, char *argv[], int c, DBusConnection *conn,
-                                               struct service_data *service)
-{
-       const char *name;
-       DBusMessage *message;
-       int error = 0;
-
-       message = get_message(conn, "GetServices");
-       if (message == NULL)
-               return -ENOMEM;
-
-       switch (c) {
-       case 'p':
-               name = find_service(conn, message, argv[2], service);
-               if (name == NULL) {
-                       error = -ENXIO;
-                       break;
-               }
-
-               error = list_properties(conn, "GetServices", (char *) name);
-               break;
-       default:
-               fprintf(stderr, "Command not recognized, please check help\n");
-               error = -EINVAL;
-               break;
-       }
-
-       dbus_message_unref(message);
-
-       return error;
-}
-
-int config_switch(int argc, char *argv[], int c, DBusConnection *conn)
-{
-       DBusMessage *message;
-       int num_args = argc - MANDATORY_ARGS;
-       int error = 0;
-       dbus_bool_t val;
+       int i;
 
-       message = get_message(conn, "GetServices");
-       if (message == NULL)
-               return -ENOMEM;
+       if (arg == NULL)
+               return -1;
 
-       switch (c) {
-       case 'a':
-               switch (*optarg) {
-               case 'y':
-               case '1':
-               case 't':
-                       val = TRUE;
-                       break;
-               case 'n':
-               case '0':
-               case 'f':
-                       val = FALSE;
-                       break;
-               default:
-                       return -EINVAL;
-               }
-               error = set_service_property(conn, message, argv[1],
-                                               "AutoConnect", NULL,
-                                               &val, 0);
-               break;
-       case 'i':
-               error = set_service_property(conn, message, argv[1],
-                                       "IPv4.Configuration", ipv4,
-                                       argv + MANDATORY_ARGS, num_args);
-               break;
-       case 'v':
-               error = set_service_property(conn, message, argv[1],
-                                       "IPv6.Configuration", ipv6,
-                                       argv + MANDATORY_ARGS, num_args);
-               break;
-       case 'n':
-               error = set_service_property(conn, message, argv[1],
-                                       "Nameservers.Configuration", NULL,
-                                       argv + MANDATORY_ARGS, num_args);
-               break;
-       case 't':
-               error = set_service_property(conn, message, argv[1],
-                                       "Timeservers.Configuration", NULL,
-                                       argv + MANDATORY_ARGS, num_args);
-               break;
-       case 'd':
-               error = set_service_property(conn, message, argv[1],
-                                       "Domains.Configuration", NULL,
-                                       argv + MANDATORY_ARGS, num_args);
-               break;
-       case 'x':
-               if ((strcmp(argv[3], "direct") == 0 && argc < 5) ||
-                       (strcmp(argv[3], "auto") == 0 && argc < 6)) {
-                       error = set_service_property(conn, message, argv[1],
-                                       "Proxy.Configuration", proxy_simple,
-                                       argv + MANDATORY_ARGS, num_args);
-               } else if (strcmp(argv[3], "manual") == 0
-                                 && strcmp(argv[4], "servers") == 0
-                                 && argc > 5) {
-                       argc -= 5;
-                       error = store_proxy_input(conn, message, argv[1],
-                                                               argc, &argv[5]);
-               } else {
-                       fprintf(stderr, "Incorrect arguments\n");
-                       error = -EINVAL;
-               }
-               break;
-       case 'r':
-               error = remove_service(conn, message, argv[1]);
-               break;
-       default:
-               fprintf(stderr, "Command not recognized, please check help\n");
-               error = -EINVAL;
-               break;
+       for (i = 0; options[i].name != NULL; i++) {
+               if (strcmp(options[i].name, arg) == 0 ||
+                               (strncmp(arg, "--", 2) == 0 &&
+                                       strcmp(&arg[2], options[i].name) == 0))
+                       return options[i].val;
        }
 
-       dbus_message_unref(message);
-
-       return error;
+       return '?';
 }
 
 int monitor_switch(int argc, char *argv[], int c, DBusConnection *conn)
@@ -297,7 +155,38 @@ static int cmd_state(char *args[], int num, struct option *options)
 
 static int cmd_services(char *args[], int num, struct option *options)
 {
-       return -1;
+       char *service_name = NULL;
+       int err = 0;
+       int c;
+       DBusMessage *message;
+
+       if (num > 3)
+               return -E2BIG;
+
+       c = parse_args(args[1], options);
+       switch (c) {
+       case -1:
+               break;
+       case 'p':
+               if (num < 3)
+                       return -EINVAL;
+               service_name = args[2];
+               break;
+       default:
+               if (num > 2)
+                       return -E2BIG;
+               service_name = args[1];
+               break;
+       }
+
+       message = get_message(connection, "GetServices");
+       if (message == NULL)
+               return -ENOMEM;
+
+       err = list_properties(connection, "GetServices", service_name);
+       dbus_message_unref(message);
+
+       return err;
 }
 
 static int cmd_technologies(char *args[], int num, struct option *options)
@@ -322,7 +211,135 @@ static int cmd_disconnect(char *args[], int num, struct option *options)
 
 static int cmd_config(char *args[], int num, struct option *options)
 {
-       return -1;
+       int res = 0, index = 2, oldindex = 0;
+       int c;
+       char *service_name;
+       DBusMessage *message;
+       char **opt_start;
+       dbus_bool_t val;
+
+       service_name = args[1];
+       if (service_name == NULL)
+               return -EINVAL;
+
+       while (index < num && args[index] != NULL) {
+               c = parse_args(args[index], options);
+               opt_start = &args[index + 1];
+               res = 0;
+
+               message = get_message(connection, "GetServices");
+               if (message == NULL)
+                       return -ENOMEM;
+
+               oldindex = index;
+
+               switch (c) {
+               case 'a':
+                       switch (parse_boolean(*opt_start)) {
+                       case 1:
+                               val = TRUE;
+                               break;
+                       case 0:
+                               val = FALSE;
+                               break;
+                       default:
+                               res = -EINVAL;
+                               break;
+                       }
+                       if (res == 0)
+                               res = set_service_property(connection, message,
+                                               service_name, "AutoConnect",
+                                               NULL, &val, 0);
+                       break;
+               case 'i':
+                       res = set_service_property(connection, message,
+                                       service_name, "IPv4.Configuration",
+                                       ipv4, opt_start, 0);
+                       if (res < 0)
+                               index += 4;
+                       break;
+               case 'v':
+                       res = set_service_property(connection, message,
+                                       service_name, "IPv6.Configuration",
+                                       ipv6, opt_start, 0);
+                       if (res < 0)
+                               index += 5;
+                       break;
+               case 'n':
+                       res = set_service_property(connection, message,
+                                       service_name,
+                                       "Nameservers.Configuration",
+                                       NULL, opt_start, 0);
+                       break;
+               case 't':
+                       res = set_service_property(connection, message,
+                                       service_name,
+                                       "Timeservers.Configuration",
+                                       NULL, opt_start, 0);
+                       break;
+               case 'd':
+                       res = set_service_property(connection, message,
+                                       service_name,
+                                       "Domains.Configuration",
+                                       NULL, opt_start, 0);
+                       break;
+               case 'x':
+                       if (*opt_start == NULL) {
+                               res = -EINVAL;
+                               break;
+                       }
+
+                       if (strcmp(*opt_start, "direct") == 0) {
+                               res = set_service_property(connection, message,
+                                               service_name,
+                                               "Proxy.Configuration",
+                                               proxy_simple, opt_start, 1);
+                               break;
+                       }
+
+                       if (strcmp(*opt_start, "auto") == 0) {
+                               res = set_service_property(connection, message,
+                                               service_name,
+                                               "Proxy.Configuration",
+                                               proxy_simple, opt_start, 1);
+                               break;
+                       }
+
+                       if (strcmp(*opt_start, "manual") == 0) {
+                                       char **url_start = &args[index + 2];
+
+                                       if (*url_start != NULL &&
+                                               strcmp(*url_start,
+                                                       "servers") == 0) {
+                                               url_start = &args[index + 3];
+                                               index++;
+                                       }
+                                       res = store_proxy_input(connection,
+                                                       message, service_name,
+                                                       0, url_start);
+                       }
+
+                       break;
+               case 'r':
+                       res = remove_service(connection, message, service_name);
+                       break;
+               default:
+                       res = -EINVAL;
+                       break;
+               }
+
+               dbus_message_unref(message);
+
+               if (res < 0) {
+                       printf("Error '%s': %s\n", args[oldindex],
+                                       strerror(-res));
+               } else
+                       index += res;
+
+               index++;
+       }
+
+       return 0;
 }
 
 static int cmd_monitor(char *args[], int num, struct option *options)
@@ -335,6 +352,55 @@ static int cmd_exit(char *args[], int num, struct option *options)
        return 0;
 }
 
+static struct option service_options[] = {
+       {"properties", required_argument, 0, 'p'},
+       { NULL, }
+};
+
+static const char *service_desc[] = {
+       "[<service>]      (obsolete)",
+       NULL
+};
+
+static struct option config_options[] = {
+       {"nameservers", required_argument, 0, 'n'},
+       {"timeservers", required_argument, 0, 't'},
+       {"domains", required_argument, 0, 'd'},
+       {"ipv6", required_argument, 0, 'v'},
+       {"proxy", required_argument, 0, 'x'},
+       {"autoconnect", required_argument, 0, 'a'},
+       {"ipv4", required_argument, 0, 'i'},
+       {"remove", 0, 0, 'r'},
+       { NULL, }
+};
+
+static const char *config_desc[] = {
+       "<dns1> [<dns2>] [<dns3>]",
+       "<ntp1> [<ntp2>] [...]",
+       "<domain1> [<domain2>] [...]",
+       "off|auto|manual <address> <prefixlength> <gateway> <privacy>",
+       "direct|auto <URL>|manual <URL1> [<URL2>] [...]\n"
+       "                   [exclude <exclude1> [<exclude2>] [...]]",
+       "yes|no",
+       "off|dhcp|manual <address> <prefixlength> <gateway>",
+       "                 Remove service",
+       NULL
+};
+
+static struct option monitor_options[] = {
+       {"services", no_argument, 0, 's'},
+       {"tech", no_argument, 0, 'c'},
+       {"manager", no_argument, 0, 'm'},
+       { NULL, }
+};
+
+static const char *monitor_desc[] = {
+       "                 Monitor only services",
+       "                 Monitor only technologies",
+       "                 Monitor only manager interface",
+       NULL
+};
+
 static const struct {
         const char *cmd;
        const char *argument;
@@ -349,7 +415,7 @@ static const struct {
          cmd_disable, "Disables given technology or offline mode"},
        { "state",        NULL,           NULL,            NULL,
          cmd_state, "Shows if the system is online or offline" },
-       { "services",     NULL,           NULL,            NULL,
+       { "services",     "[<service>]",  service_options, &service_desc[0],
          cmd_services, "Display services" },
        { "technologies", NULL,           NULL,            NULL,
          cmd_technologies, "Display technologies" },
@@ -359,9 +425,9 @@ static const struct {
          cmd_connect, "Connect a given service" },
        { "disconnect",   "<service>",    NULL,            NULL,
          cmd_disconnect, "Disconnect a given service" },
-       { "config",       "<service>",    NULL,            NULL,
+       { "config",       "<service>",    config_options,  &config_desc[0],
          cmd_config, "Set service configuration options" },
-       { "monitor",      NULL,           NULL,            NULL,
+       { "monitor",      NULL,           monitor_options, &monitor_desc[0],
          cmd_monitor, "Monitor signals from interfaces" },
        { "help",         NULL,           NULL,            NULL,
          cmd_help, "Show help" },
@@ -374,18 +440,47 @@ static const struct {
 
 static int cmd_help(char *args[], int num, struct option *options)
 {
-       return -1;
+       int i, j;
+
+       for (i = 0; cmd_table[i].cmd != NULL; i++) {
+               const char *cmd = cmd_table[i].cmd;
+               const char *argument = cmd_table[i].argument;
+               const char *desc = cmd_table[i].desc;
+
+               printf("%-12s%-22s%s\n", cmd != NULL? cmd: "",
+                               argument != NULL? argument: "",
+                               desc != NULL? desc: "");
+
+               if (cmd_table[i].options != NULL) {
+                       for (j = 0; cmd_table[i].options[j].name != NULL;
+                            j++) {
+                               const char *options_desc =
+                                       cmd_table[i].options_desc != NULL ?
+                                       cmd_table[i].options_desc[j]: "";
+
+                               printf("   --%-12s%s\n",
+                                               cmd_table[i].options[j].name,
+                                               options_desc);
+                       }
+               }
+       }
+
+       return 0;
 }
 
 int commands(DBusConnection *connection, char *argv[], int argc)
 {
-       int i;
+       int i, result;
 
        for (i = 0; cmd_table[i].cmd != NULL; i++) {
                if (g_strcmp0(cmd_table[i].cmd, argv[0]) == 0 &&
                                cmd_table[i].func != NULL) {
-                       return cmd_table[i].func(argv, argc,
+                       result = cmd_table[i].func(argv, argc,
                                        cmd_table[i].options);
+                       if (result < 0)
+                               printf("Error '%s': %s\n", argv[0],
+                                               strerror(-result));
+                       return 0;
                }
        }
 
@@ -397,10 +492,12 @@ int commands_no_options(DBusConnection *connection, char *argv[], int argc)
        DBusMessage *message = NULL;
        int error = 0;
 
-
        if (strcmp(argv[0], "--help") == 0 || strcmp(argv[0], "help") == 0  ||
                                                strcmp(argv[0], "h") == 0) {
-               show_help();
+               printf("Usage: connmanctl [[command] [args]]\n");
+               cmd_help(NULL, 0, NULL);
+               printf("\nNote: arguments and output are considered "
+                               "EXPERIMENTAL for now.\n\n");
        } else if (strcmp(argv[0], "state") == 0) {
                if (argc != 1) {
                        fprintf(stderr, "State cannot accept an argument, "
@@ -501,84 +598,8 @@ int commands_options(DBusConnection *connection, char *argv[], int argc)
 {
        int error, c;
        int option_index = 0;
-       struct service_data service;
-
-       static struct option service_options[] = {
-               {"properties", required_argument, 0, 'p'},
-               {0, 0, 0, 0}
-       };
-
-       static struct option config_options[] = {
-               {"nameservers", required_argument, 0, 'n'},
-               {"timeservers", required_argument, 0, 't'},
-               {"domains", required_argument, 0, 'd'},
-               {"ipv6", required_argument, 0, 'v'},
-               {"proxy", required_argument, 0, 'x'},
-               {"autoconnect", required_argument, 0, 'a'},
-               {"ipv4", required_argument, 0, 'i'},
-               {"remove", 0, 0, 'r'},
-               {0, 0, 0, 0}
-       };
-
-       static struct option monitor_options[] = {
-               {"services", no_argument, 0, 's'},
-               {"tech", no_argument, 0, 'c'},
-               {"manager", no_argument, 0, 'm'},
-               {0, 0, 0, 0}
-       };
-
-       if (strcmp(argv[0], "services") == 0) {
-               if (argc > 3) {
-                       fprintf(stderr, "Too many arguments for services, "
-                                                               "see help\n");
-                       return -EINVAL;
-               }
-               if (argc < 2) {
-                       printf("List of all services:\n");
-                       error = list_properties(connection, "GetServices", NULL);
-                       if (error != 0)
-                               return error;
-               } else {
-                       while ((c = getopt_long(argc, argv, "", service_options,
-                                               &option_index))) {
-                               if (c == -1) {
-                                       if (option_index == 0) {
-                                               printf("Services takes an "
-                                                       "option, see help.\n");
-                                               return -EINVAL;
-                                       }
-                                       break;
-                               }
-                               error = service_switch(argc, argv, c,
-                                                               connection,
-                                                               &service);
-                               if (error != 0)
-                                       return error;
-                               option_index++;
-                       }
-               }
-       } else if (strcmp(argv[0], "config") == 0) {
-               if (argc < 3) {
-                       fprintf(stderr, "Config requires an option, "
-                                                               "see help\n");
-                       return -EINVAL;
-               }
-               while ((c = getopt_long(argc, argv, "", config_options,
-                                                       &option_index))) {
-                       if (c == -1) {
-                               if (option_index == 0) {
-                                       printf("Config requires an option, "
-                                                       "see help\n");
-                                       return -EINVAL;
-                               }
-                               break;
-                       }
-                       error = config_switch(argc, argv, c, connection);
-                       if (error != 0)
-                               return error;
-                       option_index++;
-               }
-       } else if (strcmp(argv[0], "monitor") == 0) {
+
+       if (strcmp(argv[0], "monitor") == 0) {
                if (argc > 2) {
                        fprintf(stderr, "Too many arguments for monitor, "
                                                                "see help\n");