X-Git-Url: https://git.tokkee.org/?p=sysdb.git;a=blobdiff_plain;f=src%2Ftools%2Fsysdb%2Fmain.c;h=b22e11f0f89da462596783a000ffdcb2d70835fa;hp=0639e5f74829042a4e3a8532b97f6ee74d853236;hb=1d4f883090c6e081041d8909256a393727a2ecf1;hpb=edba65afec8c547fb6c02346eda68595ce9a5839 diff --git a/src/tools/sysdb/main.c b/src/tools/sysdb/main.c index 0639e5f..b22e11f 100644 --- a/src/tools/sysdb/main.c +++ b/src/tools/sysdb/main.c @@ -29,10 +29,15 @@ # include "config.h" #endif /* HAVE_CONFIG_H */ +#include "tools/sysdb/command.h" +#include "tools/sysdb/input.h" + #include "client/sysdb.h" #include "client/sock.h" #include "utils/error.h" +#include "utils/llist.h" #include "utils/strbuf.h" +#include "utils/os.h" #include @@ -72,22 +77,34 @@ # endif #endif /* READLINEs */ +#include +#include + #ifndef DEFAULT_SOCKET # define DEFAULT_SOCKET "unix:"LOCALSTATEDIR"/run/sysdbd.sock" #endif + static void exit_usage(char *name, int status) { + char *user = sdb_get_current_user(); printf( "Usage: %s \n" "\nOptions:\n" +" -H HOST the host to connect to\n" +" default: "DEFAULT_SOCKET"\n" +" -U USER the username to connect as\n" +" default: %s\n" +" -c CMD execute the specified command and then exit\n" +"\n" " -h display this help and exit\n" " -V display the version number and copyright\n" "\nSysDB client "SDB_CLIENT_VERSION_STRING SDB_CLIENT_VERSION_EXTRA", " -PACKAGE_URL"\n", basename(name)); +PACKAGE_URL"\n", basename(name), user); + free(user); exit(status); } /* exit_usage */ @@ -97,7 +114,7 @@ exit_version(void) printf("SysDB version "SDB_CLIENT_VERSION_STRING SDB_CLIENT_VERSION_EXTRA", built "BUILD_DATE"\n" "using libsysdbclient version %s%s\n" - "Copyright (C) 2012-2013 "PACKAGE_MAINTAINER"\n" + "Copyright (C) 2012-2014 "PACKAGE_MAINTAINER"\n" "\nThis is free software under the terms of the BSD license, see " "the source for\ncopying conditions. There is NO WARRANTY; not " @@ -107,74 +124,72 @@ exit_version(void) exit(0); } /* exit_version */ -static const char * -get_current_user(void) +static int +execute_commands(sdb_client_t *client, sdb_llist_t *commands) { - struct passwd pw_entry; - struct passwd *result = NULL; - - uid_t uid; - - /* needs to be static because we return a pointer into this buffer - * to the caller */ - static char buf[1024]; + sdb_llist_iter_t *iter; + int status = 0; - int status; - - uid = geteuid(); - - memset(&pw_entry, 0, sizeof(pw_entry)); - status = getpwuid_r(uid, &pw_entry, buf, sizeof(buf), &result); - - if (status || (! result)) { - char errbuf[1024]; - sdb_log(SDB_LOG_ERR, "Failed to determine current username: %s", - sdb_strerror(errno, errbuf, sizeof(errbuf))); - return NULL; + iter = sdb_llist_get_iter(commands); + if (! iter) { + sdb_log(SDB_LOG_ERR, "Failed to iterate commands"); + return 1; } - return result->pw_name; -} /* get_current_user */ -static const char * -get_homedir(const char *username) -{ - struct passwd pw_entry; - struct passwd *result = NULL; + while (sdb_llist_iter_has_next(iter)) { + sdb_object_t *obj = sdb_llist_iter_get_next(iter); - /* needs to be static because we return a pointer into this buffer - * to the caller */ - static char buf[1024]; + if (sdb_client_send(client, SDB_CONNECTION_QUERY, + (uint32_t)strlen(obj->name), obj->name) <= 0) { + sdb_log(SDB_LOG_ERR, "Failed to send command '%s' to server", + obj->name); + status = 1; + break; + } - int status; + /* Wait for server replies. We might get any number of log messages + * but eventually see the reply to the query, which is either DATA or + * ERROR. */ + while (42) { + status = sdb_command_print_reply(client); + if (status < 0) { + sdb_log(SDB_LOG_ERR, "Failed to read reply from server"); + break; + } - memset(&pw_entry, 0, sizeof(pw_entry)); - status = getpwnam_r(username, &pw_entry, buf, sizeof(buf), &result); + if ((status == SDB_CONNECTION_DATA) + || (status == SDB_CONNECTION_ERROR)) + break; + if (status == SDB_CONNECTION_OK) { + /* pre 0.4 versions used OK instead of DATA */ + sdb_log(SDB_LOG_WARNING, "Received unexpected OK status from " + "server in response to a QUERY (expected DATA); " + "assuming we're talking to an old server"); + break; + } + } - if (status || (! result)) { - char errbuf[1024]; - sdb_log(SDB_LOG_WARNING, "Failed to determine home directory " - "for user %s: %s", username, - sdb_strerror(errno, errbuf, sizeof(errbuf))); - return NULL; + if ((status != SDB_CONNECTION_OK) && (status != SDB_CONNECTION_DATA)) + break; /* error */ } - return result->pw_dir; -} /* get_homedir */ + + sdb_llist_iter_destroy(iter); + return status; +} /* execute_commands */ int main(int argc, char **argv) { - sdb_client_t *client; - const char *host = NULL; - const char *user = NULL; - const char *homedir; + char *homedir; char hist_file[1024] = ""; - sdb_strbuf_t *buf; + sdb_input_t input = SDB_INPUT_INIT; + sdb_llist_t *commands = NULL; while (42) { - int opt = getopt(argc, argv, "H:U:hV"); + int opt = getopt(argc, argv, "H:U:c:hV"); if (-1 == opt) break; @@ -184,7 +199,31 @@ main(int argc, char **argv) host = optarg; break; case 'U': - user = optarg; + input.user = optarg; + break; + + case 'c': + { + sdb_object_t *obj; + + if (! commands) + commands = sdb_llist_create(); + if (! commands) { + sdb_log(SDB_LOG_ERR, "Failed to create list object"); + exit(1); + } + + if (! (obj = sdb_object_create_T(optarg, sdb_object_t))) { + sdb_log(SDB_LOG_ERR, "Failed to create object"); + exit(1); + } + if (sdb_llist_append(commands, obj)) { + sdb_log(SDB_LOG_ERR, "Failed to append command to list"); + sdb_object_deref(obj); + exit(1); + } + sdb_object_deref(obj); + } break; case 'h': @@ -203,32 +242,51 @@ main(int argc, char **argv) if (! host) host = DEFAULT_SOCKET; - if (! user) { - user = get_current_user(); - if (! user) - exit(1); - } + if (! input.user) + input.user = sdb_get_current_user(); + else + input.user = strdup(input.user); + if (! input.user) + exit(1); + + SSL_load_error_strings(); + OpenSSL_add_ssl_algorithms(); - client = sdb_client_create(host); - if (! client) { + input.client = sdb_client_create(host); + if (! input.client) { sdb_log(SDB_LOG_ERR, "Failed to create client object"); + free(input.user); exit(1); } - if (sdb_client_connect(client, user)) { + if (sdb_client_connect(input.client, input.user)) { sdb_log(SDB_LOG_ERR, "Failed to connect to SysDBd"); - sdb_client_destroy(client); + sdb_client_destroy(input.client); + free(input.user); exit(1); } + if (commands) { + int status = execute_commands(input.client, commands); + sdb_llist_destroy(commands); + sdb_client_destroy(input.client); + free(input.user); + if ((status != SDB_CONNECTION_OK) && (status != SDB_CONNECTION_DATA)) + exit(1); + exit(0); + } + sdb_log(SDB_LOG_INFO, "SysDB client "SDB_CLIENT_VERSION_STRING - SDB_CLIENT_VERSION_EXTRA"\n"); + SDB_CLIENT_VERSION_EXTRA" (libsysdbclient %s%s)\n", + sdb_client_version_string(), sdb_client_version_extra()); using_history(); - if ((homedir = get_homedir(user))) { + if ((homedir = sdb_get_homedir())) { snprintf(hist_file, sizeof(hist_file) - 1, "%s/.sysdb_history", homedir); hist_file[sizeof(hist_file) - 1] = '\0'; + free(homedir); + homedir = NULL; errno = 0; if (read_history(hist_file) && (errno != ENOENT)) { @@ -237,31 +295,16 @@ main(int argc, char **argv) hist_file, sdb_strerror(errno, errbuf, sizeof(errbuf))); } } + free(input.user); - buf = sdb_strbuf_create(1024); + input.input = sdb_strbuf_create(2048); + sdb_input_init(&input); + sdb_input_mainloop(); - while (42) { - const char *prompt = "sysdb=> "; - const char *query; - char *input; - - if (sdb_strbuf_len(buf)) - prompt = "sysdb-> "; - - input = readline(prompt); - - if (! input) - break; - - sdb_strbuf_append(buf, input); - free(input); - - query = sdb_strbuf_string(buf); - if (! strchr(query, (int)';')) - continue; - - /* XXX */ - sdb_strbuf_clear(buf); + sdb_client_shutdown(input.client, SHUT_WR); + while (! sdb_client_eof(input.client)) { + /* wait for remaining data to arrive */ + sdb_command_print_reply(input.client); } if (hist_file[0] != '\0') { @@ -273,7 +316,10 @@ main(int argc, char **argv) } } - sdb_client_destroy(client); + sdb_client_destroy(input.client); + sdb_strbuf_destroy(input.input); + + ERR_free_strings(); return 0; } /* main */